Free cookie consent management tool by TermsFeed Policy Generator

Changeset 17661


Ignore:
Timestamp:
07/09/20 15:55:03 (4 years ago)
Author:
dleko
Message:

#2825 Correct reference point generation.

Location:
branches/2825-NSGA3/HeuristicLab.Algorithms.NSGA3/3.3
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/2825-NSGA3/HeuristicLab.Algorithms.NSGA3/3.3/NSGA3.cs

    r17657 r17661  
    144144        public List<ReferencePoint> ReferencePoints { get; private set; }
    145145
     146        // todo: create one property for the Generated Reference Points and one for the current
     147        // generations reference points
     148
    146149        #endregion Properties
    147150
     
    236239        {
    237240            // Generate reference points and add them to results
    238             int nDiv = 5; // todo: figure out the correct number of divisions
    239             ReferencePoints = ReferencePoint.GenerateReferencePoints(random, Problem.Encoding.Length, nDiv);
     241            ReferencePoints = ReferencePoint.GenerateReferencePoints(random, Problem.Maximization.Length);
    240242            ResultsGeneratedReferencePoints = Utility.ConvertToDoubleMatrix(ReferencePoints);
    241243        }
     
    253255        protected override void Run(CancellationToken cancellationToken)
    254256        {
    255             ReferencePoints = new List<ReferencePoint>(); // todo: use existing list of reference points
    256257            while (generation != MaximumGenerations.Value)
    257258            {
    258                 ToNextGeneration();
     259                // create copies of generated reference points (to preserve the original ones for
     260                // the next generation) maybe todo: use cloner?
     261                ToNextGeneration(CreateCopyOfReferencePoints());
    259262                generation++;
    260263            }
     
    264267
    265268        #region Private Methods
     269
     270        private List<ReferencePoint> CreateCopyOfReferencePoints()
     271        {
     272            if (ReferencePoints == null) return null;
     273
     274            List<ReferencePoint> referencePoints = new List<ReferencePoint>();
     275            foreach (var referencePoint in ReferencePoints)
     276                referencePoints.Add(new ReferencePoint(referencePoint));
     277
     278            return referencePoints;
     279        }
    266280
    267281        private void Analyze()
     
    287301        }
    288302
    289         private void ToNextGeneration()
     303        private void ToNextGeneration(List<ReferencePoint> referencePoints)
    290304        {
    291305            List<Solution> st = new List<Solution>();
     
    320334                int k = PopulationSize.Value - nextGeneration.Count;
    321335                Normalize(st);
    322                 Associate();
    323                 List<Solution> solutionsToAdd = Niching(k);
     336                Associate(referencePoints);
     337                List<Solution> solutionsToAdd = Niching(k, referencePoints);
    324338                nextGeneration = Utility.Concat(nextGeneration, solutionsToAdd);
    325339            }
     
    380394        }
    381395
    382         private void Associate()
     396        private void Associate(List<ReferencePoint> referencePoints)
    383397        {
    384398            for (int f = 0; f < Fronts.Count; f++)
     
    388402                    // find reference point for which the perpendicular distance to the current
    389403                    // solution is the lowest
    390                     var rpAndDist = Utility.MinArgMin(rp => GetPerpendicularDistance(rp.Values, solution.Fitness), ReferencePoints);
     404                    var rpAndDist = Utility.MinArgMin(rp => GetPerpendicularDistance(rp.Values, solution.Fitness), referencePoints);
    391405                    // associated reference point
    392406                    var arp = rpAndDist.Item1;
     
    394408                    var dist = rpAndDist.Item2;
    395409
    396                     //// todo: delete this
    397                     //int min_rp = -1;
    398                     //double min_dist = double.MaxValue;
    399                     //for (int r = 0; r < referencePoints.Count; r++)
    400                     //{
    401                     //    double d = GetPerpendicularDistance(referencePoints[r].Values, solution.Fitness);
    402                     //    if (d < min_dist)
    403                     //    {
    404                     //        min_dist = d;
    405                     //        min_rp = r;
    406                     //    }
    407                     //}
    408410                    if (f + 1 != Fronts.Count)
    409411                    {
     
    420422        }
    421423
    422         private List<Solution> Niching(int k)
     424        private List<Solution> Niching(int k, List<ReferencePoint> referencePoints)
    423425        {
    424426            List<Solution> solutions = new List<Solution>();
    425427            while (solutions.Count != k)
    426428            {
    427                 ReferencePoint min_rp = FindNicheReferencePoint();
     429                ReferencePoint min_rp = FindNicheReferencePoint(referencePoints);
    428430
    429431                Solution chosen = SelectClusterMember(min_rp);
    430432                if (chosen == null)
    431433                {
    432                     ReferencePoints.Remove(min_rp);
     434                    referencePoints.Remove(min_rp);
    433435                }
    434436                else
     
    443445        }
    444446
    445         private ReferencePoint FindNicheReferencePoint()
     447        private ReferencePoint FindNicheReferencePoint(List<ReferencePoint> referencePoints)
    446448        {
    447449            // the minimum number of associated solutions for a reference point over all reference points
    448             int minNumber = Utility.Min(rp => rp.NumberOfAssociatedSolutions, ReferencePoints);
     450            int minNumber = Utility.Min(rp => rp.NumberOfAssociatedSolutions, referencePoints);
     451
    449452            // the reference points that share the number of associated solutions where that number
    450453            // is equal to minNumber
    451             List<ReferencePoint> referencePoints = new List<ReferencePoint>();
    452             foreach (var referencePoint in ReferencePoints)
     454            List<ReferencePoint> minAssociatedReferencePoints = new List<ReferencePoint>();
     455            foreach (var referencePoint in referencePoints)
    453456                if (referencePoint.NumberOfAssociatedSolutions == minNumber)
    454                     referencePoints.Add(referencePoint);
    455 
    456             if (referencePoints.Count > 1)
    457                 return referencePoints[random.Next(referencePoints.Count)];
     457                    minAssociatedReferencePoints.Add(referencePoint);
     458
     459            if (minAssociatedReferencePoints.Count > 1)
     460                return minAssociatedReferencePoints[random.Next(minAssociatedReferencePoints.Count)];
    458461            else
    459                 return referencePoints.Single();
     462                return minAssociatedReferencePoints.Single();
    460463        }
    461464
  • branches/2825-NSGA3/HeuristicLab.Algorithms.NSGA3/3.3/ReferencePoint.cs

    r17619 r17661  
    66namespace HeuristicLab.Algorithms.NSGA3
    77{
    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 
    148    public class ReferencePoint
    159    {
     10        // The potentially associated solutions to this reference point and the distance to that solution
    1611        private readonly Dictionary<Solution, double> potentialAssociatedSolutions = new Dictionary<Solution, double>();
    1712
    1813        #region Properties
    1914
    20         public IRandom random;
     15        private readonly IRandom random;
    2116        public double[] Values { get; }
    2217        public int NumberOfDimensions => Values.Length;
     
    3732            random = other.random;
    3833            Values = new double[other.NumberOfDimensions];
    39             for (int i = 0; i < other.NumberOfDimensions; i++)
    40                 Values[i] = other.Values[i];
     34            other.Values.CopyTo(Values, 0);
    4135        }
    4236
     
    4539        #region Static methods
    4640
    47         // todo: use this (for optimization)
    4841        /// <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.
     42        /// Generate reference points that are evenly distributed over a hyperplane with dimensions
     43        /// <paramref name="nDim" /> - 1 with the sum of the values in all dimensions being equal to
     44        /// 1 for each reference point. <paramref name="nDim" /> may only be one of {3, 5, 8, 10, 15}
     45        /// -&gt; The number of inner divisions and outer divisions are determined based on the
     46        /// values provided in the NSGA-III paper, chapter V: Results. If different dimensions are
     47        /// given, null is returned.
    5248        /// </summary>
    53         /// <param name="nDim">The number of dimensions</param>
    54         /// <param name="nDiv">The number of divisions</param>
     49        /// <param name="random">
     50        /// The <see cref="IRandom" /> to give as a parameter to the ReferencePoint constructors.
     51        /// </param>
     52        /// <param name="nDim">The dimensionality of the Reference Points</param>
    5553        /// <returns></returns>
    56         internal static int GetNumberOfReferencePoints(int nDim, int nDiv)
     54        internal static List<ReferencePoint> GenerateReferencePoints(IRandom random, int nDim)
    5755        {
    58             return Utility.NCR(nDim + nDiv - 1, nDiv);
     56            List<ReferencePoint> referencePoints;
     57            switch (nDim)
     58            {
     59                case 3:
     60                    referencePoints = GenerateReferencePoints(random, nDim, 12, 0);
     61                    break;
     62
     63                case 5:
     64                    referencePoints = GenerateReferencePoints(random, nDim, 6, 0);
     65                    break;
     66
     67                case 8:
     68                    referencePoints = GenerateReferencePoints(random, nDim, 3, 2);
     69                    break;
     70
     71                case 10:
     72                    referencePoints = GenerateReferencePoints(random, nDim, 3, 2);
     73                    break;
     74
     75                case 15:
     76                    referencePoints = GenerateReferencePoints(random, nDim, 2, 1);
     77                    break;
     78
     79                default:
     80                    referencePoints = null;
     81                    break;
     82            }
     83
     84            return referencePoints;
    5985        }
    6086
    61         // maybe todo: move this to another class?
     87        internal static List<ReferencePoint> GenerateReferencePoints(IRandom random, int nDim, int outerDiv)
     88        {
     89            return GenerateReferencePoints(random, nDim, outerDiv, 0);
     90        }
     91
     92        /*
     93         * This method is based on Tsung-Che Chiang's NSGA-III implementation (version 1.20)
     94         * http://web.ntnu.edu.tw/~tcchiang/publications/nsga3cpp/nsga3cpp.htm
     95         */
     96
    6297        /// <summary>
    6398        /// Generate reference points that are evenly distributed over a hyperplane with dimensions
     
    65100        /// 1 for each reference point.
    66101        /// </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)
     102        /// <param name="nDim">The number of dimensions for the reference points.</param>
     103        /// <param name="outerDiv">The number of divisions for the outer reference points</param>
     104        /// <returns>The generated reference points (Check Fig. 4 in NSGA-III paper).</returns>
     105        /// <param name="innerDiv">The number of divisions for the inner reference points</param>
     106        /// <returns>
     107        /// The generated reference points (Check Fig. 4 in NSGA-III paper). Set to 0, in order to
     108        /// not have inner reference points
     109        /// </returns>
     110        internal static List<ReferencePoint> GenerateReferencePoints(IRandom random, int nDim, int outerDiv, int innerDiv)
    71111        {
     112            if (nDim <= 0) throw new ArgumentException("nDim must be greater than 0");
     113            if (outerDiv <= 1) throw new ArgumentException("outerDiv must be greater than 1");
     114
    72115            List<ReferencePoint> referencePoints = new List<ReferencePoint>();
    73116            ReferencePoint refPoint = new ReferencePoint(random, nDim);
    74             GenerateRecursive(referencePoints, refPoint, nDim, nDiv, nDiv, 0);
     117            GenerateRecursive(referencePoints, refPoint, nDim, outerDiv, outerDiv, 0);
     118
     119            if (innerDiv > 0)
     120            {
     121                List<ReferencePoint> insideReferencePoints = new List<ReferencePoint>();
     122                GenerateRecursive(insideReferencePoints, refPoint, nDim, innerDiv, innerDiv, 0);
     123
     124                double center = 1.0 / nDim;
     125
     126                for (int i = 0; i < insideReferencePoints.Count; i++)
     127                {
     128                    for (int j = 0; j < insideReferencePoints[i].Values.Length; j++)
     129                    {
     130                        insideReferencePoints[i].Values[j] = (center + insideReferencePoints[i].Values[j]) / 2;
     131                    }
     132                    referencePoints.Add(insideReferencePoints[i]);
     133                }
     134            }
    75135
    76136            return referencePoints;
    77137        }
     138
     139        /*
     140         * This method is based on Tsung-Che Chiang's NSGA-III implementation (version 1.20)
     141         * http://web.ntnu.edu.tw/~tcchiang/publications/nsga3cpp/nsga3cpp.htm
     142         */
    78143
    79144        private static void GenerateRecursive(List<ReferencePoint> referencePoints, ReferencePoint refPoint, int numberOfObjectives, int left, int total, int element)
     
    100165        {
    101166            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");
     167                throw new InvalidOperationException("Given solution was already added as a potential solution");
    103168
    104169            potentialAssociatedSolutions.Add(s, distance);
Note: See TracChangeset for help on using the changeset viewer.