/// <summary> /// Converts the program to the XML String representation /// </summary> /// <param name="Program"></param> /// <returns>XML String representation of the program</returns> private String CreateProgramString(GPProgram Program) { String ProgramString = ""; // // Serialize the program to an XML string Program.ConvertToTree(this.FunctionSet, false); GPLanguageWriterXML ProgramWriterXML = new GPLanguageWriterXML(Program, this.Training.TimeSeries); using (MemoryStream ms = new MemoryStream()) { ProgramWriterXML.Write(ms); ms.Seek(0, SeekOrigin.Begin); using (StreamReader reader = new StreamReader(ms)) { ProgramString = reader.ReadToEnd(); } } // // Convert it back to an array. I forgot to do this and it kept messing // things up as the modeling continued. Program.ConvertToArray(this.FunctionSet); return(ProgramString); }
/// <summary> /// Select two parents, based upon fitness, for a crossover operation. /// Place the two children into the new Population. /// </summary> /// <param name="PopNew">Population to add the newly created program to</param> private void Crossover(GPPopulation PopNew, GPFitnessObjectiveBase FitnessSelection) { GPProgram Child1 = (GPProgram)FitnessSelection.Programs(ExecProgramSelection()).Clone(); GPProgram Child2 = (GPProgram)FitnessSelection.Programs(ExecProgramSelection()).Clone(); // // Convert to trees Child1.ConvertToTree(m_ModelerConfig.FunctionSet, false); Child2.ConvertToTree(m_ModelerConfig.FunctionSet, false); // // Perform the crossover m_TreeFactory.Attach(Child1); Child2 = m_TreeFactory.Crossover(Child2); // // Convert to arrays Child1.ConvertToArray(m_ModelerConfig.FunctionSet); Child2.ConvertToArray(m_ModelerConfig.FunctionSet); // // Add them to the new Population PopNew.Programs.Add(Child1); if (PopNew.Count < m_PopCurrent.Count) { PopNew.Programs.Add(Child2); } }
/// <summary> /// Compute the fitness of the entire Population and return the value of /// the best program in the Population. /// </summary> public void EvaluateFitness(int Generation) { // // First time through the fitness object doesn't exist, so have to create it if (m_Fitness == null) { m_Fitness = new GPFitness( this, this.Training, GPEnums.RESULTS_TOLERANCE, m_FunctionSet.UseInputHistory); } m_BestProgram = m_Fitness.Compute(Generation, m_Population); // // Always simplify a program before it is transmitted. m_BestProgram.ConvertToTree(this.FunctionSet, false); m_BestProgram.Edit(); m_BestProgram.ConvertToArray(this.FunctionSet); // // Obtain the Population stats m_Population.ComputeComplexity( out m_PopulationComplexityMin, out m_PopulationComplexityMax, out m_PopulationComplexityAve); }
/// <summary> /// Select a program, based on fitness, for mutation. Place // the mutated program into the new Population. /// </summary> /// <param name="PopNew">Population to add the newly created program to</param> private void Mutate(GPPopulation PopNew, GPFitnessObjectiveBase FitnessSelection) { GPProgram Copy = (GPProgram)FitnessSelection.Programs(ExecProgramSelection()).Clone(); // // Convert it to a tree Copy.ConvertToTree(m_ModelerConfig.FunctionSet, false); // // Perform the mutation m_TreeFactory.Attach(Copy); m_TreeFactory.Mutate(); // // Return it back to an array Copy.ConvertToArray(m_ModelerConfig.FunctionSet); // // Add this mutated individual to the new Population PopNew.Programs.Add(Copy); }
/// <summary> /// Evaluates the program versus each set of training inputs and /// computes the custom fitness of the program. /// </summary> /// <param name="ProgramID">Index of the program in the Population</param> /// <param name="Predictions">Set of predicted values by the program</param> /// <returns>Custom fitness of the program</returns> private double ComputeProgramFitness(int ProgramID, double[] Predictions) { GPProgram Program = m_Population.Programs[ProgramID]; // // Start by converting the program into a tree representation Program.ConvertToTree(m_Config.FunctionSet, true); // // Set the memory size Program.CountMemory = m_Config.Profile.CountMemory; // // Test each item in the training data set m_FitnessHits[ProgramID] = 0; for (int FitnessTest = 0; FitnessTest < m_TrainingData.Rows && !m_Abort; FitnessTest++) { // // Assign the input values to the program Program.UserTerminals = m_TrainingData.InputRow(FitnessTest); // // Assign a reference to the historical set of data for this fitness test if (m_UseInputHistory) { Program.InputHistory = m_UserInputHistory[FitnessTest]; } // // This is the money shot, execute the genetic program! double Result = Program.EvaluateAsDouble(); // // Deal with problems that might have come up during the fitness computation if (double.IsInfinity(Result) || double.IsNaN(Result) || double.IsNegativeInfinity(Result) || double.IsPositiveInfinity(Result)) { Result = m_MaximumError; } // // If the program size is above our threshold size, give it the // worst possible result to prevent it from being used in any of the // genetic operations. There is a problem if the number of nodes in // the tree gets about the size of a 'short', we loose the ability to // count and label them. Question...why not use an 'int'? Two reasons... // 1. A program bigger than 16bits of nodes is ridiculous in the first place // 2. Memory, each node would require 32bits for a lable, instead of 16bits, // it doubles that bit of storage, which we don't need. if (Program.CountNodes >= GPEnums.PROGRAMSIZE_THRESHOLD) { Result = m_MaximumError; } // // Store the Program result Predictions[FitnessTest] = Result; // // Determine if we have a "hit" against the input data double Error = Math.Abs(Result - m_TrainingData.ObjectiveRow(FitnessTest)[0]); if (Error <= m_Tolerance && Error >= -m_Tolerance) { m_FitnessHits[ProgramID]++; } } // // Restore it back to an array. Program.ConvertToArray(m_Config.FunctionSet); // // Make a call into the custom fitness object to evaluate the // fitness of the program. double ProgramFitness = m_Config.Fitness.ComputeFitness( m_UserInputHistoryCustomFitness, Predictions, m_TrainingData.ObjectiveColumn(0), m_TrainingAverage, m_Tolerance); // // Still have to check the result for problems if (double.IsNaN(ProgramFitness) || double.IsInfinity(ProgramFitness) || double.IsPositiveInfinity(ProgramFitness) || double.IsNegativeInfinity(ProgramFitness)) { ProgramFitness = m_FitnessMeasure[m_WorstProgramGeneration]; } return(ProgramFitness); }