Free cookie consent management tool by TermsFeed Policy Generator

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

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

#2825 The list of Reference Points are now a storable field in the NSGA3 class.

File size: 10.9 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Threading;
5using HEAL.Attic;
6using HeuristicLab.Common;
7using HeuristicLab.Core;
8using HeuristicLab.Data;
9using HeuristicLab.Encodings.RealVectorEncoding;
10using HeuristicLab.Optimization;
11using HeuristicLab.Parameters;
12using HeuristicLab.Random;
13
14namespace HeuristicLab.Algorithms.NSGA3
15{
16    /// <summary>
17    /// The Reference Point Based Non-dominated Sorting Genetic Algorithm III was introduced in Deb
18    /// et al. 2013. An Evolutionary Many-Objective Optimization Algorithm Using Reference Point
19    /// Based Non-dominated Sorting Approach. IEEE Transactions on Evolutionary Computation, 18(4),
20    /// pp. 577-601.
21    /// </summary>
22    [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.")]
23    [Creatable(Category = CreatableAttribute.Categories.PopulationBasedAlgorithms, Priority = 136)]
24    [StorableType("07C745F7-A8A3-4F99-8B2C-F97E639F9AC3")]
25    public class NSGA3 : BasicAlgorithm
26    {
27        public override bool SupportsPause => false; // todo: make true
28
29        #region ProblemProperties
30
31        public override Type ProblemType
32        {
33            get { return typeof(MultiObjectiveBasicProblem<RealVectorEncoding>); }
34        }
35
36        public new MultiObjectiveBasicProblem<RealVectorEncoding> Problem
37        {
38            get { return (MultiObjectiveBasicProblem<RealVectorEncoding>)base.Problem; }
39            set { base.Problem = value; }
40        }
41
42        #endregion ProblemProperties
43
44        #region Storable fields
45
46        [Storable]
47        private IRandom random;
48
49        [Storable]
50        private Solution[] solutions;
51
52        [Storable]
53        private List<ReferencePoint> referencePoints;
54
55        #endregion Storable fields
56
57        #region ParameterAndResultsNames
58
59        // Parameter Names
60
61        private const string SeedName = "Seed";
62        private const string SetSeedRandomlyName = "SetSeedRandomly";
63        private const string PopulationSizeName = "PopulationSize";
64        private const string CrossoverProbabilityName = "CrossOverProbability";
65        private const string MutationProbabilityName = "MutationProbability";
66        private const string MaximumGenerationsName = "MaximumGenerations";
67        private const string DominateOnEqualQualitiesName = "DominateOnEqualQualities";
68
69        // Results Names
70
71        private const string GeneratedReferencePointsResultName = "Generated Reference Points";
72        private const string CurrentFrontResultName = "Pareto Front"; // Do not touch this
73
74        #endregion ParameterAndResultsNames
75
76        #region ParameterProperties
77
78        private IFixedValueParameter<IntValue> SeedParameter
79        {
80            get { return (IFixedValueParameter<IntValue>)Parameters[SeedName]; }
81        }
82
83        private IFixedValueParameter<BoolValue> SetSeedRandomlyParameter
84        {
85            get { return (IFixedValueParameter<BoolValue>)Parameters[SetSeedRandomlyName]; }
86        }
87
88        private IFixedValueParameter<IntValue> PopulationSizeParameter
89        {
90            get { return (IFixedValueParameter<IntValue>)Parameters[PopulationSizeName]; }
91        }
92
93        private IFixedValueParameter<PercentValue> CrossoverProbabilityParameter
94        {
95            get { return (IFixedValueParameter<PercentValue>)Parameters[CrossoverProbabilityName]; }
96        }
97
98        private IFixedValueParameter<PercentValue> MutationProbabilityParameter
99        {
100            get { return (IFixedValueParameter<PercentValue>)Parameters[MutationProbabilityName]; }
101        }
102
103        private IFixedValueParameter<IntValue> MaximumGenerationsParameter
104        {
105            get { return (IFixedValueParameter<IntValue>)Parameters[MaximumGenerationsName]; }
106        }
107
108        private IFixedValueParameter<BoolValue> DominateOnEqualQualitiesParameter
109        {
110            get { return (IFixedValueParameter<BoolValue>)Parameters[DominateOnEqualQualitiesName]; }
111        }
112
113        #endregion ParameterProperties
114
115        #region Properties
116
117        public IntValue Seed => SeedParameter.Value;
118
119        public BoolValue SetSeedRandomly => SetSeedRandomlyParameter.Value;
120
121        public IntValue PopulationSize => PopulationSizeParameter.Value;
122
123        public PercentValue CrossoverProbability => CrossoverProbabilityParameter.Value;
124
125        public PercentValue MutationProbability => MutationProbabilityParameter.Value;
126
127        public IntValue MaximumGenerations => MaximumGenerationsParameter.Value;
128
129        public BoolValue DominateOnEqualQualities => DominateOnEqualQualitiesParameter.Value;
130
131        #endregion Properties
132
133        #region ResultsProperties
134
135        public DoubleMatrix ResultsGeneratedReferencePoints
136        {
137            get { return (DoubleMatrix)Results[GeneratedReferencePointsResultName].Value; }
138            set { Results[GeneratedReferencePointsResultName].Value = value; }
139        }
140
141        public DoubleMatrix ResultsSolutions
142        {
143            get { return (DoubleMatrix)Results[CurrentFrontResultName].Value; }
144            set { Results[CurrentFrontResultName].Value = value; }
145        }
146
147        #endregion ResultsProperties
148
149        public NSGA3() : base()
150        {
151            Parameters.Add(new FixedValueParameter<IntValue>(SeedName, "The random seed used to initialize the new pseudo random number generator.", new IntValue(0)));
152            Parameters.Add(new FixedValueParameter<BoolValue>(SetSeedRandomlyName, "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true)));
153            Parameters.Add(new FixedValueParameter<IntValue>(PopulationSizeName, "The size of the population of Individuals.", new IntValue(100)));
154            Parameters.Add(new FixedValueParameter<PercentValue>(CrossoverProbabilityName, "The probability that the crossover operator is applied on two parents.", new PercentValue(0.9)));
155            Parameters.Add(new FixedValueParameter<PercentValue>(MutationProbabilityName, "The probability that the mutation operator is applied on a Individual.", new PercentValue(0.05)));
156            Parameters.Add(new FixedValueParameter<IntValue>(MaximumGenerationsName, "The maximum number of generations which should be processed.", new IntValue(1000)));
157            Parameters.Add(new FixedValueParameter<BoolValue>(DominateOnEqualQualitiesName, "Flag which determines wether Individuals with equal quality values should be treated as dominated.", new BoolValue(false)));
158        }
159
160        // Persistence uses this ctor to improve deserialization efficiency. If we would use the
161        // default ctor instead this would completely initialize the object (e.g. creating
162        // parameters) even though the data is later overwritten by the stored data.
163        [StorableConstructor]
164        public NSGA3(StorableConstructorFlag _) : base(_) { }
165
166        // Each clonable item must have a cloning ctor (deep cloning, the cloner is used to handle
167        // cyclic object references). Don't forget to call the cloning ctor of the base class
168        public NSGA3(NSGA3 original, Cloner cloner) : base(original, cloner)
169        {
170            // todo: don't forget to clone storable fields
171            random = cloner.Clone(original.random);
172            solutions = original.solutions?.Select(cloner.Clone).ToArray();
173        }
174
175        #region Overriden Methods
176
177        public override IDeepCloneable Clone(Cloner cloner)
178        {
179            return new NSGA3(this, cloner);
180        }
181
182        protected override void Initialize(CancellationToken cancellationToken)
183        {
184            base.Initialize(cancellationToken);
185
186            InitFields();
187            InitReferencePoints();
188            InitResults();
189            Analyze();
190        }
191
192        protected override void Run(CancellationToken cancellationToken)
193        {
194            throw new NotImplementedException();
195        }
196
197        #endregion Overriden Methods
198
199        #region Private Methods
200
201        private void InitFields()
202        {
203            random = new MersenneTwister();
204            InitSolutions();
205        }
206
207        private void InitSolutions()
208        {
209            int minBound = 0; // todo: find min inside Problem.Encoding
210            int maxBound = 1; // todo: find max inside Problem.Encoding
211
212            // Initialise solutions
213            solutions = new Solution[PopulationSize.Value];
214            for (int i = 0; i < PopulationSize.Value; i++)
215            {
216                RealVector randomRealVector = new RealVector(Problem.Encoding.Length, random, minBound, maxBound);
217
218                solutions[i] = new Solution(StorableConstructorFlag.Default)
219                {
220                    Chromosome = randomRealVector
221                };
222                solutions[i].Fitness = Evaluate(solutions[i].Chromosome);
223            }
224        }
225
226        private void InitReferencePoints()
227        {
228            // Generate reference points and add them to results
229            int nDiv = 5; // todo: figure out the correct number of divisions
230            referencePoints = ReferencePoint.GenerateReferencePoints(Problem.Encoding.Length, nDiv);
231            ResultsGeneratedReferencePoints = Utility.ConvertToDoubleMatrix(referencePoints);
232        }
233
234        private void InitResults()
235        {
236            Results.Add(new Result(GeneratedReferencePointsResultName, "The initially generated reference points", Utility.ConvertToDoubleMatrix(referencePoints)));
237            Results.Add(new Result(CurrentFrontResultName, "The Pareto Front", new DoubleMatrix()));
238        }
239
240        private void Analyze()
241        {
242            ResultsSolutions = solutions.Select(s => s.Chromosome.ToArray()).ToMatrix();
243            Problem.Analyze(
244                solutions.Select(s => (Individual)new SingleEncodingIndividual(Problem.Encoding, new Scope { Variables = { new Variable(Problem.Encoding.Name, s.Chromosome) } })).ToArray(),
245                solutions.Select(s => s.Fitness).ToArray(),
246                Results,
247                random
248                );
249        }
250
251        /// <summary>
252        /// Returns the fitness of the given <paramref name="chromosome" /> by applying the Evaluate
253        /// method of the Problem.
254        /// </summary>
255        /// <param name="chromosome"></param>
256        /// <returns></returns>
257        private double[] Evaluate(RealVector chromosome)
258        {
259            return Problem.Evaluate(new SingleEncodingIndividual(Problem.Encoding, new Scope { Variables = { new Variable(Problem.Encoding.Name, chromosome) } }), random);
260        }
261
262        #endregion Private Methods
263    }
264}
Note: See TracBrowser for help on using the repository browser.