1 | using System;
|
---|
2 | using System.Collections.Generic;
|
---|
3 | using System.Linq;
|
---|
4 | using HeuristicLab.Data;
|
---|
5 | using HeuristicLab.Encodings.RealVectorEncoding;
|
---|
6 | using HeuristicLab.Problems.MultiObjectiveTestFunctions.Comparators;
|
---|
7 |
|
---|
8 | namespace HeuristicLab.Problems.MultiObjectiveTestFunctions {
|
---|
9 |
|
---|
10 | /// <summary>
|
---|
11 | /// Crowding distance d(x,A) is usually defined between a point x and a set of points A
|
---|
12 | /// 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
|
---|
13 | /// 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
|
---|
14 | /// C(A) = mean(d(x,A)) where x in A and d(x,A) is not infinite
|
---|
15 | /// </summary>
|
---|
16 | public class Crowding : IMultiObjectiveDistance {
|
---|
17 | private double[,] bounds;
|
---|
18 |
|
---|
19 | public Crowding(double[,] bounds) {
|
---|
20 | this.bounds = bounds;
|
---|
21 |
|
---|
22 | }
|
---|
23 |
|
---|
24 | public static double GetDistance(IEnumerable<double[]> front, IEnumerable<double[]> optimalFront, double[,] bounds) {
|
---|
25 | return new Crowding(bounds).Compare(front, optimalFront);
|
---|
26 | }
|
---|
27 |
|
---|
28 | public static double GetCrowding(IEnumerable<double[]> front, double[,] bounds) {
|
---|
29 | return new Crowding(bounds).Get(front);
|
---|
30 | }
|
---|
31 |
|
---|
32 | public double Get(IEnumerable<double[]> front) {
|
---|
33 | double sum = 0;
|
---|
34 | int c = 0;
|
---|
35 | foreach (double[] point in front) {
|
---|
36 | double d = CalcCrowding(point, front);
|
---|
37 | if (!Double.IsInfinity(d)) {
|
---|
38 | sum += d;
|
---|
39 | c++;
|
---|
40 | }
|
---|
41 | }
|
---|
42 | return c==0?Double.PositiveInfinity:sum / c;
|
---|
43 | }
|
---|
44 |
|
---|
45 | public double Compare(IEnumerable<double[]> front, IEnumerable<double[]> optimalFront) {
|
---|
46 | return Get(optimalFront) - Get(front);
|
---|
47 | }
|
---|
48 |
|
---|
49 | private double CalcCrowding(double[] point, IEnumerable<double[]> list) {
|
---|
50 | double sum = 0;
|
---|
51 | for (int i = 0; i < point.Length; i++) {
|
---|
52 | sum += CalcCrowding(point, list, i);
|
---|
53 | }
|
---|
54 | return sum;
|
---|
55 | }
|
---|
56 |
|
---|
57 | private double CalcCrowding(double[] point, IEnumerable<double[]> list, int dim) {
|
---|
58 | double fmax = bounds[dim % bounds.GetLength(0), 1];
|
---|
59 | double fmin = bounds[dim % bounds.GetLength(0), 0];
|
---|
60 | double[][] arr = list.ToArray(); //TODO Shady
|
---|
61 | Array.Sort<double[]>(arr, Utilities.getDimensionComparer(dim, false));
|
---|
62 | if (arr[0][dim] == point[0] || arr[arr.Length - 1][dim] == point[0]) return Double.PositiveInfinity;
|
---|
63 | int pos = Utilities.binarySearch(point[dim], arr, dim);
|
---|
64 | if (pos == 0 || pos == list.Count()-1) return Double.PositiveInfinity;
|
---|
65 | return (arr[pos + 1][dim] - arr[pos - 1][dim]) / (fmax - fmin);
|
---|
66 | }
|
---|
67 |
|
---|
68 | }
|
---|
69 | }
|
---|