// 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>(); }