Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.MultiObjectiveTestFunctions/HeuristicLab.Problems.MultiObjectiveTestFunctions/3.3/Analyzers/NormalizedHypervolumeAnalyzer.cs @ 14081

Last change on this file since 14081 was 14081, checked in by mkommend, 8 years ago

#1087: Refactored utility class NonDominatedSelect.

File size: 5.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2016 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 HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.Optimization;
29using HeuristicLab.Parameters;
30using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
31
32namespace HeuristicLab.Problems.MultiObjectiveTestFunctions {
33  [StorableClass]
34  [Item("NormalizedHypervolumeAnalyzer", "Computes the enclosed Hypervolume between the current front and a given reference Point")]
35  public class NormalizedHypervolumeAnalyzer : MOTFAnalyzer {
36    private const string bestKnownFront = "BestKnownFront Zitzler";
37    private const string resultsHV = "NormalizedHypervolume";
38    private const string resultsDist = "Absolute Distance to Normalized BestKnownHypervolume";
39
40    private const string bestknownHV = "NormalizedBestKnownHyperVolume";
41
42    public IValueParameter<DoubleMatrix> OptimalFrontParameter {
43      get { return (IValueParameter<DoubleMatrix>)Parameters[bestKnownFront]; }
44    }
45
46    public IValueParameter<DoubleValue> BestKnownHyperVolumeParameter {
47      get { return (IValueParameter<DoubleValue>)Parameters[bestknownHV]; }
48    }
49
50
51    public NormalizedHypervolumeAnalyzer()
52      : base() {
53      Parameters.Add(new ValueParameter<DoubleMatrix>(bestKnownFront, "The true / best known pareto front"));
54      Parameters.Add(new ValueParameter<DoubleValue>(bestknownHV, "The currently best known hypervolume"));
55    }
56
57    [StorableConstructor]
58    protected NormalizedHypervolumeAnalyzer(bool deserializing) : base(deserializing) { }
59    protected NormalizedHypervolumeAnalyzer(NormalizedHypervolumeAnalyzer original, Cloner cloner) : base(original, cloner) { }
60    public override IDeepCloneable Clone(Cloner cloner) {
61      return new NormalizedHypervolumeAnalyzer(this, cloner);
62    }
63
64
65    private void RegisterEventHandlers() {
66      OptimalFrontParameter.ValueChanged += OptimalFrontParameterOnValueChanged;
67    }
68
69    private void OptimalFrontParameterOnValueChanged(object sender, EventArgs e) {
70      BestKnownHyperVolumeParameter.Value = new DoubleValue(0);
71    }
72
73    public override IOperation Apply() {
74      var results = ResultsParameter.ActualValue;
75      var qualities = QualitiesParameter.ActualValue;
76      var testFunction = TestFunctionParameter.ActualValue;
77      int objectives = qualities[0].Length;
78
79      double best = BestKnownHyperVolumeParameter.Value.Value;
80      if (OptimalFrontParameter.Value == null || OptimalFrontParameter.Value.Rows < 1 || OptimalFrontParameter.Value.Columns != qualities[0].Length) {
81        return base.Apply(); // too pareto front nonexistant or with wrong number of dimensions
82      }
83
84      IEnumerable<double[]> front = NonDominatedSelect.SelectNonDominatedVectors(qualities.Select(q => q.ToArray()), testFunction.Maximization(objectives), true);
85
86      if (!results.ContainsKey(resultsHV)) results.Add(new Result(resultsHV, typeof(DoubleValue)));
87      if (!results.ContainsKey(resultsDist)) results.Add(new Result(resultsDist, typeof(DoubleValue)));
88      if (!results.ContainsKey(bestknownHV)) results.Add(new Result(bestknownHV, typeof(DoubleValue)));
89      else {
90        DoubleValue dv = (DoubleValue)(results[bestknownHV].Value);
91        best = dv.Value;
92      }
93
94      bool[] maximization = testFunction.Maximization(objectives);
95      double[] invPoint = GetBestPoint(OptimalFrontParameter.Value, maximization);
96      double[] refPoint = GetWorstPoint(OptimalFrontParameter.Value, maximization);
97      double normalization = Hypervolume.Calculate(new double[][] { invPoint }, refPoint, maximization);
98      double hv = front.Any() ? Hypervolume.Calculate(front, refPoint, maximization) / normalization : 0;
99
100      if (double.IsNaN(best) || best < hv) {
101        best = hv;
102        BestKnownFrontParameter.ActualValue = new DoubleMatrix(MultiObjectiveTestFunctionProblem.To2D(qualities.Select(q => q.ToArray()).ToArray()));
103      }
104
105      results[resultsHV].Value = new DoubleValue(hv);
106      results[bestknownHV].Value = new DoubleValue(best);
107      results[resultsDist].Value = new DoubleValue(best - hv);
108
109      return base.Apply();
110    }
111
112
113    private static double[] GetWorstPoint(DoubleMatrix value, bool[] maximization) {
114      bool[] invMax = new bool[maximization.Length];
115      int i = 0;
116      foreach (bool b in maximization) {
117        invMax[i++] = !b;
118      }
119      return GetBestPoint(value, invMax);
120    }
121
122    private static double[] GetBestPoint(DoubleMatrix value, bool[] maximization) {
123      double[] res = new double[maximization.Length];
124      for (int i = 0; i < maximization.Length; i++) {
125        res[i] = maximization[i] ? Double.MinValue : Double.MaxValue;
126      }
127
128      for (int r = 0; r < value.Rows; r++) {
129        for (int c = 0; c < maximization.Length; c++) {
130          res[c] = maximization[c] ? Math.Max(res[c], value[r, c]) : Math.Min(res[c], value[r, c]);
131        }
132      }
133      return res;
134    }
135  }
136}
Note: See TracBrowser for help on using the repository browser.