Free cookie consent management tool by TermsFeed Policy Generator

source: branches/3057_DynamicALPS/backup/17032020/HeuristicLab.Algorithms.DynamicALPS/3.4/DynamicALPSAlgorithmBase.cs @ 17709

Last change on this file since 17709 was 17479, checked in by kyang, 5 years ago

#3057

  1. upload the latest version of ALPS with SMS-EMOA
  2. upload the related dynamic test problems (dynamic, single-objective symbolic regression), written by David Daninel.
File size: 37.9 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2019 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22// 03/02/2020
23// TODO LIST:                                                                     
24// 1. Dynamic reference point strategy                                               
25// 2. Normalized fitness value strategy, desibility function.                         
26// 3. HVC calculation should be definitely improved, at least in the 2D case.
27// 4. multiple point strategy when $\lambda>1$
28
29using HEAL.Attic;
30using HeuristicLab.Analysis;
31using HeuristicLab.Common;
32using HeuristicLab.Core;
33using HeuristicLab.Data;
34using HeuristicLab.ExpressionGenerator;
35using HeuristicLab.Optimization;
36using HeuristicLab.Parameters;
37using HeuristicLab.Problems.DataAnalysis;
38using HeuristicLab.Problems.TestFunctions.MultiObjective;
39using HeuristicLab.Random;
40using System;
41using System.Collections.Generic;
42using System.Drawing;
43using System.Linq;
44using CancellationToken = System.Threading.CancellationToken;
45
46namespace HeuristicLab.Algorithms.DynamicALPS {
47  [Item("DynamicALPSAlgorithmBase", "Base class for all DynamicALPS algorithm variants.")]
48  [StorableType("C0141748-DF5A-4CA0-A3DD-1DFB98236F7E")]
49  public abstract class DynamicALPSAlgorithmBase : BasicAlgorithm {
50    #region data members
51 
52    [StorableType("75C9EA99-D699-4A1F-8AB2-AB86B7A2FD68")]
53    protected enum NeighborType { NEIGHBOR, POPULATION }
54
55
56    [StorableType("2A71E397-05CE-460F-B982-EE2F4B37C354")]
57    // TCHE = Chebyshev (Tchebyshev)
58    // PBI  = Penalty-based boundary intersection
59    // AGG  = Weighted sum
60    public enum FunctionType { TCHE, PBI, AGG }
61
62    [Storable]
63    protected double[] IdealPoint { get; set; }
64    [Storable]
65    protected double[] NadirPoint { get; set; } // potentially useful for objective normalization
66
67    [Storable]
68    protected double[][] lambda_moead;
69
70    [Storable]
71    protected int[][] neighbourhood;
72
73    [Storable]
74    protected IDynamicALPSSolution[] solutions;
75
76    [Storable]
77    protected FunctionType functionType;
78
79    [Storable]
80    protected IDynamicALPSSolution[] population;
81
82    [Storable]
83    protected IDynamicALPSSolution[][] layerPopulation;
84
85    [Storable]
86    protected bool[] activeLayer;
87
88    [Storable]
89    protected IDynamicALPSSolution[][] layerDiscardPopulation;
90
91    [Storable]
92    protected IDynamicALPSSolution[][] layerOffspringPopulation;
93
94    [Storable]
95    protected IDynamicALPSSolution[][] layerJointPopulation;
96
97    [Storable]
98    protected IDynamicALPSSolution[] offspringPopulation;
99
100    //[Storable]
101    //protected IDynamicALPSSolution[] jointPopulation;
102
103    [Storable]
104    protected int evaluatedSolutions;
105
106    [Storable]
107    protected ExecutionContext executionContext;
108
109    [Storable]
110    protected IScope globalScope;
111
112    [Storable]
113    protected ExecutionState previousExecutionState;
114
115    [Storable]
116    protected ExecutionState executionState;
117
118    private DoubleArray ReferencePoint {
119      get {
120        var problem = (MultiObjectiveTestFunctionProblem)Problem;
121        return problem.ReferencePoint;
122      }
123    }
124    #endregion
125
126    #region parameters
127    private const string SeedParameterName = "Seed";
128    private const string SetSeedRandomlyParameterName = "SetSeedRandomly";
129    private const string PopulationSizeParameterName = "PopulationSize";
130    private const string ResultPopulationSizeParameterName = "ResultPopulationSize";
131    private const string CrossoverProbabilityParameterName = "CrossoverProbability";
132    private const string CrossoverParameterName = "Crossover";
133    private const string MutationProbabilityParameterName = "MutationProbability";
134    private const string MutatorParameterName = "Mutator";
135    private const string MaximumEvaluatedSolutionsParameterName = "MaximumEvaluatedSolutions";
136    private const string RandomParameterName = "Random";
137    private const string AnalyzerParameterName = "Analyzer";
138    // MOEA-D parameters
139    //private const string NeighbourSizeParameterName = "NeighbourSize";
140    //private const string NeighbourhoodSelectionProbabilityParameterName = "NeighbourhoodSelectionProbability";
141    //private const string MaximumNumberOfReplacedSolutionsParameterName = "MaximumNumberOfReplacedSolutions";
142    //private const string FunctionTypeParameterName = "FunctionType";
143    // private const string NormalizeObjectivesParameterName = "NormalizeObjectives";
144
145    // SMS-EMOA parameters:
146    private const string LambdaParameterName = "Lambda";   // The number of offspring size
147    private const string ALPSLayersParameterName = "ALPSLayers";   // The number of offspring size
148    private const string ALPSAgeGapParameterName = "ALPSAgeGap";   // The number of offspring size
149
150
151
152    // "Parameters" are defined in "HeuristicLab.Parameters"
153    // Contains: generic parameters of every class/algorithm/instance,
154    // It seems that "I***ValueParameter" is declared in "Heuristic.core", where "***ValueParameter" are defined in "HeuristicLab.Parameter"
155    // The function of "I***ValueParameter" is to bridge current scripts to "HeuristicLab.Parameter".
156    public IValueParameter<MultiAnalyzer> AnalyzerParameter {
157      get { return (ValueParameter<MultiAnalyzer>)Parameters[AnalyzerParameterName]; }
158    }
159
160    //public IConstrainedValueParameter<StringValue> FunctionTypeParameter
161    //{
162    //  get { return (IConstrainedValueParameter<StringValue>)Parameters[FunctionTypeParameterName]; }
163    //}
164    //public IFixedValueParameter<IntValue> NeighbourSizeParameter
165    //{
166    //  get { return (IFixedValueParameter<IntValue>)Parameters[NeighbourSizeParameterName]; }
167    //}
168    //public IFixedValueParameter<BoolValue> NormalizeObjectivesParameter
169    //{
170    //  get { return (IFixedValueParameter<BoolValue>)Parameters[NormalizeObjectivesParameterName]; }
171    //}
172    //public IFixedValueParameter<IntValue> MaximumNumberOfReplacedSolutionsParameter
173    //{
174    //  get { return (IFixedValueParameter<IntValue>)Parameters[MaximumNumberOfReplacedSolutionsParameterName]; }
175    //}
176    //public IFixedValueParameter<DoubleValue> NeighbourhoodSelectionProbabilityParameter
177    //{
178    //  get { return (IFixedValueParameter<DoubleValue>)Parameters[NeighbourhoodSelectionProbabilityParameterName]; }
179    //}
180    public IFixedValueParameter<IntValue> SeedParameter {
181      get { return (IFixedValueParameter<IntValue>)Parameters[SeedParameterName]; }
182    }
183    public IFixedValueParameter<BoolValue> SetSeedRandomlyParameter {
184      get { return (IFixedValueParameter<BoolValue>)Parameters[SetSeedRandomlyParameterName]; }
185    }
186    private IValueParameter<IntValue> PopulationSizeParameter {
187      get { return (IValueParameter<IntValue>)Parameters[PopulationSizeParameterName]; }
188    }
189    // KF, SMS-EMOA
190    private IValueParameter<IntValue> LambdaParameter {
191      get { return (IValueParameter<IntValue>)Parameters[LambdaParameterName]; }
192    }
193    //// KF, DynamicALPS
194    private IValueParameter<IntValue> ALPSLayersParameter{
195      get { return (IValueParameter<IntValue>)Parameters[ALPSLayersParameterName]; }
196    }
197    private IValueParameter<IntValue> ALPSAgeGapParameter {
198      get { return (IValueParameter<IntValue>)Parameters[ALPSAgeGapParameterName]; }
199    }
200
201    private IValueParameter<IntValue> ResultPopulationSizeParameter {
202      get { return (IValueParameter<IntValue>)Parameters[ResultPopulationSizeParameterName]; }
203    }
204
205    public IValueParameter<PercentValue> CrossoverProbabilityParameter {
206      get { return (IValueParameter<PercentValue>)Parameters[CrossoverProbabilityParameterName]; }
207    }
208    public IConstrainedValueParameter<ICrossover> CrossoverParameter {
209      get { return (IConstrainedValueParameter<ICrossover>)Parameters[CrossoverParameterName]; }
210    }
211    public IValueParameter<PercentValue> MutationProbabilityParameter {
212      get { return (IValueParameter<PercentValue>)Parameters[MutationProbabilityParameterName]; }
213    }
214    public IConstrainedValueParameter<IManipulator> MutatorParameter {
215      get { return (IConstrainedValueParameter<IManipulator>)Parameters[MutatorParameterName]; }
216    }
217    public IValueParameter<IntValue> MaximumEvaluatedSolutionsParameter {
218      get { return (IValueParameter<IntValue>)Parameters[MaximumEvaluatedSolutionsParameterName]; }
219    }
220    public IValueParameter<IRandom> RandomParameter {
221      get { return (IValueParameter<IRandom>)Parameters[RandomParameterName]; }
222    }
223    #endregion
224
225    #region parameter properties
226    public new IMultiObjectiveHeuristicOptimizationProblem Problem {
227      get { return (IMultiObjectiveHeuristicOptimizationProblem)base.Problem; }
228      set { base.Problem = value; }
229    }
230    public int Seed {
231      get { return SeedParameter.Value.Value; }
232      set { SeedParameter.Value.Value = value; }
233    }
234    public bool SetSeedRandomly {
235      get { return SetSeedRandomlyParameter.Value.Value; }
236      set { SetSeedRandomlyParameter.Value.Value = value; }
237    }
238    public IntValue PopulationSize {
239      get { return PopulationSizeParameter.Value; }
240      set { PopulationSizeParameter.Value = value; }
241    }
242    public IntValue Lambda {
243      get { return LambdaParameter.Value; }
244      set { LambdaParameter.Value = value; }
245    }
246
247    public IntValue ResultPopulationSize {
248      get { return ResultPopulationSizeParameter.Value; }
249      set { ResultPopulationSizeParameter.Value = value; }
250    }
251
252    public IntValue ALPSLayers {
253      get { return ALPSLayersParameter.Value; }
254      set { ALPSLayersParameter.Value = value; }
255    }
256
257    public IntValue ALPSAgeGap {
258      get { return ALPSAgeGapParameter.Value; }
259      set { ALPSAgeGapParameter.Value = value; }
260    }
261
262    public PercentValue CrossoverProbability {
263      get { return CrossoverProbabilityParameter.Value; }
264      set { CrossoverProbabilityParameter.Value = value; }
265    }
266    public ICrossover Crossover {
267      get { return CrossoverParameter.Value; }
268      set { CrossoverParameter.Value = value; }
269    }
270    public PercentValue MutationProbability {
271      get { return MutationProbabilityParameter.Value; }
272      set { MutationProbabilityParameter.Value = value; }
273    }
274    public IManipulator Mutator {
275      get { return MutatorParameter.Value; }
276      set { MutatorParameter.Value = value; }
277    }
278    public MultiAnalyzer Analyzer {
279      get { return AnalyzerParameter.Value; }
280      set { AnalyzerParameter.Value = value; }
281    }
282    public IntValue MaximumEvaluatedSolutions {
283      get { return MaximumEvaluatedSolutionsParameter.Value; }
284      set { MaximumEvaluatedSolutionsParameter.Value = value; }
285    }
286    #endregion
287
288    #region constructors
289    public DynamicALPSAlgorithmBase() {
290      // Add or define or specify the parameters that may be use in SMS-EMOA.   
291      // ***("Name", "Description", "Value")
292      //  Name                            Type                Description
293      //  FixedValueParameter:            ANY                 Not changed???
294      //  ValueParameter:                                     Changable??? What is the difference between "ValueParameter" and "FixedVlaueParameter"?????
295
296
297      // types:
298      //      IntValue
299      //      BoolValue
300      //      DoubleValue
301      //      PercentValue
302      //      ICrossover:       
303      //      IManipulator:     
304      //      IRandom:         
305      //      MultiAnalyzer:   
306      //      ---------
307      Parameters.Add(new FixedValueParameter<IntValue>(SeedParameterName, "The random seed used to initialize the new pseudo random number generator.", new IntValue(0)));
308      Parameters.Add(new FixedValueParameter<BoolValue>(SetSeedRandomlyParameterName, "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true)));
309      Parameters.Add(new ValueParameter<IntValue>(PopulationSizeParameterName, "The size of the population of solutions.", new IntValue(100)));
310      Parameters.Add(new ValueParameter<IntValue>(ResultPopulationSizeParameterName, "The size of the population of solutions.", new IntValue(100)));
311      Parameters.Add(new ValueParameter<PercentValue>(CrossoverProbabilityParameterName, "The probability that the crossover operator is applied.", new PercentValue(0.9)));
312      Parameters.Add(new ConstrainedValueParameter<ICrossover>(CrossoverParameterName, "The operator used to cross solutions."));
313      Parameters.Add(new ValueParameter<PercentValue>(MutationProbabilityParameterName, "The probability that the mutation operator is applied on a solution.", new PercentValue(0.25)));
314      Parameters.Add(new ConstrainedValueParameter<IManipulator>(MutatorParameterName, "The operator used to mutate solutions."));
315      Parameters.Add(new ValueParameter<MultiAnalyzer>("Analyzer", "The operator used to analyze each generation.", new MultiAnalyzer()));
316      Parameters.Add(new ValueParameter<IntValue>(MaximumEvaluatedSolutionsParameterName, "The maximum number of evaluated solutions (approximately).", new IntValue(100_000)));
317      Parameters.Add(new ValueParameter<IRandom>(RandomParameterName, new FastRandom()));
318
319      // SMS-EMOA, kf
320      Parameters.Add(new ValueParameter<IntValue>(LambdaParameterName, "The size of the offsprings. Now, it only works when lambda = 1", new IntValue(1)));
321      // DynamicALPS, KF
322      Parameters.Add(new ValueParameter<IntValue>(ALPSLayersParameterName, "Test, maximum = 1000, defualt is 1", new IntValue(10)));
323      Parameters.Add(new ValueParameter<IntValue>(ALPSAgeGapParameterName, "Test, maximum = 1000, defualt is 20", new IntValue(20)));
324     
325
326    }
327
328    protected DynamicALPSAlgorithmBase(DynamicALPSAlgorithmBase original, Cloner cloner) : base(original, cloner) {
329      functionType = original.functionType;
330      evaluatedSolutions = original.evaluatedSolutions;
331      previousExecutionState = original.previousExecutionState;
332
333      if (original.IdealPoint != null) {
334        IdealPoint = (double[])original.IdealPoint.Clone();
335      }
336
337      if (original.NadirPoint != null) {
338        NadirPoint = (double[])original.NadirPoint.Clone();
339      }
340
341      if (original.lambda_moead != null) {
342        lambda_moead = (double[][])original.lambda_moead.Clone();
343      }
344
345      if (original.neighbourhood != null) {
346        neighbourhood = (int[][])original.neighbourhood.Clone();
347      }
348
349      if (original.solutions != null) {
350        solutions = original.solutions.Select(cloner.Clone).ToArray();
351      }
352
353      if (original.population != null) {
354        population = original.population.Select(cloner.Clone).ToArray();
355      }
356
357      if (original.offspringPopulation != null) {
358        offspringPopulation = original.offspringPopulation.Select(cloner.Clone).ToArray();
359      }
360
361      //if (original.jointPopulation != null) {
362      //  jointPopulation = original.jointPopulation.Select(x => cloner.Clone(x)).ToArray();
363      //}
364
365      if (original.executionContext != null) {
366        executionContext = cloner.Clone(original.executionContext);
367      }
368
369      if (original.globalScope != null) {
370        globalScope = cloner.Clone(original.globalScope);
371      }
372    }
373
374
375
376    [StorableConstructor]
377    protected DynamicALPSAlgorithmBase(StorableConstructorFlag deserializing) : base(deserializing) { }
378    #endregion
379
380    private void InitializePopulation(ExecutionContext executionContext, CancellationToken cancellationToken, IRandom random, bool[] maximization) {
381      // creator: how to create the initilized population. "UniformRandom" is used here.
382      // TODO: LHS, latin hypercube sampling? Exisit???
383      var creator = Problem.SolutionCreator;
384      var evaluator = Problem.Evaluator;
385
386      // dimensions: objective space
387      var dimensions = maximization.Length;
388      var populationSize = PopulationSize.Value;
389      population = new IDynamicALPSSolution[populationSize];
390
391      var parentScope = executionContext.Scope;
392      // first, create all individuals
393      for (int i = 0; i < populationSize; ++i) {
394        var childScope = new Scope(i.ToString()) { Parent = parentScope };
395        ExecuteOperation(executionContext, cancellationToken, executionContext.CreateChildOperation(creator, childScope));
396        parentScope.SubScopes.Add(childScope);
397      }
398
399      for (int i = 0; i < populationSize; ++i) {
400        var childScope = parentScope.SubScopes[i];
401        ExecuteOperation(executionContext, cancellationToken, executionContext.CreateChildOperation(evaluator, childScope));
402
403        var qualities = (DoubleArray)childScope.Variables["Qualities"].Value;
404
405        // solution: a method, contains a decision vector and objecitve values     
406        //    solution.Qualities:     objective values, fitness values
407        //    solution.Individual:    decision vector
408        var solution = new DynamicALPSSolution(childScope, dimensions, 0);
409        for (int j = 0; j < dimensions; ++j) {
410          // TODO: convert maximization problems into minimization problems.
411          solution.Qualities[j] = maximization[j] ? 1 - qualities[j] : qualities[j];
412        }
413
414        // population is a collection of solution. 
415        population[i] = solution;
416
417        // KF, DyanmicALPS
418        population[i].HypervolumeContribution[0] = -0;
419        population[i].NondominanceRanking[0] = -0;
420        population[i].Age = 1;
421        population[i].IndividualPc = CrossoverProbability.Value;
422        population[i].IndividualPc = MutationProbability.Value;
423      }
424    }
425
426    protected void InitializeAlgorithm(CancellationToken cancellationToken) { // Type of random operator, "FastRandom" in this script.
427      // RandomParameter <-- Parameters in "HeuristicLab.Core.ParameterizedNameItem",
428      var rand = RandomParameter.Value;
429
430      // Initialize random seed
431      // If random seed exist, get it; otherwise,
432      if (SetSeedRandomly) Seed = RandomSeedGenerator.GetSeed();
433
434      // Call
435      rand.Reset(Seed);
436
437      bool[] maximization = ((BoolArray)Problem.MaximizationParameter.ActualValue).CloneAsArray();
438
439      // dimensions: the dimension in an objective space
440      var dimensions = maximization.Length;
441
442
443      var populationSize = PopulationSize.Value;
444
445      InitializePopulation(executionContext, cancellationToken, rand, maximization);
446
447      IdealPoint = new double[dimensions];
448      IdealPoint.UpdateIdeal(population);
449
450      NadirPoint = Enumerable.Repeat(double.MinValue, dimensions).ToArray();
451      //NadirPoint = new double[dimensions];
452      NadirPoint.UpdateNadir(population);
453
454
455      evaluatedSolutions = populationSize;
456    }
457
458    protected override void Initialize(CancellationToken cancellationToken) {
459      globalScope = new Scope("Global Scope");
460      executionContext = new ExecutionContext(null, this, globalScope);
461
462      // set the execution context for parameters to allow lookup
463      foreach (var parameter in Problem.Parameters.OfType<IValueParameter>()) {
464        // we need all of these in order for the wiring of the operators to work
465        globalScope.Variables.Add(new Variable(parameter.Name, parameter.Value));
466      }
467      globalScope.Variables.Add(new Variable("Results", Results)); // make results available as a parameter for analyzers etc.
468
469      base.Initialize(cancellationToken);
470    }
471
472    public override bool SupportsPause => true;
473
474
475
476
477    // Mate Selection.
478    // Randomly select a specific number of individuals for later operators.
479    // Inputs:
480    //    1. random:                      Random number generate method
481    //    2. numberOfSolutionToSelect:    The number of selection   
482    // Outputs:
483    //    1. listOfSolutions:             The selection individuals
484    protected List<int> MatingSelection(IRandom random, int numberOfSolutionsToSelect) {
485      int populationSize = PopulationSize.Value;
486
487      var listOfSolutions = new List<int>(numberOfSolutionsToSelect);
488
489      while (listOfSolutions.Count < numberOfSolutionsToSelect) {
490        var selectedSolution = random.Next(populationSize);
491
492        bool flag = true;
493        foreach (int individualId in listOfSolutions) {
494          if (individualId == selectedSolution) {
495            flag = false;
496            break;
497          }
498        }
499
500        if (flag) {
501          listOfSolutions.Add(selectedSolution);
502        }
503      }
504      return listOfSolutions;
505    }
506
507    protected void ApplyCrossover(int lambda) {
508    }
509
510    protected void ApplyMutation(int lambda) {
511    }
512
513
514    protected void ApplyEvaluation(int lambda) {
515    }
516
517    protected void ApplyMateSelection(int rho) {
518    }
519
520    protected void InitializeLayer(int indexLayer, int populationSize, int lambda) {
521      layerPopulation[indexLayer] = new IDynamicALPSSolution[populationSize];
522      layerJointPopulation[indexLayer] = new IDynamicALPSSolution[populationSize + lambda];
523      layerOffspringPopulation[indexLayer] = new IDynamicALPSSolution[lambda];
524      layerDiscardPopulation[indexLayer] = new IDynamicALPSSolution[populationSize];
525      activeLayer[indexLayer] = true;
526    }
527
528
529    // Select/Discard the individual(s) according to HVC
530    protected void SmetricSelection(int lambda, int nLayerALPS) {
531      var wholePopulation = layerJointPopulation[nLayerALPS];
532      var qualities = wholePopulation.Select(x => x.Qualities).ToArray();
533
534      var maximization = Enumerable.Repeat(false, IdealPoint.Length).ToArray(); // Minimization or maximization ????
535      var pf2 = DominationCalculator<IDynamicALPSSolution>.CalculateAllParetoFronts(wholePopulation, qualities, maximization, out int[] ranking);
536
537      int numberOfLayer;             // number of layers in PF
538      int numberOfLastLayer;          // number of discarded points in PF (the number of points in the last layer)
539
540      pf2.RemoveAt(pf2.Count() - 1);
541      numberOfLayer = pf2.Count();
542      numberOfLastLayer = pf2[numberOfLayer - 1].Count();
543      double[] hvc = new double[numberOfLastLayer];
544      int discardIndex;
545      if (numberOfLastLayer > lambda) {
546        double tempHV;
547        double smetric;
548        var lastLayer = pf2.Last();
549
550        // TODO: This can be use for dynamic reference point strategy later. Kaifeng , 02/2020
551        // smetric = Hypervolume.Calculate(lastLayer.Select(x => x.Item2), Enumerable.Repeat(11d, NadirPoint.Length).ToArray(), maximization);
552        var reference = ReferencePoint.ToArray();
553        var nondominated = NonDominatedSelect.GetDominatingVectors(lastLayer.Select(x => x.Item2), reference, maximization, false);
554        smetric = nondominated.Any() ? Hypervolume.Calculate(nondominated, reference, maximization) : int.MinValue;
555
556        for (int ii = 0; ii < lastLayer.Count; ++ii) {
557          try { // TODO: This can be use for dynamic reference point strategy later. Kaifeng , 02/2020
558            // tempHV = Hypervolume.Calculate(indices.Where(idx => idx != ii).Select(idx => lastLayer[idx].Item2), Enumerable.Repeat(11d, NadirPoint.Length).ToArray(), maximization);
559            tempHV = Hypervolume.Calculate(Enumerable.Range(0, lastLayer.Count).Where(idx => idx != ii).Select(idx => lastLayer[idx].Item2), reference, maximization);
560          }
561          catch {
562            tempHV = int.MinValue;
563          }
564          hvc[ii] = smetric - tempHV;
565          tempHV = 0;
566        }
567        discardIndex = Array.IndexOf(hvc, hvc.Min());
568        pf2[numberOfLayer - 1].RemoveAt(discardIndex);
569      }
570      else {
571        // TODO: This should be updated when $lambda > 1$
572        pf2.RemoveAt(pf2.Count() - 1);
573        numberOfLayer = numberOfLayer - 1;
574      }
575      layerPopulation[nLayerALPS] = pf2.SelectMany(x => x.Select(y => y.Item1)).ToArray();
576    }
577
578    protected int SMSEMOA(int populationSize, int lambda, int counterLayerALPS) {
579      var innerToken = new CancellationToken();
580      bool[] maximization = ((BoolArray)Problem.MaximizationParameter.ActualValue).CloneAsArray();
581      var maximumEvaluatedSolutions = MaximumEvaluatedSolutions.Value;
582      var crossover = Crossover;
583      var crossoverProbability = CrossoverProbability.Value;
584      var mutator = Mutator;
585      var mutationProbability = MutationProbability.Value;
586      var evaluator = Problem.Evaluator;
587      var analyzer = Analyzer;
588      var rand = RandomParameter.Value;
589
590
591      int indexOffspring = 0;
592      var mates = MatingSelection(rand, 2); // select parents
593                                            //var s1 = (IScope)population[mates[0]].Individual.Clone();
594                                            //var s2 = (IScope)population[mates[1]].Individual.Clone();
595                                            //var ages = population.Select(x => x.Age).ToArray();
596
597      var s1 = (IScope)layerPopulation[counterLayerALPS][mates[0]].Individual.Clone();
598      var s2 = (IScope)layerPopulation[counterLayerALPS][mates[1]].Individual.Clone();
599      var ages = layerPopulation[counterLayerALPS].Select(x => x.Age).ToArray();
600
601      var s1_age = ages[mates[0]];
602      var s2_age = ages[mates[1]];
603      int offSpringAge = 0;
604      s1.Parent = s2.Parent = globalScope;
605      IScope childScope = null;
606
607      // crossover
608      if (rand.NextDouble() < crossoverProbability) {
609        childScope = new Scope($"{mates[0]}+{mates[1]}") { Parent = executionContext.Scope };
610        childScope.SubScopes.Add(s1);
611        childScope.SubScopes.Add(s2);
612        var opCrossover = executionContext.CreateChildOperation(crossover, childScope);
613        ExecuteOperation(executionContext, innerToken, opCrossover);
614        offSpringAge = Math.Max(s1_age, s2_age) + 1;
615        childScope.SubScopes.Clear(); // <<-- VERY IMPORTANT!
616      }
617      else { // MUTATION   POLISHI
618        if (childScope == null) {
619          offSpringAge = ages[mates[0]] + 1;
620        }
621        else {
622        }
623        childScope = childScope ?? s1;
624        var opMutation = executionContext.CreateChildOperation(mutator, childScope);
625        ExecuteOperation(executionContext, innerToken, opMutation);
626      }
627      if (childScope != null) { // Evaluate the childScope
628        var opEvaluation = executionContext.CreateChildOperation(evaluator, childScope);
629        ExecuteOperation(executionContext, innerToken, opEvaluation);
630        // childScope
631        var qualities = (DoubleArray)childScope.Variables["Qualities"].Value;
632        var childSolution = new DynamicALPSSolution(childScope, maximization.Length, 0);
633        // set child qualities
634        for (int j = 0; j < maximization.Length; ++j) {
635          childSolution.Qualities[j] = maximization[j] ? 1 - qualities[j] : qualities[j];
636        }
637        IdealPoint.UpdateIdeal(childSolution.Qualities);
638        NadirPoint.UpdateNadir(childSolution.Qualities);
639        // TODO, KF -- For later usage when $lambda > 1$
640        childSolution.HypervolumeContribution = null;
641        childSolution.NondominanceRanking = null;
642        childSolution.Age = offSpringAge;
643        layerOffspringPopulation[counterLayerALPS][indexOffspring] = childSolution;
644        ++evaluatedSolutions;
645        indexOffspring += 1;
646      }
647      else {
648        // no crossover or mutation were applied, a child was not produced, do nothing
649      }
650
651
652      layerJointPopulation[counterLayerALPS] = new IDynamicALPSSolution[populationSize + lambda];
653      layerPopulation[counterLayerALPS].CopyTo(layerJointPopulation[counterLayerALPS], 0);
654      layerOffspringPopulation[counterLayerALPS].CopyTo(layerJointPopulation[counterLayerALPS], populationSize);
655
656      SmetricSelection(lambda, counterLayerALPS);   // SMS-EMOA
657      return evaluatedSolutions;
658    }
659
660
661
662
663
664
665
666    // Update the Pareto-front approximation set and scatter the solutions in PF approximation set.
667    protected void UpdateParetoFronts() {
668      //var qualities = population.Select(x => Enumerable.Range(0, NadirPoint.Length).Select(i => x.Qualities[i] / NadirPoint[i]).ToArray()).ToArray();
669      var qualities = population.Select(x => x.Qualities).ToArray();
670      var maximization = Enumerable.Repeat(false, IdealPoint.Length).ToArray();                             // DynamicALPS minimizes everything internally
671      var pf = DominationCalculator<IDynamicALPSSolution>.CalculateBestParetoFront(population, qualities, maximization);
672
673      var pf2 = DominationCalculator<IDynamicALPSSolution>.CalculateAllParetoFronts(population, qualities, maximization, out int[] ranking);
674      var n = (int)EnumerableExtensions.BinomialCoefficient(IdealPoint.Length, 2);
675
676
677      // Struture hypervolume
678      // [0,0]:  Value of HV
679      // [0,1]:  PF size, $|PF|$
680      var hypervolumes = new DoubleMatrix(n == 1 ? 1 : n + 1, 2) { ColumnNames = new[] { "PF hypervolume", "PF size" } };
681
682
683      // HV calculation
684      // pf.Select(x => x.Item2): the "Item2" in var "pd"
685      // Enumerable.Repeat(1d, NadirPoint.Length).ToArray():     reference point
686      // maximization:   type of optimization problem:
687      //               True:  maximization problem
688      //               False: minimization problem
689      var reference = ReferencePoint.ToArray();
690      var nondominated = NonDominatedSelect.GetDominatingVectors(pf.Select(x => x.Item2), reference, maximization, false);
691      hypervolumes[0, 0] = nondominated.Any() ? Hypervolume.Calculate(nondominated, reference, maximization) : int.MinValue;
692
693      //hypervolumes[0, 0] = Hypervolume.Calculate(pf.Select(x => x.Item2), reference, maximization);
694      hypervolumes[0, 1] = pf.Count;
695      Console.WriteLine("Current HV is", hypervolumes[0, 0]);
696
697      var elementNames = new List<string>() { "Pareto Front" };
698
699      ResultCollection results;
700      if (Results.ContainsKey("Hypervolume Analysis")) {
701        results = (ResultCollection)Results["Hypervolume Analysis"].Value;
702      }
703      else {
704        results = new ResultCollection();
705        Results.AddOrUpdateResult("Hypervolume Analysis", results);
706      }
707
708      ScatterPlot sp;
709      if (IdealPoint.Length == 2) {
710        var points = pf.Select(x => new Point2D<double>(x.Item2[0], x.Item2[1]));
711        var r = OnlinePearsonsRCalculator.Calculate(points.Select(x => x.X), points.Select(x => x.Y), out OnlineCalculatorError error);
712        if (error != OnlineCalculatorError.None) { r = double.NaN; }
713        var resultName = "Pareto Front Analysis ";
714        if (!results.ContainsKey(resultName)) {
715          sp = new ScatterPlot() {
716            VisualProperties = {
717              XAxisMinimumAuto = false, XAxisMinimumFixedValue = 0d, XAxisMaximumAuto = false, XAxisMaximumFixedValue = 1d,
718              YAxisMinimumAuto = false, YAxisMinimumFixedValue = 0d, YAxisMaximumAuto = false, YAxisMaximumFixedValue = 1d
719            }
720          };
721          sp.Rows.Add(new ScatterPlotDataRow(resultName, "", points) { VisualProperties = { PointSize = 8 } });
722          results.AddOrUpdateResult(resultName, sp);
723        }
724        else {
725          sp = (ScatterPlot)results[resultName].Value;
726          sp.Rows[resultName].Points.Replace(points);
727        }
728        sp.Name = $"Dimensions [0, 1], correlation: {r.ToString("N2")}";
729      }
730      else if (IdealPoint.Length > 2) {
731        var indices = Enumerable.Range(0, IdealPoint.Length).ToArray();
732        var visualProperties = new ScatterPlotDataRowVisualProperties { PointSize = 8, Color = Color.LightGray };
733        var combinations = indices.Combinations(2).ToArray();
734        var maximization2d = new[] { false, false };
735        var solutions2d = pf.Select(x => x.Item1).ToArray();
736        for (int i = 0; i < combinations.Length; ++i) {
737          var c = combinations[i].ToArray();
738
739          // calculate the hypervolume in the 2d coordinate space
740          var reference2d = new[] { 1d, 1d };
741          var qualities2d = pf.Select(x => new[] { x.Item2[c[0]], x.Item2[c[1]] }).ToArray();
742          var pf2d = DominationCalculator<IDynamicALPSSolution>.CalculateBestParetoFront(solutions2d, qualities2d, maximization2d);
743
744          hypervolumes[i + 1, 0] = pf2d.Count > 0 ? Hypervolume.Calculate(pf2d.Select(x => x.Item2), reference2d, maximization2d) : 0d;
745          hypervolumes[i + 1, 1] = pf2d.Count;
746
747          var resultName = $"Pareto Front Analysis [{c[0]}, {c[1]}]";
748          elementNames.Add(resultName);
749
750          var points = pf.Select(x => new Point2D<double>(x.Item2[c[0]], x.Item2[c[1]]));
751          var pf2dPoints = pf2d.Select(x => new Point2D<double>(x.Item2[0], x.Item2[1]));
752
753          if (!results.ContainsKey(resultName)) {
754            sp = new ScatterPlot() {
755              VisualProperties = {
756                XAxisMinimumAuto = false, XAxisMinimumFixedValue = 0d, XAxisMaximumAuto = false, XAxisMaximumFixedValue = 1d,
757                YAxisMinimumAuto = false, YAxisMinimumFixedValue = 0d, YAxisMaximumAuto = false, YAxisMaximumFixedValue = 1d
758              }
759            };
760            sp.Rows.Add(new ScatterPlotDataRow("Pareto Front", "", points) { VisualProperties = visualProperties });
761            sp.Rows.Add(new ScatterPlotDataRow($"Pareto Front [{c[0]}, {c[1]}]", "", pf2dPoints) { VisualProperties = { PointSize = 10, Color = Color.OrangeRed } });
762            results.AddOrUpdateResult(resultName, sp);
763          }
764          else {
765            sp = (ScatterPlot)results[resultName].Value;
766            sp.Rows["Pareto Front"].Points.Replace(points);
767            sp.Rows[$"Pareto Front [{c[0]}, {c[1]}]"].Points.Replace(pf2dPoints);
768          }
769          var r = OnlinePearsonsRCalculator.Calculate(points.Select(x => x.X), points.Select(x => x.Y), out OnlineCalculatorError error);
770          var r2 = r * r;
771          sp.Name = $"Pareto Front [{c[0]}, {c[1]}], correlation: {r2.ToString("N2")}";
772        }
773      }
774      hypervolumes.RowNames = elementNames;
775      results.AddOrUpdateResult("Hypervolumes", hypervolumes);
776    }
777
778    #region operator wiring and events
779    protected void ExecuteOperation(ExecutionContext executionContext, CancellationToken cancellationToken, IOperation operation) {
780      Stack<IOperation> executionStack = new Stack<IOperation>();
781      executionStack.Push(operation);
782      while (executionStack.Count > 0) {
783        cancellationToken.ThrowIfCancellationRequested();
784        IOperation next = executionStack.Pop();
785        if (next is OperationCollection) {
786          OperationCollection coll = (OperationCollection)next;
787          for (int i = coll.Count - 1; i >= 0; i--)
788            if (coll[i] != null) executionStack.Push(coll[i]);
789        }
790        else if (next is IAtomicOperation) {
791          IAtomicOperation op = (IAtomicOperation)next;
792          next = op.Operator.Execute((IExecutionContext)op, cancellationToken);
793          if (next != null) executionStack.Push(next);
794        }
795      }
796    }
797
798    protected virtual void UpdateAnalyzers() {
799      Analyzer.Operators.Clear();
800      if (Problem != null) {
801        foreach (IAnalyzer analyzer in Problem.Operators.OfType<IAnalyzer>()) {
802          foreach (IScopeTreeLookupParameter param in analyzer.Parameters.OfType<IScopeTreeLookupParameter>())
803            param.Depth = 1;
804          Analyzer.Operators.Add(analyzer, analyzer.EnabledByDefault);
805        }
806      }
807    }
808
809    private void UpdateCrossovers() {
810      ICrossover oldCrossover = CrossoverParameter.Value;
811      CrossoverParameter.ValidValues.Clear();
812      ICrossover defaultCrossover = Problem.Operators.OfType<ICrossover>().FirstOrDefault();
813
814      foreach (ICrossover crossover in Problem.Operators.OfType<ICrossover>().OrderBy(x => x.Name))
815        CrossoverParameter.ValidValues.Add(crossover);
816
817      if (oldCrossover != null) {
818        ICrossover crossover = CrossoverParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldCrossover.GetType());
819        if (crossover != null) CrossoverParameter.Value = crossover;
820        else oldCrossover = null;
821      }
822      if (oldCrossover == null && defaultCrossover != null)
823        CrossoverParameter.Value = defaultCrossover;
824    }
825
826    private void UpdateMutators() {
827      IManipulator oldMutator = MutatorParameter.Value;
828      MutatorParameter.ValidValues.Clear();
829      IManipulator defaultMutator = Problem.Operators.OfType<IManipulator>().FirstOrDefault();
830
831      foreach (IManipulator mutator in Problem.Operators.OfType<IManipulator>().OrderBy(x => x.Name))
832        MutatorParameter.ValidValues.Add(mutator);
833
834      if (oldMutator != null) {
835        IManipulator mutator = MutatorParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldMutator.GetType());
836        if (mutator != null) MutatorParameter.Value = mutator;
837        else oldMutator = null;
838      }
839
840      if (oldMutator == null && defaultMutator != null)
841        MutatorParameter.Value = defaultMutator;
842    }
843
844    protected override void OnProblemChanged() {
845      UpdateCrossovers();
846      UpdateMutators();
847      UpdateAnalyzers();
848      base.OnProblemChanged();
849    }
850
851    protected override void OnExecutionStateChanged() {
852      previousExecutionState = executionState;
853      executionState = ExecutionState;
854      base.OnExecutionStateChanged();
855    }
856
857    public void ClearState() {
858      solutions = null;
859      population = null;
860      offspringPopulation = null;
861      //jointPopulation = null;
862      lambda_moead = null;
863      neighbourhood = null;
864      if (executionContext != null && executionContext.Scope != null) {
865        executionContext.Scope.SubScopes.Clear();
866      }
867    }
868
869    protected override void OnStopped() {
870      ClearState();
871      base.OnStopped();
872    }
873    #endregion
874  }
875}
Note: See TracBrowser for help on using the repository browser.