Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Algorithms.CMAEvolutionStrategy/sources/3.3/MOCMAES/MOCMASEvolutionStrategy.cs @ 13793

Last change on this file since 13793 was 13793, checked in by bwerth, 8 years ago

#2592 first unfinished implementation similiar to Shark – Machine Learning 3.1

File size: 35.7 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 * and the BEACON Center for the Study of Evolution in Action.
5 *
6 * This file is part of HeuristicLab.
7 *
8 * HeuristicLab is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * HeuristicLab is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
20 */
21#endregion
22
23using System;
24using System.Collections.Generic;
25using System.Threading;
26using HeuristicLab.Analysis;
27using HeuristicLab.Common;
28using HeuristicLab.Core;
29using HeuristicLab.Data;
30using HeuristicLab.Encodings.RealVectorEncoding;
31using HeuristicLab.Optimization;
32using HeuristicLab.Parameters;
33using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
34using HeuristicLab.Problems.MultiObjectiveTestFunctions;
35using HeuristicLab.Random;
36
37namespace HeuristicLab.Algorithms.CMAEvolutionStrategy {
38  [Item("MOCMAS Evolution Strategy (MOCMASES)", "A multi objective evolution strategy based on covariance matrix adaptation. Code is based on 'Covariance Matrix Adaptation for Multi - objective Optimization' by Igel, Hansen and Roth")]
39  [Creatable(CreatableAttribute.Categories.PopulationBasedAlgorithms, Priority = 210)]
40  [StorableClass]
41  public class MOCMASEvolutionStrategy : BasicAlgorithm {
42    public override Type ProblemType {
43      get { return typeof(MultiObjectiveTestFunctionProblem); }
44    }
45    public new MultiObjectiveTestFunctionProblem Problem {
46      get { return (MultiObjectiveTestFunctionProblem)base.Problem; }
47      set { base.Problem = value; }
48    }
49
50    private readonly IRandom random = new MersenneTwister();
51
52
53    #region ParameterNames
54    private const string MaximumRuntimeName = "Maximum Runtime";
55    private const string SeedName = "Seed";
56    private const string SetSeedRandomlyName = "SetSeedRandomly";
57    private const string PopulationSizeName = "PopulationSize";
58    private const string InitialIterationsName = "InitialIterations";
59    private const string InitialSigmaName = "InitialSigma";
60    private const string MuName = "Mu";
61    private const string CMAInitializerName = "CMAInitializer";
62    private const string CMAMutatorName = "CMAMutator";
63    private const string CMARecombinatorName = "CMARecombinator";
64    private const string CMAUpdaterName = "CMAUpdater";
65    private const string AnalyzerName = "Analyzer";
66    private const string MaximumGenerationsName = "MaximumGenerations";
67    private const string MaximumEvaluatedSolutionsName = "MaximumEvaluatedSolutions";
68    private const string TargetQualityName = "TargetQuality";
69    private const string MinimumQualityChangeName = "MinimumQualityChange";
70    private const string MinimumQualityHistoryChangeName = "MinimumQualityHistoryChange";
71    private const string MinimumStandardDeviationName = "MinimumStandardDeviation";
72    private const string MaximumStandardDeviationChangeName = "MaximumStandardDeviationChange";
73    #endregion
74
75    #region ParameterProperties
76    public IFixedValueParameter<IntValue> MaximumRuntimeParameter {
77      get { return (IFixedValueParameter<IntValue>)Parameters[MaximumRuntimeName]; }
78    }
79    public IFixedValueParameter<IntValue> SeedParameter {
80      get { return (IFixedValueParameter<IntValue>)Parameters[SeedName]; }
81    }
82    public FixedValueParameter<BoolValue> SetSeedRandomlyParameter {
83      get { return (FixedValueParameter<BoolValue>)Parameters[SetSeedRandomlyName]; }
84    }
85    private IFixedValueParameter<IntValue> PopulationSizeParameter {
86      get { return (IFixedValueParameter<IntValue>)Parameters[PopulationSizeName]; }
87    }
88    public IValueParameter<MultiAnalyzer> AnalyzerParameter {
89      get { return (IValueParameter<MultiAnalyzer>)Parameters[AnalyzerName]; }
90    }
91    private IFixedValueParameter<IntValue> InitialIterationsParameter {
92      get { return (IFixedValueParameter<IntValue>)Parameters[InitialIterationsName]; }
93    }
94    public IValueParameter<DoubleValue> InitialSigmaParameter {
95      get { return (IValueParameter<DoubleValue>)Parameters[InitialSigmaName]; }
96    }
97    private OptionalValueParameter<IntValue> MuParameter {
98      get { return (OptionalValueParameter<IntValue>)Parameters[MuName]; }
99    }
100    public IConstrainedValueParameter<ICMAInitializer> CMAInitializerParameter {
101      get { return (IConstrainedValueParameter<ICMAInitializer>)Parameters[CMAInitializerName]; }
102    }
103    public IConstrainedValueParameter<ICMAManipulator> CMAMutatorParameter {
104      get { return (IConstrainedValueParameter<ICMAManipulator>)Parameters[CMAMutatorName]; }
105    }
106    public IConstrainedValueParameter<ICMARecombinator> CMARecombinatorParameter {
107      get { return (IConstrainedValueParameter<ICMARecombinator>)Parameters[CMARecombinatorName]; }
108    }
109    public IConstrainedValueParameter<ICMAUpdater> CMAUpdaterParameter {
110      get { return (IConstrainedValueParameter<ICMAUpdater>)Parameters[CMAUpdaterName]; }
111    }
112    private IFixedValueParameter<IntValue> MaximumGenerationsParameter {
113      get { return (IFixedValueParameter<IntValue>)Parameters[MaximumGenerationsName]; }
114    }
115    private IFixedValueParameter<IntValue> MaximumEvaluatedSolutionsParameter {
116      get { return (IFixedValueParameter<IntValue>)Parameters[MaximumEvaluatedSolutionsName]; }
117    }
118    private IFixedValueParameter<DoubleValue> TargetQualityParameter {
119      get { return (IFixedValueParameter<DoubleValue>)Parameters[TargetQualityName]; }
120    }
121    private IFixedValueParameter<DoubleValue> MinimumQualityChangeParameter {
122      get { return (IFixedValueParameter<DoubleValue>)Parameters[MinimumQualityChangeName]; }
123    }
124    private IFixedValueParameter<DoubleValue> MinimumQualityHistoryChangeParameter {
125      get { return (IFixedValueParameter<DoubleValue>)Parameters[MinimumQualityHistoryChangeName]; }
126    }
127    private IFixedValueParameter<DoubleValue> MinimumStandardDeviationParameter {
128      get { return (IFixedValueParameter<DoubleValue>)Parameters[MinimumStandardDeviationName]; }
129    }
130    private IFixedValueParameter<DoubleValue> MaximumStandardDeviationChangeParameter {
131      get { return (IFixedValueParameter<DoubleValue>)Parameters[MaximumStandardDeviationChangeName]; }
132    }
133    #endregion
134
135    #region Properties
136    public int MaximumRuntime {
137      get { return MaximumRuntimeParameter.Value.Value; }
138      set { MaximumRuntimeParameter.Value.Value = value; }
139    }
140    public int Seed {
141      get { return SeedParameter.Value.Value; }
142      set { SeedParameter.Value.Value = value; }
143    }
144    public bool SetSeedRandomly {
145      get { return SetSeedRandomlyParameter.Value.Value; }
146      set { SetSeedRandomlyParameter.Value.Value = value; }
147    }
148    public int PopulationSize {
149      get { return PopulationSizeParameter.Value.Value; }
150      set { PopulationSizeParameter.Value.Value = value; }
151    }
152    public int InitialIterations {
153      get { return InitialIterationsParameter.Value.Value; }
154      set { InitialIterationsParameter.Value.Value = value; }
155    }
156    public int MaximumGenerations {
157      get { return MaximumGenerationsParameter.Value.Value; }
158      set { MaximumGenerationsParameter.Value.Value = value; }
159    }
160    public int MaximumEvaluatedSolutions {
161      get { return MaximumEvaluatedSolutionsParameter.Value.Value; }
162      set { MaximumEvaluatedSolutionsParameter.Value.Value = value; }
163    }
164    public double TargetQuality {
165      get { return TargetQualityParameter.Value.Value; }
166      set { TargetQualityParameter.Value.Value = value; }
167    }
168    public double MinimumQualityChange {
169      get { return MinimumQualityChangeParameter.Value.Value; }
170      set { MinimumQualityChangeParameter.Value.Value = value; }
171    }
172    public double MinimumQualityHistoryChange {
173      get { return MinimumQualityHistoryChangeParameter.Value.Value; }
174      set { MinimumQualityHistoryChangeParameter.Value.Value = value; }
175    }
176    public double MinimumStandardDeviation {
177      get { return MinimumStandardDeviationParameter.Value.Value; }
178      set { MinimumStandardDeviationParameter.Value.Value = value; }
179    }
180    public double MaximumStandardDeviationChange {
181      get { return MaximumStandardDeviationChangeParameter.Value.Value; }
182      set { MaximumStandardDeviationChangeParameter.Value.Value = value; }
183    }
184    public DoubleValue InitialSigma {
185      get { return InitialSigmaParameter.Value; }
186      set { InitialSigmaParameter.Value = value; }
187    }
188    public IntValue Mu {
189      get { return MuParameter.Value; }
190      set { MuParameter.Value = value; }
191    }
192    public ICMAInitializer CMAInitializer {
193      get { return CMAInitializerParameter.Value; }
194      set { CMAInitializerParameter.Value = value; }
195    }
196    public ICMAManipulator CMAMutator {
197      get { return CMAMutatorParameter.Value; }
198      set { CMAMutatorParameter.Value = value; }
199    }
200    public ICMARecombinator CMARecombinator {
201      get { return CMARecombinatorParameter.Value; }
202      set { CMARecombinatorParameter.Value = value; }
203    }
204    public MultiAnalyzer Analyzer {
205      get { return AnalyzerParameter.Value; }
206      set { AnalyzerParameter.Value = value; }
207    }
208    public ICMAUpdater CMAUpdater {
209      get { return CMAUpdaterParameter.Value; }
210      set { CMAUpdaterParameter.Value = value; }
211    }
212
213    #endregion
214
215    #region ResultsProperties
216    private double ResultsBestQuality {
217      get { return ((DoubleValue)Results["Best Quality"].Value).Value; }
218      set { ((DoubleValue)Results["Best Quality"].Value).Value = value; }
219    }
220
221    private RealVector ResultsBestSolution {
222      get { return (RealVector)Results["Best Solution"].Value; }
223      set { Results["Best Solution"].Value = value; }
224    }
225
226    private int ResultsBestFoundOnEvaluation {
227      get { return ((IntValue)Results["Evaluation Best Solution Was Found"].Value).Value; }
228      set { ((IntValue)Results["Evaluation Best Solution Was Found"].Value).Value = value; }
229    }
230
231    private int ResultsEvaluations {
232      get { return ((IntValue)Results["Evaluations"].Value).Value; }
233      set { ((IntValue)Results["Evaluations"].Value).Value = value; }
234    }
235    private int ResultsIterations {
236      get { return ((IntValue)Results["Iterations"].Value).Value; }
237      set { ((IntValue)Results["Iterations"].Value).Value = value; }
238    }
239
240    private DataTable ResultsQualities {
241      get { return ((DataTable)Results["Qualities"].Value); }
242    }
243    private DataRow ResultsQualitiesBest {
244      get { return ResultsQualities.Rows["Best Quality"]; }
245    }
246
247    private DataRow ResultsQualitiesIteration {
248      get { return ResultsQualities.Rows["Iteration Quality"]; }
249    }
250
251    #endregion
252
253    #region constructors and hlBoilerPlate-code
254    [StorableConstructor]
255    protected MOCMASEvolutionStrategy(bool deserializing) : base(deserializing) { }
256
257    protected MOCMASEvolutionStrategy(MOCMASEvolutionStrategy original, Cloner cloner)
258        : base(original, cloner) {
259    }
260
261    public override IDeepCloneable Clone(Cloner cloner) {
262      return new MOCMASEvolutionStrategy(this, cloner);
263    }
264
265    public MOCMASEvolutionStrategy() {
266      Parameters.Add(new FixedValueParameter<IntValue>(MaximumRuntimeName, "The maximum runtime in seconds after which the algorithm stops. Use -1 to specify no limit for the runtime", new IntValue(3600)));
267      Parameters.Add(new FixedValueParameter<IntValue>(SeedName, "The random seed used to initialize the new pseudo random number generator.", new IntValue(0)));
268      Parameters.Add(new FixedValueParameter<BoolValue>(SetSeedRandomlyName, "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true)));
269      Parameters.Add(new FixedValueParameter<IntValue>(PopulationSizeName, "λ (lambda) - the size of the offspring population.", new IntValue(20)));
270      Parameters.Add(new FixedValueParameter<IntValue>(InitialIterationsName, "The number of iterations that should be performed with only axis parallel mutation.", new IntValue(0)));
271      Parameters.Add(new FixedValueParameter<DoubleValue>(InitialSigmaName, "The initial sigma can be a single value or a value for each dimension. All values need to be > 0.", new DoubleValue(0.5)));
272      Parameters.Add(new OptionalValueParameter<IntValue>(MuName, "Optional, the mu best offspring that should be considered for update of the new mean and strategy parameters. If not given it will be automatically calculated."));
273      Parameters.Add(new ConstrainedValueParameter<ICMARecombinator>(CMARecombinatorName, "The operator used to calculate the new mean."));
274      Parameters.Add(new ConstrainedValueParameter<ICMAManipulator>(CMAMutatorName, "The operator used to manipulate a point."));
275      Parameters.Add(new ConstrainedValueParameter<ICMAInitializer>(CMAInitializerName, "The operator that initializes the covariance matrix and strategy parameters."));
276      Parameters.Add(new ConstrainedValueParameter<ICMAUpdater>(CMAUpdaterName, "The operator that updates the covariance matrix and strategy parameters."));
277      Parameters.Add(new ValueParameter<MultiAnalyzer>(AnalyzerName, "The operator used to analyze each generation.", new MultiAnalyzer()));
278      Parameters.Add(new FixedValueParameter<IntValue>(MaximumGenerationsName, "The maximum number of generations which should be processed.", new IntValue(1000)));
279      Parameters.Add(new FixedValueParameter<IntValue>(MaximumEvaluatedSolutionsName, "The maximum number of evaluated solutions that should be computed.", new IntValue(int.MaxValue)));
280      Parameters.Add(new FixedValueParameter<DoubleValue>(TargetQualityName, "(stopFitness) Surpassing this quality value terminates the algorithm.", new DoubleValue(double.NaN)));
281      Parameters.Add(new FixedValueParameter<DoubleValue>(MinimumQualityChangeName, "(stopTolFun) If the range of fitness values is less than a certain value the algorithm terminates (set to 0 or positive value to enable).", new DoubleValue(double.NaN)));
282      Parameters.Add(new FixedValueParameter<DoubleValue>(MinimumQualityHistoryChangeName, "(stopTolFunHist) If the range of fitness values is less than a certain value for a certain time the algorithm terminates (set to 0 or positive to enable).", new DoubleValue(double.NaN)));
283      Parameters.Add(new FixedValueParameter<DoubleValue>(MinimumStandardDeviationName, "(stopTolXFactor) If the standard deviation falls below a certain value the algorithm terminates (set to 0 or positive to enable).", new DoubleValue(double.NaN)));
284      Parameters.Add(new FixedValueParameter<DoubleValue>(MaximumStandardDeviationChangeName, "(stopTolUpXFactor) If the standard deviation changes by a value larger than this parameter the algorithm stops (set to a value > 0 to enable).", new DoubleValue(double.NaN)));
285
286    }
287    #endregion
288
289    #region updates
290    private void updatePopulation(CMAHansenIndividual[] parents) {
291      int[] offspringSucess = new int[solutions.Length];
292      int offspringLength = parents.Length - solutions.Length;
293
294      for (int i = 0; i < offspringLength; i++) {
295        if (parents[i + solutions.Length].selected) {
296          updateAsOffspring(parents[i + solutions.Length]);
297
298          //TODO this may change if more offspring per parent is allowed
299          offspringSucess[i] += CMAHansenIndividual.success;
300        }
301      }
302      for (int i = 0; i < solutions.Length; i++) {
303        if (parents[i].selected) {
304          updateAsParent(parents[i], offspringSucess[i]);
305        }
306      }
307
308      solutions = new CMAHansenIndividual[solutions.Length];
309      int j = 0;
310      foreach (CMAHansenIndividual ind in parents) {
311        if (ind.selected) {
312          solutions[j++] = ind;
313        }
314      }
315
316    }
317
318    private void updateAsParent(CMAHansenIndividual c, int v) {
319      c.successProbability = (1 - stepSizeLearningRate) * c.successProbability + stepSizeLearningRate * (v == CMAHansenIndividual.success ? 1 : 0);
320      c.sigma *= Math.Exp(1 / stepSizeDampeningFactor * (c.successProbability - targetSuccessProbability) / (1 - targetSuccessProbability));
321      if (v != CMAHansenIndividual.failure) return;
322      if (c.successProbability < successThreshold) {
323        double stepNormSqr = c.getSetpNormSqr();
324        double rate = covarianceMatrixUnlearningRate;
325        if (stepNormSqr > 1 && 1 < covarianceMatrixUnlearningRate * (2 * stepNormSqr - 1)) {
326          rate = 1 / (2 * stepNormSqr - 1);
327        }
328        rankOneUpdate(c, 1 + rate, -rate, c.lastStep);
329
330      } else {
331        roundUpdate(c);
332      }
333
334    }
335
336    private void updateAsOffspring(CMAHansenIndividual c) {
337      c.successProbability = (1 - stepSizeLearningRate) * c.successProbability + stepSizeLearningRate;
338      c.sigma *= Math.Exp(1 / stepSizeDampeningFactor * (c.successProbability - targetSuccessProbability) / (1 - targetSuccessProbability));
339      double evolutionpathUpdateWeight = evolutionPathLearningRate * (2.0 - evolutionPathLearningRate);
340      if (c.successProbability < successThreshold) {
341        c.updateEvolutionPath(1 - evolutionPathLearningRate, evolutionpathUpdateWeight);
342        rankOneUpdate(c, 1 - covarianceMatrixLearningRate, covarianceMatrixLearningRate, c.evolutionPath);
343      } else {
344        roundUpdate(c);
345      }
346    }
347
348    private void rankOneUpdate(CMAHansenIndividual c, double v1, double v2, RealVector lastStep) {
349      c.choleskyUpdate(lastStep, v1, v2);
350    }
351
352    private void roundUpdate(CMAHansenIndividual c) {
353      double evolutionPathUpdateWeight = evolutionPathLearningRate * (2.0 - evolutionPathLearningRate);
354      c.updateEvolutionPath(1 - evolutionPathLearningRate, 0);
355      rankOneUpdate(c, 1 - covarianceMatrixLearningRate + evolutionPathUpdateWeight,
356        covarianceMatrixLearningRate, c.evolutionPath);
357    }
358    #endregion
359
360    #region selection
361
362    private T[] merge<T>(T[] parents, T[] offspring) {
363      T[] merged = new T[parents.Length + offspring.Length];
364      for (int i = 0; i < parents.Length; i++) {
365        merged[i] = parents[i];
366      }
367      for (int i = 0; i < offspring.Length; i++) {
368        merged[i + parents.Length] = offspring[i];
369      }
370      return merged;
371    }
372
373    private void selection(CMAHansenIndividual[] parents, int length) {
374      //perform a nondominated sort to assign the rank to every element
375      var fronts = NonDominatedSort(parents);
376
377      //deselect the highest rank fronts until we would end up with less or equal mu elements
378      int rank = fronts.Count - 1;
379      int popSize = parents.Length;
380      while (popSize - fronts[rank].Count >= length) {
381        var front = fronts[rank];
382        foreach (var i in front) i.selected = false;
383        popSize -= front.Count;
384        rank--;
385      }
386
387      //now use the indicator to deselect the worst approximating elements of the last selected front
388      var front_ = fronts[rank];
389      for (; popSize > length; popSize--) {
390        int lc = indicator.leastContributer<CMAHansenIndividual>(front_.ToArray(), x => x.penalizedFitness);   //TODO: This is a battel in its own right to be fought another day
391        front_[lc].selected = false;
392        front_.Swap(lc, front_.Count - 1);
393        fronts.RemoveAt(front_.Count - 1);
394      }
395    }
396    #endregion
397
398    #region penalize Box-Constraints
399    private void penalizeEvaluate(IEnumerable<CMAHansenIndividual> offspring) {
400      foreach (CMAHansenIndividual child in offspring) {
401        penalizeEvaluate(child);
402      }
403    }
404
405    private void penalizeEvaluate(CMAHansenIndividual offspring) {
406      if (isFeasable(offspring.x)) {
407        offspring.fitness = Problem.Evaluate(offspring.x, random);
408        offspring.penalizedFitness = offspring.fitness;
409      } else {
410        RealVector t = closestFeasible(offspring.x);
411        offspring.fitness = Problem.Evaluate(t, random);
412        offspring.penalizedFitness = penalize(offspring.x, t, offspring.fitness);
413      }
414    }
415
416    private double[] penalize(RealVector x, RealVector t, double[] fitness) {
417      double[] d = new double[fitness.Length];
418      double penality = penalize(x, t);
419      for (int i = 0; i < fitness.Length; i++) {
420        d[i] = fitness[i] + penality;
421      }
422      return d;
423    }
424
425    private double penalize(RealVector x, RealVector t) {
426      double sum = 0;
427      for (int i = 0; i < x.Length; i++) {
428        double d = x[i] - t[i];
429        sum += d * d;
430      }
431      return sum;
432    }
433
434    private RealVector closestFeasible(RealVector x) {
435      DoubleMatrix bounds = Problem.Bounds;
436      RealVector r = new RealVector(x.Length);
437      for (int i = 0; i < x.Length; i++) {
438        r[i] = Math.Min(Math.Max(bounds[i, 0], x[i]), bounds[i, 1]);
439      }
440      return r;
441    }
442
443    private bool isFeasable(RealVector offspring) {
444      DoubleMatrix bounds = Problem.Bounds;
445      for (int i = 0; i < offspring.Length; i++) {
446        if (bounds[i, 0] > offspring[i] || offspring[i] > bounds[i, 1]) return false;
447      }
448      return true;
449    }
450
451    #endregion
452
453    #region mutation
454    private CMAHansenIndividual[] generateOffspring() {
455      CMAHansenIndividual[] offspring = new CMAHansenIndividual[PopulationSize];  //TODO this changes if 1,1-ES is replaced with 1,n-ES
456      for (int i = 0; i < offspring.Length; i++) {
457        offspring[i] = new CMAHansenIndividual(solutions[i]);
458        offspring[i].mutate(gauss);
459      }
460      return offspring;
461    }
462    #endregion
463
464    #region initialization
465    private CMAHansenIndividual initializeIndividual(RealVector x) {
466      var zeros = new RealVector(x.Length);
467      var identity = new double[x.Length, x.Length];
468      for (int i = 0; i < x.Length; i++) {
469        identity[i, i] = 1;
470      }
471      return new CMAHansenIndividual(x, targetSuccessProbability, InitialSigma.Value, zeros, identity);
472    }
473
474    private void initSolutions() {
475      for (int i = 0; i < PopulationSize; i++) {
476        RealVector x = null; //TODO get those with magic
477        solutions[i] = initializeIndividual(x);
478      }
479      penalizeEvaluate(solutions);
480    }
481
482    private void initStrategy() {
483      int lambda = 1;
484      double n = Problem.ProblemSize;
485      indicator = new CrowdingIndicator();
486      gauss = new NormalDistributedRandom(random, 0, 1);
487      targetSuccessProbability = 1.0 / (5.0 + Math.Sqrt(lambda) / 2.0);
488      stepSizeDampeningFactor = 1.0 + n / (2.0 * lambda);
489      stepSizeLearningRate = targetSuccessProbability * lambda / (2.0 + targetSuccessProbability * lambda);
490      evolutionPathLearningRate = 2.0 / (n + 2.0);
491      covarianceMatrixLearningRate = 2.0 / (n * n + 6.0);
492      covarianceMatrixUnlearningRate = 0.4 / (Math.Pow(n, 1.6) + 1);
493      successThreshold = 0.44;
494
495    }
496
497    #endregion
498
499    #region analyze
500    private void analyzeSolutions() {
501      //TODO give HyperVolume stuff
502      //Problem.Analyze();   
503
504    }
505
506    #endregion
507
508
509    //MU = populationSize
510    #region mainloop
511    protected override void Run(CancellationToken cancellationToken) {
512      // Set up the algorithm
513      if (SetSeedRandomly) Seed = new System.Random().Next();
514      random.Reset(Seed);
515
516
517      // Set up the results display
518      Results.Add(new Result("Iterations", new IntValue(0)));
519      Results.Add(new Result("Evaluations", new IntValue(0)));
520      var table = new DataTable("Hypervolumes");
521      table.Rows.Add(new DataRow("Best Hypervolumes"));
522      var iterationRows = new DataRow("Iteration Hypervolumes");
523      iterationRows.VisualProperties.LineStyle = DataRowVisualProperties.DataRowLineStyle.Dot;
524      table.Rows.Add(iterationRows);
525      Results.Add(new Result("Hypervolumes", table));
526
527
528      initStrategy();
529      initSolutions();
530
531
532
533      // Loop until iteration limit reached or canceled.
534      for (ResultsIterations = 0; ResultsIterations < MaximumGenerations; ResultsIterations++) {
535
536        try {
537          iterate();
538          cancellationToken.ThrowIfCancellationRequested();
539        }
540        finally {
541        }
542      }
543    }
544
545    protected override void OnExecutionTimeChanged() {
546      base.OnExecutionTimeChanged();
547      if (CancellationTokenSource == null) return;
548      if (MaximumRuntime == -1) return;
549      if (ExecutionTime.TotalSeconds > MaximumRuntime) CancellationTokenSource.Cancel();
550    }
551
552    private void iterate() {
553      CMAHansenIndividual[] offspring = generateOffspring();
554      penalizeEvaluate(offspring);
555      selection(merge(solutions, offspring), solutions.Length);
556      updatePopulation(offspring);
557
558    }
559    #endregion
560
561    #region bernhard properties
562    private NormalDistributedRandom gauss;
563    private CMAHansenIndividual[] solutions;
564    private const double penalizeFactor = 1e-6;
565    private IIndicator indicator;
566
567    private double stepSizeLearningRate; //=cp learning rate in [0,1]
568    private double stepSizeDampeningFactor; //d
569    private double targetSuccessProbability;// p^target_succ
570    private double evolutionPathLearningRate;//cc
571    private double covarianceMatrixLearningRate;//ccov
572    private double covarianceMatrixUnlearningRate;   //from shark
573    private double successThreshold; //ptresh
574    #endregion
575
576    private class CMAHansenIndividual {
577      public static readonly int success = 1;
578      public static readonly int noSuccess = 2;
579      public static readonly int failure = 3;
580
581
582      //Chromosome
583      public RealVector x;
584      public double successProbability;
585      public double sigma;//stepsize
586      public RealVector evolutionPath; // pc
587      public RealVector lastStep;
588      public RealVector lastZ;
589      private double[,] lowerCholesky;
590
591
592      //Phenotype
593      public double[] fitness;
594      public double[] penalizedFitness;
595      public bool selected = true;
596
597      internal double rank;
598
599
600
601      /// <summary>
602      ///
603      /// </summary>
604      /// <param name="x">has to be 0-vector with correct lenght</param>
605      /// <param name="p_succ">has to be ptargetsucc</param>
606      /// <param name="sigma">initialSigma</param>
607      /// <param name="pc">has to be 0-vector with correct lenght</param>
608      /// <param name="C">has to be a symmetric positive definit Covariance matrix</param>
609      public CMAHansenIndividual(RealVector x, double p_succ, double sigma, RealVector pc, double[,] C) {
610        this.x = x;
611        this.successProbability = p_succ;
612        this.sigma = sigma;
613        this.evolutionPath = pc;
614        choleskyDecomposition(C);
615      }
616
617      private void choleskyDecomposition(double[,] C) {
618        if (C.GetLength(0) != C.GetLength(1)) throw new ArgumentException("Covariancematrix is not quadratic");
619        int n = C.GetLength(0);
620        lowerCholesky = new double[n, n];
621        double[,] A = lowerCholesky;
622        for (int i = 0; i < n; i++) {
623          for (int j = 0; j <= i; j++) {
624            A[i, j] = C[i, j];   //simulate inplace transform
625            double sum = A[i, j];
626            for (int k = 0; k < j; k++) {
627              sum = sum - A[i, k] * A[j, k];
628              if (i > j) { A[i, j] = sum / A[j, j]; } else if (sum > 0) {
629                A[i, i] = Math.Sqrt(sum);
630              } else {
631                throw new ArgumentException("Covariancematrix is not symetric positiv definit");
632              }
633            }
634          }
635
636        }
637      }
638
639      public CMAHansenIndividual(CMAHansenIndividual other) {
640
641
642        this.successProbability = other.successProbability;
643        this.sigma = other.sigma;
644
645        // no no no make DEEP copies
646        this.x = (RealVector)other.x.Clone();    //This may be ommited
647        this.evolutionPath = (RealVector)other.evolutionPath.Clone();
648        this.lastStep = (RealVector)lastStep.Clone();  //This may be ommited
649        this.lastZ = (RealVector)lastZ.Clone();  //This may be ommited
650
651
652        this.lowerCholesky = (double[,])other.lowerCholesky.Clone();
653      }
654
655      public void updateEvolutionPath(double learningRate, double updateWeight) {
656        updateWeight = Math.Sqrt(updateWeight);
657        for (int i = 0; i < evolutionPath.Length; i++) {
658          evolutionPath[i] *= learningRate;
659          evolutionPath[i] += updateWeight * lastStep[i];
660        }
661      }
662
663      public double getSetpNormSqr() {
664        double sum = 0;
665        foreach (double d in lastZ) {
666          sum += d * d;
667        }
668        return sum;
669      }
670
671      public void choleskyUpdate(RealVector v, double alpha, double beta) {
672        int n = v.Length;
673        double[] temp = new double[n];
674        for (int i = 0; i < n; i++) temp[i] = v[i];
675        double betaPrime = 1;
676        double a = Math.Sqrt(alpha);
677        for (int j = 0; j < n; j++) {
678          double Ljj = a * lowerCholesky[j, j];
679          double dj = Ljj * Ljj;
680          double wj = temp[j];
681          double swj2 = beta * wj * wj;
682          double gamma = dj * betaPrime + swj2;
683          double x = dj + swj2 / betaPrime;
684          if (x < 0.0) throw new ArgumentException("Update makes Covariancematrix indefinite");
685          double nLjj = Math.Sqrt(x);
686          lowerCholesky[j, j] = nLjj;
687          betaPrime += swj2 / dj;
688          if (j + 1 < n) {
689            for (int i = j + 1; i < n; i++) {
690              lowerCholesky[i, j] *= a;
691            }
692            for (int i = j + 1; i < n; i++) {
693              temp[i] = wj / Ljj * lowerCholesky[i, j];
694            }
695            if (gamma == 0) continue;
696            for (int i = j + 1; i < n; i++) {
697              lowerCholesky[i, j] *= nLjj / Ljj;
698            }
699            for (int i = j + 1; i < n; i++) {
700              lowerCholesky[i, j] += (nLjj * beta * wj / gamma) * temp[i];
701            }
702          }
703
704        }
705
706      }
707
708      public void mutate(NormalDistributedRandom gauss) {
709
710        //sampling a random z from N(0,I) where I is the Identity matrix;
711        int n = lastZ.Length;
712        for (int i = 0; i < n; i++) {
713          lastZ[i] = gauss.NextDouble();
714        }
715        //Matrixmultiplication: lastStep = lowerCholesky * lastZ;
716        for (int i = 0; i < n; i++) {
717          double sum = 0;
718          for (int j = 0; j <= i; j++) {
719            sum += lowerCholesky[i, j] * lastZ[j];
720          }
721          lastStep[i] = sum;
722        }
723
724        //add the step to x weighted by stepsize;
725        for (int i = 0; i < x.Length; i++) {
726          x[i] += sigma * lastStep[i];
727        }
728
729      }
730
731    }
732
733    //blatantly stolen form HeuristicLab.Optimization.Operators.FastNonDominatedSort
734    #region FastNonDominatedSort   
735    private enum DominationResult { Dominates, IsDominated, IsNonDominated };
736
737    private List<List<CMAHansenIndividual>> NonDominatedSort(CMAHansenIndividual[] individuals) {
738      bool dominateOnEqualQualities = false;
739      bool[] maximization = Problem.Maximization;
740      if (individuals == null) throw new InvalidOperationException(Name + ": No qualities found.");
741      int populationSize = individuals.Length;
742
743      List<List<CMAHansenIndividual>> fronts = new List<List<CMAHansenIndividual>>();
744      Dictionary<CMAHansenIndividual, List<int>> dominatedScopes = new Dictionary<CMAHansenIndividual, List<int>>();
745      int[] dominationCounter = new int[populationSize];
746      //ItemArray<IntValue> rank = new ItemArray<IntValue>(populationSize);
747
748      for (int pI = 0; pI < populationSize - 1; pI++) {
749        CMAHansenIndividual p = individuals[pI];
750        List<int> dominatedScopesByp;
751        if (!dominatedScopes.TryGetValue(p, out dominatedScopesByp))
752          dominatedScopes[p] = dominatedScopesByp = new List<int>();
753        for (int qI = pI + 1; qI < populationSize; qI++) {
754          DominationResult test = Dominates(individuals[pI], individuals[qI], maximization, dominateOnEqualQualities);
755          if (test == DominationResult.Dominates) {
756            dominatedScopesByp.Add(qI);
757            dominationCounter[qI] += 1;
758          } else if (test == DominationResult.IsDominated) {
759            dominationCounter[pI] += 1;
760            if (!dominatedScopes.ContainsKey(individuals[qI]))
761              dominatedScopes.Add(individuals[qI], new List<int>());
762            dominatedScopes[individuals[qI]].Add(pI);
763          }
764          if (pI == populationSize - 2
765            && qI == populationSize - 1
766            && dominationCounter[qI] == 0) {
767            //rank[qI] = new IntValue(0);
768            AddToFront(individuals[qI], fronts, 0);
769          }
770        }
771        if (dominationCounter[pI] == 0) {
772          //rank[pI] = new IntValue(0);
773          AddToFront(p, fronts, 0);
774        }
775      }
776      int i = 0;
777      while (i < fronts.Count && fronts[i].Count > 0) {
778        List<CMAHansenIndividual> nextFront = new List<CMAHansenIndividual>();
779        foreach (CMAHansenIndividual p in fronts[i]) {
780          List<int> dominatedScopesByp;
781          if (dominatedScopes.TryGetValue(p, out dominatedScopesByp)) {
782            for (int k = 0; k < dominatedScopesByp.Count; k++) {
783              int dominatedScope = dominatedScopesByp[k];
784              dominationCounter[dominatedScope] -= 1;
785              if (dominationCounter[dominatedScope] == 0) {
786                //rank[dominatedScope] = new IntValue(i + 1);
787                nextFront.Add(individuals[dominatedScope]);
788              }
789            }
790          }
791        }
792        i += 1;
793        fronts.Add(nextFront);
794      }
795
796      //RankParameter.ActualValue = rank;
797
798      //scope.SubScopes.Clear();
799
800      CMAHansenIndividual[] result = new CMAHansenIndividual[individuals.Length];
801      int j = 0;
802
803      for (i = 0; i < fronts.Count; i++) {
804        foreach (var p in fronts[i]) {
805          p.rank = i;
806        }
807      }
808      return fronts;
809    }
810
811
812    private static void AddToFront(CMAHansenIndividual p, List<List<CMAHansenIndividual>> fronts, int i) {
813      if (i == fronts.Count) fronts.Add(new List<CMAHansenIndividual>());
814      fronts[i].Add(p);
815    }
816
817    private static DominationResult Dominates(CMAHansenIndividual left, CMAHansenIndividual right, bool[] maximizations, bool dominateOnEqualQualities) {
818      return Dominates(left.penalizedFitness, right.penalizedFitness, maximizations, dominateOnEqualQualities);
819    }
820
821    private static DominationResult Dominates(double[] left, double[] right, bool[] maximizations, bool dominateOnEqualQualities) {
822      //mkommend Caution: do not use LINQ.SequenceEqual for comparing the two quality arrays (left and right) due to performance reasons
823      if (dominateOnEqualQualities) {
824        var equal = true;
825        for (int i = 0; i < left.Length; i++) {
826          if (left[i] != right[i]) {
827            equal = false;
828            break;
829          }
830        }
831        if (equal) return DominationResult.Dominates;
832      }
833
834      bool leftIsBetter = false, rightIsBetter = false;
835      for (int i = 0; i < left.Length; i++) {
836        if (IsDominated(left[i], right[i], maximizations[i])) rightIsBetter = true;
837        else if (IsDominated(right[i], left[i], maximizations[i])) leftIsBetter = true;
838        if (leftIsBetter && rightIsBetter) break;
839      }
840
841      if (leftIsBetter && !rightIsBetter) return DominationResult.Dominates;
842      if (!leftIsBetter && rightIsBetter) return DominationResult.IsDominated;
843      return DominationResult.IsNonDominated;
844    }
845
846    private static bool IsDominated(double left, double right, bool maximization) {
847      return maximization && left < right
848        || !maximization && left > right;
849    }
850
851    #endregion
852  }
853}
Note: See TracBrowser for help on using the repository browser.