/// <summary> /// Trains and evaluates a genetic algorithm with the specified parameters. /// </summary> /// <param name="data">The data to be used for training.</param> /// <param name="solution">The reference to where the solution will be stored.</param> /// <param name="bestChromosome">The best chromosome.</param> /// <param name="error">The reference where error rate will be stored.</param> /// <param name="predictions">The reference to where the predictions will be stored.</param> /// <param name="iterations">The number of iterations to perform.</param> /// <param name="population">The size of the population.</param> /// <param name="inputCount">The number of inputs.</param> /// <param name="shuffle">Value indicating whether to shuffle the chromosomes on each epoch.</param> /// <param name="constants">The constant inputs.</param> /// <param name="geneType">Type of the gene functions.</param> /// <param name="chromosomeType">Type of the chromosome.</param> /// <param name="selectionType">Type of the chromosome selection.</param> /// <param name="cancelToken">The cancellation token for the async operation.</param> /// <param name="progressCallback">The progress callback: current iteration.</param> /// <returns> /// <c>true</c> if the training and evaluation was successful, <c>false</c> otherwise.</returns> /// <exception cref="ArgumentException">Array should be size of data minus number of inputs.</exception> public static bool TrainAndEval(double[] data, ref double[] solution, ref string bestChromosome, ref double error, ref double[] predictions, int iterations, int population, int inputCount, bool shuffle, double[] constants, GeneFunctions geneType, Chromosomes chromosomeType, Selections selectionType, CancellationToken cancelToken, Action <int> progressCallback = null) { IGPGene gene; switch (geneType) { case GeneFunctions.Simple: gene = new SimpleGeneFunction(inputCount + constants.Length); break; case GeneFunctions.Extended: gene = new ExtendedGeneFunction(inputCount + constants.Length); break; default: return(false); } IChromosome chromosome; switch (chromosomeType) { case Chromosomes.GPT: chromosome = new GPTreeChromosome(gene); break; case Chromosomes.GEP: chromosome = new GEPChromosome(gene, 20); break; default: return(false); } ISelectionMethod selection; switch (selectionType) { case Selections.Elite: selection = new EliteSelection(); break; case Selections.Rank: selection = new RankSelection(); break; case Selections.Roulette: selection = new RouletteWheelSelection(); break; default: return(false); } cancelToken.ThrowIfCancellationRequested(); var ga = new Population( population, chromosome, new TimeSeriesPredictionFitness(data, inputCount, 0, constants), selection ) { AutoShuffling = shuffle }; if (solution.Length != data.Length - inputCount) { throw new ArgumentException("Array should be the size of data minus number of inputs.", nameof(solution)); } var input = new double[inputCount + constants.Length]; for (var j = 0; j < data.Length - inputCount; j++) { solution[j] = j + inputCount; } Array.Copy(constants, 0, input, inputCount, constants.Length); for (var i = 0; i < iterations; i++) { ga.RunEpoch(); progressCallback?.Invoke(i); cancelToken.ThrowIfCancellationRequested(); } error = 0.0; bestChromosome = ga.BestChromosome.ToString(); for (int j = 0, n = data.Length - inputCount; j < n; j++) { for (int k = 0, b = j + inputCount - 1; k < inputCount; k++) { input[k] = data[b - k]; } solution[j] = PolishExpression.Evaluate(bestChromosome, input); error += Math.Abs((solution[j] - data[inputCount + j]) / data[inputCount + j]); cancelToken.ThrowIfCancellationRequested(); } error = error / (data.Length - inputCount) * 100; if (predictions.Length != 0) { Array.Copy(solution, solution.Length - inputCount, predictions, 0, inputCount); for (var i = inputCount; i < predictions.Length; i++) { for (int j = 0; j < inputCount; j++) { input[j] = predictions[(i - inputCount) + j]; } predictions[i] = PolishExpression.Evaluate(bestChromosome, input); cancelToken.ThrowIfCancellationRequested(); } } return(true); }
/// <summary> /// One-point recombination (crossover). /// </summary> /// /// <param name="pair">Pair chromosome to crossover with.</param> /// public void RecombinationOnePoint( GEPChromosome pair ) { // check for correct pair if ( ( pair.length == length ) ) { // crossover point int crossOverPoint = rand.Next( length - 1 ) + 1; // length of chromosome to be crossed int crossOverLength = length - crossOverPoint; // swap parts of chromosomes Recombine( genes, pair.genes, crossOverPoint, crossOverLength ); } }
/// <summary> /// Two point recombination (crossover). /// </summary> /// /// <param name="pair">Pair chromosome to crossover with.</param> /// public void RecombinationTwoPoint( GEPChromosome pair ) { // check for correct pair if ( ( pair.length == length ) ) { // crossover point int crossOverPoint = rand.Next( length - 1 ) + 1; // length of chromosome to be crossed int crossOverLength = length - crossOverPoint; // if crossover length already equals to 1, then it becomes // usual one point crossover. otherwise crossover length // also randomly chosen if ( crossOverLength != 1 ) { crossOverLength = rand.Next( crossOverLength - 1 ) + 1; } // swap parts of chromosomes Recombine( genes, pair.genes, crossOverPoint, crossOverLength ); } }
/// <summary> /// Initializes a new instance of the <see cref="GEPChromosome"/> class. /// </summary> /// /// <param name="source">Source GEP chromosome to clone from.</param> /// protected GEPChromosome( GEPChromosome source ) { headLength = source.headLength; length = source.length; fitness = source.fitness; // allocate genes array genes = new IGPGene[length]; // copy genes for ( int i = 0; i < length; i++ ) genes[i] = source.genes[i].Clone( ); }