#region License Information /* HeuristicLab * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.Collections.Generic; using System.Linq; using System.Threading; using HeuristicLab.Algorithms.DataAnalysis; using HeuristicLab.Algorithms.SAPBA.Strategies; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Encodings.RealVectorEncoding; using HeuristicLab.Optimization; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Problems.DataAnalysis; using HeuristicLab.Random; namespace HeuristicLab.Algorithms.SAPBA { [StorableClass] [Creatable(CreatableAttribute.Categories.Algorithms, Priority = 95)] [Item("SurrogateAssistedPopulationBasedAlgorithm", "")] public class SurrogateAssistedPopulationBasedAlgorithm : BasicAlgorithm, ISurrogateAlgorithm { #region Basic-Alg-Essentials public override bool SupportsPause => true; public override Type ProblemType => typeof(SingleObjectiveBasicProblem); public new SingleObjectiveBasicProblem Problem { get { return (SingleObjectiveBasicProblem)base.Problem; } set { base.Problem = value; } } #endregion #region ParameterNames private const string InitialEvaluationsParameterName = "Initial Evaluations"; private const string MaximalDataSetSizeParameterName = "Maximal Dataset Size"; private const string MaximumEvaluationsParameterName = "Maximum Evaluations"; private const string MaximumRuntimeParameterName = "Maximum Runtime"; private const string OptimizationAlgorithmParameterName = "Optimization Algorithm"; private const string RemoveDuplicatesParamterName = "RemoveDuplicates"; private const string RegressionAlgorithmParameterName = "RegressionAlgorithm"; private const string SeedParameterName = "Seed"; private const string SetSeedRandomlyParameterName = "SetSeedRandomly"; private const string StrategyParameterName = "Strategy"; #endregion #region ParameterProperties public IFixedValueParameter InitialEvaluationsParameter => Parameters[InitialEvaluationsParameterName] as IFixedValueParameter; public IFixedValueParameter MaximalDataSetSizeParameter => Parameters[MaximalDataSetSizeParameterName] as IFixedValueParameter; public IFixedValueParameter MaximumEvaluationsParameter => Parameters[MaximumEvaluationsParameterName] as IFixedValueParameter; public IFixedValueParameter MaximumRuntimeParameter => Parameters[MaximumRuntimeParameterName] as IFixedValueParameter; public IValueParameter OptimizationAlgorithmParameter => Parameters[OptimizationAlgorithmParameterName] as IValueParameter; public IValueParameter> RegressionAlgorithmParameter => Parameters[RegressionAlgorithmParameterName] as IValueParameter>; public IFixedValueParameter RemoveDuplicatesParameter => Parameters[RemoveDuplicatesParamterName] as IFixedValueParameter; public IFixedValueParameter SeedParameter => Parameters[SeedParameterName] as IFixedValueParameter; public IFixedValueParameter SetSeedRandomlyParameter => Parameters[SetSeedRandomlyParameterName] as IFixedValueParameter; public IConstrainedValueParameter StrategyParameter => Parameters[StrategyParameterName] as IConstrainedValueParameter; #endregion #region Properties public int InitialEvaluations => InitialEvaluationsParameter.Value.Value; public int MaximalDatasetSize => MaximalDataSetSizeParameter.Value.Value; public int MaximumEvaluations => MaximumEvaluationsParameter.Value.Value; public int MaximumRuntime => MaximumRuntimeParameter.Value.Value; public Algorithm OptimizationAlgorithm => OptimizationAlgorithmParameter.Value; public IDataAnalysisAlgorithm RegressionAlgorithm => RegressionAlgorithmParameter.Value; public bool RemoveDuplicates => RemoveDuplicatesParameter.Value.Value; public int Seed => SeedParameter.Value.Value; public bool SetSeedRandomly => SetSeedRandomlyParameter.Value.Value; public ISurrogateStrategy SurrogateStrategy => StrategyParameter.Value; #endregion #region StorableProperties [Storable] private IRandom Random = new MersenneTwister(); [Storable] public List> InitialSamples { get; private set; } [Storable] public SurrogateProblem surrogateProblem; public void SetInitialSamples(RealVector[] solutions, double[] qualities) { InitialSamples = solutions.Zip(qualities, (vector, d) => new Tuple(vector, d)).ToList(); } #endregion #region HLConstructors [StorableConstructor] protected SurrogateAssistedPopulationBasedAlgorithm(bool deserializing) : base(deserializing) { } [StorableHook(HookType.AfterDeserialization)] private void AfterDeseialization() { RegisterEventhandlers(); } protected SurrogateAssistedPopulationBasedAlgorithm(SurrogateAssistedPopulationBasedAlgorithm original, Cloner cloner) : base(original, cloner) { Random = cloner.Clone(Random); if (original.InitialSamples != null) InitialSamples = original.InitialSamples.Select(x => new Tuple(cloner.Clone(x.Item1), x.Item2)).ToList(); RegisterEventhandlers(); } public override IDeepCloneable Clone(Cloner cloner) { return new SurrogateAssistedPopulationBasedAlgorithm(this, cloner); } public SurrogateAssistedPopulationBasedAlgorithm() { surrogateProblem = new SurrogateProblem(); var geneticAlgorithm = new GeneticAlgorithm.GeneticAlgorithm { PopulationSize = { Value = 50 }, Problem = surrogateProblem }; var model = new GaussianProcessRegression { Problem = new RegressionProblem() }; model.CovarianceFunctionParameter.Value = new CovarianceRationalQuadraticIso(); Parameters.Add(new FixedValueParameter(MaximumEvaluationsParameterName, "", new IntValue(int.MaxValue))); Parameters.Add(new FixedValueParameter(InitialEvaluationsParameterName, "", new IntValue(10))); Parameters.Add(new FixedValueParameter(MaximumRuntimeParameterName, "The maximum runtime in seconds after which the algorithm stops. Use -1 to specify no limit for the runtime", new IntValue(-1))); Parameters.Add(new FixedValueParameter(SeedParameterName, "The random seed used to initialize the new pseudo random number generator.", new IntValue(0))); Parameters.Add(new FixedValueParameter(SetSeedRandomlyParameterName, "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true))); Parameters.Add(new ValueParameter>(RegressionAlgorithmParameterName, "The model used to approximate the problem", model)); Parameters.Add(new ValueParameter(OptimizationAlgorithmParameterName, "The algorithm used to solve the expected improvement subproblem", geneticAlgorithm)); Parameters.Add(new FixedValueParameter(MaximalDataSetSizeParameterName, "The maximum number of sample points used to generate the model. Set 0 or less to use always all samples ", new IntValue(-1))); Parameters.Add(new FixedValueParameter(RemoveDuplicatesParamterName, "Wether duplicate samples should be replaced by a single sample with an averaged quality. This GREATLY decreases the chance of ill conditioned models (unbuildable models) but is not theoretically sound as the model ignores the increasing certainty in this region")); var strategies = new ItemSet { new GenerationalStrategy(), new IndividualStrategy() }; Parameters.Add(new ConstrainedValueParameter(StrategyParameterName, "The surrogate strategy that dictates how the optimization alg is assisted", strategies, strategies.First())); RegisterEventhandlers(); } #endregion protected override void Initialize(CancellationToken cancellationToken) { base.Initialize(cancellationToken); //encoding var enc = Problem.Encoding as RealVectorEncoding; if (enc == null) throw new ArgumentException("The SAPBA algorithm can only be applied to RealVectorEncodings"); //random if (SetSeedRandomly) SeedParameter.Value.Value = new System.Random().Next(); Random.Reset(Seed); //initialize Strategy and Problem SurrogateStrategy.Initialize(this); SurrogateStrategy.UpdateCancellation(cancellationToken); surrogateProblem.SetStrategy(SurrogateStrategy); surrogateProblem.SetProblem(Problem); } protected override void Run(CancellationToken cancellationToken) { SurrogateStrategy.UpdateCancellation(cancellationToken); try { EgoUtilities.SyncRunSubAlgorithm(OptimizationAlgorithm, Random.Next()); } finally { Analyze(); } } private void Analyze() { } #region Eventhandling private void RegisterEventhandlers() { DeregisterEventhandlers(); OptimizationAlgorithmParameter.ValueChanged += OnOptimizationAlgorithmChanged; } private void DeregisterEventhandlers() { OptimizationAlgorithmParameter.ValueChanged -= OnOptimizationAlgorithmChanged; } private void OnOptimizationAlgorithmChanged(object sender, EventArgs e) { OptimizationAlgorithm.Problem = surrogateProblem; } protected override void OnExecutionTimeChanged() { base.OnExecutionTimeChanged(); if (CancellationTokenSource == null) return; if (MaximumRuntime == -1) return; if (ExecutionTime.TotalSeconds > MaximumRuntime) CancellationTokenSource.Cancel(); } public override void Pause() { base.Pause(); if (RegressionAlgorithm.ExecutionState == ExecutionState.Started) RegressionAlgorithm.Pause(); if (OptimizationAlgorithm.ExecutionState == ExecutionState.Started) OptimizationAlgorithm.Pause(); } public override void Stop() { base.Stop(); if (RegressionAlgorithm.ExecutionState == ExecutionState.Started) RegressionAlgorithm.Stop(); if (OptimizationAlgorithm.ExecutionState == ExecutionState.Started) OptimizationAlgorithm.Stop(); } protected override void OnProblemChanged() { base.OnProblemChanged(); surrogateProblem.SetProblem(Problem); } #endregion } }