Free cookie consent management tool by TermsFeed Policy Generator

Changeset 17724


Ignore:
Timestamp:
08/12/20 23:36:45 (4 years ago)
Author:
dleko
Message:

#2825 Improve Intercept computation (result improvement -> convergence +). Minor refactoring.

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

Legend:

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

    r17720 r17724  
    6363        private List<ReferencePoint> referencePoints;
    6464
     65        [Storable]
     66        private NSGA3Selection selection;
     67
    6568        #endregion Storable fields
    6669
     
    222225            Parameters.Add(new FixedValueParameter<PercentValue>(CrossoverProbabilityName, "The probability that the crossover operator is applied on two parents.", new PercentValue(1.0)));
    223226            Parameters.Add(new FixedValueParameter<PercentValue>(MutationProbabilityName, "The probability that the mutation operator is applied on a Individual.", new PercentValue(0.05)));
    224             Parameters.Add(new FixedValueParameter<BoolValue>(DominateOnEqualQualitiesName, "Flag which determines wether Individuals with equal quality values should be treated as dominated.", new BoolValue(false)));
     227            Parameters.Add(new FixedValueParameter<BoolValue>(DominateOnEqualQualitiesName, "Flag which determines wether Individuals with equal quality values should be treated as dominated.", new BoolValue(true)));
    225228            Parameters.Add(new FixedValueParameter<BoolValue>(SetSeedRandomlyName, "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true)));
    226229            Parameters.Add(new FixedValueParameter<IntValue>(SeedName, "The random seed used to initialize the new pseudo random number generator.", new IntValue(0)));
     
    241244            solutions = original.solutions?.Select(cloner.Clone).ToList();
    242245            referencePoints = original.referencePoints?.Select(cloner.Clone).ToList();
     246            selection = cloner.Clone(original.selection);
    243247        }
    244248
     
    289293            referencePoints = ReferencePoint.GenerateReferencePoints(random, Objectives);
    290294            ResultsGeneratedReferencePoints = Utility.ConvertToDoubleMatrix(referencePoints);
     295            var problem = Problem as MultiObjectiveTestFunctionProblem;
     296
     297            selection = new NSGA3Selection(problem.Objectives, problem.Maximization, PopulationSize.Value, random, DominateOnEqualQualities.Value);
    291298        }
    292299
     
    328335                    List<Solution> rt = Utility.Concat(solutions, qt);
    329336
    330                     solutions = NSGA3Selection.SelectSolutionsForNextGeneration(rt, GetCopyOfReferencePoints(), Problem.Maximization, PopulationSize.Value, random);
     337                    solutions = selection.SelectSolutionsForNextGeneration(rt, GetCopyOfReferencePoints());
    331338
    332339                    if (AnalyzeEveryGeneration.Value)
     
    359366            if (referencePoints == null) return null;
    360367
    361             return referencePoints.Select(rp => (ReferencePoint)rp.Clone()).ToList();
     368            return referencePoints.Select(rp => new ReferencePoint(rp)).ToList();
    362369        }
    363370
     
    377384            ResultsHypervolume = new DoubleValue(Hypervolume.Calculate(front, problem.ReferencePoint.CloneAsArray(), problem.Maximization));
    378385            ResultsDifferenceToBestKnownHypervolume = new DoubleValue(ResultsBestKnownHypervolume.Value - ResultsHypervolume.Value);
     386
     387            Problem.Analyze(
     388                solutions.Select(s => (Individual)new SingleEncodingIndividual(Problem.Encoding, new Scope { Variables = { new Variable(Problem.Encoding.Name, s.Chromosome) } })).ToArray(),
     389                solutions.Select(s => s.Fitness).ToArray(),
     390                Results,
     391                random);
    379392        }
    380393
     
    393406        private List<Solution> Recombine(List<Solution> solutions)
    394407        {
     408            //List<Solution> childSolutions = new List<Solution>();
     409            //for (int i = 0; i < solutions.Count; i++)
     410            //{
     411            //    var parent1 = solutions[random.Next(solutions.Count)];
     412            //    var parent2 = solutions[random.Next(solutions.Count)];
     413            //    var childChromosome = HeuristicLab.Encodings.RealVectorEncoding.SimulatedBinaryCrossover.Apply(random, parent1.Chromosome, parent2.Chromosome, new DoubleValue(5));
     414
     415            // BoundsChecker.Apply(childChromosome, Problem.Encoding.Bounds);
     416
     417            //    Solution child = new Solution(childChromosome);
     418            //    childSolutions.Add(child);
     419            //}
     420
     421            //return childSolutions;
     422
    395423            List<Solution> childSolutions = new List<Solution>();
    396             for (int i = 0; i < solutions.Count; i++)
    397             {
    398                 var parent1 = solutions[random.Next(solutions.Count)];
    399                 var parent2 = solutions[random.Next(solutions.Count)];
    400                 var childChromosome = HeuristicLab.Encodings.RealVectorEncoding.SimulatedBinaryCrossover.Apply(random, parent1.Chromosome, parent2.Chromosome, new DoubleValue(5));
    401 
    402                 BoundsChecker.Apply(childChromosome, Problem.Encoding.Bounds);
    403 
    404                 Solution child = new Solution(childChromosome);
    405                 childSolutions.Add(child);
     424
     425            for (int i = 0; i < solutions.Count; i += 2)
     426            {
     427                int parentIndex1 = random.Next(solutions.Count);
     428                int parentIndex2 = random.Next(solutions.Count);
     429                // ensure that the parents are not the same object
     430                if (parentIndex1 == parentIndex2) parentIndex2 = (parentIndex2 + 1) % solutions.Count;
     431                var parent1 = solutions[parentIndex1];
     432                var parent2 = solutions[parentIndex2];
     433
     434                // Do crossover with crossoverProbabilty == 1 in order to guarantee that a crossover happens
     435                var children = SimulatedBinaryCrossover.Apply(random,
     436                    Problem.Encoding.Bounds, parent1.Chromosome, parent2.Chromosome, CrossoverProbability.Value);
     437
     438                childSolutions.Add(new Solution(children.Item1));
     439                childSolutions.Add(new Solution(children.Item2));
    406440            }
    407441
    408442            return childSolutions;
    409 
    410             //List<Solution> childSolutions = new List<Solution>();
    411 
    412             //for (int i = 0; i < solutions.Count; i += 2)
    413             //{
    414             //    int parentIndex1 = random.Next(solutions.Count);
    415             //    int parentIndex2 = random.Next(solutions.Count);
    416             //    // ensure that the parents are not the same object
    417             //    if (parentIndex1 == parentIndex2) parentIndex2 = (parentIndex2 + 1) % solutions.Count;
    418             //    var parent1 = solutions[parentIndex1];
    419             //    var parent2 = solutions[parentIndex2];
    420 
    421             // // Do crossover with crossoverProbabilty == 1 in order to guarantee that a crossover
    422             // happens var children = SimulatedBinaryCrossover.Apply(random,
    423             // Problem.Encoding.Bounds, parent1.Chromosome, parent2.Chromosome, CrossoverProbability.Value);
    424 
    425             //    childSolutions.Add(new Solution(children.Item1));
    426             //    childSolutions.Add(new Solution(children.Item2));
    427             //}
    428 
    429             //return childSolutions;
    430443        }
    431444
  • branches/2825-NSGA3/HeuristicLab.Algorithms.NSGA3/3.3/NSGA3Selection.cs

    r17720 r17724  
    22using System.Collections.Generic;
    33using System.Linq;
     4using HEAL.Attic;
     5using HeuristicLab.Common;
    46using HeuristicLab.Core;
    57using HeuristicLab.Optimization;
     
    79namespace HeuristicLab.Algorithms.NSGA3
    810{
    9     public static class NSGA3Selection
     11    [StorableType("53158EA5-4D1C-42DB-90F5-EC555EC0A450")]
     12    public class NSGA3Selection : IDeepCloneable
    1013    {
    1114        private const double EPSILON = 10e-6; // a tiny number that is greater than 0
     15
     16        [Storable]
     17        private int numberOfObjectives;
     18
     19        [Storable]
     20        private bool[] maximization;
     21
     22        [Storable]
     23        private int populationSize;
     24
     25        [Storable]
     26        private IRandom random;
     27
     28        [Storable]
     29        private bool dominateOnEqualQualities;
     30
     31        [StorableConstructor]
     32        public NSGA3Selection(StorableConstructorFlag _) { }
     33
     34        public NSGA3Selection(int numberOfObjectives, bool[] maximization, int populationSize, IRandom random, bool dominateOnEqualQualities)
     35        {
     36            if (maximization == null) throw new ArgumentNullException(nameof(maximization));
     37            if (random == null) throw new ArgumentNullException(nameof(random));
     38            if (numberOfObjectives != maximization.Length) throw new ArgumentException($"{nameof(numberOfObjectives)} and the length of {nameof(maximization)} do not match.");
     39            if (populationSize < 1) throw new ArgumentOutOfRangeException($"{nameof(populationSize)} has to be >= 1.");
     40
     41            this.numberOfObjectives = numberOfObjectives;
     42            this.maximization = maximization;
     43            this.populationSize = populationSize;
     44            this.random = random;
     45            this.dominateOnEqualQualities = dominateOnEqualQualities;
     46        }
     47
     48        public NSGA3Selection(NSGA3Selection other, Cloner cloner)
     49        {
     50            numberOfObjectives = other.numberOfObjectives;
     51            maximization = new bool[other.maximization.Length];
     52            Array.Copy(other.maximization, maximization, maximization.Length);
     53            populationSize = other.populationSize;
     54            random = cloner.Clone(other.random);
     55            dominateOnEqualQualities = other.dominateOnEqualQualities;
     56        }
     57
     58        public IDeepCloneable Clone(Cloner cloner)
     59        {
     60            return new NSGA3Selection(this, cloner);
     61        }
     62
     63        public object Clone()
     64        {
     65            return new Cloner().Clone(this);
     66        }
    1267
    1368        /// <summary>
     
    1772        /// <param name="rt">The previous generation and its mutated children.</param>
    1873        /// <param name="referencePoints"></param>
    19         /// <param name="maximization"></param>
    20         /// <param name="N">Number of solutions to select.</param>
    21         /// <param name="random">The <see cref="IRandom" /> to use for randomness.</param>
    2274        /// <returns></returns>
    23         public static List<Solution> SelectSolutionsForNextGeneration(List<Solution> rt, List<ReferencePoint> referencePoints, bool[] maximization, int N, IRandom random)
    24         {
    25             int numberOfObjectives = rt.First().Fitness.Length;
     75        public List<Solution> SelectSolutionsForNextGeneration(List<Solution> rt, List<ReferencePoint> referencePoints)
     76        {
    2677            List<Solution> st = new List<Solution>();
    2778
     
    3081
    3182            // compute the pareto fronts using the DominationCalculator
    32             var fronts = DominationCalculator<Solution>.CalculateAllParetoFronts(rt.ToArray(), qualities, maximization, out int[] rank, true)
     83            List<List<Solution>> fronts = DominationCalculator<Solution>.CalculateAllParetoFronts(rt.ToArray(), qualities, maximization, out int[] rank, dominateOnEqualQualities)
    3384                .Select(list => new List<Solution>(list.Select(pair => pair.Item1))).ToList();
    3485
    3586            int lf = -1; // last front to be included
    36             for (int i = 0; i < fronts.Count && st.Count < N; i++)
     87            for (int i = 0; i < fronts.Count && st.Count < populationSize; i++)
    3788            {
    3889                st = Utility.Concat(st, fronts[i]);
     
    4394
    4495            List<Solution> nextGeneration = new List<Solution>();
    45             if (st.Count == N) // no special selection needs to be done
     96            if (st.Count == populationSize) // no special selection needs to be done
    4697                nextGeneration = st;
    4798            else
     
    51102                for (int f = 0; f < lf; f++)
    52103                    nextGeneration = Utility.Concat(nextGeneration, fronts[f]);
    53                 int k = N - nextGeneration.Count;
    54                 Normalize(st, numberOfObjectives);
     104                int k = populationSize - nextGeneration.Count;
     105                Normalize(rt, fronts);
    55106                Associate(fronts, referencePoints);
    56107                List<Solution> solutionsToAdd = Niching(k, referencePoints, random);
     
    61112        }
    62113
    63         private static void Normalize(List<Solution> st, int numberOfObjectives)
     114        private void Normalize(List<Solution> solutions, List<List<Solution>> fronts)
    64115        {
    65116            // Find the ideal point
    66117            double[] idealPoint = new double[numberOfObjectives];
    67118
    68             foreach (var solution in st)
     119            foreach (var solution in solutions)
    69120                solution.ConvertedFitness = new double[numberOfObjectives];
    70121
     
    72123            {
    73124                // Compute ideal point
    74                 idealPoint[j] = Utility.Min(s => s.Fitness[j], st);
     125                // todo: search only in first front
     126                idealPoint[j] = Utility.Min(s => s.Fitness[j], solutions);
     127                var x = Utility.Min(s => s.Fitness[j], fronts.First());
     128                if (Math.Abs(idealPoint[j] - x) > 10e-5) throw new Exception("idealPoint value is not in first front");
    75129
    76130                // Translate objectives and save the modified fitness values in ConvertedFitness
    77                 foreach (var solution in st)
     131                foreach (var solution in solutions)
    78132                    solution.ConvertedFitness[j] = solution.Fitness[j] - idealPoint[j];
    79133            }
    80134
    81135            // Find the extreme points
    82             Solution[] extremePoints = new Solution[numberOfObjectives];
     136            List<Solution> extremePoints = new List<Solution>(numberOfObjectives);
    83137            for (int j = 0; j < numberOfObjectives; j++)
    84138            {
     
    88142                weights[j] = 1;
    89143
    90                 extremePoints[j] = Utility.ArgMin(s => ASF(s.ConvertedFitness, weights), st);
     144                var extremePoint = Utility.ArgMin(s => ASF(s.ConvertedFitness, weights), solutions);
     145                extremePoints.Add(extremePoint);
    91146            }
    92147
    93148            // Compute intercepts
    94             List<double> intercepts = GetIntercepts(extremePoints.ToList());
     149            double[] intercepts = GetIntercepts(extremePoints, solutions);
    95150
    96151            // Normalize objectives
    97             NormalizeObjectives(st, intercepts, idealPoint);
    98         }
    99 
    100         private static void NormalizeObjectives(List<Solution> st, List<double> intercepts, double[] idealPoint)
    101         {
    102             int numberOfObjectives = st.First().Fitness.Length;
    103 
    104             foreach (var solution in st)
     152            NormalizeObjectives(solutions, intercepts, idealPoint);
     153        }
     154
     155        private void NormalizeObjectives(List<Solution> solutions, double[] intercepts, double[] idealPoint)
     156        {
     157            foreach (var solution in solutions)
    105158            {
    106159                for (int i = 0; i < numberOfObjectives; i++)
    107160                {
    108                     if (Math.Abs(intercepts[i] - idealPoint[i]) > EPSILON)
    109                     {
    110                         solution.ConvertedFitness[i] = solution.ConvertedFitness[i] / (intercepts[i] - idealPoint[i]);
     161                    // if (Math.Abs(intercepts[i] - idealPoints[i]) > EPSILON)
     162                    if (Math.Abs(intercepts[i]) > EPSILON)
     163                    {
     164                        //solution.ConvertedFitness[i] = solution.ConvertedFitness[i] / (intercepts[i] - idealPoint[i]);
    111165                        // todo: try this
    112                         //solution.ConvertedFitness[i] = solution.ConvertedFitness[i] / intercepts[i];
     166                        solution.ConvertedFitness[i] = solution.ConvertedFitness[i] / intercepts[i];
    113167                    }
    114168                    else
     
    120174        }
    121175
    122         private static void Associate(List<List<Solution>> fronts, List<ReferencePoint> referencePoints)
     176        private void Associate(List<List<Solution>> fronts, List<ReferencePoint> referencePoints)
    123177        {
    124178            for (int f = 0; f < fronts.Count; f++)
     
    148202        }
    149203
    150         private static List<Solution> Niching(int k, List<ReferencePoint> referencePoints, IRandom random)
     204        private List<Solution> Niching(int k, List<ReferencePoint> referencePoints, IRandom random)
    151205        {
    152206            List<Solution> solutions = new List<Solution>();
     
    171225        }
    172226
    173         private static ReferencePoint FindNicheReferencePoint(List<ReferencePoint> referencePoints, IRandom random)
     227        private ReferencePoint FindNicheReferencePoint(List<ReferencePoint> referencePoints, IRandom random)
    174228        {
    175229            // the minimum number of associated solutions for a reference point over all reference points
    176230            int minNumber = Utility.Min(rp => rp.NumberOfAssociatedSolutions, referencePoints);
     231
     232            // todo: try this instead of the current implementation
     233            //var min_rps = new List<ReferencePoint>(referencePoints.Where(r => r.NumberOfAssociatedSolutions == minNumber));
     234            //if (min_rps.Count == 0) return min_rps.Single();
     235            //else return min_rps[random.Next(min_rps.Count)];
    177236
    178237            // the reference points that share the number of associated solutions where that number
     
    189248        }
    190249
    191         private static Solution SelectClusterMember(ReferencePoint referencePoint)
     250        private Solution SelectClusterMember(ReferencePoint referencePoint)
    192251        {
    193252            Solution chosen = null;
     
    202261        }
    203262
    204         private static double GetPerpendicularDistance(double[] values, double[] fitness)
     263        private double GetPerpendicularDistance(double[] values, double[] fitness)
    205264        {
    206265            double numerator = 0;
     
    221280        }
    222281
    223         private static double ASF(double[] x, double[] weight)
    224         {
    225             int numberOfObjectives = x.Length;
     282        private double ASF(double[] x, double[] weight)
     283        {
    226284            List<int> dimensions = new List<int>();
    227285            for (int i = 0; i < numberOfObjectives; i++)
     
    231289        }
    232290
    233         private static List<double> GetIntercepts(List<Solution> extremePoints)
    234         {
    235             int numberOfObjectives = extremePoints.First().Fitness.Length;
    236 
     291        private double[] GetIntercepts(List<Solution> extremePoints, List<Solution> solutions)
     292        {
    237293            // Check whether there are duplicate extreme points. This might happen but the original
    238294            // paper does not mention how to deal with it.
     
    246302            }
    247303
    248             List<double> intercepts = new List<double>();
    249 
    250             // todo: do handling of this case as in Tsung Che Chiang's implementation
    251             if (duplicate)
    252             { // cannot construct the unique hyperplane (this is a casual method to deal with the condition)
     304            double[] intercepts = new double[numberOfObjectives];
     305
     306            bool negative_intercept = false;
     307            if (!duplicate)
     308            {
     309                // Find the equation of the hyperplane
     310                List<double> b = new List<double>(numberOfObjectives);
     311                for (int i = 0; i < numberOfObjectives; i++)
     312                    b.Add(1.0);
     313
     314                List<List<double>> a = new List<List<double>>(extremePoints.Count);
     315
     316                for (int i = 0; i < extremePoints.Count; i++)
     317                {
     318                    List<double> convertedFitness = new List<double>(extremePoints[i].ConvertedFitness);
     319                    a.Add(convertedFitness);
     320                }
     321                List<double> x = GaussianElimination(a, b);
     322
     323                // Find intercepts
     324                for (int i = 0; i < intercepts.Length; i++)
     325                {
     326                    intercepts[i] = 1.0 / x[i];
     327
     328                    if (x[i] < 0)
     329                    {
     330                        negative_intercept = true;
     331                        break;
     332                    }
     333                }
     334            }
     335
     336            // follow the method in Yuan et al. (GECCO 2015)
     337            if (duplicate || negative_intercept)
     338            {
     339                double[] maxObjectives = FindMaxObjectives(solutions);
     340                for (int i = 0; i < intercepts.Length; i++)
     341                    intercepts[i] = maxObjectives[i];
     342            }
     343
     344            return intercepts;
     345        }
     346
     347        private double[] FindMaxObjectives(List<Solution> solutions)
     348        {
     349            double[] maxPoint = new double[numberOfObjectives];
     350            for (int i = 0; i < maxPoint.Length; i++) maxPoint[i] = double.MinValue;
     351
     352            foreach (var solution in solutions)
     353            {
    253354                for (int f = 0; f < numberOfObjectives; f++)
    254355                {
    255                     // extreme_points[f] stands for the individual with the largest value of
    256                     // objective f
    257                     intercepts.Add(extremePoints[f].ConvertedFitness[f]);
    258                 }
    259             }
    260             else
    261             {
    262                 // Find the equation of the hyperplane
    263                 List<double> b = new List<double>(); //(pop[0].objs().size(), 1.0);
    264                 for (int i = 0; i < numberOfObjectives; i++)
    265                 {
    266                     b.Add(1.0);
    267                 }
    268 
    269                 List<List<double>> a = extremePoints.Select(p => p.ConvertedFitness.ToList()).ToList();
    270 
    271                 List<double> x = GaussianElimination(a, b);
    272 
    273                 // Find intercepts
    274                 for (int f = 0; f < numberOfObjectives; f++)
    275                 {
    276                     intercepts.Add(1.0 / x[f]);
    277                 }
    278             }
    279 
    280             return intercepts;
    281         }
    282 
    283         private static List<double> GaussianElimination(List<List<double>> a, List<double> b)
     356                    maxPoint[f] = Math.Max(maxPoint[f], solution.ConvertedFitness[f]);
     357                }
     358            }
     359
     360            return maxPoint;
     361        }
     362
     363        private List<double> GaussianElimination(List<List<double>> a, List<double> b)
    284364        {
    285365            List<double> x = new List<double>();
  • branches/2825-NSGA3/HeuristicLab.Algorithms.NSGA3/3.3/ReferencePoint.cs

    r17719 r17724  
    2525        public int NumberOfAssociatedSolutions { get; set; } = 0;
    2626
    27         public int Objectives => Values.Length;
    28 
    2927        #endregion Properties
    3028
     
    3230
    3331        [StorableConstructor]
    34         public ReferencePoint(StorableConstructorFlag _)
    35         {
    36         }
     32        public ReferencePoint(StorableConstructorFlag _) { }
    3733
    3834        public ReferencePoint(IRandom random, int obj)
     
    4541        {
    4642            random = cloner.Clone(other.random);
    47             Values = new double[other.Objectives];
    48             other.Values.CopyTo(Values, 0);
     43            Values = new double[other.Values.Length];
     44            Array.Copy(other.Values, Values, Values.Length);
     45        }
     46
     47        public ReferencePoint(ReferencePoint other)
     48        {
     49            random = other.random;
     50            Values = new double[other.Values.Length];
     51            Array.Copy(other.Values, Values, Values.Length);
    4952        }
    5053
  • branches/2825-NSGA3/HeuristicLab.Algorithms.NSGA3/3.3/Solution.cs

    r17719 r17724  
    2222
    2323        [StorableConstructor]
    24         public Solution(StorableConstructorFlag _)
    25         {
    26         }
     24        public Solution(StorableConstructorFlag _) { }
    2725
    2826        public Solution(RealVector chromosome)
  • branches/2825-NSGA3/HeuristicLab.Algorithms.NSGA3/3.3/Utility.cs

    r17720 r17724  
    114114        {
    115115            if (referencePoints == null || !referencePoints.Any()) throw new ArgumentException($"{nameof(referencePoints)} is null or empty");
    116             int obj = referencePoints.First().Objectives;
     116            int obj = referencePoints.First().Values.Length;
    117117            int pointCount = referencePoints.Count;
    118118            double[,] array = new double[pointCount, obj];
Note: See TracChangeset for help on using the changeset viewer.