Ejemplo n.º 1
0
        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.");
            }
        }
Ejemplo n.º 2
0
 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.");
        }
Ejemplo n.º 4
0
        /// <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());
        }
Ejemplo n.º 5
0
        /// <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);
        }
Ejemplo n.º 6
0
        /// <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());
            }
        }
Ejemplo n.º 7
0
 /// <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;
 }
Ejemplo n.º 8
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)}");
     }
 }
Ejemplo n.º 14
0
        /// <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!");
        }
Ejemplo n.º 16
0
 /// <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);