public void FinishPhaseKeepsAgeDistributionEvenWithOldElitistIncumbent() { var originalPopulation = this.CreatePopulation(); var incumbent = new IncumbentGenomeWrapper <IntegerResult> { IncumbentGeneration = 0, IncumbentGenome = originalPopulation.GetCompetitiveIndividuals().First(), IncumbentInstanceResults = new List <IntegerResult>().ToImmutableList(), }; while (incumbent.IncumbentGenome.Age <= this.Configuration.MaxGenomeAge) { incumbent.IncumbentGenome.AgeOnce(); } Assert.Equal( 1, originalPopulation.GetCompetitiveIndividuals().Count(genome => genome.Age == this.Configuration.MaxGenomeAge + 1)); this.Strategy.Initialize(originalPopulation, incumbent, this.SingleTestInstance, 0, false); this.Strategy.PerformIteration(0, this.SingleTestInstance, false); var updatedPopulation = this.Strategy.FinishPhase(originalPopulation); for (int age = 0; age < this.Configuration.MaxGenomeAge; age++) { Assert.True( originalPopulation.GetCompetitiveIndividuals().Count(genome => genome.Age == age) == updatedPopulation.GetCompetitiveIndividuals().Count(genome => genome.Age == age), $"Number of competitive genomes with age {age} changed."); } }
public Status( int generation, Population population, AlgorithmTunerConfiguration configuration, GeneticEngineering <TLearnerModel, TPredictorModel, TSamplingStrategy> geneticEngineering, int currentUpdateStrategyIndex, List <double> incumbentQuality, IncumbentGenomeWrapper <TResult> incumbentGenomeWrapper, List <GenerationInformation> informationHistory, TimeSpan elapsedTime, ImmutableGenome defaultGenome = null) { this.Generation = generation; this.Population = population ?? throw new ArgumentNullException(nameof(population)); this.Configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); this.GeneticEngineering = geneticEngineering ?? throw new ArgumentNullException(nameof(geneticEngineering)); this.CurrentUpdateStrategyIndex = currentUpdateStrategyIndex; this.IncumbentQuality = incumbentQuality ?? throw new ArgumentNullException(nameof(incumbentQuality)); this.IncumbentGenomeWrapper = incumbentGenomeWrapper ?? throw new ArgumentNullException(nameof(incumbentGenomeWrapper)); this.InformationHistory = informationHistory ?? throw new ArgumentNullException(nameof(informationHistory)); this.ElapsedTime = elapsedTime; this.DefaultGenome = defaultGenome; }
/// <inheritdoc /> protected override void InitializeContinuousOptimizer( Population basePopulation, IncumbentGenomeWrapper <TResult> currentIncumbent) { if (basePopulation == null) { throw new ArgumentNullException(nameof(basePopulation)); } if (!basePopulation.GetCompetitiveIndividuals().Any()) { throw new ArgumentOutOfRangeException( nameof(basePopulation), "Population must have competitive individuals."); } // Continue the parameter adaptation where we left off before, but re-initialize everything else. // If the adaptation was restarted every time, we would need quite long phases to actually see the // adaptation happening. this._differentialEvolutionRunner = this.CreateDifferentialEvolutionRunner( meanMutationFactor: this._differentialEvolutionRunner.MeanMutationFactor, meanCrossoverRate: this._differentialEvolutionRunner.MeanCrossoverRate); var initialPositions = this._informationFlow .DetermineInitialPoints(basePopulation, currentIncumbent?.IncumbentGenome) .ToList(); this._differentialEvolutionRunner.Initialize( initialPositions, this._strategyConfiguration.MaximumNumberGenerations); LoggingHelper.WriteLine( VerbosityLevel.Debug, $"Tuning {initialPositions.First().Values.Count} continuous parameters."); }
/// <inheritdoc /> protected override void InitializeContinuousOptimizer( Population basePopulation, IncumbentGenomeWrapper <TResult> currentIncumbent) { if (basePopulation == null) { throw new ArgumentNullException(nameof(basePopulation)); } if (currentIncumbent == null) { LoggingHelper.WriteLine( VerbosityLevel.Warn, "CMA-ES with focus on incumbent can only be executed if an incumbent exists, i.e. it is not possible to run it on its own."); throw new ArgumentNullException(nameof(currentIncumbent)); } // We do not reuse anything from potential old configurations, because old information may be // outdated at the point a new phase is started. var initialMean = PartialGenomeSearchPoint.CreateFromGenome( currentIncumbent.IncumbentGenome, this.ParameterTree, this.StrategyConfiguration.MinimumDomainSize).Values; var cmaEsConfiguration = new CmaEsConfiguration( populationSize: basePopulation.CompetitiveCount, initialDistributionMean: initialMean, initialStepSize: this.StrategyConfiguration.InitialStepSize); this._cmaEsRunner = this.CreateCmaEsRunner(evaluationBase: currentIncumbent.IncumbentGenome); this._cmaEsRunner.Initialize(cmaEsConfiguration, this.CreateTerminationCriteria()); }
/// <summary> /// Changes to the correct <see cref="IPopulationUpdateStrategy{TInstance,TResult}"/> based on the current /// strategy. /// </summary> /// <param name="initializationInstances"> /// Instances to use for potential evaluations on strategy initialization. /// </param> /// <param name="currentIncumbent">Most recent incumbent genome. Might be <c>null</c>.</param> /// <param name="currentGeneration">The current generation.</param> /// <param name="useGrayBoxInGeneration">Boolean indicating whether to use gray box tuning in current generation.</param> /// <returns>The chosen <see cref="IPopulationUpdateStrategy{TInstance,TResult}"/>.</returns> public IPopulationUpdateStrategy <TInstance, TResult> ChangePopulationUpdateStrategy( ICollection <TInstance> initializationInstances, IncumbentGenomeWrapper <TResult> currentIncumbent, int currentGeneration, bool useGrayBoxInGeneration) { var currentStrategy = this.CurrentStrategy; while (currentStrategy.HasTerminated()) { this.FinishPhase(); this.CurrentUpdateStrategyIndex = currentStrategy.NextStrategy(this._populationUpdateStrategies); var newStrategy = this.CurrentStrategy; newStrategy.Initialize(this.BasePopulation, currentIncumbent, initializationInstances, currentGeneration, useGrayBoxInGeneration); LoggingHelper.WriteLine( VerbosityLevel.Info, $"Changing strategy from {currentStrategy.GetType().Name} to {newStrategy.GetType().Name}."); currentStrategy = newStrategy; } return(currentStrategy); }
/// <summary> /// Updates the current population. /// </summary> /// <param name="currentGeneration">The current generation index.</param> /// <param name="instancesForEvaluation">Instances to use for evaluation.</param> /// <param name="useGrayBoxInGeneration">Boolean indicating whether to use gray box tuning in current generation.</param> public void PerformIteration( int currentGeneration, IEnumerable <TInstance> instancesForEvaluation, bool useGrayBoxInGeneration) { this._iterationCounter++; this._currentGeneration = currentGeneration; this._useGrayBoxInGeneration = useGrayBoxInGeneration; var tournamentResults = this.PerformSelection(instancesForEvaluation); this.UpdateIncumbentKeptCounter( previousIncumbent: this._mostRecentBest?.IncumbentGenome, newIncumbent: tournamentResults.GenerationBest); this._mostRecentBest = new IncumbentGenomeWrapper <TResult> { IncumbentGeneration = currentGeneration, IncumbentGenome = tournamentResults.GenerationBest, IncumbentInstanceResults = tournamentResults.GenerationBestResult, }; bool isLastGeneration = currentGeneration >= this._configuration.Generations - 1; if (!isLastGeneration) { // only perform expensive population update until penultimate generation. this.UpdateAllKnownRanks(tournamentResults); this.UpdatePopulation(tournamentResults.CompetitiveParents.ToList()); } }
/// <summary> /// Initializes a new phase for the strategy. /// </summary> /// <param name="basePopulation">Population to start with.</param> /// <param name="currentIncumbent">Most recent incumbent genome. Might be <c>null</c>.</param> /// <param name="instancesForEvaluation">Instances to use for evaluation.</param> public void Initialize( Population basePopulation, IncumbentGenomeWrapper <TResult> currentIncumbent, IEnumerable <TInstance> instancesForEvaluation) { this._population = basePopulation; this._iterationCounter = 0; this._incumbentKeptCounter = 0; }
public void TrackConvergenceBehaviorThrowsForMissingRunEvaluator() { var incumbentWrapper = new IncumbentGenomeWrapper <TestResult> { IncumbentGeneration = 0, IncumbentGenome = new Genome(), IncumbentInstanceResults = new List <TestResult>().ToImmutableList(), }; Assert.Throws <ArgumentNullException>(() => RunStatisticTracker.TrackConvergenceBehavior(incumbentWrapper, runEvaluator: null)); }
public void UseStatusDump(string pathToStatusFile) { if (this._currGeneration > 0) { throw new InvalidOperationException("Status dump should only be read in at the very beginning of tuning."); } // Read status from file. var status = StatusBase.ReadFromFile <Status <TInstance, TResult, TModelLearner, TPredictorModel, TSamplingStrategy> >(pathToStatusFile); // Check if old tuner parameters match the new ones. if (this._configuration.StrictCompatibilityCheck && !this._configuration.IsCompatible(status.Configuration)) { throw new InvalidOperationException( $"Current configuration is too different from the one used to create status file {pathToStatusFile}."); } if (!this._configuration.IsTechnicallyCompatible(status.Configuration)) { throw new InvalidOperationException( $"It is technically not possible to continue the tuning of {pathToStatusFile} with the current configuration."); } if (status.ElapsedTime > TimeSpan.Zero) { this._logWriter.SetElapsedTimeOffset(status.ElapsedTime); } // Update fields. this._currGeneration = status.Generation; this._incumbentGenomeWrapper = status.IncumbentGenomeWrapper; this.IncumbentQuality = status.IncumbentQuality; this.GeneticEngineering = status.GeneticEngineering; this.GeneticEngineering?.RestoreInternalDictionariesWithCorrectComparers(); this._informationHistory = status.InformationHistory; // Send all run results to storage. foreach (var genomeResults in status.RunResults) { foreach (var result in genomeResults.Value) { this._targetRunResultStorage.Tell(new ResultMessage <TInstance, TResult>(genomeResults.Key, result.Key, result.Value)); } } // Restore status of all population update strategies. this._populationUpdateStrategyManager.UseStatusDump(status.CurrentUpdateStrategyIndex, status.Population, this.GeneticEngineering); Randomizer.Reset(); Randomizer.Configure(new Random().Next()); }
/// <inheritdoc /> public virtual void Initialize( Population basePopulation, IncumbentGenomeWrapper <TResult> currentIncumbent, IEnumerable <TInstance> instancesForEvaluation) { // If the instance set is fixed throughout the phase, this is the only place it is updated. // Even if it is not fixed, some methods sort provided points in their Initialize methods and // therefore need the update. this.CurrentEvaluationInstances = instancesForEvaluation?.ToList() ?? throw new ArgumentNullException(nameof(instancesForEvaluation)); this.SearchPointSorter.UpdateInstances(this.CurrentEvaluationInstances); this.InitializeContinuousOptimizer(basePopulation, currentIncumbent); this.OriginalIncumbent = currentIncumbent?.IncumbentGenome; }
public void FinishPhaseReplacesCompetitiveGenomes() { var originalPopulation = this.CreatePopulation(); var incumbent = new IncumbentGenomeWrapper <IntegerResult> { IncumbentGeneration = 0, IncumbentGenome = originalPopulation.GetCompetitiveIndividuals().First(), IncumbentInstanceResults = new List <IntegerResult>().ToImmutableList(), }; this.Strategy.Initialize(originalPopulation, incumbent, this.SingleTestInstance); this.Strategy.PerformIteration(0, this.SingleTestInstance); this.Strategy.DumpStatus(); var status = StatusBase.ReadFromFile <CovarianceMatrixAdaptationStrategyStatus <ContinuizedGenomeSearchPoint, TestInstance> >(this.StatusFilePath); var searchPoints = status.MostRecentSorting; var updatedPopulation = this.Strategy.FinishPhase(originalPopulation); Assert.Equal( originalPopulation.GetCompetitiveIndividuals().Count, updatedPopulation.GetCompetitiveIndividuals().Count); var valueComparer = new Genome.GeneValueComparator(); foreach (var point in searchPoints.Take(searchPoints.Count - 1)) { var mappedGenome = point.Genome.CreateMutableGenome(); Assert.True( updatedPopulation.GetCompetitiveIndividuals() .Any(genome => valueComparer.Equals(genome, mappedGenome)), $"{mappedGenome} is not worst search point, but was not found in new competitives."); } Assert.Contains( incumbent.IncumbentGenome, updatedPopulation.GetCompetitiveIndividuals().ToArray()); for (int age = 0; age < this.Configuration.MaxGenomeAge; age++) { Assert.True( originalPopulation.GetCompetitiveIndividuals().Count(genome => genome.Age == age) == updatedPopulation.GetCompetitiveIndividuals().Count(genome => genome.Age == age), $"Number of competitive genomes with age {age} changed."); } }
/// <summary> /// Track convergence behavior. /// </summary> /// <param name="incumbentGenomeWrapper"> /// The incumbent genome wrapper. /// </param> /// <param name="runEvaluator"> /// A <see cref="IMetricRunEvaluator{TResult}"/> to evaluate the incumbent's results. /// </param> /// <typeparam name="TResult"> /// Type of single instance evaluation result. /// </typeparam> /// <returns> /// The <see cref="double"/> average <see cref="IMetricRunEvaluator{TResult}.GetMetricRepresentation"/> of the /// current incumbent. /// </returns> public static double TrackConvergenceBehavior <TResult>( IncumbentGenomeWrapper <TResult> incumbentGenomeWrapper, IMetricRunEvaluator <TResult> runEvaluator) where TResult : ResultBase <TResult>, new() { if (runEvaluator == null) { throw new ArgumentNullException(nameof(runEvaluator)); } var currentAverage = incumbentGenomeWrapper.IncumbentInstanceResults.Average(r => runEvaluator.GetMetricRepresentation(r)); LoggingHelper.WriteLine( VerbosityLevel.Info, $"Incumbent solved {incumbentGenomeWrapper.IncumbentInstanceResults.Count(i => !i.IsCancelled)}/{incumbentGenomeWrapper.IncumbentInstanceResults.Count} instances."); LoggingHelper.WriteLine( VerbosityLevel.Info, $"Average compare-value score: {currentAverage}."); return(currentAverage); }
/// <summary> /// Updates the incumbent genome wrapper. /// </summary> /// <param name="generationBest"> /// Best genome of most recent generation. /// </param> private void UpdateIncumbentGenomeWrapper(IncumbentGenomeWrapper <TResult> generationBest) { if (this._incumbentGenomeWrapper == null || !new Genome.GeneValueComparator().Equals( this._incumbentGenomeWrapper.IncumbentGenome, generationBest.IncumbentGenome)) { this._incumbentGenomeWrapper = generationBest; LoggingHelper.WriteLine(VerbosityLevel.Info, "Found new incumbent."); LoggingHelper.WriteLine( VerbosityLevel.Info, $"Incumbent Genome:\r\n{this._incumbentGenomeWrapper.IncumbentGenome.ToFilteredGeneString(this._parameterTree)}"); } else { // we want to log the most recent results this._incumbentGenomeWrapper.IncumbentInstanceResults = generationBest.IncumbentInstanceResults; LoggingHelper.WriteLine( VerbosityLevel.Debug, $"Incumbent Genome:\r\n{this._incumbentGenomeWrapper.IncumbentGenome.ToFilteredGeneString(this._parameterTree)}"); } }
/// <inheritdoc /> protected override void InitializeContinuousOptimizer( Population basePopulation, IncumbentGenomeWrapper <TResult> currentIncumbent) { if (basePopulation == null) { throw new ArgumentNullException(nameof(basePopulation)); } // We do not reuse anything from potential old configurations, because old information may be // outdated at the point a new phase is started. var initialMean = currentIncumbent != null ? ContinuizedGenomeSearchPoint.CreateFromGenome(currentIncumbent.IncumbentGenome, this.ParameterTree).Values : this.ComputeMeanOfCompetitivePopulationPart(basePopulation); var cmaEsConfiguration = new CmaEsConfiguration( populationSize: basePopulation.CompetitiveCount, initialDistributionMean: initialMean, initialStepSize: this.StrategyConfiguration.InitialStepSize); this._cmaEsRunner = new CmaEs <ContinuizedGenomeSearchPoint>(this.SearchPointSorter, this._searchPointFactory); this._cmaEsRunner.Initialize(cmaEsConfiguration, this.CreateTerminationCriteria()); }
public void FinishPhaseWorks() { // Create a population which contains the same genome twice. var basePopulation = this.CreatePopulation(); var incumbent = new IncumbentGenomeWrapper <IntegerResult> { IncumbentGeneration = 0, IncumbentGenome = basePopulation.GetCompetitiveIndividuals()[1], IncumbentInstanceResults = new List <IntegerResult>().ToImmutableList(), }; basePopulation.AddGenome(new Genome(incumbent.IncumbentGenome), isCompetitive: true); // Find some search points using CMA-ES. this.Strategy.Initialize(basePopulation, incumbent, this.SingleTestInstance); this.Strategy.PerformIteration(0, this.SingleTestInstance); this.Strategy.DumpStatus(); var status = StatusBase.ReadFromFile <CovarianceMatrixAdaptationStrategyStatus <PartialGenomeSearchPoint, TestInstance> >(this.StatusFilePath); var searchPoints = status.MostRecentSorting; var updatedPopulation = this.Strategy.FinishPhase(basePopulation); // Start by checking non-competitive genomes are the same. Assert.Equal( basePopulation.GetNonCompetitiveMates().Select(genome => genome.ToString()).OrderBy(x => x).ToArray(), updatedPopulation.GetNonCompetitiveMates().Select(genome => genome.ToString()).OrderBy(x => x).ToArray()); // Then check if best points were added to population. Assert.True( updatedPopulation.GetCompetitiveIndividuals().Contains( searchPoints[0].Genome.CreateMutableGenome(), new Genome.GeneValueComparator()), "Updated population should contain best search point, but does not."); Assert.True( updatedPopulation.GetCompetitiveIndividuals().Contains( searchPoints[1].Genome.CreateMutableGenome(), new Genome.GeneValueComparator()), "Updated population should contain second best search point, but does not."); Assert.False( updatedPopulation.GetCompetitiveIndividuals().Contains( searchPoints[2].Genome.CreateMutableGenome(), new Genome.GeneValueComparator()), "Updated population should not contain worst search point."); // Incumbent should still exist. Assert.True( updatedPopulation.GetCompetitiveIndividuals().Contains(incumbent.IncumbentGenome, new Genome.GeneValueComparator()), "Updated population should contain incumbent, but does not."); // Finally, check ages. for (int age = 0; age < 3; age++) { Assert.True( basePopulation.GetCompetitiveIndividuals().Count(individual => individual.Age == age) == updatedPopulation.GetCompetitiveIndividuals().Count(individual => individual.Age == age), $"Different number of genomes with age {age}."); } Assert.False( updatedPopulation.GetCompetitiveIndividuals().Any(individual => individual.Age < 0 || individual.Age > 3), "There exists a genome with age not in age range!"); }
/// <summary> /// Initializes the <see cref="ContinuousOptimizer"/> for a new strategy phase. /// </summary> /// <param name="basePopulation">Population to start with.</param> /// <param name="currentIncumbent">Most recent incumbent genome. Might be <c>null</c>.</param> protected abstract void InitializeContinuousOptimizer( Population basePopulation, IncumbentGenomeWrapper <TResult> currentIncumbent);