Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 17577 was 17559, checked in by dleko, 5 years ago

#2825: Initialize and analyze solutions of first generation.

File size: 10.8 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("30DF878D-D655-4E76-B3AD-2292C9DD6C5F")]
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        #endregion Storable fields
53
54        #region ParameterAndResultsNames
55
56        // Parameter Names
57
58        private const string SeedName = "Seed";
59        private const string SetSeedRandomlyName = "SetSeedRandomly";
60        private const string PopulationSizeName = "PopulationSize";
61        private const string CrossoverProbabilityName = "CrossOverProbability";
62        private const string MutationProbabilityName = "MutationProbability";
63        private const string MaximumGenerationsName = "MaximumGenerations";
64        private const string DominateOnEqualQualitiesName = "DominateOnEqualQualities";
65
66        // Results Names
67
68        private const string GeneratedReferencePointsResultName = "Generated Reference Points";
69        private const string CurrentFrontResultName = "Pareto Front"; // Do not touch this
70
71        #endregion ParameterAndResultsNames
72
73        #region ParameterProperties
74
75        private IFixedValueParameter<IntValue> SeedParameter
76        {
77            get { return (IFixedValueParameter<IntValue>)Parameters[SeedName]; }
78        }
79
80        private IFixedValueParameter<BoolValue> SetSeedRandomlyParameter
81        {
82            get { return (IFixedValueParameter<BoolValue>)Parameters[SetSeedRandomlyName]; }
83        }
84
85        private IFixedValueParameter<IntValue> PopulationSizeParameter
86        {
87            get { return (IFixedValueParameter<IntValue>)Parameters[PopulationSizeName]; }
88        }
89
90        private IFixedValueParameter<PercentValue> CrossoverProbabilityParameter
91        {
92            get { return (IFixedValueParameter<PercentValue>)Parameters[CrossoverProbabilityName]; }
93        }
94
95        private IFixedValueParameter<PercentValue> MutationProbabilityParameter
96        {
97            get { return (IFixedValueParameter<PercentValue>)Parameters[MutationProbabilityName]; }
98        }
99
100        private IFixedValueParameter<IntValue> MaximumGenerationsParameter
101        {
102            get { return (IFixedValueParameter<IntValue>)Parameters[MaximumGenerationsName]; }
103        }
104
105        private IFixedValueParameter<BoolValue> DominateOnEqualQualitiesParameter
106        {
107            get { return (IFixedValueParameter<BoolValue>)Parameters[DominateOnEqualQualitiesName]; }
108        }
109
110        #endregion ParameterProperties
111
112        #region Properties
113
114        public IntValue Seed => SeedParameter.Value;
115
116        public BoolValue SetSeedRandomly => SetSeedRandomlyParameter.Value;
117
118        public IntValue PopulationSize => PopulationSizeParameter.Value;
119
120        public PercentValue CrossoverProbability => CrossoverProbabilityParameter.Value;
121
122        public PercentValue MutationProbability => MutationProbabilityParameter.Value;
123
124        public IntValue MaximumGenerations => MaximumGenerationsParameter.Value;
125
126        public BoolValue DominateOnEqualQualities => DominateOnEqualQualitiesParameter.Value;
127
128        #endregion Properties
129
130        #region ResultsProperties
131
132        public DoubleMatrix ResultsGeneratedReferencePoints
133        {
134            get { return (DoubleMatrix)Results[GeneratedReferencePointsResultName].Value; }
135            set { Results[GeneratedReferencePointsResultName].Value = value; }
136        }
137
138        public DoubleMatrix ResultsSolutions
139        {
140            get { return (DoubleMatrix)Results[CurrentFrontResultName].Value; }
141            set { Results[CurrentFrontResultName].Value = value; }
142        }
143
144        #endregion ResultsProperties
145
146        public NSGA3() : base()
147        {
148            Parameters.Add(new FixedValueParameter<IntValue>(SeedName, "The random seed used to initialize the new pseudo random number generator.", new IntValue(0)));
149            Parameters.Add(new FixedValueParameter<BoolValue>(SetSeedRandomlyName, "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true)));
150            Parameters.Add(new FixedValueParameter<IntValue>(PopulationSizeName, "The size of the population of Individuals.", new IntValue(100)));
151            Parameters.Add(new FixedValueParameter<PercentValue>(CrossoverProbabilityName, "The probability that the crossover operator is applied on two parents.", new PercentValue(0.9)));
152            Parameters.Add(new FixedValueParameter<PercentValue>(MutationProbabilityName, "The probability that the mutation operator is applied on a Individual.", new PercentValue(0.05)));
153            Parameters.Add(new FixedValueParameter<IntValue>(MaximumGenerationsName, "The maximum number of generations which should be processed.", new IntValue(1000)));
154            Parameters.Add(new FixedValueParameter<BoolValue>(DominateOnEqualQualitiesName, "Flag which determines wether Individuals with equal quality values should be treated as dominated.", new BoolValue(false)));
155        }
156
157        // Persistence uses this ctor to improve deserialization efficiency. If we would use the
158        // default ctor instead this would completely initialize the object (e.g. creating
159        // parameters) even though the data is later overwritten by the stored data.
160        [StorableConstructor]
161        public NSGA3(StorableConstructorFlag _) : base(_) { }
162
163        // Each clonable item must have a cloning ctor (deep cloning, the cloner is used to handle
164        // cyclic object references). Don't forget to call the cloning ctor of the base class
165        public NSGA3(NSGA3 original, Cloner cloner) : base(original, cloner)
166        {
167            // todo: don't forget to clone storable fields
168            random = cloner.Clone(original.random);
169            solutions = original.solutions?.Select(cloner.Clone).ToArray();
170        }
171
172        #region Overriden Methods
173
174        public override IDeepCloneable Clone(Cloner cloner)
175        {
176            return new NSGA3(this, cloner);
177        }
178
179        protected override void Initialize(CancellationToken cancellationToken)
180        {
181            base.Initialize(cancellationToken);
182
183            InitFields();
184            InitResults();
185            InitReferencePoints();
186            Analyze();
187        }
188
189        protected override void Run(CancellationToken cancellationToken)
190        {
191            throw new NotImplementedException();
192        }
193
194        #endregion Overriden Methods
195
196        #region Private Methods
197
198        private void InitFields()
199        {
200            random = new MersenneTwister();
201            InitSolutions();
202        }
203
204        private void InitResults()
205        {
206            Results.Add(new Result(GeneratedReferencePointsResultName, "The initially generated reference points", new DoubleMatrix()));
207            Results.Add(new Result(CurrentFrontResultName, "The Pareto Front", new DoubleMatrix()));
208        }
209
210        private void InitReferencePoints()
211        {
212            // Generate reference points and add them to results
213            int nDiv = 5; // todo: figure out the correct number of divisions
214            List<ReferencePoint> referencePoints = ReferencePoint.GenerateReferencePoints(Problem.Encoding.Length, nDiv);
215            ResultsGeneratedReferencePoints = Utility.ConvertToDoubleMatrix(referencePoints);
216        }
217
218        private void InitSolutions()
219        {
220            int minBound = 0; // todo: find min inside Problem.Encoding
221            int maxBound = 1; // todo: find max inside Problem.Encoding
222
223            // Initialise solutions
224            solutions = new Solution[PopulationSize.Value];
225            for (int i = 0; i < PopulationSize.Value; i++)
226            {
227                RealVector randomRealVector = new RealVector(Problem.Encoding.Length, random, minBound, maxBound);
228
229                solutions[i] = new Solution(StorableConstructorFlag.Default)
230                {
231                    Chromosome = randomRealVector
232                };
233                solutions[i].Fitness = Evaluate(solutions[i].Chromosome);
234            }
235        }
236
237        /// <summary>
238        /// Returns the fitness of the given <paramref name="chromosome" /> by applying the Evaluate
239        /// method of the Problem.
240        /// </summary>
241        /// <param name="chromosome"></param>
242        /// <returns></returns>
243        private double[] Evaluate(RealVector chromosome)
244        {
245            return Problem.Evaluate(new SingleEncodingIndividual(Problem.Encoding, new Scope { Variables = { new Variable(Problem.Encoding.Name, chromosome) } }), random);
246        }
247
248        private void Analyze()
249        {
250            ResultsSolutions = solutions.Select(s => s.Chromosome.ToArray()).ToMatrix();
251            Problem.Analyze(
252                solutions.Select(s => (Individual)new SingleEncodingIndividual(Problem.Encoding, new Scope { Variables = { new Variable(Problem.Encoding.Name, s.Chromosome) } })).ToArray(),
253                solutions.Select(s => s.Fitness).ToArray(),
254                Results,
255                random
256                );
257        }
258
259        #endregion Private Methods
260    }
261}
Note: See TracBrowser for help on using the repository browser.