public void Add(Genome genome) { Genomes.Add(genome); }
private static ConnectionGene GetGeneFromFitterParent(NeatEvaluator evaluator, Genome fitParent, bool fitnessEqual, ConnectionGene connection, Genome genome) { ConnectionGene geneToTake = null; if (fitnessEqual) { if (evaluator.GetRandomFloat() < 0.5) { geneToTake = connection.Copy(null); } } else { if (genome == fitParent) { geneToTake = connection.Copy(null); } } return(geneToTake); }
public Dictionary <Genome, Species> Selection(int population) { if (SpeciesItems.Count == 0) { throw new InvalidOperationException("No species found!?"); } Dictionary <Genome, Species> nextGeneration = new Dictionary <Genome, Species>(); float sumOfAllAdjustedFitnesses = SpeciesItems.Sum(x => x.CalcuateAdjustedFitnessSum()); var speciesByFitness = SpeciesItems.OrderByDescending(x => x.AdjustedFitnessSum).ToList(); int rank = 1; float totalSum = sumOfAllAdjustedFitnesses; int offspringToDistribute = population; foreach (var species in speciesByFitness) { species.SetRank(rank); rank++; var fitnessSum = species.AdjustedFitnessSum; float offspringPerSpecies = fitnessSum / totalSum; totalSum -= fitnessSum; int offspring = (int)Math.Ceiling(offspringToDistribute * offspringPerSpecies); if (offspring > offspringToDistribute) { offspring = offspringToDistribute; } int offspringToUse = offspring; int offspringAssigned = 0; var champ = species.Champion.Copy(); if (champ != null && species.Genomes.Count > Evaluator.NeatConfig.ChampCopyThreshold) { nextGeneration.Add(champ, species); offspringAssigned++; offspringToUse--; } if (Evaluator.NeatConfig.UseStagnation) { float stagnationEqualTolerance = 0.001f; float difference = species.AdjustedFitnessSum - species.LastFitness; if (difference < stagnationEqualTolerance) { species.StagnationCounter++; if (species.StagnationCounter > Evaluator.NeatConfig.StagnationThreshold) { offspringToUse = 0; species.Stagnated = true; } } else { species.StagnationCounter = 0; } } species.LastFitness = species.AdjustedFitnessSum; if (offspringToUse <= 0) { continue; // skip this species, because it received no population at all } int offspringToMate = (int)Math.Floor(offspringToUse * Evaluator.NeatConfig.CrossoverOffspringRate); int offspringToClone = offspringToUse - offspringToMate; var selection = species.Selection(); var adjustedFitnessGenomesLookup = selection.ToDictionary(x => x, x => (x.Fitness / species.Genomes.Count)); for (int i = 0; i < offspringToMate; i++) { // only mate interspecies if the rate matches and var doInterspeciesCrossover = speciesByFitness.Count > 1 && Evaluator.GetRandomFloat() < Evaluator.NeatConfig.InterspeciesMatingRate; if (doInterspeciesCrossover) { var p1 = GetRandomGenomeBiasedAdjustedFitness(adjustedFitnessGenomesLookup); var intermateSpeciesList = speciesByFitness.Where(x => x != species).ToList(); var intermateSpeciesRndIndex = Evaluator.Random.Next(0, intermateSpeciesList.Count); var intermateSpecies = intermateSpeciesList[intermateSpeciesRndIndex]; if (intermateSpecies.Genomes.Count > 0) { var intermateGenomeIndex = Evaluator.Random.Next(0, intermateSpecies.Genomes.Count); var intermateGenome = intermateSpecies.Genomes.Items[intermateGenomeIndex]; var child = Genome.Crossover(Evaluator, p1, intermateGenome); child.Mutate(); nextGeneration.Add(child, species); offspringAssigned++; } else { doInterspeciesCrossover = false; // fallback when somehow there were no genomes in the other species } } if (!doInterspeciesCrossover) { var p1 = GetRandomGenomeBiasedAdjustedFitness(adjustedFitnessGenomesLookup); var p2 = GetRandomGenomeBiasedAdjustedFitness(adjustedFitnessGenomesLookup); var child = Genome.Crossover(Evaluator, p1, p2); child.Mutate(); nextGeneration.Add(child, species); offspringAssigned++; } } for (int i = 0; i < offspringToClone; i++) { var p1 = GetRandomGenomeBiasedAdjustedFitness(adjustedFitnessGenomesLookup); var clone = p1.Copy(); clone.Mutate(); nextGeneration.Add(clone, species); offspringAssigned++; } offspringToDistribute -= offspringAssigned; } return(nextGeneration); }