Free cookie consent management tool by TermsFeed Policy Generator

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

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

#2825 Refactoring.

File size: 25.9 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Linq;
5using System.Threading;
6using HEAL.Attic;
7using HeuristicLab.Common;
8using HeuristicLab.Core;
9using HeuristicLab.Data;
10using HeuristicLab.Encodings.RealVectorEncoding;
11using HeuristicLab.Optimization;
12using HeuristicLab.Parameters;
13using HeuristicLab.Problems.TestFunctions.MultiObjective;
14using HeuristicLab.Problems.TestFunctions.MultiObjective.TestFunctions;
15using HeuristicLab.Random;
16
17namespace HeuristicLab.Algorithms.NSGA3
18{
19    /// <summary>
20    /// The Reference Point Based Non-dominated Sorting Genetic Algorithm III was introduced in Deb
21    /// et al. 2013. An Evolutionary Many-Objective Optimization Algorithm Using Reference Point
22    /// Based Non-dominated Sorting Approach. IEEE Transactions on Evolutionary Computation, 18(4),
23    /// pp. 577-601.
24    /// </summary>
25    [Item("NSGA-III", "The Reference Point Based Non-dominated Sorting Genetic Algorithm III was introduced in Deb et al. 2013. An Evolutionary Many-Objective Optimization Algorithm Using Reference Point Based Non-dominated Sorting Approach. IEEE Transactions on Evolutionary Computation, 18(4), pp. 577-601.")]
26    [Creatable(Category = CreatableAttribute.Categories.PopulationBasedAlgorithms, Priority = 136)]
27    [StorableType("07C745F7-A8A3-4F99-8B2C-F97E639F9AC3")]
28    public class NSGA3 : BasicAlgorithm
29    {
30        public override bool SupportsPause => true;
31
32        #region ProblemProperties
33
34        public override Type ProblemType
35        {
36            get { return typeof(MultiObjectiveBasicProblem<RealVectorEncoding>); }
37        }
38
39        public new MultiObjectiveBasicProblem<RealVectorEncoding> Problem
40        {
41            get { return (MultiObjectiveBasicProblem<RealVectorEncoding>)base.Problem; }
42            set { base.Problem = value; }
43        }
44
45        public int Objectives
46        {
47            get
48            {
49                if (!(Problem is MultiObjectiveTestFunctionProblem testFunctionProblem)) throw new NotSupportedException("Only Multi Objective Test Function problems are supported");
50                return testFunctionProblem.Objectives;
51            }
52        }
53
54        #endregion ProblemProperties
55
56        #region Storable fields
57
58        [Storable]
59        private IRandom random;
60
61        [Storable]
62        private List<Solution> solutions; // maybe todo: rename to nextGeneration (see Run method)
63
64        [Storable]
65        private List<ReferencePoint> referencePoints;
66
67        [Storable]
68        private NSGA3Selection selection;
69
70        [Storable]
71        private double[] allIgds;
72
73        #endregion Storable fields
74
75        #region ParameterAndResultsNames
76
77        // Parameter Names
78
79        private const string PopulationSizeName = "Population Size";
80        private const string MaximumGenerationsName = "Maximum Generations";
81        private const string CrossoverProbabilityName = "Crossover Probability";
82        private const string CrossoverEtaName = "Crossover eta";
83        private const string MutationProbabilityName = "Mutation Probability";
84        private const string DominateOnEqualQualitiesName = "Dominate On Equal Qualities";
85        private const string SetSeedRandomlyName = "Set Seed Randomly";
86        private const string SeedName = "Seed";
87        private const string AnalyzeEveryGenerationName = "Analyze Every Generation";
88
89        // Results Names
90
91        private const string GeneratedReferencePointsResultName = "Generated Reference Points";
92        private const string CurrentGenerationResultName = "Generations";
93        private const string GenerationalDistanceResultName = "Generational Distance";
94        private const string InvertedGenerationalDistanceResultName = "Inverted Generational Distance";
95        private const string HypervolumeResultName = "Hypervolume";
96        private const string BestKnownHypervolumeResultName = "Best known hypervolume";
97        private const string DifferenceToBestKnownHypervolumeResultName = "Absolute Distance to BestKnownHypervolume";
98        private const string ScatterPlotResultName = "Scatter Plot";
99        private const string CurrentFrontResultName = "Pareto Front"; // Do not touch this
100        private const string RandomSeedUsedName = "Random Seed Used";
101
102        #endregion ParameterAndResultsNames
103
104        #region ParameterProperties
105
106        private IFixedValueParameter<IntValue> PopulationSizeParameter
107        {
108            get { return (IFixedValueParameter<IntValue>)Parameters[PopulationSizeName]; }
109        }
110
111        private IFixedValueParameter<IntValue> MaximumGenerationsParameter
112        {
113            get { return (IFixedValueParameter<IntValue>)Parameters[MaximumGenerationsName]; }
114        }
115
116        private IFixedValueParameter<PercentValue> CrossoverProbabilityParameter
117        {
118            get { return (IFixedValueParameter<PercentValue>)Parameters[CrossoverProbabilityName]; }
119        }
120
121        private IFixedValueParameter<DoubleValue> CrossoverEtaParameter
122        {
123            get { return (IFixedValueParameter<DoubleValue>)Parameters[CrossoverEtaName]; }
124        }
125
126        private IFixedValueParameter<PercentValue> MutationProbabilityParameter
127        {
128            get { return (IFixedValueParameter<PercentValue>)Parameters[MutationProbabilityName]; }
129        }
130
131        private IFixedValueParameter<BoolValue> DominateOnEqualQualitiesParameter
132        {
133            get { return (IFixedValueParameter<BoolValue>)Parameters[DominateOnEqualQualitiesName]; }
134        }
135
136        private IFixedValueParameter<BoolValue> SetSeedRandomlyParameter
137        {
138            get { return (IFixedValueParameter<BoolValue>)Parameters[SetSeedRandomlyName]; }
139        }
140
141        private IFixedValueParameter<IntValue> SeedParameter
142        {
143            get { return (IFixedValueParameter<IntValue>)Parameters[SeedName]; }
144        }
145
146        private IFixedValueParameter<BoolValue> AnalyzeEveryGenerationParameter
147        {
148            get { return (IFixedValueParameter<BoolValue>)Parameters[AnalyzeEveryGenerationName]; }
149        }
150
151        #endregion ParameterProperties
152
153        #region Properties
154
155        public IntValue PopulationSize => PopulationSizeParameter.Value;
156
157        public IntValue MaximumGenerations => MaximumGenerationsParameter.Value;
158
159        public PercentValue CrossoverProbability => CrossoverProbabilityParameter.Value;
160
161        public DoubleValue CrossoverEta => CrossoverEtaParameter.Value;
162
163        public PercentValue MutationProbability => MutationProbabilityParameter.Value;
164
165        public BoolValue DominateOnEqualQualities => DominateOnEqualQualitiesParameter.Value;
166
167        public BoolValue SetSeedRandomly => SetSeedRandomlyParameter.Value;
168
169        public IntValue Seed => SeedParameter.Value;
170
171        public BoolValue AnalyzeEveryGeneration => AnalyzeEveryGenerationParameter.Value;
172
173        #endregion Properties
174
175        #region ResultsProperties
176
177        public DoubleMatrix ResultsGeneratedReferencePoints
178        {
179            get { return (DoubleMatrix)Results[GeneratedReferencePointsResultName].Value; }
180            set { Results[GeneratedReferencePointsResultName].Value = value; }
181        }
182
183        public IntValue ResultsCurrentGeneration
184        {
185            get { return (IntValue)Results[CurrentGenerationResultName].Value; }
186            set { Results[CurrentGenerationResultName].Value = value; }
187        }
188
189        public DoubleValue ResultsGenerationalDistance
190        {
191            get { return (DoubleValue)Results[GenerationalDistanceResultName].Value; }
192            set { Results[GenerationalDistanceResultName].Value = value; }
193        }
194
195        public DoubleValue ResultsInvertedGenerationalDistance
196        {
197            get { return (DoubleValue)Results[InvertedGenerationalDistanceResultName].Value; }
198            set { Results[InvertedGenerationalDistanceResultName].Value = value; }
199        }
200
201        public DoubleValue ResultsHypervolume
202        {
203            get { return (DoubleValue)Results[HypervolumeResultName].Value; }
204            set { Results[HypervolumeResultName].Value = value; }
205        }
206
207        public DoubleValue ResultsBestKnownHypervolume
208        {
209            get { return (DoubleValue)Results[BestKnownHypervolumeResultName].Value; }
210            set { Results[BestKnownHypervolumeResultName].Value = value; }
211        }
212
213        public DoubleValue ResultsDifferenceToBestKnownHypervolume
214        {
215            get { return (DoubleValue)Results[DifferenceToBestKnownHypervolumeResultName].Value; }
216            set { Results[DifferenceToBestKnownHypervolumeResultName].Value = value; }
217        }
218
219        public ParetoFrontScatterPlot ResultsScatterPlot
220        {
221            get { return (ParetoFrontScatterPlot)Results[ScatterPlotResultName].Value; }
222            set { Results[ScatterPlotResultName].Value = value; }
223        }
224
225        public DoubleMatrix ResultsSolutions
226        {
227            get { return (DoubleMatrix)Results[CurrentFrontResultName].Value; }
228            set { Results[CurrentFrontResultName].Value = value; }
229        }
230
231        public IntValue ResultsRandomSeedUsed
232        {
233            get { return (IntValue)Results[RandomSeedUsedName].Value; }
234            set { Results[RandomSeedUsedName].Value = value; }
235        }
236
237        #endregion ResultsProperties
238
239        #region Constructors
240
241        public NSGA3() : base()
242        {
243            Parameters.Add(new FixedValueParameter<IntValue>(PopulationSizeName, "The size of the population of Individuals.", new IntValue(200)));
244            Parameters.Add(new FixedValueParameter<IntValue>(MaximumGenerationsName, "The maximum number of generations which should be processed.", new IntValue(1000)));
245            Parameters.Add(new FixedValueParameter<PercentValue>(CrossoverProbabilityName, "The probability that the crossover operator is applied on two parents.", new PercentValue(1.0)));
246            Parameters.Add(new FixedValueParameter<DoubleValue>(CrossoverEtaName, "TODO: description of this parameter", new DoubleValue(30)));
247            Parameters.Add(new FixedValueParameter<PercentValue>(MutationProbabilityName, "The probability that the mutation operator is applied on a Individual.", new PercentValue(0.05)));
248            Parameters.Add(new FixedValueParameter<BoolValue>(DominateOnEqualQualitiesName, "Flag which determines wether Individuals with equal quality values should be treated as dominated.", new BoolValue(true)));
249            Parameters.Add(new FixedValueParameter<BoolValue>(SetSeedRandomlyName, "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true)));
250            Parameters.Add(new FixedValueParameter<IntValue>(SeedName, "The random seed used to initialize the new pseudo random number generator.", new IntValue(0)));
251            Parameters.Add(new FixedValueParameter<BoolValue>(AnalyzeEveryGenerationName, "If set to false, will only calculate the indicators (IGD, etc.) on the last generation and when pausing or stopping the algorithm.", new BoolValue(true)));
252        }
253
254        [StorableConstructor]
255        public NSGA3(StorableConstructorFlag _) : base(_) { }
256
257        // Each clonable item must have a cloning ctor (deep cloning, the cloner is used to handle
258        // cyclic object references). Don't forget to call the cloning ctor of the base class
259        public NSGA3(NSGA3 original, Cloner cloner) : base(original, cloner)
260        {
261            random = cloner.Clone(original.random);
262            solutions = original.solutions?.Select(cloner.Clone).ToList();
263            referencePoints = original.referencePoints?.Select(cloner.Clone).ToList();
264            selection = cloner.Clone(original.selection);
265            if (original.allIgds != null)
266            {
267                allIgds = new double[original.allIgds.Length];
268                Array.Copy(original.allIgds, allIgds, allIgds.Length);
269            }
270        }
271
272        public override IDeepCloneable Clone(Cloner cloner)
273        {
274            return new NSGA3(this, cloner);
275        }
276
277        #endregion Constructors
278
279        #region Initialization
280
281        protected override void Initialize(CancellationToken cancellationToken)
282        {
283            base.Initialize(cancellationToken);
284
285            InitResults();
286            InitFields();
287            Analyze(false);
288        }
289
290        private void InitResults()
291        {
292            Results.Add(new Result(GeneratedReferencePointsResultName, "The initially generated reference points", new DoubleMatrix()));
293            Results.Add(new Result(CurrentGenerationResultName, "The current generation", new IntValue(1)));
294            Results.Add(new Result(GenerationalDistanceResultName, "The generational distance to an optimal pareto front defined in the Problem", new DoubleValue(double.NaN)));
295            Results.Add(new Result(InvertedGenerationalDistanceResultName, "The inverted generational distance to an optimal pareto front defined in the Problem", new DoubleValue(double.NaN)));
296            Results.Add(new Result(HypervolumeResultName, "The hypervolume of the current front considering the Reference point defined in the Problem", new DoubleValue(double.NaN)));
297            Results.Add(new Result(BestKnownHypervolumeResultName, "The best known hypervolume considering the Reference point defined in the Problem", new DoubleValue(double.NaN)));
298            Results.Add(new Result(DifferenceToBestKnownHypervolumeResultName, "The difference between the current and the best known hypervolume", new DoubleValue(double.NaN)));
299            Results.Add(new Result(ScatterPlotResultName, "A scatterplot displaying the evaluated solutions and (if available) the analytically optimal front", new ParetoFrontScatterPlot()));
300            Results.Add(new Result(CurrentFrontResultName, "The Pareto Front", new DoubleMatrix()));
301            Results.Add(new Result(RandomSeedUsedName, "The random seed used in the end", new IntValue(-1)));
302
303            if (!(Problem is MultiObjectiveTestFunctionProblem problem)) return;
304            var bestKnownFront = problem.BestKnownFront.ToJaggedArray();
305            if (problem.BestKnownFront == null) return;
306            ResultsScatterPlot = new ParetoFrontScatterPlot(new double[0][], new double[0][], bestKnownFront, problem.Objectives, problem.ProblemSize);
307            ResultsBestKnownHypervolume = new DoubleValue(Hypervolume.Calculate(problem.BestKnownFront.ToJaggedArray(), problem.ReferencePoint.CloneAsArray(), problem.Maximization));
308        }
309
310        private void InitFields()
311        {
312            if (SetSeedRandomly.Value)
313            {
314                System.Random seedRand = new System.Random();
315                ResultsRandomSeedUsed.Value = seedRand.Next();
316                random = new MersenneTwister(Convert.ToUInt32(ResultsRandomSeedUsed.Value));
317            }
318            else
319            {
320                ResultsRandomSeedUsed.Value = Seed.Value;
321                random = new MersenneTwister(Convert.ToUInt32(Seed.Value));
322            }
323
324            solutions = GetInitialPopulation();
325            referencePoints = ReferencePoint.GenerateReferencePoints(random, Objectives);
326            ResultsGeneratedReferencePoints = Utility.ConvertToDoubleMatrix(referencePoints);
327            var problem = Problem as MultiObjectiveTestFunctionProblem;
328
329            selection = new NSGA3Selection(problem.Objectives, problem.Maximization, PopulationSize.Value, random, DominateOnEqualQualities.Value);
330
331            allIgds = new double[MaximumGenerations.Value];
332        }
333
334        private List<Solution> GetInitialPopulation()
335        {
336            var problem = Problem as MultiObjectiveTestFunctionProblem;
337            if (problem.Bounds.Rows != 1) throw new Exception();
338
339            // Initialise solutions
340            List<Solution> solutions = new List<Solution>(PopulationSize.Value);
341            for (int i = 0; i < PopulationSize.Value; i++)
342            {
343                double minBound = problem.Bounds[0, 0];
344                double maxBound = problem.Bounds[0, 1];
345                RealVector randomRealVector = new RealVector(Problem.Encoding.Length, random, minBound, maxBound);
346                var solution = new Solution(randomRealVector);
347                solution.Objectives = Evaluate(solution.Chromosome);
348                solutions.Add(solution);
349            }
350
351            return solutions;
352        }
353
354        #endregion Initialization
355
356        #region Overriden Methods
357
358        protected override void Run(CancellationToken cancellationToken)
359        {
360            try
361            {
362                while (ResultsCurrentGeneration.Value < MaximumGenerations.Value)
363                {
364                    List<Solution> qt = Mutate(Recombine(solutions));
365                    foreach (var solution in qt)
366                    {
367                        solution.Objectives = Evaluate(solution.Chromosome);
368                    }
369
370                    List<Solution> rt = Utility.Concat(solutions, qt);
371
372                    solutions = selection.SelectSolutionsForNextGeneration(rt, GetCopyOfReferencePoints());
373
374                    Analyze(!AnalyzeEveryGeneration.Value);
375
376                    ResultsCurrentGeneration.Value++;
377                    cancellationToken.ThrowIfCancellationRequested();
378                }
379            }
380            catch (OperationCanceledException ex)
381            {
382                throw new OperationCanceledException("Optimization process was cancelled.", ex);
383            }
384            catch (Exception ex)
385            {
386                throw new Exception($"Failed in generation {ResultsCurrentGeneration}.", ex);
387            }
388            finally
389            {
390                Analyze(false);
391                WriteIGDsToFile();
392            }
393        }
394
395        private void WriteIGDsToFile()
396        {
397            string resultsDirectory = "Results";
398            Directory.CreateDirectory(resultsDirectory);
399            var problem = Problem as MultiObjectiveTestFunctionProblem;
400            string fileName = Path.Combine(resultsDirectory, $"{problem.TestFunction.Name}({problem.Objectives})_DOEQ={DominateOnEqualQualities.Value}_Seed={ResultsRandomSeedUsed.Value}.txt");
401
402            File.WriteAllLines(fileName, allIgds.Select(igd => igd.ToString()));
403        }
404
405        #endregion Overriden Methods
406
407        #region Private Methods
408
409        private List<ReferencePoint> GetCopyOfReferencePoints()
410        {
411            if (referencePoints == null) return null;
412
413            return referencePoints.Select(rp => new ReferencePoint(rp)).ToList();
414        }
415
416        private void Analyze(bool calculateOnlyIGD)
417        {
418            if (!calculateOnlyIGD)
419            {
420                ResultsScatterPlot = new ParetoFrontScatterPlot(solutions.Select(x => x.Objectives).ToArray(), solutions.Select(x => x.Chromosome.ToArray()).ToArray(), ResultsScatterPlot.ParetoFront, ResultsScatterPlot.Objectives, ResultsScatterPlot.ProblemSize);
421                ResultsSolutions = solutions.Select(s => s.Chromosome.ToArray()).ToMatrix();
422            }
423
424            if (!(Problem is MultiObjectiveTestFunctionProblem problem)) return;
425
426            CalculateInvertedGenerationalDistance(problem);
427
428            if (!calculateOnlyIGD)
429            {
430                ResultsGenerationalDistance = new DoubleValue(problem.BestKnownFront != null ? GenerationalDistance.Calculate(solutions.Select(s => s.Objectives), problem.BestKnownFront.ToJaggedArray(), 1) : double.NaN);
431                var front = NonDominatedSelect.GetDominatingVectors(solutions.Select(x => x.Objectives), problem.ReferencePoint.CloneAsArray(), Problem.Maximization, true).ToArray();
432                if (front.Length == 0) return;
433                ResultsHypervolume = new DoubleValue(Hypervolume.Calculate(front, problem.ReferencePoint.CloneAsArray(), problem.Maximization));
434                ResultsDifferenceToBestKnownHypervolume = new DoubleValue(ResultsBestKnownHypervolume.Value - ResultsHypervolume.Value);
435
436                Problem.Analyze(
437                    solutions.Select(s => (Individual)new SingleEncodingIndividual(Problem.Encoding, new Scope { Variables = { new Variable(Problem.Encoding.Name, s.Chromosome) } })).ToArray(),
438                    solutions.Select(s => s.Objectives).ToArray(),
439                    Results,
440                    random);
441            }
442        }
443
444        private void CalculateInvertedGenerationalDistance(MultiObjectiveTestFunctionProblem problem)
445        {
446            double igd;
447            if (problem.TestFunction is ScaledDTLZ dtlz)
448            {
449                // Normalize objectives before calculating the igd
450                var scalingFactor = dtlz.GetScalingFactor(problem.Objectives);
451                var front = new double[solutions.Count][];
452
453                for (int i = 0; i < solutions.Count; i++)
454                {
455                    front[i] = new double[problem.Objectives];
456                    Array.Copy(solutions[i].Objectives, front[i], front[i].Length);
457                    for (int objective = 0; objective < problem.Objectives; objective++)
458                    {
459                        // get normalized value
460                        front[i][objective] = front[i][objective] / Math.Pow(scalingFactor, objective);
461                    }
462                }
463
464                // Normalize best known front before calculating the igd
465                var bestKnownFront = problem.BestKnownFront.ToJaggedArray();
466                foreach (var point in bestKnownFront)
467                {
468                    for (int objective = 0; objective < problem.Objectives; objective++)
469                    {
470                        point[objective] = point[objective] / Math.Pow(scalingFactor, objective);
471                    }
472                }
473
474                igd = InvertedGenerationalDistance.Calculate(front, bestKnownFront, 1);
475            }
476            else
477            {
478                igd = problem.BestKnownFront != null ? InvertedGenerationalDistance.Calculate(solutions.Select(s => s.Objectives), problem.BestKnownFront.ToJaggedArray(), 1) : double.NaN;
479            }
480            ResultsInvertedGenerationalDistance = new DoubleValue(igd);
481            allIgds[ResultsCurrentGeneration.Value - 1] = ResultsInvertedGenerationalDistance.Value;
482        }
483
484        /// <summary>
485        /// Returns the fitness of the given <paramref name="chromosome" /> by applying the Evaluate
486        /// method of the Problem.
487        /// </summary>
488        /// <param name="chromosome"></param>
489        /// <returns></returns>
490        private double[] Evaluate(RealVector chromosome)
491        {
492            return Problem.Evaluate(new SingleEncodingIndividual(Problem.Encoding, new Scope { Variables = { new Variable(Problem.Encoding.Name, chromosome) } }), random);
493        }
494
495        private List<Solution> Recombine(List<Solution> solutions)
496        {
497            List<Solution> childSolutions = new List<Solution>();
498
499            for (int i = 0; i < solutions.Count; i += 2)
500            {
501                if (solutions.Count != PopulationSize.Value) throw new Exception("solutions.Count != PopulationSize");
502                int parentIndex1 = random.Next(solutions.Count);
503                int parentIndex2 = random.Next(solutions.Count);
504                // ensure that the parents are not the same object
505                if (parentIndex1 == parentIndex2) parentIndex2 = (parentIndex2 + 1) % solutions.Count;
506                var parent1 = solutions[parentIndex1];
507                var parent2 = solutions[parentIndex2];
508
509                // Do crossover with crossoverProbabilty == 1 in order to guarantee that a crossover happens
510                var children = SimulatedBinaryCrossover.Apply(random,
511                    Problem.Encoding.Bounds, parent1.Chromosome, parent2.Chromosome, CrossoverProbability.Value, CrossoverEta.Value);
512
513                childSolutions.Add(new Solution(children.Item1));
514                childSolutions.Add(new Solution(children.Item2));
515            }
516
517            return childSolutions;
518        }
519
520        private List<Solution> Mutate(List<Solution> solutions, double eta = 20)
521        {
522            foreach (var solution in solutions)
523            {
524                for (int i = 0; i < solution.Chromosome.Length; i++)
525                {
526                    if (random.NextDouble() > MutationProbability.Value) continue;
527
528                    double y = solution.Chromosome[i];
529                    double lb;
530                    double ub;
531                    var problem = Problem as MultiObjectiveTestFunctionProblem;
532                    if (problem.Bounds.Rows == 1) lb = problem.Bounds[0, 0];
533                    else lb = problem.Bounds[i, 0];
534                    if (problem.Bounds.Rows == 1) ub = problem.Bounds[0, 1];
535                    else ub = problem.Bounds[i, 1];
536
537                    double delta1 = (y - lb) / (ub - lb);
538                    double delta2 = (ub - y) / (ub - lb);
539
540                    double mut_pow = 1.0 / (eta + 1.0);
541
542                    double rnd = random.NextDouble();
543                    double deltaq;
544                    if (rnd <= 0.5)
545                    {
546                        double xy = 1.0 - delta1;
547                        double val = 2.0 * rnd + (1.0 - 2.0 * rnd) * (Math.Pow(xy, (eta + 1.0)));
548                        deltaq = Math.Pow(val, mut_pow) - 1.0;
549                    }
550                    else
551                    {
552                        double xy = 1.0 - delta2;
553                        double val = 2.0 * (1.0 - rnd) + 2.0 * (rnd - 0.5) * (Math.Pow(xy, (eta + 1.0)));
554                        deltaq = 1.0 - (Math.Pow(val, mut_pow));
555                    }
556
557                    y += deltaq * (ub - lb);
558                    y = Math.Min(ub, Math.Max(lb, y));
559
560                    solution.Chromosome[i] = y;
561                }
562            }
563            return solutions;
564        }
565
566        #endregion Private Methods
567    }
568}
Note: See TracBrowser for help on using the repository browser.