Beispiel #1
0
        /// <summary>
        /// Runs the genetic algorithm for the specified number of generations
        /// </summary>
        /// <param name="numGenerations">The number of generations</param>
        /// <returns></returns>
        public void Run()
        {
            ICollection <IGenotype> nextPopulation;
            List <IGenotype>        parents;

            Gene[][]  children;
            IGenotype child;
            double    fitness;
            bool      mutated, solutionFound;

            ParameterCheck();

            if (Population == null)
            {
                InitializePopulation();
            }

            if (AllowDuplicates)
            {
                nextPopulation = new List <IGenotype>(PopulationSize);
            }
            else
            {
                nextPopulation = new SafeHashSet <IGenotype>(MaxRetriesForDuplicates);
            }

            solutionFound = false;

            if (PreserveElitePercent > 0)
            {
                foreach (IGenotype individual in Population.Take((int)(PreserveElitePercent * PopulationSize)).ToList())
                {
                    nextPopulation.Add(individual);
                }
            }

            SelectionMethod.Initialize(Population);

            while (nextPopulation.Count < PopulationSize)
            {
                try
                {
                    parents = SelectionMethod.DoSelection();
                }
                catch (SafeHashSetException)
                {
                    Converged = true;
                    break;
                }

                // Perform crossover
                children = CrossoverMethod.DoCrossover <Gene>(parents);

                // Iterate through each child produced by crossover
                for (int i = 0; i < children.Length; i++)
                {
                    // Calculate fitness of child
                    fitness = FitnessFunction(children[i], out solutionFound);

                    // Perform mutation (but skip if solution has been found)
                    mutated = solutionFound ? false : MutationMethod.DoMutation <Gene>(ref children[i]); // TODO return mutation and use only if better fitness??? Make a parameter to turn on/off

                    // Recalculate fitness if mutation occurred
                    if (mutated)
                    {
                        fitness = FitnessFunction(children[i], out solutionFound);
                    }

                    // Instantiate child
                    child = CreateMethod(children[i], fitness);

                    try
                    {
                        nextPopulation.Add(child);

                        if (solutionFound)
                        {
                            break;
                        }
                    }
                    catch (SafeHashSetException)
                    {
                        Converged = true;
                        break;
                    }
                }

                if (solutionFound || Converged)
                {
                    break;
                }
            }

            GenerationNumber++;
            SolutionFound = solutionFound;
            Population    = nextPopulation.OrderByDescending(x => x.Fitness).ToList();
            BestCurrent   = Population.First();

            FinishedGeneration?.Invoke();

            foreach (Termination.TerminationMethod t in TerminationMethods)
            {
                if (t.CheckTermination(this))
                {
                    Terminated = true;
                    TerminationReached?.Invoke();
                }
            }
        }