Пример #1
0
        /// <summary>
        /// Called before Optimize() to setup the optimizer.
        /// Always called in main thread which would allow for putting additional GUI in here.
        /// </summary>
        public override void Initialize()
        {
            // don't forget to call Initialize() on the base class before any custom handling
            base.Initialize();
            bool optionWindowRequired = false;

            StrategyParameters = new Chromosomes(Strategy, true);
            if (StrategyParameters.HasBoolOrEnum)
            {
                optionWindowRequired = true;
                if (options == null)
                {
                    options = new GoForm(StrategyParameters);
                }
            }

            if (optionWindowRequired && options.ShowDialog(Form.ActiveForm) != DialogResult.OK)
            {
                StrategyParameters = new Chromosomes(Strategy, true);
            }
        }
Пример #2
0
        /// <summary>
        /// Runs the optimizer on a given parameter set.
        /// Beware: this method might be called in a non-main, worker thread. E.g. driving GUI logic from here forward would cause issues.
        /// </summary>
        public override void Optimize()
        {
            Individual supremeIndividual = null;

            try
            {
                var realStabilitySize          = (int)Math.Ceiling(populationSize * stabilitySize);
                var realResetSize              = (int)Math.Ceiling(populationSize * resetSize);
                var numberOfStrategyParameters = StrategyParameters.Count;
                var combinations       = StrategyParameters.CountCombinations;
                var siblings           = new Dictionary <Individual, bool>();
                var children           = new List <Individual>();
                var parents            = new List <Individual>();
                var prevStabilityScore = double.NaN;

                // Start optimization process
                for (int generation = 1; generation <= maxGenerations; generation++)
                {
                    //If Initial generation, seed the population with random individuals
                    while (children.Count < populationSize && siblings.Count < combinations)
                    {
                        ValidateIndividual(children, siblings, CreateRandomIndividual());
                    }

                    foreach (Individual individual in children)
                    {
                        if (UserAbort)
                        {
                            throw new AbortException();
                        }
                        StrategyParameters.SetStrategyParameters(individual, Strategy, Parameters);
                        RunIteration(IterationCompleted, individual);
                    }

                    WaitForIterationsCompleted(false);                     //Make sure that each individual completed its iteration

                    parents.AddRange(children);
                    parents.Sort();

                    Individual generationBest = parents[0];                     //This is the best performing individual since stability reset
                    if (parents.Count > 0 && generationBest != null &&
                        (supremeIndividual == null || supremeIndividual.Performance < generationBest.Performance))
                    {
                        supremeIndividual = generationBest;
                    }

                    int    stabilityIndividuals = Math.Max(1, Math.Min(parents.Count, realStabilitySize));
                    double stabilityScore       = 0.0;
                    for (int i = 0; i < stabilityIndividuals; i++)
                    {
                        stabilityScore += parents[i].Performance;
                    }

                    if (supremeIndividual != null && minimumPerformance > 0 && supremeIndividual.Performance > minimumPerformance)
                    {
                        break;
                    }

                    children.Clear();                     //Clearing up space for the next generation

                    if (siblings.Count >= combinations || generation == maxGenerations)
                    {
                        break;
                    }

                    //Repopulating the next generation.

                    //If Population is stable, leave just best performing individuals
                    if (stabilityScore == prevStabilityScore)
                    {
                        if (realResetSize <= 0)
                        {
                            parents.Clear();
                        }
                        else
                        if (parents.Count > 0)
                        {
                            parents = parents.GetRange(0, Math.Min(parents.Count, realResetSize));
                        }
                        continue;
                    }

                    //Assign a weight for each parent
                    RankPopulation(parents);

                    //Reproduce extra individuals mutated from the best
                    ShakeBestPerformer(children, siblings, combinations, generationBest, numberOfStrategyParameters);

                    //Reproduce children using Crossover, Mutation and totally random genomes
                    while (children.Count < populationSize && siblings.Count < combinations)
                    {
                        if (UserAbort)
                        {
                            throw new AbortException();
                        }
                        if (random.NextDouble() <= crossoverRate)
                        {
                            int[] chromosomeIndexesForSon;
                            int[] chromosomeIndexesForDaughter;
                            //Produce two children from two parents
                            //Parents are selected using Roulette Selection Method
                            //Note: There are many other selection algorithms (Google them out...)
                            //TODO: Implements some additional selection methods
                            //Crossover is performed using single break point
                            //TODO: implement 2 or 3 break points Crossover algorithms
                            Crossover(numberOfStrategyParameters, parents[RouletteSelection(parents)], parents[RouletteSelection(parents)], out chromosomeIndexesForSon, out chromosomeIndexesForDaughter);
                            for (var idx = 0; idx < numberOfStrategyParameters; idx++)
                            {
                                if (StrategyParameters[idx].Count <= 1)
                                {
                                    continue;
                                }

                                //After children are produced from crossover, small part should be mutated
                                if (random.NextDouble() <= mutationRate)
                                {
                                    chromosomeIndexesForSon[idx] = Mutate(mutationStrength, StrategyParameters[idx].Count, chromosomeIndexesForSon[idx]);
                                }
                                if (random.NextDouble() <= mutationRate)
                                {
                                    chromosomeIndexesForDaughter[idx] = Mutate(mutationStrength, StrategyParameters[idx].Count, chromosomeIndexesForDaughter[idx]);
                                }
                            }
                            //Make sure that children are unique, so we wont waste any time for evaluation of their performance
                            ValidateIndividual(children, siblings, new Individual(chromosomeIndexesForSon));
                            ValidateIndividual(children, siblings, new Individual(chromosomeIndexesForDaughter));
                        }
                        else
                        {
                            //Create random children
                            //Make sure that children are unique, so we wont waste any time for evaluation of their performance
                            ValidateIndividual(children, siblings, CreateRandomIndividual());
                            ValidateIndividual(children, siblings, CreateRandomIndividual());
                        }
                    }
                    prevStabilityScore = stabilityScore;
                }
            }
            catch
            {
            }
            finally
            {
                WaitForIterationsCompleted(true);
                if (options != null)
                {
                    options.Dispose();
                    options = null;
                }
            }
        }