Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2825-NSGA3/HeuristicLab.Algorithms.NSGA3/3.3/ReferencePoint.cs @ 17619

Last change on this file since 17619 was 17619, checked in by dleko, 4 years ago

#2825 Implement second part of NSGA3. Add random field to ReferencePoint.

File size: 5.1 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using HeuristicLab.Core;
5
6namespace HeuristicLab.Algorithms.NSGA3
7{
8    /*
9     * The method for generating the reference points is based on the NSGA3 implementation in the jMetal framework (http://jmetal.sourceforge.net/).
10     * That implementation in return is based on Tsung-Che Chiang's code
11     * http://web.ntnu.edu.tw/~tcchiang/publications/nsga3cpp/nsga3cpp.htm
12     */
13
14    public class ReferencePoint
15    {
16        private readonly Dictionary<Solution, double> potentialAssociatedSolutions = new Dictionary<Solution, double>();
17
18        #region Properties
19
20        public IRandom random;
21        public double[] Values { get; }
22        public int NumberOfDimensions => Values.Length;
23        public int NumberOfAssociatedSolutions { get; set; } = 0;
24
25        #endregion Properties
26
27        #region Constructors
28
29        public ReferencePoint(IRandom random, int numberOfDimensions)
30        {
31            this.random = random;
32            Values = new double[numberOfDimensions];
33        }
34
35        public ReferencePoint(ReferencePoint other)
36        {
37            random = other.random;
38            Values = new double[other.NumberOfDimensions];
39            for (int i = 0; i < other.NumberOfDimensions; i++)
40                Values[i] = other.Values[i];
41        }
42
43        #endregion Constructors
44
45        #region Static methods
46
47        // todo: use this (for optimization)
48        /// <summary>
49        /// Returns the number of reference points that are generated by <see
50        /// cref="GenerateReferencePoints(List{ReferencePoint}, int, int)" /> for the given number
51        /// of dimensions and divisions.
52        /// </summary>
53        /// <param name="nDim">The number of dimensions</param>
54        /// <param name="nDiv">The number of divisions</param>
55        /// <returns></returns>
56        internal static int GetNumberOfReferencePoints(int nDim, int nDiv)
57        {
58            return Utility.NCR(nDim + nDiv - 1, nDiv);
59        }
60
61        // maybe todo: move this to another class?
62        /// <summary>
63        /// Generate reference points that are evenly distributed over a hyperplane with dimensions
64        /// <paramref name="nDim" /> - 1 with the sum of the values in all dimensions being equal to
65        /// 1 for each reference point.
66        /// </summary>
67        /// <param name="nDim">The number of dimensions for the reference points</param>
68        /// <param name="nDiv">The number of divisions to use to generate reference points</param>
69        /// <returns>The generated reference points</returns>
70        internal static List<ReferencePoint> GenerateReferencePoints(IRandom random, int nDim, int nDiv)
71        {
72            List<ReferencePoint> referencePoints = new List<ReferencePoint>();
73            ReferencePoint refPoint = new ReferencePoint(random, nDim);
74            GenerateRecursive(referencePoints, refPoint, nDim, nDiv, nDiv, 0);
75
76            return referencePoints;
77        }
78
79        private static void GenerateRecursive(List<ReferencePoint> referencePoints, ReferencePoint refPoint, int numberOfObjectives, int left, int total, int element)
80        {
81            if (element == numberOfObjectives - 1)
82            {
83                refPoint.Values[element] = ((double)left) / total;
84                var newRefPoint = new ReferencePoint(refPoint);
85                referencePoints.Add(newRefPoint);
86            }
87            else
88            {
89                for (int i = 0; i <= left; i++)
90                {
91                    refPoint.Values[element] = (double)i / total;
92                    GenerateRecursive(referencePoints, refPoint, numberOfObjectives, left - i, total, element + 1);
93                }
94            }
95        }
96
97        #endregion Static methods
98
99        public void AddPotentialAssociatedSolution(Solution s, double distance)
100        {
101            if (potentialAssociatedSolutions.ContainsKey(s))
102                throw new InvalidOperationException("Attempt to add potential solution to reference point failed: That solution was already added as a potential solution");
103
104            potentialAssociatedSolutions.Add(s, distance);
105        }
106
107        public void RemovePotentialAssociatedSolution(Solution s)
108        {
109            potentialAssociatedSolutions.Remove(s);
110        }
111
112        public bool HasPotentialMember()
113        {
114            return potentialAssociatedSolutions.Any();
115        }
116
117        internal Solution FindClosestMember()
118        {
119            if (!potentialAssociatedSolutions.Any())
120                throw new InvalidOperationException("No potential members exist");
121
122            return Utility.ArgMin(pair => pair.Value, potentialAssociatedSolutions).Key;
123        }
124
125        internal Solution RandomMember()
126        {
127            if (!potentialAssociatedSolutions.Any())
128                throw new InvalidOperationException("No potential members exist");
129
130            return potentialAssociatedSolutions.Keys.ElementAt(random.Next(potentialAssociatedSolutions.Count));
131        }
132    }
133}
Note: See TracBrowser for help on using the repository browser.