示例#1
0
文件: Generation.cs 项目: afalz/NEAT
        public IGeneration Evolve(Func <IGenome, double> getFitness)
        {
            IGeneration nextGeneration = new Generation(new Population());

            Population.Evaluate(getFitness);

            int spareOffspring = 0;

            Population.Species.ForEach(s =>
            {
                s.Age++;

                if (s.LastImprovementAge > SpeciesParameters.DropOffAge)
                {
                    spareOffspring     += s.ExpectedOffspring;
                    s.ExpectedOffspring = 0;
                }
            });

            if (spareOffspring > 0)
            {
                Population.BestSpecies.ExpectedOffspring += spareOffspring;
            }

            // Compensate for floating point inaccuracy
            while (Population.ExpectedOffspring < Population.Genomes.Count)
            {
                Population.BestSpecies.ExpectedOffspring++;
            }

            // Create the Offspring for each species
            List <ISpecies> populationSpecies = Population.Species.ToList();

            populationSpecies.ForEach(s =>
            {
                bool championSelected = false;

                IEnumerable <IGenome> speciesGenomes = s.NaturalSelect();

                // Create the offspring
                Enumerable.Range(0, s.ExpectedOffspring).ToList().ForEach(i =>
                {
                    IGenome offspring = null;

                    if (s.ExpectedOffspring > GenerationParameters.ChampionCopyMinimumGenomes && !championSelected)
                    {
                        offspring        = speciesGenomes.OrderByDescending(p => p.Fitness / s.Genomes.Count).First();
                        championSelected = true;
                    }
                    else if (new Random().NextDouble() < GenerationParameters.MutateOnlyProbability || s.Genomes.Count == 1)
                    {
                        // Mutate
                        IGenome candidate = GetRandomGenomeBiasFitness(speciesGenomes);

                        Mutate(candidate, GetSoftenFactor(candidate.Fitness, speciesGenomes));

                        offspring = candidate;
                    }
                    else
                    {
                        IGenome parent = null;
                        IGenome mate   = null;

                        // Mate
                        if (new Random().NextDouble() < GenerationParameters.InterspeciesBreedingRate)
                        {
                            // Interspecies mating
                            parent = GetRandomGenomeBiasFitness(speciesGenomes);
                            mate   = GetRandomGenomeBiasFitness(speciesGenomes);

                            offspring = parent.Breed(mate);
                        }
                        else
                        {
                            // Mate outside of species
                            ISpecies speciesMate = GetRandomSpeciesBiasFitness(Population.Species.Where(sp => sp != s));

                            parent = GetRandomGenomeBiasFitness(speciesGenomes);
                            mate   = GetRandomGenomeBiasFitness(speciesMate.NaturalSelect());

                            offspring = parent.Breed(mate);
                        }

                        if (new Random().NextDouble() < GenerationParameters.MutateOffspringProbability || parent == mate)
                        {
                            Mutate(offspring, GetSoftenFactor(Math.Max(parent.Fitness, mate.Fitness), speciesGenomes));
                        }
                    }

                    if (offspring != null)
                    {
                        IGenome genome = offspring.Copy();

                        // Speciate the offspring against the current population
                        // This way we can see what species need to be carried over into the next generation population
                        Population.Speciate(genome);
                        ISpecies species = Population.Species.First(sp => sp.Id == genome.SpeciesId).CopyWithoutGenomes();

                        if (!nextGeneration.Population.Species.Contains(species, new SpeciesComparer()))
                        {
                            nextGeneration.Population.Species.Add(species);
                        }

                        nextGeneration.Population.Species.First(sp => sp.Id == species.Id).Genomes.Add(genome);
                        nextGeneration.Population.Genomes.Add(genome);
                    }
                });
            });

            nextGeneration.FittestGenome = Population.Genomes.OrderByDescending(p => p.Fitness).First();

            return(nextGeneration);
        }