Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/GenerationalDistanceAnalyzer.cs @ 18242

Last change on this file since 18242 was 17225, checked in by mkommend, 5 years ago

#2521: Integrated changes of #2943 into problem refactoring branch.

File size: 4.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using HEAL.Attic;
26using HeuristicLab.Common;
27using HeuristicLab.Core;
28using HeuristicLab.Data;
29using HeuristicLab.Optimization;
30using HeuristicLab.Parameters;
31
32namespace HeuristicLab.Analysis {
33  [StorableType("f8ae6c1c-5f8f-45d6-b513-bb8041546808")]
34  [Item("GenerationalDistanceAnalyzer", "The generational distance between the current and the optimal front (if known)(see Multi-Objective Performance Metrics - Shodhganga for more information). The calculation of generational distance requires a known optimal pareto front")]
35  public class GenerationalDistanceAnalyzer : MultiObjectiveSuccessAnalyzer {
36    public override string ResultName {
37      get { return "Generational Distance"; }
38    }
39
40    public IFixedValueParameter<DoubleValue> DampeningParameter {
41      get { return (IFixedValueParameter<DoubleValue>)Parameters["Dampening"]; }
42    }
43
44    public double Dampening {
45      get { return DampeningParameter.Value.Value; }
46      set { DampeningParameter.Value.Value = value; }
47    }
48
49    public ILookupParameter<DoubleMatrix> OptimalParetoFrontParameter {
50      get { return (ILookupParameter<DoubleMatrix>)Parameters["BestKnownFront"]; }
51    }
52
53
54    [StorableConstructor]
55    protected GenerationalDistanceAnalyzer(StorableConstructorFlag _) : base(_) { }
56    protected GenerationalDistanceAnalyzer(GenerationalDistanceAnalyzer original, Cloner cloner) : base(original, cloner) { }
57    public override IDeepCloneable Clone(Cloner cloner) {
58      return new GenerationalDistanceAnalyzer(this, cloner);
59    }
60
61    public GenerationalDistanceAnalyzer() : base() {
62      Parameters.Add(new FixedValueParameter<DoubleValue>("Dampening", "", new DoubleValue(1)));
63      Parameters.Add(new LookupParameter<ItemArray<DoubleArray>>("OptimalParetoFront", "The analytically best known Pareto front"));
64      Parameters.Add(new ResultParameter<DoubleValue>(ResultName, "The generational distance between the current front and the optimal front", "Results", new DoubleValue(double.NaN)));
65    }
66
67    public override IOperation Apply() {
68      var qualities = QualitiesParameter.ActualValue;
69      var optimalFront = OptimalParetoFrontParameter.ActualValue;
70      if (optimalFront == null) return base.Apply();
71      var front = Enumerable.Range(0, optimalFront.Rows).Select(r => Enumerable.Range(0, optimalFront.Columns).Select(c => optimalFront[r, c]).ToArray()).ToList();
72      ResultParameter.ActualValue.Value = CalculateDistance(qualities, front);
73      return base.Apply();
74    }
75
76    protected virtual double CalculateDistance(ItemArray<DoubleArray> qualities, IEnumerable<double[]> optimalFront) {
77      return CalculateGenerationalDistance(qualities.Select(x => x.ToArray()), optimalFront, Dampening);
78    }
79
80    public static double CalculateGenerationalDistance(IEnumerable<double[]> qualities, IEnumerable<double[]> bestKnownFront, double p) {
81      if (qualities == null || bestKnownFront == null) throw new ArgumentNullException("qualities");
82      if (p.IsAlmost(0.0)) throw new ArgumentException("p must not be zero.");
83      var mat = bestKnownFront.ToMatrix();
84      if (mat.GetLength(0) == 0) throw new ArgumentException("Fronts must not be empty.");
85      alglib.kdtree tree;
86      alglib.kdtreebuild(mat, mat.GetLength(0), mat.GetLength(1), 0, 2, out tree);
87      var sum = 0.0;
88      var summand = new double[1];
89      var count = 0;
90      foreach (var point in qualities) {
91        alglib.kdtreequeryknn(tree, point.ToArray(), 1, true);
92        alglib.kdtreequeryresultsdistances(tree, ref summand);
93        sum += Math.Pow(summand[0], p);
94        count++;
95      }
96
97      if (count == 0) throw new ArgumentException("Fronts must not be empty.");
98      return Math.Pow(sum, 1 / p) / count;
99    }
100
101    public static double CalculateInverseGenerationalDistance(IEnumerable<double[]> qualities, IEnumerable<double[]> bestKnownFront, double p) {
102      return CalculateGenerationalDistance(bestKnownFront, qualities, p);
103    }
104  }
105}
Note: See TracBrowser for help on using the repository browser.