Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.MultiObjectiveTestFunctions/HeuristicLab.Problems.MultiObjectiveTestFunctions/3.3/Calculators/FastHV2.cs @ 13672

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

#1087 added Analyzers, reworked PFStore, added licence information, cleaned code

File size: 8.4 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;
26
27namespace HeuristicLab.Problems.MultiObjectiveTestFunctions {
28  public class FastHV2 {
29
30    public static double Calculate(IEnumerable<double[]> points, double[] referencePoint) {
31      if (referencePoint == null || referencePoint.Length < 3) throw new ArgumentException("ReferencePoint unfit for complex Hypervolume calculation");
32      int objectives = referencePoint.Length;
33      List<double[]> lpoints = new List<double[]>();
34      foreach (double[] p in points) {
35        lpoints.Add(p);
36      }
37      lpoints.StableSort(Utilities.getDimensionComparer(objectives - 1, false));
38
39      double[] regLow = new double[objectives];
40      for (int i = 0; i < objectives; i++) {
41        regLow[i] = 1E15;
42      }
43      foreach (double[] p in lpoints) {
44        for (int i = 0; i < regLow.Length; i++) {
45          if (regLow[i] > p[i]) regLow[i] = p[i];
46        }
47      }
48
49      return Stream(regLow, referencePoint, lpoints, 0, referencePoint[objectives - 1], (int)Math.Sqrt(points.Count()), objectives);
50    }
51
52    private static double Stream(double[] regionLow, double[] regionUp, List<double[]> points, int split, double cover, int sqrtNoPoints, int objectives) {
53      double coverOld = cover;
54      int coverIndex = 0;
55      int coverIndexOld = -1;
56      int c;
57      double result = 0;
58
59      double dMeasure = GetMeasure(regionLow, regionUp, objectives);
60      while (cover == coverOld && coverIndex < points.Count()) {
61        if (coverIndexOld == coverIndex) break;
62        coverIndexOld = coverIndex;
63        if (Covers(points[coverIndex], regionLow, objectives)) {
64          cover = points[coverIndex][objectives - 1];
65          result += dMeasure * (coverOld - cover);
66        } else coverIndex++;
67
68      }
69
70      for (c = coverIndex; c > 0; c--) if (points[c - 1][objectives - 1] == cover) coverIndex--;
71      if (coverIndex == 0) return result;
72
73      bool allPiles = true;
74      int[] piles = new int[coverIndex];
75      for (int i = 0; i < coverIndex; i++) {
76        piles[i] = IsPile(points[i], regionLow, regionUp, objectives);
77        if (piles[i] == -1) {
78          allPiles = false;
79          break;
80        }
81      }
82
83      if (allPiles) {
84        double[] trellis = new double[regionUp.Length];
85        for (int j = 0; j < trellis.Length; j++) trellis[j] = regionUp[j];
86        double current = 0;
87        double next = 0;
88        int i = 0;
89        do {
90          current = points[i][objectives - 1];
91          do {
92            if (points[i][piles[i]] < trellis[piles[i]]) trellis[piles[i]] = points[i][piles[i]];
93            i++;
94            if (i < coverIndex) next = points[i][objectives - 1];
95            else { next = cover; break; }
96          } while (next == current);
97          result += ComputeTrellis(regionLow, regionUp, trellis, objectives) * (next - current);
98        } while (next != cover);
99      } else {
100        double bound = -1;
101        double[] boundaries = new double[coverIndex];
102        double[] noBoundaries = new double[coverIndex];
103        int boundIdx = 0;
104        int noBoundIdx = 0;
105
106        do {
107          for (int i = 0; i < coverIndex; i++) {
108            int contained = ContainesBoundary(points[i], regionLow, split);
109            if (contained == 0) boundaries[boundIdx++] = points[i][split];
110            else if (contained == 1) noBoundaries[noBoundIdx++] = points[i][split];
111          }
112          if (boundIdx > 0) bound = GetMedian(boundaries, boundIdx);
113          else if (noBoundIdx > sqrtNoPoints) bound = GetMedian(noBoundaries, noBoundIdx);
114          else split++;
115        } while (bound == -1.0);
116
117        List<double[]> pointsChildLow, pointsChildUp;
118        pointsChildLow = new List<double[]>();
119        pointsChildUp = new List<double[]>();
120        double[] regionUpC = new double[regionUp.Length];
121        for (int j = 0; j < regionUpC.Length; j++) regionUpC[j] = regionUp[j];
122        double[] regionLowC = new double[regionLow.Length];
123        for (int j = 0; j < regionLowC.Length; j++) regionLowC[j] = regionLow[j];
124
125        for (int i = 0; i < coverIndex; i++) {
126          if (PartCovers(points[i], regionUpC, objectives)) pointsChildUp.Add(points[i]);
127          if (PartCovers(points[i], regionUp, objectives)) pointsChildLow.Add(points[i]);
128        }
129        //this could/should be done in Parallel
130
131        if (pointsChildUp.Count() > 0) result += Stream(regionLow, regionUpC, pointsChildUp, split, cover, sqrtNoPoints, objectives);
132        if (pointsChildLow.Count() > 0) result += Stream(regionLowC, regionUp, pointsChildLow, split, cover, sqrtNoPoints, objectives);
133      }
134      return result;
135    }
136
137    private static double GetMedian(double[] vector, int length) {
138      if (vector.Length != length) {
139        double[] vec = new double[length];
140        Array.Copy(vector, vec, length);
141        vector = vec;
142      }
143      return vector.Median();
144
145    }
146
147    private static double ComputeTrellis(double[] regionLow, double[] regionUp, double[] trellis, int objectives) {
148      bool[] bs = new bool[objectives - 1];
149      for (int i = 0; i < bs.Length; i++) bs[i] = true;
150
151      double result = 0;
152      uint noSummands = BinarayToInt(bs);
153      int oneCounter; double summand;
154      for (uint i = 1; i <= noSummands; i++) {
155        summand = 1;
156        IntToBinary(i, bs);
157        oneCounter = 0;
158        for (int j = 0; j < objectives - 1; j++) {
159          if (bs[j]) {
160            summand *= regionUp[j] - trellis[j];
161            oneCounter++;
162          } else {
163            summand *= regionUp[j] - regionLow[j];
164          }
165        }
166        if (oneCounter % 2 == 0) result -= summand;
167        else result += summand;
168
169      }
170      return result;
171    }
172
173    private static void IntToBinary(uint i, bool[] bs) {
174      for (int j = 0; j < bs.Length; j++) bs[j] = false;
175      uint rest = i;
176      int idx = 0;
177      while (rest != 0) {
178        bs[idx] = rest % 2 == 1;
179        rest = rest / 2;
180        idx++;
181      }
182
183    }
184
185    private static uint BinarayToInt(bool[] bs) {
186      uint result = 0;
187      for (int i = 0; i < bs.Length; i++) {
188        result += bs[i] ? ((uint)1 << i) : 0;
189      }
190      return result;
191    }
192
193    private static int IsPile(double[] cuboid, double[] regionLow, double[] regionUp, int objectives) {
194      int pile = cuboid.Length;
195      for (int i = 0; i < objectives - 1; i++) {
196        if (cuboid[i] > regionLow[i]) {
197          if (pile != objectives) return 1;
198          pile = i;
199        }
200      }
201      return pile;
202    }
203
204    private static double GetMeasure(double[] regionLow, double[] regionUp, int objectives) {
205      double volume = 1;
206      for (int i = 0; i < objectives - 1; i++) {
207        volume *= (regionUp[i] - regionLow[i]);
208      }
209      return volume;
210    }
211
212    private static int ContainesBoundary(double[] cub, double[] regionLow, int split) {
213      if (regionLow[split] >= cub[split]) return -1;
214      else {
215        for (int j = 0; j < split; j++) {
216          if (regionLow[j] < cub[j]) return 1;
217        }
218      }
219      return 0;
220    }
221
222    private static bool PartCovers(double[] v, double[] regionUp, int objectives) {
223      for (int i = 0; i < objectives - 1; i++) {
224        if (v[i] >= regionUp[i]) return false;
225      }
226      return true;
227    }
228
229    private static bool Covers(double[] v, double[] regionLow, int objectives) {
230      for (int i = 0; i < objectives - 1; i++) {
231        if (v[i] > regionLow[i]) return false;
232      }
233      return true;
234    }
235
236
237  }
238}
Note: See TracBrowser for help on using the repository browser.