public static int CompareTo(FitnessGenome one, FitnessGenome two) { if (one.fitness > two.fitness) { return(1); } else if (one.fitness < two.fitness) { return(-1); } return(0); }
// Runs one generation public void Evaluate() { // Reset everything for next generation foreach (Species s in species) { s.Reset(random); } fitnessMap.Clear(); speciesMap.Clear(); nextGenGenomes.Clear(); highestFitness = float.MinValue; fittestGenome = null; int count1 = 0; int count2 = 0; // Place genomes into species foreach (Genome g in genomes) { count1++; bool foundSpecies = false; foreach (Species s in species) { count2++; if (Genome.CompatibilityDistance(g, s.mascot, C1, C2, C3) < DT) { // compatibility distance is less than DT, so genome belongs to this species s.members.Add(g); speciesMap[g] = s; foundSpecies = true; break; } } if (!foundSpecies) { // if there is no appropiate species for genome, make a new one Species newSpecies = new Species(g); species.Add(newSpecies); Debug.Log("New species created. Species amount: " + species.Count + ", g.Nodes.Count = " + g.Nodes.Count); speciesMap[g] = newSpecies; } } // Remove unused species //using(IEnumerator<Species> sEnumerator = species.GetEnumerator()) //{ // while (sEnumerator.MoveNext()) // { // Species s = sEnumerator.Current; // if (!s.members.Any()) // { // sEnumerator // } // } //} foreach (Species s in species.ToList()) { if (!s.members.Any()) { species.Remove(s); } } // Evaluate genomes and assign score foreach (Genome g in genomes) { Species s = speciesMap[g]; // Get species of the genome float score = evaluateGenome(g); // fitness of Genome float adjustedScore = score / speciesMap[g].members.Count; s.AddAdjustedFitness(adjustedScore); s.fitnessPop.Add(new FitnessGenome(g, adjustedScore)); fitnessMap[g] = adjustedScore; if (score > highestFitness) { highestFitness = score; fittestGenome = g; } } // put best genome from each species into next generation // species = species.OrderByDescending(s => s.fitnessPop).ToList(); foreach (Species s in species) { float bestFitness = 0; FitnessGenome fittestInSpecies = new FitnessGenome(); foreach (FitnessGenome fit in s.fitnessPop) { if (fit.fitness > bestFitness) { fittestInSpecies = fit; bestFitness = fit.fitness; } } if (fittestInSpecies.genome.Nodes.Count != 0) { // Debug.Log("OMG, g.Nodes.Count == 0 row 224"); nextGenGenomes.Add(fittestInSpecies.genome); } } // Breed the rest of the genomes while (nextGenGenomes.Count < populationSize) { // replace removed genomes by randomly breeding Species s = getRandomSpeciesBiasedAjdustedFitness(random); Genome p1 = getRandomGenomeBiasedAdjustedFitness(s, random); Genome p2 = getRandomGenomeBiasedAdjustedFitness(s, random); Genome child = new Genome(); if (fitnessMap[p1] >= fitnessMap[p2]) { child.Crossover(p1, p2); } else { child.Crossover(p2, p1); } if (random.NextDouble() < MUTATION_RATE) { child.Mutation(); } if (random.NextDouble() < ADD_CONNECTION_RATE) { //Debug.Log("Adding connection mutation..."); child.AddConnectionMutation(connectionInnovation, 10); } if (random.NextDouble() < ADD_NODE_RATE) { //Debug.Log("Adding node mutation..."); child.AddNodeMutation(nodeInnovation, connectionInnovation); } nextGenGenomes.Add(child); } genomes = nextGenGenomes; nextGenGenomes = new List <Genome>(); }
public void Evaluate(float[] scores) { // reset everything foreach (Species s in species) { s.ResetSpecies(new System.Random()); } scoreMap.Clear(); speciesMap.Clear(); nextGenGenomes.Clear(); highestScore = float.MinValue; fittestGenome = null; // place genomes into species foreach (Genome g in genomes) { bool foundSpecies = false; foreach (Species s in species) { if (Genome.CompatibilityDist(g, s.mascot, c1, c2, c3) < dt) { s.members.Add(g); speciesMap.Add(g, s); foundSpecies = true; break; } } if (!foundSpecies) // make new species { Species newSpecies = new Species(g); species.Add(newSpecies); speciesMap.Add(g, newSpecies); } } // remove dead species foreach (Species s in species.ToList()) { if (s.members.Count == 0) { species.Remove(s); } } if (species.Count > 11) { dt += 0.04f; ConsoleLogger.Log("dt: " + dt.ToString()); } else if (species.Count < 9) { dt -= 0.04f; ConsoleLogger.Log("dt: " + dt.ToString()); } ConsoleLogger.Log("No. species: " + species.Count.ToString()); // evaluate genomes and assign fitness foreach (Genome g in genomes) { Species s = speciesMap[g]; float score = scores.ToList()[genomes.IndexOf(g)]; float adjustedScore = score / speciesMap[g].members.Count; s.AddAdjustedFitness(adjustedScore); s.fitnessPop.Add(new FitnessGenome(g, adjustedScore)); scoreMap.Add(g, adjustedScore); if (score > highestScore) { highestScore = score; fittestGenome = g; } } // put best genomes from species into next generation foreach (Species s in species) { // sort genomes by fitness s.fitnessPop.Sort(FitnessGenomeComparator.CompareTo); s.fitnessPop.Reverse(); FitnessGenome fittestInSpecies = s.fitnessPop[0]; nextGenGenomes.Add(fittestInSpecies.genome); } Random rand = new Random(); // breed genomes while (nextGenGenomes.Count < populationSize) { Species s = GetRandomSpeciesBiasedAdjustedFitness(rand); Genome p1 = GetRandomGenomeBiasedAdjustedFitness(s, rand); if (rand.NextDouble() < _INTER_SPECIES_RATE) { s = GetRandomSpeciesBiasedAdjustedFitness(rand); } Genome p2 = GetRandomGenomeBiasedAdjustedFitness(s, rand); Genome child; if (scoreMap[p1] >= scoreMap[p2]) { child = Genome.Crossover(p1, p2); } else { child = Genome.Crossover(p2, p1); } if (rand.NextDouble() < _MUTATION_RATE) { child.ValueMutation(); } if (rand.NextDouble() < _ADD_CONONECTION_RATE) { child.AddConnectionMutation(); } if (rand.NextDouble() < _ADD_NODE_RATE) { child.AddNodeMutation(); } nextGenGenomes.Add(child); } genomes = nextGenGenomes; nextGenGenomes = new List <Genome>(); }
public void EvaluateGeneration() { _lastGenerationResults.Clear(); _evaluatedGenomes.Clear(); for (int i = 0; i < _genomes.Count; i++) { var genome = _genomes[i]; var fitnessGenome = new FitnessGenome() { Fitness = EvaluateGenome(genome), Genome = genome }; _evaluatedGenomes.Add(fitnessGenome); } //Sort Collections _evaluatedGenomes = _evaluatedGenomes.OrderByDescending(g => g.Fitness).ToList(); _lastGenerationResults.AddRange(_evaluatedGenomes); //kill the 9/10 worst genomes var cutoffIndex = _evaluatedGenomes.Count / 10; _evaluatedGenomes = _evaluatedGenomes.Take(cutoffIndex).ToList(); //find next generation population _nextGeneration.Clear(); // save champ var champion = _evaluatedGenomes.First(); FittestGenome = champion; _nextGeneration.Add(champion.Genome); while (_nextGeneration.Count() < _neatConfiguration.PopulationSize) { if (_random.NextDouble() > _neatConfiguration.ASexualReproductionRate) { var parent1 = _evaluatedGenomes[_random.Next(_evaluatedGenomes.Count)]; FitnessGenome parent2; do { parent2 = _evaluatedGenomes[_random.Next(_evaluatedGenomes.Count)]; } while (parent2 == parent1); Genome child; if (parent1.Fitness > parent2.Fitness) { child = _crossFunctionStrategy.GenerateOffspring(parent1.Genome, parent2.Genome); } else { child = _crossFunctionStrategy.GenerateOffspring(parent2.Genome, parent1.Genome); } if (_random.NextDouble() < _neatConfiguration.MutationRate) { _weightMutation.Mutate(ref child); } if (_random.NextDouble() < _neatConfiguration.AddConnectionRate) { _addConnectionMutation.Mutate(ref child); } if (_random.NextDouble() < _neatConfiguration.AddNodeRate) { _addNodeMutation.Mutate(ref child); } _nextGeneration.Add(child); } else { var parent = _evaluatedGenomes[_random.Next(_evaluatedGenomes.Count)]; var child = parent.Genome.Copy(); _weightMutation.Mutate(ref child); _nextGeneration.Add(child); } } //Transfer next generation to current generation _genomes.Clear(); _genomes.AddRange(_nextGeneration); }