public void VerifyNeatPopulationStats() { IRandomSource rng = RandomDefaults.CreateRandomSource(0); // Create test population and apply speciation strategy. NeatPopulation <double> neatPop = CreateNeatPopulation(30, 10.0, rng); // Loop the species; assign the same fitness to genomes within each species. for (int i = 0; i < neatPop.SpeciesArray.Length; i++) { double fitness = (i + 1) * 10.0; neatPop.SpeciesArray[i].GenomeList.ForEach(x => x.FitnessInfo = new FitnessInfo(fitness)); } // Calc NeatPopulation statistics. neatPop.UpdateStats(PrimaryFitnessInfoComparer.Singleton, rng); // Validate expected mean fitness for each species. for (int i = 0; i < neatPop.SpeciesArray.Length; i++) { double expectedMeanFitness = (i + 1) * 10.0; Assert.Equal(expectedMeanFitness, neatPop.SpeciesArray[i].Stats.MeanFitness); } // Validate SumSpeciesMeanFitness. double expectedSumSpeciesMeanFitness = 10.0 + 20.0 + 30.0; Assert.Equal(expectedSumSpeciesMeanFitness, neatPop.NeatPopulationStats.SumSpeciesMeanFitness); // Validate BestGenomeSpeciesIdx. Assert.Equal(2, neatPop.NeatPopulationStats.BestGenomeSpeciesIdx); // Assign a high fitness to one of the genomes, and check that BestGenomeSpeciesIdx is updated accordingly. neatPop.SpeciesArray[0].GenomeList[2].FitnessInfo = new FitnessInfo(100.0); // Note. The species must be re-initialised in order for the fit genome to be sorted correctly within its // containing species. InitialiseSpecies(neatPop); neatPop.UpdateStats(PrimaryFitnessInfoComparer.Singleton, rng); Assert.Equal(0, neatPop.NeatPopulationStats.BestGenomeSpeciesIdx); // Perform the same test again with the best genome in the second species. neatPop.SpeciesArray[1].GenomeList[3].FitnessInfo = new FitnessInfo(200.0); InitialiseSpecies(neatPop); neatPop.UpdateStats(PrimaryFitnessInfoComparer.Singleton, rng); Assert.Equal(1, neatPop.NeatPopulationStats.BestGenomeSpeciesIdx); }
public void VerifyPopulationStats() { IRandomSource rng = RandomDefaults.CreateRandomSource(0); // Create a test population. NeatPopulation <double> pop = CreateNeatPopulation(100, 10.0, rng); // Modify a few genome fitnesses. pop.GenomeList[10].FitnessInfo = new FitnessInfo(100.0); pop.GenomeList[20].FitnessInfo = new FitnessInfo(0.0); // Initialise the NEAT population species; the wider population stats are dependent on this occurring. InitialiseSpecies(pop); // Calc/update stats. pop.UpdateStats(PrimaryFitnessInfoComparer.Singleton, rng); // Validate stats. // Fitness stats. PopulationStatistics stats = pop.Stats; Assert.Equal(10, stats.BestGenomeIndex); Assert.Equal(100.0, stats.BestFitness.PrimaryFitness); Assert.Equal(10.8, stats.MeanFitness); Assert.Equal(1, stats.BestFitnessHistory.Length); Assert.Equal(100.0, stats.BestFitnessHistory.Total); // Complexity stats. Assert.Equal(6.0, stats.BestComplexity); Assert.Equal(6.0, stats.MeanComplexity); Assert.Equal(1, stats.MeanComplexityHistory.Length); Assert.Equal(6.0, stats.MeanComplexityHistory.Total); }
public void UpdateSpeciesAllocationSizes() { IRandomSource rng = RandomDefaults.CreateRandomSource(0); NeatEvolutionAlgorithmSettings eaSettings = new() { SpeciesCount = 4 }; // Create population. NeatPopulation <double> neatPop = CreateNeatPopulation(100, eaSettings.SpeciesCount, 2, 2, 1.0); // Manually set-up some species. var speciesArr = neatPop.SpeciesArray; speciesArr[0].GenomeList.AddRange(neatPop.GenomeList.Take(25)); speciesArr[1].GenomeList.AddRange(neatPop.GenomeList.Skip(25).Take(25)); speciesArr[2].GenomeList.AddRange(neatPop.GenomeList.Skip(50).Take(25)); speciesArr[3].GenomeList.AddRange(neatPop.GenomeList.Skip(75).Take(25)); // Manually assign fitness scores to the genomes. speciesArr[0].GenomeList.ForEach(x => x.FitnessInfo = new FitnessInfo(100.0)); speciesArr[1].GenomeList.ForEach(x => x.FitnessInfo = new FitnessInfo(200.0)); speciesArr[2].GenomeList.ForEach(x => x.FitnessInfo = new FitnessInfo(400.0)); speciesArr[3].GenomeList.ForEach(x => x.FitnessInfo = new FitnessInfo(800.0)); // Invoke species target size calcs. neatPop.UpdateStats(PrimaryFitnessInfoComparer.Singleton, rng); SpeciesAllocationCalcs <double> .UpdateSpeciesAllocationSizes( neatPop, eaSettings, RandomDefaults.CreateRandomSource()); // Species target sizes should be relative to the species mean fitness. double totalMeanFitness = 1500.0; double popSize = 100.0; Assert.Equal((100.0 / totalMeanFitness) * popSize, speciesArr[0].Stats.TargetSizeReal); Assert.Equal((200.0 / totalMeanFitness) * popSize, speciesArr[1].Stats.TargetSizeReal); Assert.Equal((400.0 / totalMeanFitness) * popSize, speciesArr[2].Stats.TargetSizeReal); Assert.Equal((800.0 / totalMeanFitness) * popSize, speciesArr[3].Stats.TargetSizeReal); // Note. Discretized target sizes will generally be equal to ceil(TargetSizeReal) or floor(TargetSizeReal), // but may not be due to the target size adjustment logic that is used to ensure that sum(TargetSizeInt) is equal // to the required population size. // Check that sum(TargetSizeInt) is equal to the required population size. Assert.Equal(speciesArr.Sum(x => x.Stats.TargetSizeInt), neatPop.GenomeList.Count); }