Free cookie consent management tool by TermsFeed Policy Generator

source: branches/MOCMAEvolutionStrategy/HeuristicLab.Algorithms.MOCMAEvolutionStrategy/3.3/MOCMASEvolutionStrategy.cs @ 14404

Last change on this file since 14404 was 14404, checked in by bwerth, 7 years ago

#2592 several fixes and cleanups to adapt a more HeuristicLab-Code-Style + renaming of folders and Plugin

File size: 28.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.Linq;
26using System.Threading;
27using HeuristicLab.Algorithms.CMAEvolutionStrategy;
28using HeuristicLab.Analysis;
29using HeuristicLab.Common;
30using HeuristicLab.Core;
31using HeuristicLab.Data;
32using HeuristicLab.Encodings.RealVectorEncoding;
33using HeuristicLab.Optimization;
34using HeuristicLab.Parameters;
35using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
36using HeuristicLab.Problems.TestFunctions.MultiObjective;
37using HeuristicLab.Random;
38
39namespace HeuristicLab.Algorithms.MOCMAEvolutionStrategy {
40  [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")]
41  [Creatable(CreatableAttribute.Categories.PopulationBasedAlgorithms, Priority = 210)]
42  [StorableClass]
43  public class MOCMASEvolutionStrategy : BasicAlgorithm {
44    public override Type ProblemType
45    {
46      get { return typeof(MultiObjectiveTestFunctionProblem); }
47    }
48    public new MultiObjectiveTestFunctionProblem Problem
49    {
50      get { return (MultiObjectiveTestFunctionProblem)base.Problem; }
51      set { base.Problem = value; }
52    }
53    #region internal variables
54    private readonly IRandom random = new MersenneTwister();
55    private NormalDistributedRandom gauss;
56    private MOCMAESIndividual[] solutions;
57    private MOCMAESParameters internals;
58    #endregion
59
60    #region ParameterNames
61    private const string MaximumRuntimeName = "Maximum Runtime";
62    private const string SeedName = "Seed";
63    private const string SetSeedRandomlyName = "SetSeedRandomly";
64    private const string PopulationSizeName = "PopulationSize";
65    private const string MaximumGenerationsName = "MaximumGenerations";
66    private const string MaximumEvaluatedSolutionsName = "MaximumEvaluatedSolutions";
67    private const string InitialSigmaName = "InitialSigma";
68    private const string IndicatorName = "Indicator";
69
70    private const string EvaluationsResultName = "Evaluations";
71    private const string IterationsResultName = "Generations";
72    private const string TimetableResultName = "Timetable";
73    private const string HypervolumeResultName = "Hypervolume";
74    private const string GenerationalDistanceResultName = "Generational Distance";
75    private const string InvertedGenerationalDistanceResultName = "Inverted Generational Distance";
76    private const string CrowdingResultName = "Crowding";
77    private const string SpacingResultName = "Spacing";
78    private const string SolutionsResultName = "Pareto Front";
79    private const string BestHypervolumeResultName = "Best Hypervolume";
80    private const string BestKnownHypervolumeResultName = "Best known hypervolume";
81    private const string DifferenceToBestKnownHypervolumeResultName = "Absolute Distance to BestKnownHypervolume";
82    private const string ScatterPlotResultName = "ScatterPlot";
83
84    #endregion
85
86    #region ParameterProperties
87    public IFixedValueParameter<IntValue> MaximumRuntimeParameter
88    {
89      get { return (IFixedValueParameter<IntValue>)Parameters[MaximumRuntimeName]; }
90    }
91    public IFixedValueParameter<IntValue> SeedParameter
92    {
93      get { return (IFixedValueParameter<IntValue>)Parameters[SeedName]; }
94    }
95    public FixedValueParameter<BoolValue> SetSeedRandomlyParameter
96    {
97      get { return (FixedValueParameter<BoolValue>)Parameters[SetSeedRandomlyName]; }
98    }
99    private IFixedValueParameter<IntValue> PopulationSizeParameter
100    {
101      get { return (IFixedValueParameter<IntValue>)Parameters[PopulationSizeName]; }
102    }
103    private IFixedValueParameter<IntValue> MaximumGenerationsParameter
104    {
105      get { return (IFixedValueParameter<IntValue>)Parameters[MaximumGenerationsName]; }
106    }
107    private IFixedValueParameter<IntValue> MaximumEvaluatedSolutionsParameter
108    {
109      get { return (IFixedValueParameter<IntValue>)Parameters[MaximumEvaluatedSolutionsName]; }
110    }
111    private IFixedValueParameter<DoubleValue> InitialSigmaParameter
112    {
113      get { return (IFixedValueParameter<DoubleValue>)Parameters[InitialSigmaName]; }
114    }
115    private IConstrainedValueParameter<IIndicator> IndicatorParameter
116    {
117      get { return (IConstrainedValueParameter<IIndicator>)Parameters[IndicatorName]; }
118    }
119    #endregion
120
121    #region Properties
122    public int MaximumRuntime
123    {
124      get { return MaximumRuntimeParameter.Value.Value; }
125      set { MaximumRuntimeParameter.Value.Value = value; }
126    }
127    public int Seed
128    {
129      get { return SeedParameter.Value.Value; }
130      set { SeedParameter.Value.Value = value; }
131    }
132    public bool SetSeedRandomly
133    {
134      get { return SetSeedRandomlyParameter.Value.Value; }
135      set { SetSeedRandomlyParameter.Value.Value = value; }
136    }
137    public int PopulationSize
138    {
139      get { return PopulationSizeParameter.Value.Value; }
140      set { PopulationSizeParameter.Value.Value = value; }
141    }
142    public int MaximumGenerations
143    {
144      get { return MaximumGenerationsParameter.Value.Value; }
145      set { MaximumGenerationsParameter.Value.Value = value; }
146    }
147    public int MaximumEvaluatedSolutions
148    {
149      get { return MaximumEvaluatedSolutionsParameter.Value.Value; }
150      set { MaximumEvaluatedSolutionsParameter.Value.Value = value; }
151    }
152    public double InitialSigma
153    {
154      get { return InitialSigmaParameter.Value.Value; }
155      set { InitialSigmaParameter.Value.Value = value; }
156    }
157    public IIndicator Indicator
158    {
159      get { return IndicatorParameter.Value; }
160      set { IndicatorParameter.Value = value; }
161    }
162
163
164    #endregion
165
166    #region ResultsProperties
167    private int ResultsEvaluations
168    {
169      get { return ((IntValue)Results[EvaluationsResultName].Value).Value; }
170      set { ((IntValue)Results[EvaluationsResultName].Value).Value = value; }
171    }
172    private int ResultsIterations
173    {
174      get { return ((IntValue)Results[IterationsResultName].Value).Value; }
175      set { ((IntValue)Results[IterationsResultName].Value).Value = value; }
176    }
177    #region Datatable
178    private DataTable ResultsQualities
179    {
180      get { return (DataTable)Results[TimetableResultName].Value; }
181    }
182    private DataRow ResultsBestHypervolumeDataLine
183    {
184      get { return ResultsQualities.Rows[BestHypervolumeResultName]; }
185    }
186    private DataRow ResultsHypervolumeDataLine
187    {
188      get { return ResultsQualities.Rows[HypervolumeResultName]; }
189    }
190    private DataRow ResultsGenerationalDistanceDataLine
191    {
192      get { return ResultsQualities.Rows[GenerationalDistanceResultName]; }
193    }
194    private DataRow ResultsInvertedGenerationalDistanceDataLine
195    {
196      get { return ResultsQualities.Rows[InvertedGenerationalDistanceResultName]; }
197    }
198    private DataRow ResultsCrowdingDataLine
199    {
200      get { return ResultsQualities.Rows[CrowdingResultName]; }
201    }
202    private DataRow ResultsSpacingDataLine
203    {
204      get { return ResultsQualities.Rows[SpacingResultName]; }
205    }
206    private DataRow ResultsHypervolumeDifferenceDataLine
207    {
208      get { return ResultsQualities.Rows[DifferenceToBestKnownHypervolumeResultName]; }
209    }
210    #endregion
211    //QualityIndicators
212    private double ResultsHypervolume
213    {
214      get { return ((DoubleValue)Results[HypervolumeResultName].Value).Value; }
215      set { ((DoubleValue)Results[HypervolumeResultName].Value).Value = value; }
216    }
217    private double ResultsGenerationalDistance
218    {
219      get { return ((DoubleValue)Results[GenerationalDistanceResultName].Value).Value; }
220      set { ((DoubleValue)Results[GenerationalDistanceResultName].Value).Value = value; }
221    }
222    private double ResultsInvertedGenerationalDistance
223    {
224      get { return ((DoubleValue)Results[InvertedGenerationalDistanceResultName].Value).Value; }
225      set { ((DoubleValue)Results[InvertedGenerationalDistanceResultName].Value).Value = value; }
226    }
227    private double ResultsCrowding
228    {
229      get { return ((DoubleValue)Results[CrowdingResultName].Value).Value; }
230      set { ((DoubleValue)Results[CrowdingResultName].Value).Value = value; }
231    }
232    private double ResultsSpacing
233    {
234      get { return ((DoubleValue)Results[SpacingResultName].Value).Value; }
235      set { ((DoubleValue)Results[SpacingResultName].Value).Value = value; }
236    }
237    private double ResultsBestHypervolume
238    {
239      get { return ((DoubleValue)Results[BestHypervolumeResultName].Value).Value; }
240      set { ((DoubleValue)Results[BestHypervolumeResultName].Value).Value = value; }
241    }
242    private double ResultsBestKnownHypervolume
243    {
244      get { return ((DoubleValue)Results[BestKnownHypervolumeResultName].Value).Value; }
245      set { ((DoubleValue)Results[BestKnownHypervolumeResultName].Value).Value = value; }
246    }
247    private double ResultsDifferenceBestKnownHypervolume
248    {
249      get { return ((DoubleValue)Results[DifferenceToBestKnownHypervolumeResultName].Value).Value; }
250      set { ((DoubleValue)Results[DifferenceToBestKnownHypervolumeResultName].Value).Value = value; }
251
252    }
253    //Solutions
254    private DoubleMatrix ResultsSolutions
255    {
256      get { return ((DoubleMatrix)Results[SolutionsResultName].Value); }
257      set { Results[SolutionsResultName].Value = value; }
258    }
259    private ScatterPlotContent ResultsScatterPlot
260    {
261      get { return ((ScatterPlotContent)Results[ScatterPlotResultName].Value); }
262      set { Results[ScatterPlotResultName].Value = value; }
263    }
264    #endregion
265
266    #region Constructors
267    public MOCMASEvolutionStrategy() {
268      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)));
269      Parameters.Add(new FixedValueParameter<IntValue>(SeedName, "The random seed used to initialize the new pseudo random number generator.", new IntValue(0)));
270      Parameters.Add(new FixedValueParameter<BoolValue>(SetSeedRandomlyName, "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true)));
271      Parameters.Add(new FixedValueParameter<IntValue>(PopulationSizeName, "λ (lambda) - the size of the offspring population.", new IntValue(20)));
272      Parameters.Add(new FixedValueParameter<DoubleValue>(InitialSigmaName, "The initial sigma is a single value > 0.", new DoubleValue(0.5)));
273      Parameters.Add(new FixedValueParameter<IntValue>(MaximumGenerationsName, "The maximum number of generations which should be processed.", new IntValue(1000)));
274      Parameters.Add(new FixedValueParameter<IntValue>(MaximumEvaluatedSolutionsName, "The maximum number of evaluated solutions that should be computed.", new IntValue(int.MaxValue)));
275      var set = new ItemSet<IIndicator> { new HypervolumeIndicator(), new CrowdingIndicator() };
276      Parameters.Add(new ConstrainedValueParameter<IIndicator>(IndicatorName, "The selection mechanism on non-dominated solutions", set, set.First()));
277    }
278
279    [StorableConstructor]
280    protected MOCMASEvolutionStrategy(bool deserializing) : base(deserializing) { }
281    protected MOCMASEvolutionStrategy(MOCMASEvolutionStrategy original, Cloner cloner) : base(original, cloner) { }
282    public override IDeepCloneable Clone(Cloner cloner) { return new MOCMASEvolutionStrategy(this, cloner); }
283    #endregion
284
285    #region Mainloop
286    protected override void Run(CancellationToken cancellationToken) {
287      // Set up the algorithm
288      if (SetSeedRandomly) Seed = new System.Random().Next();
289      random.Reset(Seed);
290      gauss = new NormalDistributedRandom(random, 0, 1);
291
292      InitResults();
293      InitStrategy();
294      InitSolutions();
295      AnalyzeSolutions();
296
297      // Loop until iteration limit reached or canceled.
298      for (ResultsIterations = 1; ResultsIterations < MaximumGenerations; ResultsIterations++) {
299        try {
300          Iterate();
301          cancellationToken.ThrowIfCancellationRequested();
302        }
303        finally {
304          AnalyzeSolutions();
305        }
306      }
307    }
308    private void Iterate() {
309      var offspring = MutateOffspring();
310      PenalizeEvaluate(offspring);
311      var parents = solutions.Concat(offspring).ToArray();
312      SelectParents(parents, solutions.Length);
313      UpdatePopulation(parents);
314    }
315    protected override void OnExecutionTimeChanged() {
316      base.OnExecutionTimeChanged();
317      if (CancellationTokenSource == null) return;
318      if (MaximumRuntime == -1) return;
319      if (ExecutionTime.TotalSeconds > MaximumRuntime) CancellationTokenSource.Cancel();
320    }
321    #endregion
322
323    #region Initialization
324    private MOCMAESIndividual InitializeIndividual(RealVector x) {
325      var zeros = new RealVector(x.Length);
326      var identity = new double[x.Length, x.Length];
327      for (var i = 0; i < x.Length; i++) identity[i, i] = 1;
328      return new MOCMAESIndividual(x, internals.TargetSuccessProbability, InitialSigma, zeros, identity, internals);
329    }
330    private void InitSolutions() {
331      solutions = new MOCMAESIndividual[PopulationSize];
332      for (var i = 0; i < PopulationSize; i++) {
333        var x = new RealVector(Problem.ProblemSize); // Uniform distibution in all dimensions assumed.
334                                                     // There is the UniformSolutionCreater associated with the Encoding, but it was considered not usable here
335        var bounds = Problem.Bounds;
336        for (var j = 0; j < Problem.ProblemSize; j++) {
337          var dim = j % bounds.Rows;
338          x[j] = random.NextDouble() * (bounds[dim, 1] - bounds[dim, 0]) + bounds[dim, 0];
339        }
340        solutions[i] = InitializeIndividual(x);
341      }
342      PenalizeEvaluate(solutions);
343    }
344    private void InitStrategy() {
345      const int lambda = 1;
346      double n = Problem.ProblemSize;
347
348      var targetSuccessProbability = 1.0 / (5.0 + Math.Sqrt(lambda) / 2.0);
349      var stepSizeDampeningFactor = 1.0 + n / (2.0 * lambda);
350      var stepSizeLearningRate = targetSuccessProbability * lambda / (2.0 + targetSuccessProbability * lambda);
351      var evolutionPathLearningRate = 2.0 / (n + 2.0);
352      var covarianceMatrixLearningRate = 2.0 / (n * n + 6.0);
353      var covarianceMatrixUnlearningRate = 0.4 / (Math.Pow(n, 1.6) + 1);
354      var successThreshold = 0.44;
355      internals = new MOCMAESParameters(stepSizeLearningRate, stepSizeDampeningFactor, targetSuccessProbability, evolutionPathLearningRate, covarianceMatrixLearningRate, covarianceMatrixUnlearningRate, successThreshold);
356
357    }
358    private void InitResults() {
359      AddResult(IterationsResultName, "The number of gererations evaluated", new IntValue(0));
360      AddResult(EvaluationsResultName, "The number of function evaltions performed", new IntValue(0));
361      AddResult(HypervolumeResultName, "The hypervolume of the current front considering the Referencepoint defined in the Problem", new DoubleValue(0.0));
362      AddResult(BestHypervolumeResultName, "The best hypervolume of the current run considering the Referencepoint defined in the Problem", new DoubleValue(0.0));
363      AddResult(BestKnownHypervolumeResultName, "The best knwon hypervolume considering the Referencepoint defined in the Problem", new DoubleValue(double.NaN));
364      AddResult(DifferenceToBestKnownHypervolumeResultName, "The difference between the current and the best known hypervolume", new DoubleValue(double.NaN));
365      AddResult(GenerationalDistanceResultName, "The generational distance to an optimal pareto front defined in the Problem", new DoubleValue(double.NaN));
366      AddResult(InvertedGenerationalDistanceResultName, "The inverted generational distance to an optimal pareto front defined in the Problem", new DoubleValue(double.NaN));
367      AddResult(CrowdingResultName, "The average crowding value for the current front (excluding infinities)", new DoubleValue(0.0));
368      AddResult(SpacingResultName, "The spacing for the current front (excluding infinities)", new DoubleValue(0.0));
369
370      var table = new DataTable("QualityIndicators");
371      table.Rows.Add(new DataRow(BestHypervolumeResultName));
372      table.Rows.Add(new DataRow(HypervolumeResultName));
373      table.Rows.Add(new DataRow(CrowdingResultName));
374      table.Rows.Add(new DataRow(GenerationalDistanceResultName));
375      table.Rows.Add(new DataRow(InvertedGenerationalDistanceResultName));
376      table.Rows.Add(new DataRow(DifferenceToBestKnownHypervolumeResultName));
377      table.Rows.Add(new DataRow(SpacingResultName));
378      AddResult(TimetableResultName, "Different quality meassures in a timeseries", table);
379      AddResult(SolutionsResultName, "The current front", new DoubleMatrix());
380      AddResult(ScatterPlotResultName, "A scatterplot displaying the evaluated solutions and (if available) the analytically optimal front", new ScatterPlotContent(null, null, null, 2));
381
382      if (Problem.BestKnownFront != null) {
383        ResultsBestKnownHypervolume = Hypervolume.Calculate(Utilities.ToArray(Problem.BestKnownFront), Problem.TestFunction.ReferencePoint(Problem.Objectives), Problem.Maximization);
384        ResultsDifferenceBestKnownHypervolume = ResultsBestKnownHypervolume;
385      }
386      ResultsScatterPlot = new ScatterPlotContent(null, null, Utilities.ToArray(Problem.BestKnownFront), Problem.Objectives);
387    }
388    #endregion
389
390    private MOCMAESIndividual[] MutateOffspring() {
391      var offspring = new MOCMAESIndividual[PopulationSize];
392      for (var i = 0; i < PopulationSize; i++) {
393        offspring[i] = new MOCMAESIndividual(solutions[i]);
394        offspring[i].Mutate(gauss);
395      }
396      return offspring;
397    }
398
399    #region Evaluation
400    private void PenalizeEvaluate(IEnumerable<MOCMAESIndividual> offspring) {
401      foreach (var child in offspring) {
402        if (IsFeasable(child.Mean)) {
403          child.Fitness = Evaluate(child.Mean);
404          child.PenalizedFitness = child.Fitness;
405        } else {
406          var t = ClosestFeasible(child.Mean);
407          child.Fitness = Evaluate(t);
408          child.PenalizedFitness = Penalize(child.Mean, t, child.Fitness);
409        }
410      }
411    }
412    private double[] Evaluate(RealVector x) {
413      var res = Problem.Evaluate(x);
414      ResultsEvaluations++;
415      return res;
416    }
417    private static double[] Penalize(RealVector x, RealVector t, IEnumerable<double> fitness) {
418      var penalty = x.Select((t1, i) => t1 - t[i]).Sum(d => d * d);
419      return fitness.Select(v => v + penalty).ToArray();
420    }
421    private RealVector ClosestFeasible(RealVector x) {
422      var bounds = Problem.Bounds;
423      var r = new RealVector(x.Length);
424      for (var i = 0; i < x.Length; i++) {
425        var dim = i % bounds.Rows;
426        r[i] = Math.Min(Math.Max(bounds[dim, 0], x[i]), bounds[dim, 1]);
427      }
428      return r;
429    }
430    private bool IsFeasable(RealVector offspring) {
431      var bounds = Problem.Bounds;
432      for (var i = 0; i < offspring.Length; i++) {
433        var dim = i % bounds.Rows;
434        if (bounds[dim, 0] > offspring[i] || offspring[i] > bounds[dim, 1]) return false;
435      }
436      return true;
437    }
438    #endregion
439
440    private void SelectParents(IReadOnlyList<MOCMAESIndividual> parents, int length) {
441      //perform a nondominated sort to assign the rank to every element
442      var fronts = NonDominatedSort(parents);
443
444      //deselect the highest rank fronts until we would end up with less or equal mu elements
445      var rank = fronts.Count - 1;
446      var popSize = parents.Count;
447      while (popSize - fronts[rank].Count >= length) {
448        var front = fronts[rank];
449        foreach (var i in front) i.Selected = false;
450        popSize -= front.Count;
451        rank--;
452      }
453
454      //now use the indicator to deselect the approximatingly worst elements of the last selected front
455      var front1 = fronts[rank];
456      for (; popSize > length; popSize--) {
457        var lc = Indicator.LeastContributer(front1.ToArray(), x => x.PenalizedFitness, Problem);
458        front1[lc].Selected = false;
459        front1.Swap(lc, front1.Count - 1);
460        front1.RemoveAt(front1.Count - 1);
461      }
462    }
463
464    private void UpdatePopulation(IReadOnlyList<MOCMAESIndividual> parents) {
465      var offspringSucess = new int[solutions.Length];
466      var offspringLength = parents.Count - solutions.Length;
467      for (var i = 0; i < offspringLength; i++) {
468        if (!parents[i + solutions.Length].Selected) continue;
469        parents[i + solutions.Length].UpdateAsOffspring();
470        offspringSucess[i] += MOCMAESIndividual.Success;
471      }
472      for (var i = 0; i < solutions.Length; i++) if (parents[i].Selected) parents[i].UpdateAsParent(offspringSucess[i]);
473      solutions = new MOCMAESIndividual[solutions.Length];
474      var j = 0;
475      foreach (var ind in parents) if (ind.Selected) solutions[j++] = ind;
476    }
477
478    #region Analysis
479    private void AnalyzeSolutions() {
480      ResultsScatterPlot = new ScatterPlotContent(solutions.Select(x => x.Fitness).ToArray(),
481          solutions.Select(x => x.Mean.ToArray()).ToArray(),
482          ResultsScatterPlot.ParetoFront,
483          ResultsScatterPlot.Objectives);
484      ResultsSolutions = ToMatrix(solutions.Select(x => x.Mean.ToArray()));
485      AnalyzeQualityIndicators();
486    }
487    private void AnalyzeQualityIndicators() {
488      var front = NonDominatedSelect.GetDominatingVectors(solutions.Select(x => x.Fitness), Problem.TestFunction.ReferencePoint(Problem.Objectives), Problem.Maximization, true).ToArray();
489      var bounds = Problem.Bounds.CloneAsMatrix();
490      ResultsCrowding = Crowding.Calculate(front, bounds);
491      ResultsSpacing = Spacing.Calculate(front);
492      ResultsGenerationalDistance = Problem.BestKnownFront != null ? GenerationalDistance.Calculate(front, Utilities.ToArray(Problem.BestKnownFront), 1) : double.NaN;
493
494      ResultsInvertedGenerationalDistance = Problem.BestKnownFront != null ? InvertedGenerationalDistance.Calculate(front, Utilities.ToArray(Problem.BestKnownFront), 1) : double.NaN;
495
496      ResultsHypervolume = Hypervolume.Calculate(front, Problem.TestFunction.ReferencePoint(Problem.Objectives), Problem.Maximization);
497      ResultsBestHypervolume = Math.Max(ResultsHypervolume, ResultsBestHypervolume);
498      ResultsDifferenceBestKnownHypervolume = ResultsBestKnownHypervolume - ResultsBestHypervolume;
499
500      //Datalines
501      ResultsBestHypervolumeDataLine.Values.Add(ResultsBestHypervolume);
502      ResultsHypervolumeDataLine.Values.Add(ResultsHypervolume);
503      ResultsCrowdingDataLine.Values.Add(ResultsCrowding);
504      ResultsGenerationalDistanceDataLine.Values.Add(ResultsGenerationalDistance);
505      ResultsInvertedGenerationalDistanceDataLine.Values.Add(ResultsInvertedGenerationalDistance);
506      ResultsSpacingDataLine.Values.Add(ResultsSpacing);
507      ResultsHypervolumeDifferenceDataLine.Values.Add(ResultsDifferenceBestKnownHypervolume);
508
509    }
510    #endregion
511
512
513
514    #region Helpers
515    public DoubleMatrix ToMatrix(IEnumerable<double[]> data) {
516      var d2 = data.ToArray();
517      var mat = new DoubleMatrix(d2.Length, d2[0].Length);
518      for (var i = 0; i < mat.Rows; i++) {
519        for (var j = 0; j < mat.Columns; j++) {
520          mat[i, j] = d2[i][j];
521        }
522      }
523      return mat;
524    }
525    private void AddResult<T>(string name1, string desc, T defaultValue) where T : class, IItem {
526      Results.Add(new Result(name1, desc, defaultValue));
527    }
528    //blatantly stolen form HeuristicLab.Optimization.Operators.FastNonDominatedSort
529    //however: Operators.FastNonDominatedSort does not return ranked fronts => rerank after sorting would not be sensible
530    #region FastNonDominatedSort   
531    private enum DominationResult { Dominates, IsDominated, IsNonDominated };
532    private List<List<MOCMAESIndividual>> NonDominatedSort(IReadOnlyList<MOCMAESIndividual> individuals) {
533      const bool dominateOnEqualQualities = false;
534      var maximization = Problem.Maximization;
535      if (individuals == null) throw new InvalidOperationException(Name + ": No qualities found.");
536      var populationSize = individuals.Count;
537
538      var fronts = new List<List<MOCMAESIndividual>>();
539      var dominatedScopes = new Dictionary<MOCMAESIndividual, List<int>>();
540      var dominationCounter = new int[populationSize];
541
542      for (var pI = 0; pI < populationSize - 1; pI++) {
543        var p = individuals[pI];
544        List<int> dominatedScopesByp;
545        if (!dominatedScopes.TryGetValue(p, out dominatedScopesByp))
546          dominatedScopes[p] = dominatedScopesByp = new List<int>();
547        for (var qI = pI + 1; qI < populationSize; qI++) {
548          var test = Dominates(individuals[pI], individuals[qI], maximization, dominateOnEqualQualities);
549          if (test == DominationResult.Dominates) {
550            dominatedScopesByp.Add(qI);
551            dominationCounter[qI] += 1;
552          } else if (test == DominationResult.IsDominated) {
553            dominationCounter[pI] += 1;
554            if (!dominatedScopes.ContainsKey(individuals[qI]))
555              dominatedScopes.Add(individuals[qI], new List<int>());
556            dominatedScopes[individuals[qI]].Add(pI);
557          }
558          if (pI == populationSize - 2
559            && qI == populationSize - 1
560            && dominationCounter[qI] == 0) {
561            AddToFront(individuals[qI], fronts, 0);
562          }
563        }
564        if (dominationCounter[pI] == 0) {
565          AddToFront(p, fronts, 0);
566        }
567      }
568      var i = 0;
569      while (i < fronts.Count && fronts[i].Count > 0) {
570        var nextFront = new List<MOCMAESIndividual>();
571        foreach (var p in fronts[i]) {
572          List<int> dominatedScopesByp;
573          if (!dominatedScopes.TryGetValue(p, out dominatedScopesByp)) continue;
574          foreach (var dominatedScope in dominatedScopesByp) {
575            dominationCounter[dominatedScope] -= 1;
576            if (dominationCounter[dominatedScope] != 0) continue;
577            nextFront.Add(individuals[dominatedScope]);
578          }
579        }
580        i += 1;
581        fronts.Add(nextFront);
582      }
583
584      for (i = 0; i < fronts.Count; i++) {
585        foreach (var p in fronts[i]) {
586          p.Rank = i;
587        }
588      }
589      return fronts;
590    }
591    private static void AddToFront(MOCMAESIndividual p, IList<List<MOCMAESIndividual>> fronts, int i) {
592      if (i == fronts.Count) fronts.Add(new List<MOCMAESIndividual>());
593      fronts[i].Add(p);
594    }
595    private static DominationResult Dominates(MOCMAESIndividual left, MOCMAESIndividual right, bool[] maximizations, bool dominateOnEqualQualities) {
596      return Dominates(left.PenalizedFitness, right.PenalizedFitness, maximizations, dominateOnEqualQualities);
597    }
598    private static DominationResult Dominates(IReadOnlyList<double> left, IReadOnlyList<double> right, IReadOnlyList<bool> maximizations, bool dominateOnEqualQualities) {
599      //mkommend Caution: do not use LINQ.SequenceEqual for comparing the two quality arrays (left and right) due to performance reasons
600      if (dominateOnEqualQualities) {
601        var equal = true;
602        for (var i = 0; i < left.Count; i++) {
603          if (left[i] != right[i]) {
604            equal = false;
605            break;
606          }
607        }
608        if (equal) return DominationResult.Dominates;
609      }
610
611      bool leftIsBetter = false, rightIsBetter = false;
612      for (var i = 0; i < left.Count; i++) {
613        if (IsDominated(left[i], right[i], maximizations[i])) rightIsBetter = true;
614        else if (IsDominated(right[i], left[i], maximizations[i])) leftIsBetter = true;
615        if (leftIsBetter && rightIsBetter) break;
616      }
617
618      if (leftIsBetter && !rightIsBetter) return DominationResult.Dominates;
619      if (!leftIsBetter && rightIsBetter) return DominationResult.IsDominated;
620      return DominationResult.IsNonDominated;
621    }
622    private static bool IsDominated(double left, double right, bool maximization) {
623      return maximization && left < right
624        || !maximization && left > right;
625    }
626    #endregion
627    #endregion
628  }
629}
Note: See TracBrowser for help on using the repository browser.