Example #1
0
        /// <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( );
 }