private ComplexityRegulationMode DetermineMode_WhileSimplifying( EvolutionAlgorithmStatistics eaStats, PopulationStatistics popStats) { // Currently simplifying. // Test if simplification (ongoing reduction in complexity) has stalled. // We allow simplification to progress for a few generations before testing of it has stalled, this allows // a lead in time for the effects of simplification to occur. // In addition we do not switch to complexifying if complexity is above the currently defined ceiling. if ( ((eaStats.Generation - _lastTransitionGeneration) > _minSimplifcationGenerations) && (popStats.MeanComplexity < _complexityCeiling) && ((popStats.MeanComplexityHistory.Mean - _prevMeanMovingAverage) >= 0.0)) { // Simplification has stalled; switch back to complexification. _currentMode = ComplexityRegulationMode.Complexifying; _lastTransitionGeneration = eaStats.Generation; _prevMeanMovingAverage = 0.0; } // else: otherwise remain in simplifying mode. // Update previous mean moving average complexity value. _prevMeanMovingAverage = popStats.MeanComplexityHistory.Mean; // Set a new complexity ceiling, relative to the current population complexity mean. _complexityCeiling = popStats.MeanComplexity + _relativeComplexityCeiling; return(_currentMode); }
/// <summary> /// Notify the strategy of a change in complexity regulation mode in the evolution algorithm. /// </summary> /// <param name="mode">The current mode.</param> public void NotifyComplexityRegulationMode(ComplexityRegulationMode mode) { _mutationTypeDistributionsCurrent = mode switch { ComplexityRegulationMode.Complexifying => _mutationTypeDistributionsComplexifying, ComplexityRegulationMode.Simplifying => _mutationTypeDistributionsSimplifying, _ => throw new ArgumentException("Unexpected complexity regulation mode."), }; }
/// <summary> /// Constructs with the default NeatEvolutionAlgorithmParameters and speciation strategy /// (KMeansClusteringStrategy with ManhattanDistanceMetric). /// </summary> public NeatEvolutionAlgorithm() { _eaParams = new NeatEvolutionAlgorithmParameters(); _eaParamsComplexifying = _eaParams; _eaParamsSimplifying = _eaParams.CreateSimplifyingParameters(); _stats = new NeatAlgorithmStats(_eaParams); _speciationStrategy = new KMeansClusteringStrategy <TGenome>(new ManhattanDistanceMetric()); _complexityRegulationMode = ComplexityRegulationMode.Complexifying; _complexityRegulationStrategy = new NullComplexityRegulationStrategy(); }
/// <summary> /// Constructs with the provided NeatEvolutionAlgorithmParameters and ISpeciationStrategy. /// </summary> public NeatEvolutionAlgorithm(NeatEvolutionAlgorithmParameters eaParams, ISpeciationStrategy <TGenome> speciationStrategy, IComplexityRegulationStrategy complexityRegulationStrategy) { _eaParams = eaParams; _eaParamsComplexifying = _eaParams; _eaParamsSimplifying = _eaParams.CreateSimplifyingParameters(); _stats = new NeatAlgorithmStats(_eaParams); _speciationStrategy = speciationStrategy; _complexityRegulationMode = ComplexityRegulationMode.Complexifying; _complexityRegulationStrategy = complexityRegulationStrategy; }
public void TestInitialisation() { var strategy = new AbsoluteComplexityRegulationStrategy(10, 10.0); var eaStats = new EvolutionAlgorithmStatistics(); var popStats = new PopulationStatistics(); // The strategy should initialise to, and remain in, Complexifying mode. for (int i = 0; i < 100; i++) { eaStats.Generation = i; ComplexityRegulationMode mode = strategy.UpdateMode(eaStats, popStats); Assert.AreEqual(ComplexityRegulationMode.Complexifying, mode); } }
/// <summary> /// Construct the complexity regulation strategy with the provided regulation parameters. /// </summary> public DefaultComplexityRegulationStrategy(ComplexityCeilingType ceilingType, double ceilingValue) { _ceilingType = ceilingType; _complexityCeiling = ceilingValue; // For relative complexity ceiling we await the first call to DetermineMode() before setting the threshold // relative to the population mean complexity. Indicate this with -1.0. if(ComplexityCeilingType.Relative == ceilingType) { _complexityCeilingCurrent = -1.0; } else { _complexityCeilingCurrent = ceilingValue; } _currentMode = ComplexityRegulationMode.Complexifying; }
/// <summary> /// Constructs with the default NeatEvolutionAlgorithmParameters and speciation strategy /// (KMeansClusteringStrategy with ManhattanDistanceMetric). /// </summary> /* * public NeatEvolutionAlgorithm() * { * _eaParams = new NeatEvolutionAlgorithmParameters(); * _eaParamsComplexifying = _eaParams; * _eaParamsSimplifying = _eaParams.CreateSimplifyingParameters(); * _stats = new NeatAlgorithmStats(_eaParams); * _speciationStrategy = new KMeansClusteringStrategy<TGenome>(new ManhattanDistanceMetric()); * * _complexityRegulationMode = ComplexityRegulationMode.Complexifying; * _complexityRegulationStrategy = new NullComplexityRegulationStrategy(); * } */ /// <summary> /// Constructs with the provided NeatEvolutionAlgorithmParameters and ISpeciationStrategy. /// </summary> /* * public NeatEvolutionAlgorithm(NeatEvolutionAlgorithmParameters eaParams, * ISpeciationStrategy<TGenome> speciationStrategy, * IComplexityRegulationStrategy complexityRegulationStrategy) * { * _eaParams = eaParams; * _eaParamsComplexifying = _eaParams; * _eaParamsSimplifying = _eaParams.CreateSimplifyingParameters(); * _stats = new NeatAlgorithmStats(_eaParams); * _speciationStrategy = speciationStrategy; * * _complexityRegulationMode = ComplexityRegulationMode.Complexifying; * _complexityRegulationStrategy = complexityRegulationStrategy; * } */ public void Construct(NeatEvolutionAlgorithmParameters eaParams, ISpeciationStrategy <TGenome> speciationStrategy, IComplexityRegulationStrategy complexityRegulationStrategy, IGenomeListEvaluator <TGenome> initialGenomeListEvaluator) { _eaParams = eaParams; _eaParamsComplexifying = _eaParams; _eaParamsSimplifying = _eaParams.CreateSimplifyingParameters(); _stats = new NeatAlgorithmStats(_eaParams); _speciationStrategy = speciationStrategy; _complexityRegulationMode = ComplexityRegulationMode.Complexifying; _complexityRegulationStrategy = complexityRegulationStrategy; _initialGenomeListEvaluator = initialGenomeListEvaluator; }
private ComplexityRegulationMode DetermineMode_WhileComplexifying( EvolutionAlgorithmStatistics eaStats, PopulationStatistics popStats) { // Currently complexifying. // Test if the complexity ceiling has been reached. if (popStats.MeanComplexity > _complexityCeiling) { // Switch to simplifying mode. _currentMode = ComplexityRegulationMode.Simplifying; _lastTransitionGeneration = eaStats.Generation; _prevMeanMovingAverage = popStats.MeanComplexityHistory.Mean; } return(_currentMode); }
private void UpdateUIState_EaStats() { NeatEvolutionAlgorithmStatistics eaStats = (NeatEvolutionAlgorithmStatistics)_eaRunner.EA.Stats; NeatPopulationStatistics popStats = _neatPop.NeatPopulationStats; // Search mode. ComplexityRegulationMode mode = ((NeatEvolutionAlgorithm <double>)_eaRunner.EA).ComplexityRegulationMode; txtSearchStatsMode.Text = mode.ToString(); txtSearchStatsMode.BackColor = mode switch { ComplexityRegulationMode.Complexifying => Color.LightSkyBlue, _ => Color.LightSkyBlue }; txtStatsGeneration.Text = eaStats.Generation.ToString("N0"); txtStatsBest.Text = popStats.BestFitness.PrimaryFitness.ToString(); // Auxiliary fitness info. double[] auxFitnessArr = popStats.BestFitness.AuxFitnessScores; if (auxFitnessArr != null && auxFitnessArr.Length > 0) { txtStatsAlternativeFitness.Text = auxFitnessArr[0].ToString("#.######"); } else { txtStatsAlternativeFitness.Text = ""; } txtStatsMean.Text = popStats.MeanFitness.ToString("#.######"); txtSpeciesChampsMean.Text = popStats.AverageSpeciesBestFitness.ToString("#.######"); txtStatsTotalEvals.Text = eaStats.TotalEvaluationCount.ToString("N0"); txtStatsEvalsPerSec.Text = eaStats.EvaluationsPerSec.ToString("##,#.##"); txtStatsBestGenomeComplx.Text = popStats.BestComplexity.ToString("N0"); txtStatsMeanGenomeComplx.Text = popStats.MeanComplexity.ToString("#.##"); txtStatsMaxGenomeComplx.Text = popStats.MaxComplexity.ToString("N0"); ulong totalOffspringCount = eaStats.TotalOffspringCount; if (totalOffspringCount > 0) { txtStatsTotalOffspringCount.Text = totalOffspringCount.ToString("N0"); txtStatsAsexualOffspringCount.Text = string.Format("{0:N0} ({1:P})", eaStats.TotalOffspringAsexualCount, (eaStats.TotalOffspringAsexualCount / (double)totalOffspringCount)); txtStatsCrossoverOffspringCount.Text = string.Format("{0:N0} ({1:P})", eaStats.TotalOffspringSexualCount, (eaStats.TotalOffspringSexualCount / (double)totalOffspringCount)); txtStatsInterspeciesOffspringCount.Text = string.Format("{0:N0} ({1:P})", eaStats.TotalOffspringInterspeciesCount, (eaStats.TotalOffspringInterspeciesCount / (double)totalOffspringCount)); } }
/// <summary> /// Construct a new instance. /// </summary> /// <param name="complexityCeiling">The absolute complexity ceiling.</param> /// <param name="minSimplifcationGenerations">The minimum number of generations we stay within simplification mode.</param> public AbsoluteComplexityRegulationStrategy( int minSimplifcationGenerations, double complexityCeiling) { _minSimplifcationGenerations = minSimplifcationGenerations; _complexityCeiling = complexityCeiling; _currentMode = ComplexityRegulationMode.Complexifying; _lastTransitionGeneration = 0; if (minSimplifcationGenerations < 1) { throw new ArgumentException("Must be 1 or above.", nameof(minSimplifcationGenerations)); } if (complexityCeiling < 1) { throw new ArgumentException("Must be at 1 or above.", nameof(complexityCeiling)); } }
/// <summary> /// Notify the strategy of a change in complexity regulation mode in the evolution algorithm. /// </summary> /// <param name="mode">The current mode.</param> public void NotifyComplexityRegulationMode(ComplexityRegulationMode mode) { switch (mode) { case ComplexityRegulationMode.Complexifying: _settingsCurrent = _settingsComplexifying; _mutationTypeDistributionsCurrent = _mutationTypeDistributionsComplexifying; break; case ComplexityRegulationMode.Simplifying: _settingsCurrent = _settingsSimplifying; _mutationTypeDistributionsCurrent = _mutationTypeDistributionsSimplifying; break; default: throw new ArgumentException("Unexpected complexity regulation mode."); } }
/// <summary> /// Construct the complexity regulation strategy with the provided regulation parameters. /// </summary> public DefaultComplexityRegulationStrategy(ComplexityCeilingType ceilingType, double ceilingValue) { _ceilingType = ceilingType; _complexityCeiling = ceilingValue; // For relative complexity ceiling we await the first call to DetermineMode() before setting the threshold // relative to the population mean complexity. Indicate this with -1.0. if (ComplexityCeilingType.Relative == ceilingType) { _complexityCeilingCurrent = -1.0; } else { _complexityCeilingCurrent = ceilingValue; } _currentMode = ComplexityRegulationMode.Complexifying; }
/// <summary> /// Construct a new instance. /// </summary> /// <param name="relativeComplexityCeiling">The relative complexity ceiling.</param> /// <param name="minSimplifcationGenerations">The minimum number of generations we stay within simplification mode.</param> public RelativeComplexityRegulationStrategy( int minSimplifcationGenerations, double relativeComplexityCeiling) { _minSimplifcationGenerations = minSimplifcationGenerations; _relativeComplexityCeiling = relativeComplexityCeiling; _complexityCeiling = relativeComplexityCeiling; _currentMode = ComplexityRegulationMode.Complexifying; _lastTransitionGeneration = 0; if (minSimplifcationGenerations < 1) { throw new ArgumentException(nameof(minSimplifcationGenerations)); } if (relativeComplexityCeiling < 1) { throw new ArgumentException(nameof(relativeComplexityCeiling)); } }
/// <summary> /// Determine which complexity regulation mode the search should be in given the provided /// NEAT algorithm stats. /// </summary> public ComplexityRegulationMode DetermineMode(NeatAlgorithmStats stats) { if (ComplexityRegulationMode.Complexifying == _currentMode) { if (-1.0 == _complexityCeilingCurrent) { // First call to DetermineMode(). Continue complexifying and set threshold relative current complexity. _complexityCeilingCurrent = stats._meanComplexity + _complexityCeiling; } // Currently complexifying. Test if the complexity ceiling has been reached. else if (stats._meanComplexity > _complexityCeilingCurrent) { // Switch to simplifying mode. _currentMode = ComplexityRegulationMode.Simplifying; _lastTransitionGeneration = stats._generation; } } else { // Currently simplifying. Test if simplication (ongoing reduction in complexity) has stalled. // We allow simplification to progress for a few generations before testing of it has stalled, this allows // a lead in time for the effects of simplification to occur. // In addition we do not switch to complexifying if complexity is above the currently defined ceiling. if (((stats._generation - _lastTransitionGeneration) > MinSimplifcationGenerations) && (stats._meanComplexity < _complexityCeilingCurrent) && ((stats._complexityMA.Mean - stats._prevComplexityMA) >= 0.0)) { // Simplification has stalled. Switch back to complexification. _currentMode = ComplexityRegulationMode.Complexifying; _lastTransitionGeneration = stats._generation; // Redefine the complexity ceiling (for relative ceiling only). if (ComplexityCeilingType.Relative == _ceilingType) { _complexityCeilingCurrent = stats._meanComplexity + _complexityCeiling; } } } return(_currentMode); }
/// <summary> /// Progress forward by one generation. Perform one generation/iteration of the evolution algorithm. /// </summary> protected override void PerformOneGeneration() { // Calculate statistics for each specie (mean fitness, target size, number of offspring to produce etc.) int offspringCount; SpecieStats[] specieStatsArr = CalcSpecieStats(out offspringCount); // Create offspring. List <TGenome> offspringList = CreateOffspring(specieStatsArr, offspringCount); // Trim species back to their elite genomes. bool emptySpeciesFlag = TrimSpeciesBackToElite(specieStatsArr); // Rebuild _genomeList. It will now contain just the elite genomes. RebuildGenomeList(); // Append offspring genomes to the elite genomes in _genomeList. We do this before calling the // _genomeListEvaluator.Evaluate because some evaluation schemes re-evaluate the elite genomes // (otherwise we could just evaluate offspringList). _genomeList.AddRange(offspringList); // Evaluate genomes. _genomeListEvaluator.Evaluate(_genomeList); // Integrate offspring into species. if (emptySpeciesFlag) { // We have one or more terminated species. Therefore we need to fully re-speciate all genomes to divide them // evenly between the required number of species. // Clear all genomes from species (we still have the elite genomes in _genomeList). ClearAllSpecies(); // Speciate genomeList. _speciationStrategy.SpeciateGenomes(_genomeList, _specieList); } else { // Integrate offspring into the existing species. _speciationStrategy.SpeciateOffspring(offspringList, _specieList); } Debug.Assert(!TestForEmptySpecies(_specieList), "Speciation resulted in one or more empty species."); // Sort the genomes in each specie. Fittest first (secondary sort - youngest first). SortSpecieGenomes(); // Update stats and store reference to best genome. UpdateBestGenome(); UpdateStats(); // Determine the complexity regulation mode and switch over to the appropriate set of evolution // algorithm parameters. Also notify the genome factory to allow it to modify how it creates genomes // (e.g. reduce or disable additive mutations). _complexityRegulationMode = _complexityRegulationStrategy.DetermineMode(_stats); _genomeFactory.SearchMode = (int)_complexityRegulationMode; switch (_complexityRegulationMode) { case ComplexityRegulationMode.Complexifying: _eaParams = _eaParamsComplexifying; break; case ComplexityRegulationMode.Simplifying: _eaParams = _eaParamsSimplifying; break; } // TODO: More checks. Debug.Assert(_genomeList.Count == _populationSize); }
/// <summary> /// Determine which complexity regulation mode the search should be in given the provided /// NEAT algorithm stats. /// </summary> public ComplexityRegulationMode DetermineMode(NeatAlgorithmStats stats) { if(ComplexityRegulationMode.Complexifying == _currentMode) { if(-1.0 == _complexityCeilingCurrent) { // First call to DetermineMode(). Continue complexifying and set threshold relative current complexity. _complexityCeilingCurrent = stats._meanComplexity + _complexityCeiling; } // Currently complexifying. Test if the complexity ceiling has been reached. else if(stats._meanComplexity > _complexityCeilingCurrent) { // Switch to simplifying mode. _currentMode = ComplexityRegulationMode.Simplifying; _lastTransitionGeneration = stats._generation; } } else { // Currently simplifying. Test if simplication (ongoing reduction in complexity) has stalled. // We allow simplification to progress for a few generations before testing of it has stalled, this allows // a lead in time for the effects of simplification to occur. // In addition we do not switch to complexifying if complexity is above the currently defined ceiling. if(((stats._generation - _lastTransitionGeneration) > MinSimplifcationGenerations) && (stats._meanComplexity < _complexityCeilingCurrent) && ((stats._complexityMA.Mean - stats._prevComplexityMA) >= 0.0)) { // Simplification has stalled. Switch back to complexification. _currentMode = ComplexityRegulationMode.Complexifying; _lastTransitionGeneration = stats._generation; // Redefine the complexity ceiling (for relative ceiling only). if(ComplexityCeilingType.Relative == _ceilingType) { _complexityCeilingCurrent = stats._meanComplexity + _complexityCeiling; } } } return _currentMode; }