예제 #1
0
        /// <summary>
        /// Handles iterating a generation of the population.
        /// All evaluations must have been done by this point.
        /// </summary>
        /// <param name="rando">A random number generator.</param>
        public void Epoch(Random rando)
        {
            foreach (var spec in Species)
            {
                spec.SetChampions();
            }

            SortSpeciesByChampionFitness();

            Genome generationChampion = Species.Last().Fitness.Champion;

            if (generationChampion.Fitness.Score >= Fitness.ChampionScore)
            {
                GenerationPrime = Generation;
            }
            Fitness.GenerationalChampion = generationChampion;

            Dictionary <Species, int> ExpectedChildren = FindExpectedChildren();

            foreach (var spec in Species)
            {
                int numberOfParents = (int)Math.Floor(spec.Size() * Const.SurvivalThresh + 1);
                spec.SortGenomesByFitness();
                spec.Genomes.RemoveRange(0, spec.Size() - numberOfParents);
            }

            List <Genome> nextGenerationGenomes = new List <Genome>();

            foreach (var specCountPair in ExpectedChildren)
            {
                nextGenerationGenomes.AddRange(specCountPair.Key.Reproduce(specCountPair.Value, GenerationalInnovations, Species, rando));
            }

            ClearParentGeneration();
            SpeciateNewGeneration(nextGenerationGenomes);

            RemoveDeadSpecies();
            ResetSpeciesTemplates();
            AgeSpecies();
            Generation++;
            HistoricalInnovations.AddRange(GenerationalInnovations);
            GenerationalInnovations.Clear();
        }
예제 #2
0
        /// <summary>
        /// Finds the expected children of each species.
        /// </summary>
        /// <returns>A dictionary of each species that will definitely have children.</returns>
        private Dictionary <Species, int> FindExpectedChildren()
        {
            Dictionary <Species, int> expectedChildren = new Dictionary <Species, int>();
            Species mostExpectingSpecies = null;
            int     totalChildren        = 0;

            //Original NEAT calls this delta-coding.
            //Original NEAT does not check this first. It overrides the 'else' statement logic. Seemed unneccessary.
            if (Generation - GenerationPrime >= Const.PopulationDropoffGenerations)
            {
                GenerationPrime = Generation;
                int halfPopulationSize = TargetPopulationSize / 2;

                if (Species.Count == 1)
                {
                    expectedChildren[Species.Last()] = TargetPopulationSize;
                    totalChildren = TargetPopulationSize;
                    Species.Last().AgePrime = Species.Last().Age;
                    mostExpectingSpecies = Species.Last();
                }
                else
                {
                    expectedChildren[Species.Last()] = halfPopulationSize;
                    Species.Last().AgePrime = Species.Last().Age;
                    mostExpectingSpecies = Species.Last();

                    expectedChildren[Species[Species.Count - 1]] = halfPopulationSize;
                    Species[Species.Count - 1].AgePrime          = Species[Species.Count - 1].Age;

                    totalChildren = 2 * halfPopulationSize;
                }
            }
            else
            {
                if (Generation % Const.SpeciesStagnationEpochCycle == 0)
                {
                    foreach (var spec in Species)
                    {
                        if (spec.Age > Const.OverTheHillThresh)
                        {
                            spec.OnDeathBed = true;
                            break;
                        }
                    }
                }

                double sumOfTotalAdjustedScore = 0.0;
                foreach (var spec in Species)
                {
                    spec.AdjustFitness();
                    sumOfTotalAdjustedScore += spec.Fitness.TotalAdjustedScore;
                }

                int mostExpected = 0;
                foreach (var spec in Species)
                {
                    int children = 0;

                    //Warning: There is no check in the original NEAT that handles this case.
                    if (sumOfTotalAdjustedScore != 0)
                    {
                        children = (int)(spec.Fitness.TotalAdjustedScore * TargetPopulationSize / sumOfTotalAdjustedScore);
                    }

                    if (children > 0)
                    {
                        expectedChildren.Add(spec, children);
                        totalChildren += children;
                    }

                    if (children > mostExpected)
                    {
                        mostExpectingSpecies = spec;
                        mostExpected         = children;
                    }
                }
            }

            if (totalChildren > 0)
            {
                expectedChildren[mostExpectingSpecies] += TargetPopulationSize - totalChildren;
            }
            else
            {
                expectedChildren.Add(Species.Last(), TargetPopulationSize);
            }

            return(expectedChildren);
        }