Changeset 13936 for branches/HeuristicLab.Problems.MultiObjectiveTestFunctions/HeuristicLab.Problems.MultiObjectiveTestFunctions/3.3/Calculators
- Timestamp:
- 06/24/16 15:03:51 (8 years ago)
- Location:
- branches/HeuristicLab.Problems.MultiObjectiveTestFunctions/HeuristicLab.Problems.MultiObjectiveTestFunctions/3.3/Calculators
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/HeuristicLab.Problems.MultiObjectiveTestFunctions/HeuristicLab.Problems.MultiObjectiveTestFunctions/3.3/Calculators/Crowding.cs
r13672 r13936 24 24 using System.Linq; 25 25 26 namespace HeuristicLab.Problems.MultiObjectiveTestFunctions { 26 namespace HeuristicLab.Problems.MultiObjectiveTestFunctions 27 { 27 28 28 /// <summary> 29 /// Crowding distance d(x,A) is usually defined between a point x and a set of points A 30 /// d(x,A) is then a weighted sum over all dimensions where for each dimension the next larger and the next smaller Point to x are subtracted 31 /// I extended the concept and defined the Crowding distance of a front A as the mean of the crowding distances of every point x in A 32 /// C(A) = mean(d(x,A)) where x in A and d(x,A) is not infinite 33 /// </summary> 34 public class Crowding { 29 /// <summary> 30 /// Crowding distance d(x,A) is usually defined between a point x and a set of points A 31 /// d(x,A) is then a weighted sum over all dimensions where for each dimension the next larger and the next smaller Point to x are subtracted 32 /// I extended the concept and defined the Crowding distance of a front A as the mean of the crowding distances of every point x in A 33 /// C(A) = mean(d(x,A)) where x in A and d(x,A) is not infinite 34 /// </summary> 35 public class Crowding 36 { 35 37 36 public static double Calculate(IEnumerable<double[]> front, double[,] bounds) { 37 double sum = 0; 38 int c = 0; 39 double[] pointsums = new double[front.Count()]; 38 public static double Calculate(IEnumerable<double[]> front, double[,] bounds) 39 { 40 double sum = 0; 41 int c = 0; 42 double[] pointsums = new double[front.Count()]; 40 43 41 for (int dim = 0; dim < bounds.GetLength(0); dim++) { 42 double[] arr = front.Select(x => x[dim]).ToArray(); 43 Array.Sort(arr); 44 double fmax = bounds[dim % bounds.GetLength(0), 1]; 45 double fmin = bounds[dim % bounds.GetLength(0), 0]; 46 int pointIdx = 0; 47 foreach (double[] point in front) { 48 double d = 0; 49 int pos = Array.BinarySearch(arr, point[dim]); 50 if (pos != 0 && pos != arr.Count() - 1) { 51 d = (arr[pos + 1] - arr[pos - 1]) / (fmax - fmin); 52 pointsums[pointIdx++] += d; 53 } 44 for (int dim = 0; dim < front.First().Length; dim++) 45 { 46 double[] arr = front.Select(x => x[dim]).ToArray(); 47 Array.Sort(arr); 48 double fmax = bounds[dim % bounds.GetLength(0), 1]; 49 double fmin = bounds[dim % bounds.GetLength(0), 0]; 50 int pointIdx = 0; 51 foreach (double[] point in front) 52 { 53 double d = 0; 54 int pos = Array.BinarySearch(arr, point[dim]); 55 if (pos != 0 && pos != arr.Count() - 1) 56 { 57 d = (arr[pos + 1] - arr[pos - 1]) / (fmax - fmin); 58 pointsums[pointIdx++] += d; 59 } 60 } 61 } 62 63 foreach (double d in pointsums) 64 { 65 if (!Double.IsInfinity(d)) 66 { 67 sum += d; 68 c++; 69 } 70 } 71 return c == 0 ? Double.PositiveInfinity : sum / c; 54 72 } 55 }56 73 57 foreach (double d in pointsums) {58 if (!Double.IsInfinity(d)) {59 sum += d;60 c++;61 }62 }63 return c == 0 ? Double.PositiveInfinity : sum / c;64 74 } 65 66 }67 75 } -
branches/HeuristicLab.Problems.MultiObjectiveTestFunctions/HeuristicLab.Problems.MultiObjectiveTestFunctions/3.3/Calculators/HyperVolume.cs
r13894 r13936 19 19 */ 20 20 #endregion 21 using HeuristicLab.Common; 21 22 using System; 22 23 using System.Collections.Generic; 23 24 using System.Linq; 24 25 25 namespace HeuristicLab.Problems.MultiObjectiveTestFunctions { 26 27 public class Hypervolume { 28 29 /// <summary> 30 /// The Hyprevolume-metric is defined as the Hypervolume enclosed between a given reference point, 31 /// that is fixed for every evaluation function and the evaluated front. 32 /// 33 /// Example: 34 /// r is the reference Point at (1|1) and every Point p is part of the evaluated front 35 /// The filled Area labled HV is the 2 diensional Hypervolume enclosed by this front. 36 /// 37 /// (0|1) (1|1) 38 /// + +-------------r 39 /// | |###### HV ###| 40 /// | p------+######| 41 /// | p+#####| 42 /// | |#####| 43 /// | p-+###| 44 /// | p---+ 45 /// | 46 /// +--------------------1 47 /// (0|0) (1|0) 48 /// 49 /// Please note that in this example both dimensions are minimized. The reference Point need to be dominated by EVERY point in the evaluated front 50 /// 51 /// </summary> 52 public static double Calculate(IEnumerable<double[]> front, IEnumerable<double> reference, bool[] maximization) { 53 List<double> list = new List<double>(); 54 foreach (double d in reference) list.Add(d); 55 double[] refp = list.ToArray<double>(); 56 if (front == null) throw new ArgumentException("Fronts must not be null"); 57 double[][] set = front.ToArray(); //Still no Good 58 if (set.Length == 0) throw new ArgumentException("Fronts must not be empty"); 59 if (refp.Length != set[0].Length) throw new ArgumentException("Front and referencepoint need to be of the same dimensionality"); 60 Array.Sort<double[]>(set, Utilities.getDimensionComparer(0, maximization[0])); 61 double[] last = set[set.Length - 1]; 62 CheckConsistency(last, 0, refp, maximization); 63 CheckConsistency(last, 1, refp, maximization); 64 65 double sum = 0; 66 for (int i = 0; i < set.Length - 1; i++) { 67 CheckConsistency(set[i], 1, refp, maximization); 68 sum += Math.Abs((set[i][0] - set[i + 1][0])) * Math.Abs((set[i][1] - refp[1])); 69 } 70 71 sum += Math.Abs(refp[0] - last[0]) * Math.Abs(refp[1] - last[1]); 72 return sum; 26 namespace HeuristicLab.Problems.MultiObjectiveTestFunctions 27 { 28 29 public class Hypervolume 30 { 31 32 /// <summary> 33 /// The Hyprevolume-metric is defined as the Hypervolume enclosed between a given reference point, 34 /// that is fixed for every evaluation function and the evaluated front. 35 /// 36 /// Example: 37 /// r is the reference Point at (1|1) and every Point p is part of the evaluated front 38 /// The filled Area labled HV is the 2 diensional Hypervolume enclosed by this front. 39 /// 40 /// (0|1) (1|1) 41 /// + +-------------r 42 /// | |###### HV ###| 43 /// | p------+######| 44 /// | p+#####| 45 /// | |#####| 46 /// | p-+###| 47 /// | p---+ 48 /// | 49 /// +--------------------1 50 /// (0|0) (1|0) 51 /// 52 /// Please note that in this example both dimensions are minimized. The reference Point need to be dominated by EVERY point in the evaluated front 53 /// 54 /// </summary> 55 /// 56 public static double Calculate(IEnumerable<double[]> points, IEnumerable<double> reference, bool[] maximization) 57 { 58 var front = NonDominatedSelect.removeNonReferenceDominatingVectors(points, reference.ToArray<double>(), maximization, false); 59 if (maximization.Length == 2) 60 { //Hypervolume analysis only with 2 objectives for now 61 return Hypervolume.Calculate2D(front, reference, maximization); 62 } 63 else if (Array.TrueForAll(maximization, x => !x)) 64 { 65 return Hypervolume.CalculateMD(front, reference); 66 } 67 else 68 { 69 throw new NotImplementedException("Hypervolume calculation for more than two dimensions is supported only with minimization problems"); 70 } 71 } 72 73 74 private static double Calculate2D(IEnumerable<double[]> front, IEnumerable<double> reference, bool[] maximization) 75 { 76 List<double> list = new List<double>(); 77 foreach (double d in reference) list.Add(d); 78 double[] refp = list.ToArray<double>(); 79 if (front == null) throw new ArgumentException("Fronts must not be null"); 80 double[][] set = front.ToArray(); //Still no Good 81 if (set.Length == 0) throw new ArgumentException("Fronts must not be empty"); 82 if (refp.Length != set[0].Length) throw new ArgumentException("Front and referencepoint need to be of the same dimensionality"); 83 Array.Sort<double[]>(set, Utilities.getDimensionComparer(0, maximization[0])); 84 double[] last = set[set.Length - 1]; 85 CheckConsistency(last, 0, refp, maximization); 86 CheckConsistency(last, 1, refp, maximization); 87 88 double sum = 0; 89 for (int i = 0; i < set.Length - 1; i++) 90 { 91 CheckConsistency(set[i], 1, refp, maximization); 92 sum += Math.Abs((set[i][0] - set[i + 1][0])) * Math.Abs((set[i][1] - refp[1])); 93 } 94 95 sum += Math.Abs(refp[0] - last[0]) * Math.Abs(refp[1] - last[1]); 96 return sum; 97 } 98 99 private static void CheckConsistency(double[] point, int dim, double[] reference, bool[] maximization) 100 { 101 if (!maximization[dim] && point[dim] > reference[dim]) throw new ArgumentException("Reference Point must be dominated by all points of the front"); 102 if (maximization[dim] && point[dim] < reference[dim]) throw new ArgumentException("Reference Point must be dominated by all points of the front"); 103 if (point.Length != 2) throw new ArgumentException("Only 2-dimensional cases are supported yet"); 104 } 105 106 private static double CalculateMD(IEnumerable<double[]> points, IEnumerable<double> reference) 107 { 108 double[] referencePoint = reference.ToArray<double>(); 109 if (referencePoint == null || referencePoint.Length < 3) throw new ArgumentException("ReferencePoint unfit for complex Hypervolume calculation"); 110 if (!IsDominated(referencePoint, points)) 111 { 112 throw new ArgumentException("ReferencePoint unfit for complex Hypervolume calculation"); 113 } 114 int objectives = referencePoint.Length; 115 List<double[]> lpoints = new List<double[]>(); 116 foreach (double[] p in points) 117 { 118 lpoints.Add(p); 119 } 120 lpoints.StableSort(Utilities.getDimensionComparer(objectives - 1, false)); 121 122 double[] regLow = new double[objectives]; 123 for (int i = 0; i < objectives; i++) 124 { 125 regLow[i] = 1E15; 126 } 127 foreach (double[] p in lpoints) 128 { 129 for (int i = 0; i < regLow.Length; i++) 130 { 131 if (regLow[i] > p[i]) regLow[i] = p[i]; 132 } 133 } 134 135 return Stream(regLow, referencePoint, lpoints, 0, referencePoint[objectives - 1], (int)Math.Sqrt(points.Count()), objectives); 136 } 137 138 private static bool IsDominated(double[] referencePoint, IEnumerable<double[]> points) 139 { 140 foreach (double[] point in points) 141 { 142 for (int i = 0; i < referencePoint.Length; i++) 143 { 144 if (referencePoint[i] < point[i]) 145 { 146 return false; 147 } 148 } 149 } 150 return true; 151 } 152 153 private static double Stream(double[] regionLow, double[] regionUp, List<double[]> points, int split, double cover, int sqrtNoPoints, int objectives) 154 { 155 double coverOld = cover; 156 int coverIndex = 0; 157 int coverIndexOld = -1; 158 int c; 159 double result = 0; 160 161 double dMeasure = GetMeasure(regionLow, regionUp, objectives); 162 while (cover == coverOld && coverIndex < points.Count()) 163 { 164 if (coverIndexOld == coverIndex) break; 165 coverIndexOld = coverIndex; 166 if (Covers(points[coverIndex], regionLow, objectives)) 167 { 168 cover = points[coverIndex][objectives - 1]; 169 result += dMeasure * (coverOld - cover); 170 } 171 else coverIndex++; 172 173 } 174 175 for (c = coverIndex; c > 0; c--) if (points[c - 1][objectives - 1] == cover) coverIndex--; 176 if (coverIndex == 0) return result; 177 178 bool allPiles = true; 179 int[] piles = new int[coverIndex]; 180 for (int i = 0; i < coverIndex; i++) 181 { 182 piles[i] = IsPile(points[i], regionLow, regionUp, objectives); 183 if (piles[i] == -1) 184 { 185 allPiles = false; 186 break; 187 } 188 } 189 190 if (allPiles) 191 { 192 double[] trellis = new double[regionUp.Length]; 193 for (int j = 0; j < trellis.Length; j++) trellis[j] = regionUp[j]; 194 double current = 0; 195 double next = 0; 196 int i = 0; 197 do 198 { 199 current = points[i][objectives - 1]; 200 do 201 { 202 if (points[i][piles[i]] < trellis[piles[i]]) trellis[piles[i]] = points[i][piles[i]]; 203 i++; 204 if (i < coverIndex) next = points[i][objectives - 1]; 205 else { next = cover; break; } 206 } while (next == current); 207 result += ComputeTrellis(regionLow, regionUp, trellis, objectives) * (next - current); 208 } while (next != cover); 209 } 210 else 211 { 212 double bound = -1; 213 double[] boundaries = new double[coverIndex]; 214 double[] noBoundaries = new double[coverIndex]; 215 int boundIdx = 0; 216 int noBoundIdx = 0; 217 218 do 219 { 220 for (int i = 0; i < coverIndex; i++) 221 { 222 int contained = ContainesBoundary(points[i], regionLow, split); 223 if (contained == 0) boundaries[boundIdx++] = points[i][split]; 224 else if (contained == 1) noBoundaries[noBoundIdx++] = points[i][split]; 225 } 226 if (boundIdx > 0) bound = GetMedian(boundaries, boundIdx); 227 else if (noBoundIdx > sqrtNoPoints) bound = GetMedian(noBoundaries, noBoundIdx); 228 else split++; 229 } while (bound == -1.0); 230 231 List<double[]> pointsChildLow, pointsChildUp; 232 pointsChildLow = new List<double[]>(); 233 pointsChildUp = new List<double[]>(); 234 double[] regionUpC = new double[regionUp.Length]; 235 for (int j = 0; j < regionUpC.Length; j++) regionUpC[j] = regionUp[j]; 236 double[] regionLowC = new double[regionLow.Length]; 237 for (int j = 0; j < regionLowC.Length; j++) regionLowC[j] = regionLow[j]; 238 239 for (int i = 0; i < coverIndex; i++) 240 { 241 if (PartCovers(points[i], regionUpC, objectives)) pointsChildUp.Add(points[i]); 242 if (PartCovers(points[i], regionUp, objectives)) pointsChildLow.Add(points[i]); 243 } 244 //this could/should be done in Parallel 245 246 if (pointsChildUp.Count() > 0) result += Stream(regionLow, regionUpC, pointsChildUp, split, cover, sqrtNoPoints, objectives); 247 if (pointsChildLow.Count() > 0) result += Stream(regionLowC, regionUp, pointsChildLow, split, cover, sqrtNoPoints, objectives); 248 } 249 return result; 250 } 251 252 private static double GetMedian(double[] vector, int length) 253 { 254 if (vector.Length != length) 255 { 256 double[] vec = new double[length]; 257 Array.Copy(vector, vec, length); 258 vector = vec; 259 } 260 return vector.Median(); 261 262 } 263 264 private static double ComputeTrellis(double[] regionLow, double[] regionUp, double[] trellis, int objectives) 265 { 266 bool[] bs = new bool[objectives - 1]; 267 for (int i = 0; i < bs.Length; i++) bs[i] = true; 268 269 double result = 0; 270 uint noSummands = BinarayToInt(bs); 271 int oneCounter; double summand; 272 for (uint i = 1; i <= noSummands; i++) 273 { 274 summand = 1; 275 IntToBinary(i, bs); 276 oneCounter = 0; 277 for (int j = 0; j < objectives - 1; j++) 278 { 279 if (bs[j]) 280 { 281 summand *= regionUp[j] - trellis[j]; 282 oneCounter++; 283 } 284 else 285 { 286 summand *= regionUp[j] - regionLow[j]; 287 } 288 } 289 if (oneCounter % 2 == 0) result -= summand; 290 else result += summand; 291 292 } 293 return result; 294 } 295 296 private static void IntToBinary(uint i, bool[] bs) 297 { 298 for (int j = 0; j < bs.Length; j++) bs[j] = false; 299 uint rest = i; 300 int idx = 0; 301 while (rest != 0) 302 { 303 bs[idx] = rest % 2 == 1; 304 rest = rest / 2; 305 idx++; 306 } 307 308 } 309 310 private static uint BinarayToInt(bool[] bs) 311 { 312 uint result = 0; 313 for (int i = 0; i < bs.Length; i++) 314 { 315 result += bs[i] ? ((uint)1 << i) : 0; 316 } 317 return result; 318 } 319 320 private static int IsPile(double[] cuboid, double[] regionLow, double[] regionUp, int objectives) 321 { 322 int pile = cuboid.Length; 323 for (int i = 0; i < objectives - 1; i++) 324 { 325 if (cuboid[i] > regionLow[i]) 326 { 327 if (pile != objectives) return 1; 328 pile = i; 329 } 330 } 331 return pile; 332 } 333 334 private static double GetMeasure(double[] regionLow, double[] regionUp, int objectives) 335 { 336 double volume = 1; 337 for (int i = 0; i < objectives - 1; i++) 338 { 339 volume *= (regionUp[i] - regionLow[i]); 340 } 341 return volume; 342 } 343 344 private static int ContainesBoundary(double[] cub, double[] regionLow, int split) 345 { 346 if (regionLow[split] >= cub[split]) return -1; 347 else 348 { 349 for (int j = 0; j < split; j++) 350 { 351 if (regionLow[j] < cub[j]) return 1; 352 } 353 } 354 return 0; 355 } 356 357 private static bool PartCovers(double[] v, double[] regionUp, int objectives) 358 { 359 for (int i = 0; i < objectives - 1; i++) 360 { 361 if (v[i] >= regionUp[i]) return false; 362 } 363 return true; 364 } 365 366 private static bool Covers(double[] v, double[] regionLow, int objectives) 367 { 368 for (int i = 0; i < objectives - 1; i++) 369 { 370 if (v[i] > regionLow[i]) return false; 371 } 372 return true; 373 } 374 375 73 376 } 74 75 private static void CheckConsistency(double[] point, int dim, double[] reference, bool[] maximization) {76 if (!maximization[dim] && point[dim] > reference[dim]) throw new ArgumentException("Reference Point must be dominated by all points of the front");77 if (maximization[dim] && point[dim] < reference[dim]) throw new ArgumentException("Reference Point must be dominated by all points of the front");78 if (point.Length != 2) throw new ArgumentException("Only 2-dimensional cases are supported yet");79 }80 }81 377 } 378
Note: See TracChangeset
for help on using the changeset viewer.