// 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; // Place genomes into species foreach (Genome g in genomes) { bool foundSpecies = false; foreach (Species s in species) { 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); speciesMap[g] = newSpecies; } } // Remove unused species foreach (Species s in species) { 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) { FitnessGenome fittestInSpecies = s.fitnessPop.Max(); 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.Range(0f, 1f) < MUTATION_RATE) { child.Mutation(); } if (Random.Range(0f, 1f) < ADD_CONNECTION_RATE) { //Debug.Log("Adding connection mutation..."); child.AddConnectionMutation(connectionInnovation, 10); } if (Random.Range(0f, 1f) < ADD_NODE_RATE) { //Debug.Log("Adding node mutation..."); child.AddNodeMutation(connectionInnovation, nodeInnovation); } nextGenGenomes.Add(child); } genomes = nextGenGenomes; nextGenGenomes = new List <Genome>(); }