Index: . =================================================================== --- . (revision 15449) +++ . (working copy) Property changes on: . ___________________________________________________________________ Added: svn:global-ignores ## -0,0 +1 ## +.vs Added: svn:ignore ## -0,0 +1 ## +.vs Index: .vs/HeuristicLab.Algorithms.SAPBA/v14/.suo =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: .vs/HeuristicLab.Algorithms.SAPBA/v14/.suo =================================================================== --- .vs/HeuristicLab.Algorithms.SAPBA/v14/.suo (revision 15449) +++ .vs/HeuristicLab.Algorithms.SAPBA/v14/.suo (nonexistent) Property changes on: .vs/HeuristicLab.Algorithms.SAPBA/v14/.suo ___________________________________________________________________ Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: .vs/Sliding Window GP/v14/.suo =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: .vs/Sliding Window GP/v14/.suo =================================================================== --- .vs/Sliding Window GP/v14/.suo (revision 15449) +++ .vs/Sliding Window GP/v14/.suo (nonexistent) Property changes on: .vs/Sliding Window GP/v14/.suo ___________________________________________________________________ Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: .vs/HeuristicLab.Algorithms.SAPBA/v14/.suo =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: .vs/HeuristicLab.Algorithms.SAPBA/v14/.suo =================================================================== --- .vs/HeuristicLab.Algorithms.SAPBA/v14/.suo (revision 15449) +++ .vs/HeuristicLab.Algorithms.SAPBA/v14/.suo (nonexistent) Property changes on: .vs/HeuristicLab.Algorithms.SAPBA/v14/.suo ___________________________________________________________________ Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: .vs/HeuristicLab.Algorithms.SAPBA/v14/.suo =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: .vs/HeuristicLab.Algorithms.SAPBA/v14/.suo =================================================================== --- .vs/HeuristicLab.Algorithms.SAPBA/v14/.suo (revision 15449) +++ .vs/HeuristicLab.Algorithms.SAPBA/v14/.suo (nonexistent) Property changes on: .vs/HeuristicLab.Algorithms.SAPBA/v14/.suo ___________________________________________________________________ Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: .vs/HeuristicLab.Algorithms.SAPBA/v14/.suo =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: .vs/HeuristicLab.Algorithms.SAPBA/v14/.suo =================================================================== --- .vs/HeuristicLab.Algorithms.SAPBA/v14/.suo (revision 15449) +++ .vs/HeuristicLab.Algorithms.SAPBA/v14/.suo (nonexistent) Property changes on: .vs/HeuristicLab.Algorithms.SAPBA/v14/.suo ___________________________________________________________________ Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: .vs/Sliding Window GP/v14/.suo =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: .vs/Sliding Window GP/v14/.suo =================================================================== --- .vs/Sliding Window GP/v14/.suo (revision 15449) +++ .vs/Sliding Window GP/v14/.suo (nonexistent) Property changes on: .vs/Sliding Window GP/v14/.suo ___________________________________________________________________ Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: .vs/Sliding Window GP/v14/.suo =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: .vs/Sliding Window GP/v14/.suo =================================================================== --- .vs/Sliding Window GP/v14/.suo (revision 15449) +++ .vs/Sliding Window GP/v14/.suo (nonexistent) Property changes on: .vs/Sliding Window GP/v14/.suo ___________________________________________________________________ Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: .vs/Sliding Window GP/v14/.suo =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: .vs/Sliding Window GP/v14/.suo =================================================================== --- .vs/Sliding Window GP/v14/.suo (revision 15449) +++ .vs/Sliding Window GP/v14/.suo (nonexistent) Property changes on: .vs/Sliding Window GP/v14/.suo ___________________________________________________________________ Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: HeuristicLab.Algorithms.SAPBA/HeuristicLab.Algorithms.SAPBA-3.4.csproj =================================================================== --- HeuristicLab.Algorithms.SAPBA/HeuristicLab.Algorithms.SAPBA-3.4.csproj (revision 15449) +++ HeuristicLab.Algorithms.SAPBA/HeuristicLab.Algorithms.SAPBA-3.4.csproj (working copy) @@ -30,22 +30,22 @@ 4 - - False - ..\..\..\trunk\sources\bin\HeuristicLab.Algorithms.CMAEvolutionStrategy-3.4.dll - False ..\..\..\trunk\sources\bin\HeuristicLab.Algorithms.DataAnalysis-3.4.dll - + False - ..\..\..\trunk\sources\bin\HeuristicLab.Algorithms.EvolutionStrategy-3.3.dll + ..\..\..\trunk\sources\bin\HeuristicLab.Algorithms.EGO-3.4.dll False ..\..\..\trunk\sources\bin\HeuristicLab.Algorithms.GeneticAlgorithm-3.3.dll + + False + ..\..\..\trunk\sources\bin\HeuristicLab.Algorithms.OffspringSelectionEvolutionStrategy-3.3.dll + False ..\..\..\trunk\sources\bin\HeuristicLab.Analysis-3.3.dll @@ -58,10 +58,6 @@ False ..\..\..\trunk\sources\bin\HeuristicLab.Common-3.3.dll - - False - ..\..\..\trunk\sources\bin\HeuristicLab.Common.Resources-3.3.dll - False ..\..\..\trunk\sources\bin\HeuristicLab.Core-3.3.dll @@ -74,7 +70,10 @@ False ..\..\..\trunk\sources\bin\HeuristicLab.Encodings.RealVectorEncoding-3.3.dll - + + False + ..\..\..\trunk\sources\bin\HeuristicLab.Operators-3.3.dll + False ..\..\..\trunk\sources\bin\HeuristicLab.Optimization-3.3.dll @@ -99,18 +98,6 @@ False ..\..\..\trunk\sources\bin\HeuristicLab.Problems.Instances-3.3.dll - - False - ..\..\..\trunk\sources\bin\HeuristicLab.Problems.Instances.DataAnalysis-3.3.dll - - - False - ..\..\..\trunk\sources\bin\HeuristicLab.Problems.Instances.DataAnalysis.Views-3.3.dll - - - False - ..\..\..\trunk\sources\bin\HeuristicLab.Random-3.3.dll - @@ -122,9 +109,10 @@ - - - + + + + Index: HeuristicLab.Algorithms.SAPBA/Interfaces/ISurrogateStrategy.cs =================================================================== --- HeuristicLab.Algorithms.SAPBA/Interfaces/ISurrogateStrategy.cs (revision 15449) +++ HeuristicLab.Algorithms.SAPBA/Interfaces/ISurrogateStrategy.cs (working copy) @@ -19,7 +19,6 @@ */ #endregion -using System.Threading; using HeuristicLab.Core; using HeuristicLab.Encodings.RealVectorEncoding; using HeuristicLab.Optimization; @@ -29,6 +28,6 @@ double Evaluate(RealVector r, IRandom random); void Analyze(Individual[] individuals, double[] qualities, ResultCollection results, IRandom random); void Initialize(SurrogateAssistedPopulationBasedAlgorithm algorithm); - void UpdateCancellation(CancellationToken cancellationToken); + bool Maximization(); } } Index: HeuristicLab.Algorithms.SAPBA/Operators/FixedSolutionCreator.cs =================================================================== --- HeuristicLab.Algorithms.SAPBA/Operators/FixedSolutionCreator.cs (nonexistent) +++ HeuristicLab.Algorithms.SAPBA/Operators/FixedSolutionCreator.cs (working copy) @@ -0,0 +1,30 @@ +using HeuristicLab.Common; +using HeuristicLab.Core; +using HeuristicLab.Data; +using HeuristicLab.Encodings.RealVectorEncoding; +using HeuristicLab.Optimization; +using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; + +namespace HeuristicLab.Algorithms.SAPBA.Operators { + [Item("FixedRealVectorCreator", "An operator which creates a new real vector cloned from a single Point")] + [StorableClass] + public class FixedRealVectorCreator : RealVectorCreator, IStrategyParameterCreator { + [Storable] + private RealVector Point; + + [StorableConstructor] + protected FixedRealVectorCreator(bool deserializing) : base(deserializing) { } + protected FixedRealVectorCreator(FixedRealVectorCreator original, Cloner cloner) : base(original, cloner) { + Point = cloner.Clone(original.Point); + } + public FixedRealVectorCreator(RealVector r) : base() { + Point = r; + } + public override IDeepCloneable Clone(Cloner cloner) { return new FixedRealVectorCreator(this, cloner); } + protected override RealVector Create(IRandom random, IntValue length, DoubleMatrix bounds) { + return (RealVector)Point.Clone(); + } + } + +} + Index: HeuristicLab.Algorithms.SAPBA/Operators/FixedSolutionCreator.cs =================================================================== --- HeuristicLab.Algorithms.SAPBA/Operators/FixedSolutionCreator.cs (nonexistent) +++ HeuristicLab.Algorithms.SAPBA/Operators/FixedSolutionCreator.cs (working copy) @@ -0,0 +1,30 @@ +using HeuristicLab.Common; +using HeuristicLab.Core; +using HeuristicLab.Data; +using HeuristicLab.Encodings.RealVectorEncoding; +using HeuristicLab.Optimization; +using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; + +namespace HeuristicLab.Algorithms.SAPBA.Operators { + [Item("FixedRealVectorCreator", "An operator which creates a new real vector cloned from a single Point")] + [StorableClass] + public class FixedRealVectorCreator : RealVectorCreator, IStrategyParameterCreator { + [Storable] + private RealVector Point; + + [StorableConstructor] + protected FixedRealVectorCreator(bool deserializing) : base(deserializing) { } + protected FixedRealVectorCreator(FixedRealVectorCreator original, Cloner cloner) : base(original, cloner) { + Point = cloner.Clone(original.Point); + } + public FixedRealVectorCreator(RealVector r) : base() { + Point = r; + } + public override IDeepCloneable Clone(Cloner cloner) { return new FixedRealVectorCreator(this, cloner); } + protected override RealVector Create(IRandom random, IntValue length, DoubleMatrix bounds) { + return (RealVector)Point.Clone(); + } + } + +} + Index: HeuristicLab.Algorithms.SAPBA/Plugin.cs =================================================================== --- HeuristicLab.Algorithms.SAPBA/Plugin.cs (revision 15449) +++ HeuristicLab.Algorithms.SAPBA/Plugin.cs (working copy) @@ -25,25 +25,22 @@ using HeuristicLab.PluginInfrastructure; namespace HeuristicLab.Algorithms.SAPBA { - [Plugin("HeuristicLab.Algorithms.SAPBA", "3.4.5.14893")] + [Plugin("HeuristicLab.Algorithms.SAPBA", "3.4.5.14894")] [PluginFile("HeuristicLab.Algorithms.SAPBA-3.4.dll", PluginFileType.Assembly)] - [PluginFile("displayModelFrame.html", PluginFileType.Data)] - [PluginDependency("HeuristicLab.Algorithms.CMAEvolutionStrategy", "3.4")] [PluginDependency("HeuristicLab.Algorithms.DataAnalysis", "3.4")] + [PluginDependency("HeuristicLab.Algorithms.EGO", "3.4")] + [PluginDependency("HeuristicLab.Algorithms.GeneticAlgorithm", "3.3")] + [PluginDependency("HeuristicLab.Algorithms.OffspringSelectionEvolutionStrategy", "3.3")] [PluginDependency("HeuristicLab.Analysis", "3.3")] [PluginDependency("HeuristicLab.Collections", "3.3")] [PluginDependency("HeuristicLab.Common", "3.3")] - [PluginDependency("HeuristicLab.Common.Resources", "3.3")] [PluginDependency("HeuristicLab.Core", "3.3")] [PluginDependency("HeuristicLab.Data", "3.3")] [PluginDependency("HeuristicLab.Encodings.RealVectorEncoding", "3.3")] - [PluginDependency("HeuristicLab.Operators","3.3")] [PluginDependency("HeuristicLab.Optimization","3.3")] [PluginDependency("HeuristicLab.Parameters","3.3")] [PluginDependency("HeuristicLab.Persistence","3.3")] [PluginDependency("HeuristicLab.Problems.DataAnalysis", "3.4")] - [PluginDependency("HeuristicLab.Problems.Instances", "3.3")] - [PluginDependency("HeuristicLab.Random", "3.3")] public class HeuristicLabProblemsDataAnalysisSymbolicViewsPlugin : PluginBase { } } Index: HeuristicLab.Algorithms.SAPBA/Plugin.cs.frame =================================================================== --- HeuristicLab.Algorithms.SAPBA/Plugin.cs.frame (revision 15449) +++ HeuristicLab.Algorithms.SAPBA/Plugin.cs.frame (working copy) @@ -27,23 +27,20 @@ namespace HeuristicLab.Algorithms.SAPBA { [Plugin("HeuristicLab.Algorithms.SAPBA", "3.4.5.$WCREV$")] [PluginFile("HeuristicLab.Algorithms.SAPBA-3.4.dll", PluginFileType.Assembly)] - [PluginFile("displayModelFrame.html", PluginFileType.Data)] - [PluginDependency("HeuristicLab.Algorithms.CMAEvolutionStrategy", "3.4")] [PluginDependency("HeuristicLab.Algorithms.DataAnalysis", "3.4")] + [PluginDependency("HeuristicLab.Algorithms.EGO", "3.4")] + [PluginDependency("HeuristicLab.Algorithms.GeneticAlgorithm", "3.3")] + [PluginDependency("HeuristicLab.Algorithms.OffspringSelectionEvolutionStrategy", "3.3")] [PluginDependency("HeuristicLab.Analysis", "3.3")] [PluginDependency("HeuristicLab.Collections", "3.3")] [PluginDependency("HeuristicLab.Common", "3.3")] - [PluginDependency("HeuristicLab.Common.Resources", "3.3")] [PluginDependency("HeuristicLab.Core", "3.3")] [PluginDependency("HeuristicLab.Data", "3.3")] [PluginDependency("HeuristicLab.Encodings.RealVectorEncoding", "3.3")] - [PluginDependency("HeuristicLab.Operators","3.3")] [PluginDependency("HeuristicLab.Optimization","3.3")] [PluginDependency("HeuristicLab.Parameters","3.3")] [PluginDependency("HeuristicLab.Persistence","3.3")] [PluginDependency("HeuristicLab.Problems.DataAnalysis", "3.4")] - [PluginDependency("HeuristicLab.Problems.Instances", "3.3")] - [PluginDependency("HeuristicLab.Random", "3.3")] public class HeuristicLabProblemsDataAnalysisSymbolicViewsPlugin : PluginBase { } } Index: HeuristicLab.Algorithms.SAPBA/Problems/SurrogateProblem.cs =================================================================== --- HeuristicLab.Algorithms.SAPBA/Problems/SurrogateProblem.cs (revision 15449) +++ HeuristicLab.Algorithms.SAPBA/Problems/SurrogateProblem.cs (working copy) @@ -1,5 +1,29 @@ -using HeuristicLab.Common; +#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 HeuristicLab.Common; using HeuristicLab.Core; +using HeuristicLab.Data; using HeuristicLab.Encodings.RealVectorEncoding; using HeuristicLab.Optimization; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; @@ -6,9 +30,9 @@ namespace HeuristicLab.Algorithms.SAPBA { [StorableClass] - [Item("Surrogate problem (single-objective)", "Wrapper for a problem that allows surrogate models to mitigate some of the work")] + [Item("Surrogate problem (single-objective)", "A problem that uses a Surrogate Strategy to emulate an expensive problem")] public class SurrogateProblem : SingleObjectiveBasicProblem { - + public override bool Maximization => Strategy?.Maximization() ?? false; [Storable] private ISurrogateStrategy Strategy; @@ -18,11 +42,12 @@ [StorableHook(HookType.AfterDeserialization)] private void AfterDeserialization() { } protected SurrogateProblem(SurrogateProblem original, Cloner cloner) : base(original, cloner) { - Strategy = original?.Strategy; + Strategy = cloner.Clone(original.Strategy); } - public override IDeepCloneable Clone(Cloner cloner) { return new SurrogateProblem(this, cloner); } - public SurrogateProblem() { + public override IDeepCloneable Clone(Cloner cloner) { + return new SurrogateProblem(this, cloner); } + public SurrogateProblem() { } #endregion public override double Evaluate(Individual individual, IRandom random) { @@ -32,15 +57,32 @@ base.Analyze(individuals, qualities, results, random); Strategy.Analyze(individuals, qualities, results, random); } + public override IEnumerable GetNeighbors(Individual individual, IRandom random) { + var bounds = Encoding.Bounds; + var michalewiczIteration = 0; + while (true) { + var neighbour = individual.Copy(); + var r = neighbour.RealVector(); + switch (random.Next(5)) { + case 0: UniformOnePositionManipulator.Apply(random, r, bounds); break; + case 1: FixedNormalAllPositionsManipulator.Apply(random, r, new RealVector(new[] { 0.1 })); break; + case 2: MichalewiczNonUniformAllPositionsManipulator.Apply(random, r, bounds, new IntValue(michalewiczIteration++), new IntValue(10000), new DoubleValue(5.0)); break; + case 3: MichalewiczNonUniformOnePositionManipulator.Apply(random, r, bounds, new IntValue(michalewiczIteration++), new IntValue(10000), new DoubleValue(5.0)); break; + case 4: BreederGeneticAlgorithmManipulator.Apply(random, r, bounds, new DoubleValue(0.1)); break; + default: throw new NotImplementedException(); + } + yield return neighbour; + michalewiczIteration %= 10000; + } + } - public override bool Maximization { get; } - - public void SetStrategy(ISurrogateStrategy strategy) { + public void Initialize(SingleObjectiveBasicProblem expensiveProblem, ISurrogateStrategy strategy) { + if (expensiveProblem == null) return; + var enc = (RealVectorEncoding)expensiveProblem.Encoding; + Encoding.Bounds = enc.Bounds; + Encoding.Length = enc.Length; + SolutionCreator = expensiveProblem.SolutionCreator; Strategy = strategy; } - public void SetProblem(SingleObjectiveBasicProblem expensiveProblem) { - if (expensiveProblem != null) Encoding = expensiveProblem.Encoding as RealVectorEncoding; - } - } } \ No newline at end of file Index: HeuristicLab.Algorithms.SAPBA/Properties/AssemblyInfo.cs =================================================================== --- HeuristicLab.Algorithms.SAPBA/Properties/AssemblyInfo.cs (revision 15449) +++ HeuristicLab.Algorithms.SAPBA/Properties/AssemblyInfo.cs (working copy) @@ -52,4 +52,4 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("3.4.0.0")] -[assembly: AssemblyFileVersion("3.4.0.14893")] +[assembly: AssemblyFileVersion("3.4.0.14894")] Index: HeuristicLab.Algorithms.SAPBA/SapbaUtilities.cs =================================================================== --- HeuristicLab.Algorithms.SAPBA/SapbaUtilities.cs (nonexistent) +++ HeuristicLab.Algorithms.SAPBA/SapbaUtilities.cs (working copy) @@ -0,0 +1,168 @@ +#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.Common; +using HeuristicLab.Core; +using HeuristicLab.Data; +using HeuristicLab.Encodings.RealVectorEncoding; +using HeuristicLab.Optimization; +using HeuristicLab.Problems.DataAnalysis; + +namespace HeuristicLab.Algorithms.SAPBA { + internal static class SapbaUtilities { + //Extention methods for convenience + public static int ArgMax(this IEnumerable values, Func func) { + var max = double.MinValue; + var maxIdx = 0; + var idx = 0; + foreach (var v in values) { + var d = func.Invoke(v); + if (d > max) { + max = d; + maxIdx = idx; + } + idx++; + } + return maxIdx; + } + public static int ArgMin(this IEnumerable values, Func func) { + return ArgMax(values, x => -func.Invoke(x)); + } + public static double GetEstimation(this IRegressionModel model, RealVector r) { + var dataset = GetDataSet(new[] { new Tuple(r, 0.0) }, false); + return model.GetEstimatedValues(dataset, new[] { 0 }).First(); + } + public static double GetVariance(this IConfidenceRegressionModel model, RealVector r) { + var dataset = GetDataSet(new[] { new Tuple(r, 0.0) }, false); + return model.GetEstimatedVariances(dataset, new[] { 0 }).First(); + } + public static double GetDoubleValue(this IDataset dataset, int i, int j) { + return dataset.GetDoubleValue("input" + j, i); + } + + //Sub-Algorithms + public static ResultCollection SyncRunSubAlgorithm(IAlgorithm alg, int random) { + if (alg.Parameters.ContainsKey("SetSeedRandomly") && alg.Parameters.ContainsKey("Seed")) { + var setSeed = alg.Parameters["SetSeedRandomly"].ActualValue as BoolValue; + var seed = alg.Parameters["Seed"].ActualValue as IntValue; + if (seed == null || setSeed == null) throw new ArgumentException("wrong SeedParametertypes"); + setSeed.Value = false; + seed.Value = random; + + } + EventWaitHandle trigger = new AutoResetEvent(false); + Exception ex = null; + EventHandler> exhandler = (sender, e) => ex = e.Value; + EventHandler stoppedHandler = (sender, e) => trigger.Set(); + alg.ExceptionOccurred += exhandler; + alg.Stopped += stoppedHandler; + alg.Prepare(); + alg.Start(); + trigger.WaitOne(); + alg.ExceptionOccurred -= exhandler; + alg.Stopped -= stoppedHandler; + if (ex != null) throw ex; + return alg.Results; + } + public static IRegressionSolution BuildModel(IReadOnlyList> samples, IDataAnalysisAlgorithm regressionAlgorithm, IRandom random, bool removeDuplicates = true, IRegressionSolution oldSolution = null) { + var dataset = GetDataSet(samples, removeDuplicates); + var problemdata = new RegressionProblemData(dataset, dataset.VariableNames.Where(x => !x.Equals("output")), "output"); + problemdata.TrainingPartition.Start = 0; + problemdata.TrainingPartition.End = dataset.Rows; + problemdata.TestPartition.Start = dataset.Rows; + problemdata.TestPartition.End = dataset.Rows; + + if (regressionAlgorithm.Problem == null) regressionAlgorithm.Problem = new RegressionProblem(); + var problem = regressionAlgorithm.Problem; + problem.ProblemDataParameter.Value = problemdata; + var i = 0; + IRegressionSolution solution = null; + + while (solution == null && i++ < 100) { + var results = SyncRunSubAlgorithm(regressionAlgorithm, random.Next(int.MaxValue)); + solution = results.Select(x => x.Value).OfType().SingleOrDefault(); + } + + //special treatement for GaussianProcessRegression + var gp = regressionAlgorithm as GaussianProcessRegression; + var oldGaussian = oldSolution as GaussianProcessRegressionSolution; + if (gp != null && oldGaussian != null) { + const double noise = 0.0; + var n = samples.First().Item1.Length; + var mean = (IMeanFunction)oldGaussian.Model.MeanFunction.Clone(); + var cov = (ICovarianceFunction)oldGaussian.Model.CovarianceFunction.Clone(); + if (mean.GetNumberOfParameters(n) != 0 || cov.GetNumberOfParameters(n) != 0) throw new ArgumentException("DEBUG: assumption about fixed paramters wrong"); + double[] hyp = { noise }; + try { + var model = new GaussianProcessModel(problemdata.Dataset, problemdata.TargetVariable, problemdata.AllowedInputVariables, problemdata.TrainingIndices, hyp, mean, cov); + model.FixParameters(); + var sol = new GaussianProcessRegressionSolution(model, problemdata); + if (solution == null || solution.TrainingMeanSquaredError > sol.TrainingMeanSquaredError) solution = sol; + } + catch (ArgumentException) { } + } + if (solution == null) throw new ArgumentException("The algorithm didn't return a model"); + regressionAlgorithm.Runs.Clear(); + return solution; + } + + //RegressionModel extensions + public const double DuplicateResolution = 0.000001; + public static Dataset GetDataSet(IReadOnlyList> samples, bool removeDuplicates) { + if (removeDuplicates) samples = RemoveDuplicates(samples); //TODO duplicate removal leads to incorrect uncertainty values in models + var dimensions = samples[0].Item1.Length + 1; + var data = new double[samples.Count, dimensions]; + var names = new string[dimensions - 1]; + for (var i = 0; i < names.Length; i++) names[i] = "input" + i; + for (var j = 0; j < samples.Count; j++) { + for (var i = 0; i < names.Length; i++) data[j, i] = samples[j].Item1[i]; + data[j, dimensions - 1] = samples[j].Item2; + } + return new Dataset(names.Concat(new[] { "output" }).ToArray(), data); + } + private static IReadOnlyList> RemoveDuplicates(IReadOnlyList> samples) { + var res = new List>(); + foreach (var sample in samples) { + if (res.Count == 0) { + res.Add(new Tuple(sample.Item1, sample.Item2, 1)); + continue; + } + var index = res.ArgMin(x => Euclidian(sample.Item1, x.Item1)); + var d = Euclidian(res[index].Item1, sample.Item1); + if (d > DuplicateResolution) res.Add(new Tuple(sample.Item1, sample.Item2, 1)); + else { + var t = res[index]; + res.RemoveAt(index); + res.Add(new Tuple(t.Item1, t.Item2 + sample.Item2, t.Item3 + 1)); + } + } + return res.Select(x => new Tuple(x.Item1, x.Item2 / x.Item3)).ToArray(); + } + private static double Euclidian(IEnumerable a, IEnumerable b) { + return Math.Sqrt(a.Zip(b, (d, d1) => d - d1).Sum(d => d * d)); + } + } +} Index: HeuristicLab.Algorithms.SAPBA/Strategies/InfillStrategy.cs =================================================================== --- HeuristicLab.Algorithms.SAPBA/Strategies/InfillStrategy.cs (nonexistent) +++ HeuristicLab.Algorithms.SAPBA/Strategies/InfillStrategy.cs (working copy) @@ -0,0 +1,113 @@ +#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.Linq; +using HeuristicLab.Algorithms.EGO; +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; + +namespace HeuristicLab.Algorithms.SAPBA { + [StorableClass] + public class InfillStrategy : StrategyBase { + #region Parameternames + public const string NoGenerationsParameterName = "Number of generations"; + public const string NoIndividualsParameterName = "Number of individuals"; + public const string InfillCriterionParameterName = "InfillCriterion"; + #endregion + #region Paramterproperties + public IFixedValueParameter NoGenerationsParameter => Parameters[NoGenerationsParameterName] as IFixedValueParameter; + public IFixedValueParameter NoIndividualsParameter => Parameters[NoIndividualsParameterName] as IFixedValueParameter; + public IConstrainedValueParameter InfillCriterionParameter => Parameters[InfillCriterionParameterName] as IConstrainedValueParameter; + #endregion + #region Properties + public IntValue NoGenerations => NoGenerationsParameter.Value; + public IntValue NoIndividuals => NoIndividualsParameter.Value; + public IInfillCriterion InfillCriterion => InfillCriterionParameter.Value; + [Storable] + public int Generations; + #endregion + + #region Constructors + [StorableConstructor] + protected InfillStrategy(bool deserializing) : base(deserializing) { } + [StorableHook(HookType.AfterDeserialization)] + private void AfterDeserialization() { + AttachListeners(); + } + protected InfillStrategy(InfillStrategy original, Cloner cloner) : base(original, cloner) { + Generations = original.Generations; + AttachListeners(); + } + public InfillStrategy() { + var critera = new ItemSet { new ExpectedImprovement(), new AugmentedExpectedImprovement(), new ExpectedQuality(), new ExpectedQuantileImprovement(), new MinimalQuantileCriterium(), new PluginExpectedImprovement() }; + Parameters.Add(new FixedValueParameter(NoGenerationsParameterName, "The number of generations before a new model is constructed", new IntValue(3))); + Parameters.Add(new FixedValueParameter(NoIndividualsParameterName, "The number of individuals that are sampled each generation ", new IntValue(3))); + Parameters.Add(new ConstrainedValueParameter(InfillCriterionParameterName, "The infill criterion used to cheaply evaluate points.", critera, critera.First())); + AttachListeners(); + } + public override IDeepCloneable Clone(Cloner cloner) { + return new InfillStrategy(this, cloner); + } + #endregion + + protected override void Analyze(Individual[] individuals, double[] qualities, ResultCollection results, ResultCollection globalResults, IRandom random) { } + protected override void ProcessPopulation(Individual[] individuals, double[] qualities, IRandom random) { + if (RegressionSolution != null && Generations < NoGenerations.Value) Generations++; + else { + //Select NoIndividuals best samples + var samples = individuals + .Zip(qualities, (individual, d) => new Tuple(individual, d)) + .OrderBy(t => Problem.Maximization ? -t.Item2 : t.Item2) + .Take(NoIndividuals.Value) + .Select(t => t.Item1.RealVector()); + foreach (var indi in samples) EvaluateSample(indi, random); + BuildRegressionSolution(random); + Generations = 0; + } + } + protected override void Initialize() { + Generations = 0; + } + + #region events + private void AttachListeners() { + ModelChanged += OnModelChanged; + } + private void OnModelChanged(object sender, EventArgs e) { + InfillCriterion.Encoding = Problem?.Encoding as RealVectorEncoding; + InfillCriterion.RegressionSolution = RegressionSolution; + InfillCriterion.ExpensiveMaximization = Problem?.Maximization ?? false; + if (RegressionSolution != null && InfillCriterion.Encoding != null) + InfillCriterion.Initialize(); + } + #endregion + + protected override double Estimate(RealVector point, IRandom random) { + return InfillCriterion.Maximization() != Maximization() ? -InfillCriterion.Evaluate(point) : InfillCriterion.Evaluate(point); + } + } +} Index: HeuristicLab.Algorithms.SAPBA/Strategies/LamarckianStrategy.cs =================================================================== --- HeuristicLab.Algorithms.SAPBA/Strategies/LamarckianStrategy.cs (nonexistent) +++ HeuristicLab.Algorithms.SAPBA/Strategies/LamarckianStrategy.cs (working copy) @@ -0,0 +1,249 @@ +#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 HeuristicLab.Algorithms.DataAnalysis; +using HeuristicLab.Algorithms.EGO; +using HeuristicLab.Algorithms.SAPBA.Operators; +using HeuristicLab.Analysis; +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; + +namespace HeuristicLab.Algorithms.SAPBA { + [StorableClass] + public class LamarckianStrategy : InfillStrategy { + #region Parameternames + public const string NoTrainingPointsParameterName = "Number of Trainingpoints"; + public const string LocalInfillCriterionParameterName = "LocalInfillCriterion"; + public const string OptimizationAlgorithmParameterName = "Optimization Algorithm"; + public const string RegressionAlgorithmParameterName = "Regression Algorithm"; + #endregion + #region Parameters + public IFixedValueParameter NoTrainingPointsParameter => Parameters[NoTrainingPointsParameterName] as IFixedValueParameter; + public IValueParameter OptimizationAlgorithmParameter => Parameters[OptimizationAlgorithmParameterName] as IValueParameter; + public IValueParameter> RegressionAlgorithmParameter => Parameters[RegressionAlgorithmParameterName] as IValueParameter>; + public IConstrainedValueParameter LocalInfillCriterionParameter => Parameters[LocalInfillCriterionParameterName] as IConstrainedValueParameter; + #endregion + #region Properties + public IntValue NoTrainingPoints => NoTrainingPointsParameter.Value; + public IAlgorithm OptimizationAlgorithm => OptimizationAlgorithmParameter.Value; + public IDataAnalysisAlgorithm RegressionAlgorithm => RegressionAlgorithmParameter.Value; + public IInfillCriterion LocalInfillCriterion => LocalInfillCriterionParameter.Value; + #endregion + + #region Constructors + [StorableConstructor] + protected LamarckianStrategy(bool deserializing) : base(deserializing) { } + [StorableHook(HookType.AfterDeserialization)] + private void AfterDeserialization() { + RegisterParameterEvents(); + } + protected LamarckianStrategy(LamarckianStrategy original, Cloner cloner) : base(original, cloner) { + RegisterParameterEvents(); + } + public LamarckianStrategy() { + var localCritera = new ItemSet { new ExpectedQuality(), new ExpectedImprovement(), new AugmentedExpectedImprovement(), new ExpectedQuantileImprovement(), new MinimalQuantileCriterium(), new PluginExpectedImprovement() }; + var osEs = new OffspringSelectionEvolutionStrategy.OffspringSelectionEvolutionStrategy { + Problem = new InfillProblem(), + ComparisonFactor = { Value = 1.0 }, + MaximumGenerations = { Value = 1000 }, + MaximumEvaluatedSolutions = { Value = 100000 }, + PlusSelection = { Value = true }, + PopulationSize = { Value = 1 } + }; + osEs.MutatorParameter.Value = osEs.MutatorParameter.ValidValues.OfType().First(); + Parameters.Add(new FixedValueParameter(NoTrainingPointsParameterName, "The number of sample points used to create a local model", new IntValue(50))); + Parameters.Add(new ConstrainedValueParameter(LocalInfillCriterionParameterName, "The infill criterion used to cheaply evaluate points.", localCritera, localCritera.First())); + Parameters.Add(new ValueParameter(OptimizationAlgorithmParameterName, "The algorithm used to solve the expected improvement subproblem", osEs)); + Parameters.Add(new ValueParameter>(RegressionAlgorithmParameterName, "The model used to approximate the problem", new GaussianProcessRegression { Problem = new RegressionProblem() })); + RegisterParameterEvents(); + } + public override IDeepCloneable Clone(Cloner cloner) { + return new LamarckianStrategy(this, cloner); + } + #endregion + + //Short lived stores for analysis + private readonly List LamarckValues = new List(); + private readonly List SampleValues = new List(); + + protected override void Initialize() { + base.Initialize(); + var infillProblem = OptimizationAlgorithm.Problem as InfillProblem; + if (infillProblem == null) throw new ArgumentException("InfillOptimizationAlgorithm does not have an InfillProblem."); + infillProblem.InfillCriterion = LocalInfillCriterion; + } + protected override void Analyze(Individual[] individuals, double[] qualities, ResultCollection results, ResultCollection globalResults, IRandom random) { + base.Analyze(individuals, qualities, results, globalResults, random); + const string plotName = "Lamarck Comparison"; + const string lamarckRow = "Lamarck Values"; + const string samplesRow = "Original Values"; + if (!globalResults.ContainsKey(plotName)) + globalResults.Add(new Result(plotName, new DataTable(plotName))); + + var plot = (DataTable)globalResults[plotName].Value; + if (!plot.Rows.ContainsKey(lamarckRow)) plot.Rows.Add(new DataRow(lamarckRow)); + if (!plot.Rows.ContainsKey(samplesRow)) plot.Rows.Add(new DataRow(samplesRow)); + plot.Rows[lamarckRow].Values.AddRange(LamarckValues); + plot.Rows[samplesRow].Values.AddRange(SampleValues); + LamarckValues.Clear(); + SampleValues.Clear(); + + //analyze Hypervolumes + const string volPlotName = "Hypervolumes Comparison"; + const string mainRowName = "Population Volume (log)"; + const string subspaceRowName = "Subspace Volume (log) for Lamarck Candidate "; + if (!globalResults.ContainsKey(volPlotName)) + globalResults.Add(new Result(volPlotName, new DataTable(volPlotName))); + + plot = (DataTable)globalResults[volPlotName].Value; + if (!plot.Rows.ContainsKey(mainRowName)) plot.Rows.Add(new DataRow(mainRowName)); + var v = Math.Log(GetStableVolume(GetBoundingBox(individuals.Select(x => x.RealVector())))); + plot.Rows[mainRowName].Values.Add(v); + + var indis = individuals + .Zip(qualities, (individual, d) => new Tuple(individual, d)) + .OrderBy(t => SapbaAlgorithm.Problem.Maximization ? -t.Item2 : t.Item2) + .Take(NoIndividuals.Value) + .Select(t => t.Item1).ToArray(); + + for (var i = 0; i < indis.Length; i++) { + var samples = GetNearestSamples(NoTrainingPoints.Value, indis[i].RealVector()); + var d = Math.Log(GetStableVolume(GetBoundingBox(samples.Select(x => x.Item1)))); + if (!plot.Rows.ContainsKey(subspaceRowName + i)) plot.Rows.Add(new DataRow(subspaceRowName + i)); + plot.Rows[subspaceRowName + i].Values.Add(d); + } + + + + } + protected override void ProcessPopulation(Individual[] individuals, double[] qualities, IRandom random) { + if (RegressionSolution == null) return; + if (Generations < NoGenerations.Value) Generations++; + else { + //Select best Individuals + var indis = individuals + .Zip(qualities, (individual, d) => new Tuple(individual, d)) + .OrderBy(t => Problem.Maximization ? -t.Item2 : t.Item2) + .Take(NoIndividuals.Value) + .Select(t => t.Item1).ToArray(); + //Evaluate individuals + foreach (var individual in indis) + SampleValues.Add(EvaluateSample(individual.RealVector(), random).Item2); + + //Perform memetic replacement for all points + for (var i = 0; i < indis.Length; i++) { + var vector = indis[i].RealVector(); + var altVector = OptimizeInfillProblem(vector, random); + LamarckValues.Add(EvaluateSample(altVector, random).Item2); + if (LamarckValues[i] < SampleValues[i] == Problem.Maximization) continue; + for (var j = 0; j < vector.Length; j++) vector[j] = altVector[j]; + } + + BuildRegressionSolution(random); + Generations = 0; + } + } + + #region Events + private void RegisterParameterEvents() { + OptimizationAlgorithmParameter.ValueChanged += OnInfillAlgorithmChanged; + OptimizationAlgorithm.ProblemChanged += OnInfillProblemChanged; + LocalInfillCriterionParameter.ValueChanged += OnInfillCriterionChanged; + } + private void OnInfillCriterionChanged(object sender, EventArgs e) { + ((InfillProblem)OptimizationAlgorithm.Problem).InfillCriterion = LocalInfillCriterion; + } + private void OnInfillAlgorithmChanged(object sender, EventArgs e) { + OptimizationAlgorithm.Problem = new InfillProblem { InfillCriterion = LocalInfillCriterion }; + OptimizationAlgorithm.ProblemChanged -= OnInfillProblemChanged; //avoid double attaching + OptimizationAlgorithm.ProblemChanged += OnInfillProblemChanged; + } + private void OnInfillProblemChanged(object sender, EventArgs e) { + OptimizationAlgorithm.ProblemChanged -= OnInfillProblemChanged; + OptimizationAlgorithm.Problem = new InfillProblem { InfillCriterion = LocalInfillCriterion }; + OptimizationAlgorithm.ProblemChanged += OnInfillProblemChanged; + } + #endregion + + #region helpers + private RealVector OptimizeInfillProblem(RealVector point, IRandom random) { + var infillProblem = OptimizationAlgorithm.Problem as InfillProblem; + if (infillProblem == null) throw new ArgumentException("InfillOptimizationAlgorithm does not have an InfillProblem."); + if (infillProblem.InfillCriterion != LocalInfillCriterion) throw new ArgumentException("InfillCiriterion for Problem is not correctly set."); + + var points = Math.Min(NoTrainingPoints.Value, Samples.Count); + var samples = GetNearestSamples(points, point); + var regression = SapbaUtilities.BuildModel(samples, RegressionAlgorithm, random); + var box = GetBoundingBox(samples.Select(x => x.Item1)); + + infillProblem.Encoding.Length = ((RealVectorEncoding)Problem.Encoding).Length; + infillProblem.Encoding.Bounds = box; + infillProblem.Encoding.SolutionCreator = new FixedRealVectorCreator(point); + infillProblem.Initialize(regression, Problem.Maximization); + var res = SapbaUtilities.SyncRunSubAlgorithm(OptimizationAlgorithm, random.Next(int.MaxValue)); + if (!res.ContainsKey(InfillProblem.BestInfillSolutionResultName)) throw new ArgumentException("The InfillOptimizationAlgorithm did not return a best solution"); + var v = res[InfillProblem.BestInfillSolutionResultName].Value as RealVector; + if (v == null) throw new ArgumentException("The InfillOptimizationAlgorithm did not return the expected result types"); + if (!InBounds(v, box)) throw new ArgumentException("Vector not in bounds"); + OptimizationAlgorithm.Runs.Clear(); + return v; + } + private Tuple[] GetNearestSamples(int noSamples, RealVector point) { + return Samples.Select(sample => Tuple.Create(SquaredEuclidean(sample.Item1, point), sample)).OrderBy(x => x.Item1).Take(noSamples).Select(x => x.Item2).ToArray(); + } + private static DoubleMatrix GetBoundingBox(IEnumerable samples) { + DoubleMatrix m = null; + foreach (var sample in samples) + if (m == null) { + m = new DoubleMatrix(sample.Length, 2); + for (var i = 0; i < sample.Length; i++) m[i, 0] = m[i, 1] = sample[i]; + } else + for (var i = 0; i < sample.Length; i++) { + m[i, 0] = Math.Min(m[i, 0], sample[i]); + m[i, 1] = Math.Max(m[i, 1], sample[i]); + } + return m; + } + + //the volume of a bounded-box whith slightly increased dimensions (Volume can never reach 0) + private static double GetStableVolume(DoubleMatrix bounds) { + var res = 1.0; + for (var i = 0; i < bounds.Rows; i++) res *= bounds[i, 1] - bounds[i, 0] + 0.1; + return res; + } + private static bool InBounds(RealVector r, DoubleMatrix bounds) { + return !r.Where((t, i) => t < bounds[i, 0] || t > bounds[i, 1]).Any(); + } + private static double SquaredEuclidean(RealVector a, RealVector b) { + return a.Select((t, i) => t - b[i]).Sum(d => d * d); + } + #endregion + } +} Index: HeuristicLab.Algorithms.SAPBA/Strategies/StrategyBase.cs =================================================================== --- HeuristicLab.Algorithms.SAPBA/Strategies/StrategyBase.cs (revision 15449) +++ HeuristicLab.Algorithms.SAPBA/Strategies/StrategyBase.cs (working copy) @@ -22,7 +22,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading; using HeuristicLab.Analysis; using HeuristicLab.Common; using HeuristicLab.Core; @@ -32,20 +31,39 @@ using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Problems.DataAnalysis; -namespace HeuristicLab.Algorithms.SAPBA.Strategies { +namespace HeuristicLab.Algorithms.SAPBA { [StorableClass] public abstract class StrategyBase : ParameterizedNamedItem, ISurrogateStrategy { #region Properties [Storable] - protected SurrogateAssistedPopulationBasedAlgorithm Algorithm; + protected SurrogateAssistedPopulationBasedAlgorithm SapbaAlgorithm; + protected SingleObjectiveBasicProblem Problem => SapbaAlgorithm?.Problem; [Storable] - private List> Samples; + protected List> Samples; [Storable] - protected IRegressionSolution RegressionSolution; - protected CancellationToken Cancellation; - private IEnumerable> TruncatedSamples => Samples.Count > Algorithm.MaximalDatasetSize && Algorithm.MaximalDatasetSize > 0 ? Samples.Skip(Samples.Count - Algorithm.MaximalDatasetSize) : Samples; + private IRegressionSolution regressionSolution; + + public IRegressionSolution RegressionSolution + { + get { return regressionSolution; } + protected set + { + regressionSolution = value; + OnModelChanged(); + } + } + + private List> TruncatedSamples => Samples.Count > SapbaAlgorithm.MaximalDatasetSize && SapbaAlgorithm.MaximalDatasetSize > 0 ? Samples.Skip(Samples.Count - SapbaAlgorithm.MaximalDatasetSize).ToList() : Samples; #endregion + #region Events + public event EventHandler ModelChanged; + private void OnModelChanged() { + ModelChanged?.Invoke(this, EventArgs.Empty); + OnToStringChanged(); + } + #endregion + #region ResultName private const string BestQualityResultName = "Best Quality"; private const string BestSolutionResultName = "Best Solution"; @@ -64,55 +82,44 @@ [StorableConstructor] protected StrategyBase(bool deserializing) : base(deserializing) { } protected StrategyBase(StrategyBase original, Cloner cloner) : base(original, cloner) { - if (original.Samples != null) Samples = original.Samples.Select(x => new Tuple(cloner.Clone(x.Item1), x.Item2)).ToList(); + Samples = original.Samples?.Select(x => new Tuple(cloner.Clone(x.Item1), x.Item2)).ToList(); RegressionSolution = cloner.Clone(original.RegressionSolution); + SapbaAlgorithm = cloner.Clone(original.SapbaAlgorithm); } protected StrategyBase() { } #endregion - public abstract double Evaluate(RealVector r, IRandom random); protected abstract void Analyze(Individual[] individuals, double[] qualities, ResultCollection results, ResultCollection globalResults, IRandom random); protected abstract void ProcessPopulation(Individual[] individuals, double[] qualities, IRandom random); - protected abstract void Initialize(); + protected virtual void Initialize() { } + //protected virtual void OnModelChanged() { } + protected abstract double Estimate(RealVector r, IRandom random); + + public double Evaluate(RealVector r, IRandom random) { + if (Samples.Count < SapbaAlgorithm.InitialEvaluations) return EvaluateSample(r, random).Item2; + if (Samples.Count == SapbaAlgorithm.InitialEvaluations && RegressionSolution == null) { + BuildRegressionSolution(random); + OnModelChanged(); + } + return Estimate(r, random); + } public void Analyze(Individual[] individuals, double[] qualities, ResultCollection results, IRandom random) { - Algorithm.Problem.Analyze(individuals, qualities, results, random); + SapbaAlgorithm.Problem.Analyze(individuals, qualities, results, random); ProcessPopulation(individuals, qualities, random); - var globalResults = Algorithm.Results; + var globalResults = SapbaAlgorithm.Results; if (!globalResults.ContainsKey(EvaluatedSoultionsResultName)) globalResults.Add(new Result(EvaluatedSoultionsResultName, new IntValue(Samples.Count))); else ((IntValue)globalResults[EvaluatedSoultionsResultName].Value).Value = Samples.Count; if (!globalResults.ContainsKey(IterationsResultName)) globalResults.Add(new Result(IterationsResultName, new IntValue(0))); else ((IntValue)globalResults[IterationsResultName].Value).Value++; - if (Samples.Count != 0) { - var min = Samples.Min(x => x.Item2); - var max = Samples.Max(x => x.Item2); - var bestIdx = Algorithm.Problem.Maximization ? Samples.ArgMax(x => x.Item2) : Samples.ArgMin(x => x.Item2); - if (!globalResults.ContainsKey(BestQualityResultName)) globalResults.Add(new Result(BestQualityResultName, new DoubleValue(0.0))); - ((DoubleValue)globalResults[BestQualityResultName].Value).Value = Samples[bestIdx].Item2; - if (!globalResults.ContainsKey(BestSolutionResultName)) globalResults.Add(new Result(BestSolutionResultName, new RealVector())); - globalResults[BestSolutionResultName].Value = Samples[bestIdx].Item1; + AnalyzeSamplesProgression(globalResults); + AnalyzeQualities(globalResults); - DataTable table; - if (!globalResults.ContainsKey(QualityTableResultName)) { - table = new DataTable("Qualites", "Qualites over iteration"); - globalResults.Add(new Result(QualityTableResultName, table)); - table.Rows.Add(new DataRow(BestQualityRowName, "Best Quality")); - table.Rows.Add(new DataRow(WorstQualityRowName, "Worst Quality")); - table.Rows.Add(new DataRow(CurrentQualityRowName, "Current Quality")); - table.Rows.Add(new DataRow(MedianQualityRowName, "Median Quality")); - table.Rows.Add(new DataRow(AverageQualityRowName, "Average Quality")); - } - table = (DataTable)globalResults[QualityTableResultName].Value; - table.Rows[BestQualityResultName].Values.Add(Algorithm.Problem.Maximization ? max : min); - table.Rows[WorstQualityRowName].Values.Add(Algorithm.Problem.Maximization ? min : max); - table.Rows[CurrentQualityRowName].Values.Add(Samples[Samples.Count - 1].Item2); - table.Rows[AverageQualityRowName].Values.Add(Samples.Average(x => x.Item2)); - table.Rows[MedianQualityRowName].Values.Add(Samples.Select(x => x.Item2).Median()); - } + if (RegressionSolution != null) { if (!globalResults.ContainsKey(RegressionSolutionResultName)) globalResults.Add(new Result(RegressionSolutionResultName, RegressionSolution)); @@ -122,40 +129,93 @@ Analyze(individuals, qualities, results, globalResults, random); } + private void AnalyzeSamplesProgression(ResultCollection globalResults) { + const string samplesTableName = "SamplesProgression"; + const string minRowName = "Minimum"; + const string maxRowName = "Maximum"; + const string medianRowName = "Median"; + const string averageRowName = "Average"; + const string currentRowName = "Current"; + + if (!globalResults.ContainsKey(samplesTableName)) { globalResults.Add(new Result(samplesTableName, new DataTable())); } + var table = (DataTable)globalResults[samplesTableName].Value; + + if (!table.Rows.ContainsKey(minRowName)) table.Rows.Add(new DataRow(minRowName)); + if (!table.Rows.ContainsKey(maxRowName)) table.Rows.Add(new DataRow(maxRowName)); + if (!table.Rows.ContainsKey(medianRowName)) table.Rows.Add(new DataRow(medianRowName)); + if (!table.Rows.ContainsKey(averageRowName)) table.Rows.Add(new DataRow(averageRowName)); + if (!table.Rows.ContainsKey(currentRowName)) table.Rows.Add(new DataRow(currentRowName)); + + for (var i = table.Rows[minRowName].Values.Count + 1; i < Samples.Count; i++) { + var subSamples = Samples.Take(i).Select(x => x.Item2).ToArray(); + table.Rows[minRowName].Values.Add(subSamples.Min()); + table.Rows[maxRowName].Values.Add(subSamples.Max()); + table.Rows[medianRowName].Values.Add(subSamples.Median()); + table.Rows[averageRowName].Values.Add(subSamples.Average()); + table.Rows[currentRowName].Values.Add(subSamples[subSamples.Length - 1]); + } + } + private void AnalyzeQualities(ResultCollection globalResults) { + if (Samples.Count == 0) return; + var min = Samples.Min(x => x.Item2); + var max = Samples.Max(x => x.Item2); + var bestIdx = SapbaAlgorithm.Problem.Maximization ? Samples.ArgMax(x => x.Item2) : Samples.ArgMin(x => x.Item2); + + if (!globalResults.ContainsKey(BestQualityResultName)) globalResults.Add(new Result(BestQualityResultName, new DoubleValue(0.0))); + ((DoubleValue)globalResults[BestQualityResultName].Value).Value = Samples[bestIdx].Item2; + if (!globalResults.ContainsKey(BestSolutionResultName)) globalResults.Add(new Result(BestSolutionResultName, new RealVector())); + globalResults[BestSolutionResultName].Value = Samples[bestIdx].Item1; + + DataTable table; + if (!globalResults.ContainsKey(QualityTableResultName)) { + table = new DataTable("Qualites", "Qualites over iteration"); + globalResults.Add(new Result(QualityTableResultName, table)); + table.Rows.Add(new DataRow(BestQualityRowName, "Best Quality")); + table.Rows.Add(new DataRow(WorstQualityRowName, "Worst Quality")); + table.Rows.Add(new DataRow(CurrentQualityRowName, "Current Quality")); + table.Rows.Add(new DataRow(MedianQualityRowName, "Median Quality")); + table.Rows.Add(new DataRow(AverageQualityRowName, "Average Quality")); + } + table = (DataTable)globalResults[QualityTableResultName].Value; + table.Rows[BestQualityResultName].Values.Add(SapbaAlgorithm.Problem.Maximization ? max : min); + table.Rows[WorstQualityRowName].Values.Add(SapbaAlgorithm.Problem.Maximization ? min : max); + table.Rows[CurrentQualityRowName].Values.Add(Samples[Samples.Count - 1].Item2); + table.Rows[AverageQualityRowName].Values.Add(Samples.Average(x => x.Item2)); + table.Rows[MedianQualityRowName].Values.Add(Samples.Select(x => x.Item2).Median()); + } + public void Initialize(SurrogateAssistedPopulationBasedAlgorithm algorithm) { - Algorithm = algorithm; - Samples = algorithm.InitialSamples?.ToList() ?? new List>(); + SapbaAlgorithm = algorithm; + Samples = algorithm?.InitialSamples?.ToList() ?? new List>(); RegressionSolution = null; Initialize(); } + public virtual bool Maximization() { + return SapbaAlgorithm?.Problem?.Maximization ?? false; + } #region Helpers for Subclasses protected void BuildRegressionSolution(IRandom random) { - RegressionSolution = EgoUtilities.BuildModel(Cancellation, TruncatedSamples, Algorithm.RegressionAlgorithm, random, Algorithm.RemoveDuplicates, RegressionSolution); + RegressionSolution = SapbaUtilities.BuildModel(TruncatedSamples, SapbaAlgorithm.RegressionAlgorithm, random, SapbaAlgorithm.RemoveDuplicates, RegressionSolution); } protected Tuple EvaluateSample(RealVector point, IRandom random) { - Cancellation.ThrowIfCancellationRequested(); - if (Samples.Count >= Algorithm.MaximumEvaluations) { Algorithm.OptimizationAlgorithm.Stop(); return new Tuple(point, 0.0); } - var p = new Tuple(point, Algorithm.Problem.Evaluate(GetIndividual(point), random)); + if (Samples.Count >= SapbaAlgorithm.MaximumEvaluations) { SapbaAlgorithm.OptimizationAlgorithm.Stop(); return new Tuple(point, 0.0); } + var p = new Tuple((RealVector)point.Clone(), SapbaAlgorithm.Problem.Evaluate(GetIndividual(point), random)); Samples.Add(p); return p; } - protected Tuple EstimateSample(RealVector point, IRandom random) { - if (Samples.Count == Algorithm.InitialEvaluations && RegressionSolution == null) BuildRegressionSolution(random); - return Samples.Count < Algorithm.InitialEvaluations ? EvaluateSample(point, random) : new Tuple(point, RegressionSolution.Model.GetEstimation(point)); + protected double EstimateSample(RealVector r) { + return RegressionSolution.Model.GetEstimation(r); } + #endregion #region Helpers private Individual GetIndividual(RealVector r) { var scope = new Scope(); - scope.Variables.Add(new Variable(Algorithm.Problem.Encoding.Name, r)); - return new SingleEncodingIndividual(Algorithm.Problem.Encoding, scope); + scope.Variables.Add(new Variable(SapbaAlgorithm.Problem.Encoding.Name, r)); + return new SingleEncodingIndividual(SapbaAlgorithm.Problem.Encoding, scope); } - - public void UpdateCancellation(CancellationToken cancellationToken) { - Cancellation = cancellationToken; - } #endregion } } \ No newline at end of file Index: HeuristicLab.Algorithms.SAPBA/SurrogateAssistedPopulationBasedAlgorithm.cs =================================================================== --- HeuristicLab.Algorithms.SAPBA/SurrogateAssistedPopulationBasedAlgorithm.cs (revision 15449) +++ HeuristicLab.Algorithms.SAPBA/SurrogateAssistedPopulationBasedAlgorithm.cs (working copy) @@ -24,7 +24,6 @@ using System.Linq; using System.Threading; using HeuristicLab.Algorithms.DataAnalysis; -using HeuristicLab.Algorithms.SAPBA.Strategies; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; @@ -33,7 +32,6 @@ using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Problems.DataAnalysis; -using HeuristicLab.Random; namespace HeuristicLab.Algorithms.SAPBA { [StorableClass] @@ -41,7 +39,7 @@ [Item("SurrogateAssistedPopulationBasedAlgorithm", "")] public class SurrogateAssistedPopulationBasedAlgorithm : BasicAlgorithm, ISurrogateAlgorithm { #region Basic-Alg-Essentials - public override bool SupportsPause => true; + public override bool SupportsPause => false; public override Type ProblemType => typeof(SingleObjectiveBasicProblem); public new SingleObjectiveBasicProblem Problem { @@ -91,14 +89,9 @@ #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(); - } + public SurrogateProblem SurrogateProblem; #endregion #region HLConstructors @@ -109,59 +102,50 @@ 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(); + InitialSamples = original.InitialSamples?.Select(x => new Tuple(cloner.Clone(x.Item1), x.Item2)).ToList(); + SurrogateProblem = cloner.Clone(original.SurrogateProblem); 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() - }; + SurrogateProblem = new SurrogateProblem(); + var geneticAlgorithm = new GeneticAlgorithm.GeneticAlgorithm { PopulationSize = { Value = 50 }, Problem = SurrogateProblem, Elites = { Value = 0 } }; + var model = new GaussianProcessRegression { Problem = new RegressionProblem() }; + var strategies = new ItemSet { new InfillStrategy(), new LamarckianStrategy() }; + 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(InitialEvaluationsParameterName, "The initial number of evaluations performed before the first model is constructed", new IntValue(10))); + 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(MaximumEvaluationsParameterName, "The maximum number of evaluations performed", new IntValue(int.MaxValue))); 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 ValueParameter(OptimizationAlgorithmParameterName, "The algorithm used to solve the expected improvement subproblem", geneticAlgorithm)); + Parameters.Add(new ValueParameter>(RegressionAlgorithmParameterName, "The model used to approximate the problem", model)); + 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")); 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 + public void SetInitialSamples(RealVector[] solutions, double[] qualities) { + InitialSamples = solutions.Zip(qualities, (vector, d) => new Tuple(vector, d)).ToList(); + } 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); + SurrogateProblem.Initialize(Problem, SurrogateStrategy); } protected override void Run(CancellationToken cancellationToken) { - SurrogateStrategy.UpdateCancellation(cancellationToken); - try { EgoUtilities.SyncRunSubAlgorithm(OptimizationAlgorithm, Random.Next()); } - finally { Analyze(); } + try { SapbaUtilities.SyncRunSubAlgorithm(OptimizationAlgorithm, Seed); } + finally { + foreach (var surrogateStrategy in StrategyParameter.ValidValues) surrogateStrategy.Initialize(null); + OptimizationAlgorithm.Runs.Clear(); + } } - private void Analyze() { } #region Eventhandling private void RegisterEventhandlers() { @@ -172,7 +156,7 @@ OptimizationAlgorithmParameter.ValueChanged -= OnOptimizationAlgorithmChanged; } private void OnOptimizationAlgorithmChanged(object sender, EventArgs e) { - OptimizationAlgorithm.Problem = surrogateProblem; + OptimizationAlgorithm.Problem = SurrogateProblem; } protected override void OnExecutionTimeChanged() { @@ -179,23 +163,18 @@ base.OnExecutionTimeChanged(); if (CancellationTokenSource == null) return; if (MaximumRuntime == -1) return; - if (ExecutionTime.TotalSeconds > MaximumRuntime) CancellationTokenSource.Cancel(); + if (ExecutionTime.TotalSeconds > MaximumRuntime) OptimizationAlgorithm.Stop(); } public override void Pause() { base.Pause(); - if (RegressionAlgorithm.ExecutionState == ExecutionState.Started) RegressionAlgorithm.Pause(); - if (OptimizationAlgorithm.ExecutionState == ExecutionState.Started) OptimizationAlgorithm.Pause(); - + if (RegressionAlgorithm.ExecutionState == ExecutionState.Started) RegressionAlgorithm.Stop(); + if (OptimizationAlgorithm.ExecutionState == ExecutionState.Started) OptimizationAlgorithm.Stop(); } public override void Stop() { base.Stop(); - if (RegressionAlgorithm.ExecutionState == ExecutionState.Started) RegressionAlgorithm.Stop(); - if (OptimizationAlgorithm.ExecutionState == ExecutionState.Started) OptimizationAlgorithm.Stop(); + //if (RegressionAlgorithm.ExecutionState == ExecutionState.Started || RegressionAlgorithm.ExecutionState == ExecutionState.Paused) RegressionAlgorithm.Stop(); + if (OptimizationAlgorithm.ExecutionState == ExecutionState.Started || OptimizationAlgorithm.ExecutionState == ExecutionState.Paused) OptimizationAlgorithm.Stop(); } - protected override void OnProblemChanged() { - base.OnProblemChanged(); - surrogateProblem.SetProblem(Problem); - } #endregion }