Free cookie consent management tool by TermsFeed Policy Generator

source: branches/ichiriac/HeuristicLab.Algorithms.DifferentialEvolution/DifferentialEvolution.cs @ 13710

Last change on this file since 13710 was 13710, checked in by ichiriac, 8 years ago

Fix evaluation bug

Correctly update the evaluation number.
Modify the selection function to select different vectors.

File size: 15.4 KB
Line 
1using HeuristicLab.Analysis;
2using HeuristicLab.Common;
3using HeuristicLab.Core;
4using HeuristicLab.Data;
5using HeuristicLab.Encodings.RealVectorEncoding;
6using HeuristicLab.Optimization;
7using HeuristicLab.Parameters;
8using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
9using HeuristicLab.Problems.TestFunctions;
10using HeuristicLab.Random;
11using System;
12using System.Collections.Generic;
13using System.Threading;
14
15namespace HeuristicLab.Algorithms.DifferentialEvolution
16{
17
18    [Item("Differential Evolution (DE)", "A differential evolution algorithm.")]
19    [StorableClass]
20    [Creatable(CreatableAttribute.Categories.PopulationBasedAlgorithms, Priority = 400)]
21    public class DifferentialEvolution : BasicAlgorithm
22    {
23        public Func<IEnumerable<double>, double> Evaluation;
24
25        public override Type ProblemType
26        {
27            get { return typeof(SingleObjectiveTestFunctionProblem); }
28        }
29        public new SingleObjectiveTestFunctionProblem Problem
30        {
31            get { return (SingleObjectiveTestFunctionProblem)base.Problem; }
32            set { base.Problem = value; }
33        }
34
35        private readonly IRandom _random = new MersenneTwister();
36        private int evals;
37
38        #region ParameterNames
39        private const string MaximumEvaluationsParameterName = "Maximum Evaluations";
40        private const string SeedParameterName = "Seed";
41        private const string SetSeedRandomlyParameterName = "SetSeedRandomly";
42        private const string CrossoverProbabilityParameterName = "CrossoverProbability";
43        private const string PopulationSizeParameterName = "PopulationSize";
44        private const string ScalingFactorParameterName = "ScalingFactor";
45        private const string ValueToReachParameterName = "ValueToReach";
46        #endregion
47
48        #region ParameterProperties
49        public IFixedValueParameter<IntValue> MaximumEvaluationsParameter
50        {
51            get { return (IFixedValueParameter<IntValue>)Parameters[MaximumEvaluationsParameterName]; }
52        }
53        public IFixedValueParameter<IntValue> SeedParameter
54        {
55            get { return (IFixedValueParameter<IntValue>)Parameters[SeedParameterName]; }
56        }
57        public FixedValueParameter<BoolValue> SetSeedRandomlyParameter
58        {
59            get { return (FixedValueParameter<BoolValue>)Parameters[SetSeedRandomlyParameterName]; }
60        }
61        private ValueParameter<IntValue> PopulationSizeParameter
62        {
63            get { return (ValueParameter<IntValue>)Parameters[PopulationSizeParameterName]; }
64        }
65        public ValueParameter<DoubleValue> CrossoverProbabilityParameter
66        {
67            get { return (ValueParameter<DoubleValue>)Parameters[CrossoverProbabilityParameterName]; }
68        }
69        public ValueParameter<DoubleValue> ScalingFactorParameter
70        {
71            get { return (ValueParameter<DoubleValue>)Parameters[ScalingFactorParameterName]; }
72        }
73        public ValueParameter<DoubleValue> ValueToReachParameter
74        {
75            get { return (ValueParameter<DoubleValue>)Parameters[ValueToReachParameterName]; }
76        }
77        #endregion
78
79        #region Properties
80        public int MaximumEvaluations
81        {
82            get { return MaximumEvaluationsParameter.Value.Value; }
83            set { MaximumEvaluationsParameter.Value.Value = value; }
84        }
85
86        public Double CrossoverProbability
87        {
88            get { return CrossoverProbabilityParameter.Value.Value; }
89            set { CrossoverProbabilityParameter.Value.Value = value; }
90        }
91        public Double ScalingFactor
92        {
93            get { return ScalingFactorParameter.Value.Value; }
94            set { ScalingFactorParameter.Value.Value = value; }
95        }
96        public int Seed
97        {
98            get { return SeedParameter.Value.Value; }
99            set { SeedParameter.Value.Value = value; }
100        }
101        public bool SetSeedRandomly
102        {
103            get { return SetSeedRandomlyParameter.Value.Value; }
104            set { SetSeedRandomlyParameter.Value.Value = value; }
105        }
106        public IntValue PopulationSize
107        {
108            get { return PopulationSizeParameter.Value; }
109            set { PopulationSizeParameter.Value = value; }
110        }
111        public Double ValueToReach
112        {
113            get { return ValueToReachParameter.Value.Value; }
114            set { ValueToReachParameter.Value.Value = value; }
115        }
116        #endregion
117
118        #region ResultsProperties
119        private double ResultsBestQuality
120        {
121            get { return ((DoubleValue)Results["Best Quality"].Value).Value; }
122            set { ((DoubleValue)Results["Best Quality"].Value).Value = value; }
123        }
124
125        private double VTRBestQuality
126        {
127            get { return ((DoubleValue)Results["VTR"].Value).Value; }
128            set { ((DoubleValue)Results["VTR"].Value).Value = value; }
129        }
130
131        private RealVector ResultsBestSolution
132        {
133            get { return (RealVector)Results["Best Solution"].Value; }
134            set { Results["Best Solution"].Value = value; }
135        }
136
137        private int ResultsEvaluations
138        {
139            get { return ((IntValue)Results["Evaluations"].Value).Value; }
140            set { ((IntValue)Results["Evaluations"].Value).Value = value; }
141        }
142        private int ResultsIterations
143        {
144            get { return ((IntValue)Results["Iterations"].Value).Value; }
145            set { ((IntValue)Results["Iterations"].Value).Value = value; }
146        }
147
148        private DataTable ResultsQualities
149        {
150            get { return ((DataTable)Results["Qualities"].Value); }
151        }
152        private DataRow ResultsQualitiesBest
153        {
154            get { return ResultsQualities.Rows["Best Quality"]; }
155        }
156
157        #endregion
158
159        [StorableConstructor]
160        protected DifferentialEvolution(bool deserializing) : base(deserializing) { }
161
162        protected DifferentialEvolution(DifferentialEvolution original, Cloner cloner)
163          : base(original, cloner)
164        {
165        }
166
167        public override IDeepCloneable Clone(Cloner cloner)
168        {
169            return new DifferentialEvolution(this, cloner);
170        }
171
172        public DifferentialEvolution()
173        {
174            Parameters.Add(new FixedValueParameter<IntValue>(MaximumEvaluationsParameterName, "", new IntValue(Int32.MaxValue)));
175            Parameters.Add(new FixedValueParameter<IntValue>(SeedParameterName, "The random seed used to initialize the new pseudo random number generator.", new IntValue(0)));
176            Parameters.Add(new FixedValueParameter<BoolValue>(SetSeedRandomlyParameterName, "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true)));
177            Parameters.Add(new ValueParameter<IntValue>(PopulationSizeParameterName, "The size of the population of solutions.", new IntValue(75)));
178            Parameters.Add(new ValueParameter<DoubleValue>(CrossoverProbabilityParameterName, "The value for crossover rate", new DoubleValue(0.88)));
179            Parameters.Add(new ValueParameter<DoubleValue>(ScalingFactorParameterName, "The value for scaling factor", new DoubleValue(0.47)));
180            Parameters.Add(new ValueParameter<DoubleValue>(ValueToReachParameterName, "Value to reach (VTR) parameter", new DoubleValue(0.000001)));
181        }
182
183        protected override void Run(CancellationToken cancellationToken)
184        {
185
186            // Set up the results display
187            Results.Add(new Result("Iterations", new IntValue(0)));
188            Results.Add(new Result("Evaluations", new IntValue(0)));
189            Results.Add(new Result("Best Solution", new RealVector()));
190            Results.Add(new Result("Best Quality", new DoubleValue(double.NaN)));
191            Results.Add(new Result("VTR", new DoubleValue(double.NaN)));
192            var table = new DataTable("Qualities");
193            table.Rows.Add(new DataRow("Best Quality"));
194            Results.Add(new Result("Qualities", table));
195
196
197            //problem variables
198            var dim = Problem.ProblemSize.Value;
199            var lb = Problem.Bounds[0, 0];
200            var ub = Problem.Bounds[0, 1];
201            var range = ub - lb;
202
203            double[,] populationOld = new double[PopulationSizeParameter.Value.Value, Problem.ProblemSize.Value];
204            double[,] mutationPopulation = new double[PopulationSizeParameter.Value.Value, Problem.ProblemSize.Value];
205            double[,] trialPopulation = new double[PopulationSizeParameter.Value.Value, Problem.ProblemSize.Value];
206            double[] bestPopulation = new double[Problem.ProblemSize.Value];
207            double[] bestPopulationIteration = new double[Problem.ProblemSize.Value];
208
209            //create initial population
210            //population is a matrix of size PopulationSize*ProblemSize
211            for (int i = 0; i < PopulationSizeParameter.Value.Value; i++)
212            {
213                for (int j = 0; j < Problem.ProblemSize.Value; j++)
214                {
215                    populationOld[i, j] = _random.NextDouble() * range + lb;
216                }
217            }
218
219            //evaluate the best member after the intialiazation
220            //the idea is to select first member and after that to check the others members from the population
221
222            int best_index = 0;
223            double[] populationRow = new double[Problem.ProblemSize.Value];
224
225            bestPopulation = getMatrixRow(populationOld, best_index);
226            RealVector bestPopulationVector = new RealVector(bestPopulation);
227            double bestPopulationValue = Obj(bestPopulationVector);
228            RealVector selectionVector;
229            RealVector trialVector;
230            double qtrial;
231
232
233            for (var i = 0; i < PopulationSizeParameter.Value.Value; i++)
234            {
235                populationRow = getMatrixRow(populationOld, i);
236                trialVector = new RealVector(populationRow);
237
238                qtrial = Obj(trialVector);
239
240                if (qtrial > bestPopulationValue)
241                {
242                    bestPopulationVector = new RealVector(populationRow);
243                    bestPopulationValue = Obj(bestPopulationVector);
244                    best_index = i;
245                }
246            }
247
248            int iterations = 1;
249
250            // Loop until iteration limit reached or canceled.
251            // todo replace with a function
252            while (ResultsEvaluations < MaximumEvaluations
253                && !cancellationToken.IsCancellationRequested
254                && bestPopulationValue > Problem.BestKnownQuality.Value + ValueToReachParameter.Value.Value)
255            {
256
257                //mutation DE/rand/1/bin; classic DE
258                for (int i = 0; i < PopulationSizeParameter.Value.Value; i++)
259                {
260                    int r0, r1, r2;
261
262                    //assure the selected vectors r0, r1 and r2 are different
263                    do
264                     {
265                         r0 = _random.Next(0, PopulationSizeParameter.Value.Value);
266                     } while (r0 == i);
267                     do
268                     {
269                         r1 = _random.Next(0, PopulationSizeParameter.Value.Value);
270                     } while (r1 == i || r1 == r0);
271                     do
272                     {
273                         r2 = _random.Next(0, PopulationSizeParameter.Value.Value);
274                     } while (r2 == i || r2 == r0 || r2 == r1);
275
276                    for (int j = 0; j < getMatrixRow(mutationPopulation, i).Length; j++)
277                    {
278                        mutationPopulation[i,j] = populationOld[r0,j] +
279                            ScalingFactorParameter.Value.Value * (populationOld[r1,j] - populationOld[r2,j]);
280                        //check the problem upper and lower bounds
281                        if (mutationPopulation[i,j] > ub) mutationPopulation[i,j] = ub;
282                        if (mutationPopulation[i,j] < lb) mutationPopulation[i,j] = lb;
283                    }
284                }
285
286                //uniform crossover
287                for (int i = 0; i < PopulationSizeParameter.Value.Value; i++)
288                {
289                    double rnbr = _random.Next(0, Problem.ProblemSize.Value);
290                    for (int j = 0; j < getMatrixRow(mutationPopulation, i).Length; j++)
291                    {
292                        if (_random.NextDouble() <= CrossoverProbabilityParameter.Value.Value || j == rnbr)
293                        {
294                            trialPopulation[i,j] = mutationPopulation[i,j];
295                        }
296                        else
297                        {
298                            trialPopulation[i,j] = populationOld[i,j];
299                        }
300                    }
301                }
302
303                //One-to-One Survivor Selection
304                for (int i = 0; i < PopulationSizeParameter.Value.Value; i++)
305                {
306                    selectionVector = new RealVector(getMatrixRow(populationOld, i));
307                    trialVector = new RealVector(getMatrixRow(trialPopulation, i));
308
309                    var selectionEval = Obj(selectionVector);
310                    var trailEval = Obj(trialVector);
311
312                    if (trailEval < selectionEval)
313                    {
314                        for (int j = 0; j < getMatrixRow(populationOld, i).Length; j++)
315                        {
316                            populationOld[i, j] = trialPopulation[i, j];
317                        }
318                    }
319                }
320
321                //update the best candidate
322                for (int i = 0; i < PopulationSizeParameter.Value.Value; i++)
323                {
324                    selectionVector = new RealVector(getMatrixRow(populationOld, i));
325                    var quality = Obj(selectionVector);
326                    if (quality < bestPopulationValue)
327                    {
328                        bestPopulationVector = (RealVector)selectionVector.Clone();
329                        bestPopulationValue = quality;
330                    }
331                }
332
333                iterations = iterations + 1;
334
335                //update the results
336                ResultsEvaluations = evals;
337                ResultsIterations = iterations;
338                ResultsBestSolution = bestPopulationVector;
339                ResultsBestQuality = bestPopulationValue;
340
341                //update the results in view
342                if (iterations % 10 == 0 ) ResultsQualitiesBest.Values.Add(bestPopulationValue);
343                if (bestPopulationValue < Problem.BestKnownQuality.Value + ValueToReachParameter.Value.Value)
344                {
345                    VTRBestQuality = bestPopulationValue;
346                }
347            }
348        }
349       
350        //evaluate the vector
351        public double Obj(RealVector x)
352        {
353            evals = evals + 1;
354            if (Problem.Maximization.Value)
355            return -Problem.Evaluator.Evaluate(x);
356
357            return Problem.Evaluator.Evaluate(x);
358        }
359
360        // Get ith row from the matrix
361        public double[] getMatrixRow (double[,] Mat, int i)
362        {
363            double[] tmp = new double[Mat.GetUpperBound(1) + 1];
364
365            for (int j = 0; j <= Mat.GetUpperBound(1); j++)
366            {
367                tmp[j] = Mat[i, j];
368            }
369
370            return tmp;
371        }
372    }
373}
374
Note: See TracBrowser for help on using the repository browser.