public void MutateChild(Genome child) { if (child == null) { throw new ArgumentNullException(nameof(child)); } if (this.random.NextDouble() < this.ParentSimulation.Parameters.AddNodeProbability) { child.AddNodeMutation(this.Innovations); } else if (this.random.NextDouble() < this.ParentSimulation.Parameters.AddConnectionProbability) { child.AddConnectionMutation(this.Innovations); } else { if (this.random.NextDouble() < this.ParentSimulation.Parameters.MutateConnectionWeightsProbability) { child.MutateWeights(this.ParentSimulation.Parameters.WeightMutationPower); } if (this.random.NextDouble() < this.ParentSimulation.Parameters.MutateToggleEnabledProbability) { child.ToggleEnabledMutation(); } if (this.random.NextDouble() < this.ParentSimulation.Parameters.MutateReenableProbability) { child.ReenableMutation(); } } }
private void SpawnPopulation(Genome basicGenome, int populationSize) { for (int i = 0; i < populationSize; ++i) { Genome g = basicGenome.Copy(); g.ParentSimulation = this; g.MutateWeights(1.0f); this.nextGeneration.Add(g); } }
// Performs reproduction of organisms in the genomes list public void Reproduce(List <Genome> nextGeneration, List <Innovation> innovations) { if (nextGeneration == null) { throw new ArgumentNullException(nameof(nextGeneration)); } if (this.Offspring <= 0) { return; } bool championCloned = false; for (int i = 0; i < this.Offspring; ++i) { Genome child = null; if (this.ChampionOffspring > 0) { child = this.GetChampion().Copy(); child.ParentSimulation = this.ParentSimulation; if (this.ChampionOffspring > 1) { child.IsPopulationChampion = false; child.Fitness = 0.0; child.OriginalFitness = 0.0; if (this.random.NextDouble() < this.ParentSimulation.Parameters.MutateConnectionWeightsProbability) { child.MutateWeights(this.ParentSimulation.Parameters.WeightMutationPower); } else { child.AddConnectionMutation(innovations); } } else { child.IsPopulationChampion = true; } --this.ChampionOffspring; } else if (!championCloned && this.Offspring > 5) { child = this.GetChampion().Copy(); child.ParentSimulation = this.ParentSimulation; child.IsPopulationChampion = true; championCloned = true; } else { // Mutate only (without crossover) if (this.random.NextDouble() < this.ParentSimulation.Parameters.MutateWithoutCrossover) { // Select random genome to mutate child = this.genomes[this.random.Next(this.genomes.Count)].Copy(); child.ParentSimulation = this.ParentSimulation; child.Fitness = 0.0; child.OriginalFitness = 0.0; child.IsPopulationChampion = false; this.MutateChild(child); } // Perform crossover else { // Select random parents Genome parent1 = this.genomes[this.random.Next(this.genomes.Count)]; Genome parent2 = null; // Find second parent INSIDE this species if (this.random.NextDouble() > this.ParentSimulation.Parameters.InterspeciesMateRate) { parent2 = this.genomes[this.random.Next(this.genomes.Count)]; } // Find second parent OUTSIDE this species - this should happen very very rarely else { // TODO: possible modification - select only from better performing species Species speciesFound = this; int tries = 0; while (speciesFound == this && tries++ < 5) { speciesFound = this.ParentSimulation.Species[this.random.Next(this.ParentSimulation.Species.Count)]; } if (speciesFound.Genomes.Count == 0) { speciesFound = this; } parent2 = speciesFound.Genomes[this.random.Next(speciesFound.Genomes.Count)]; } if (this.random.NextDouble() > this.ParentSimulation.Parameters.AverageCrossoverProbability) { child = parent1.Crossover(parent2, this.random); } else { child = parent2.CrossoverAverage(parent2, this.random); } // Mutate child if (this.random.NextDouble() > this.ParentSimulation.Parameters.MateWithoutMutatingProbability || parent1 == parent2 || parent1.CompatibilityDistance(parent2) < 0.00001f) { this.MutateChild(child); } } } if (child != null) { nextGeneration.Add(child); } } }