/// <summary> /// Add a child to the next iteration. /// </summary> /// <param name="genome">The child.</param> /// <returns>True, if the child was added successfully.</returns> public bool AddChild(IGenome genome) { lock (_newPopulation) { if (_newPopulation.Count < Population.PopulationSize) { // don't readd the old best genome, it was already added if (genome != _oldBestGenome) { if (ValidationMode) { if (_newPopulation.Contains(genome)) { throw new EncogError( "Genome already added to population: " + genome); } } _newPopulation.Add(genome); } if (!Double.IsInfinity(genome.Score) && !Double.IsNaN(genome.Score) && BestComparer.IsBetterThan(genome, BestGenome)) { BestGenome = genome; Population.BestGenome = BestGenome; } return(true); } return(false); } }
/// <inheritdoc /> public void Iteration() { if (!_initialized) { PreIteration(); } if (Population.Species.Count == 0) { throw new EncogError("Population is empty, there are no species."); } IterationNumber++; // Clear new population to just best genome. _newPopulation.Clear(); _newPopulation.Add(BestGenome); _oldBestGenome = BestGenome; // execute species in parallel IList <EAWorker> threadList = new List <EAWorker>(); foreach (ISpecies species in Population.Species) { int numToSpawn = species.OffspringCount; // Add elite genomes directly if (species.Members.Count > 5) { var idealEliteCount = (int)(species.Members.Count * EliteRate); int eliteCount = Math.Min(numToSpawn, idealEliteCount); for (int i = 0; i < eliteCount; i++) { IGenome eliteGenome = species.Members[i]; if (_oldBestGenome != eliteGenome) { numToSpawn--; if (!AddChild(eliteGenome)) { break; } } } } // now add one task for each offspring that each species is allowed while (numToSpawn-- > 0) { var worker = new EAWorker(this, species); threadList.Add(worker); } } // run all threads and wait for them to finish Parallel.ForEach(threadList, currentTask => currentTask.PerformTask()); // validate, if requested if (ValidationMode) { if (_oldBestGenome != null && !_newPopulation.Contains(_oldBestGenome)) { throw new EncogError( "The top genome died, this should never happen!!"); } if (BestGenome != null && _oldBestGenome != null && BestComparer.IsBetterThan(_oldBestGenome, BestGenome)) { throw new EncogError( "The best genome's score got worse, this should never happen!! Went from " + _oldBestGenome.Score + " to " + BestGenome.Score); } } _speciation.PerformSpeciation(_newPopulation); // purge invalid genomes Population.PurgeInvalidGenomes(); }