source: branches/2987_MOEAD_Algorithm/HeuristicLab.Algorithms.MOEAD/3.4/MOEADAlgorithmBase.cs @ 16561

Last change on this file since 16561 was 16561, checked in by bburlacu, 6 months ago

#2987: Store the population as a List, so it can be cleared when the algorithm is finished in order to save memory. Unversion generated files (Plugin.cs and AssemblyInfo.cs)

File size: 25.2 KB
Line 
1using HeuristicLab.Analysis;
2using HeuristicLab.Common;
3using HeuristicLab.Core;
4using HeuristicLab.Data;
5using HeuristicLab.Optimization;
6using HeuristicLab.Parameters;
7using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
8using HeuristicLab.Random;
9using System;
10using System.Collections.Generic;
11using System.Linq;
12
13using CancellationToken = System.Threading.CancellationToken;
14
15namespace HeuristicLab.Algorithms.MOEAD {
16  [Item("MOEADAlgorithmBase", "Base class for all MOEA/D algorithm variants.")]
17  [StorableClass]
18  public abstract class MOEADAlgorithmBase : BasicAlgorithm {
19    #region data members
20    protected enum NeighborType { NEIGHBOR, POPULATION }
21    // TCHE = Chebyshev (Tchebyshev)
22    // PBI  = Penalty-based boundary intersection
23    // AGG  = Weighted sum
24    public enum FunctionType { TCHE, PBI, AGG }
25
26    [Storable]
27    protected double[] IdealPoint { get; set; }
28    [Storable]
29    protected double[] NadirPoint { get; set; } // potentially useful for objective normalization
30
31    [Storable]
32    protected double[][] lambda;
33
34    [Storable]
35    protected int[][] neighbourhood;
36
37    [Storable]
38    protected IList<IMOEADSolution> solutions;
39
40    [Storable]
41    protected FunctionType functionType;
42
43    [Storable]
44    protected List<IMOEADSolution> population;
45
46    [Storable]
47    protected List<IMOEADSolution> offspringPopulation;
48
49    [Storable]
50    protected List<IMOEADSolution> jointPopulation;
51
52    [Storable]
53    protected int evaluatedSolutions;
54
55    [Storable]
56    protected ExecutionContext executionContext;
57
58    [Storable]
59    protected IScope globalScope;
60    #endregion
61
62    #region parameters
63    private const string SeedParameterName = "Seed";
64    private const string SetSeedRandomlyParameterName = "SetSeedRandomly";
65    private const string PopulationSizeParameterName = "PopulationSize";
66    private const string ResultPopulationSizeParameterName = "ResultPopulationSize";
67    private const string CrossoverProbabilityParameterName = "CrossoverProbability";
68    private const string CrossoverParameterName = "Crossover";
69    private const string MutationProbabilityParameterName = "MutationProbability";
70    private const string MutatorParameterName = "Mutator";
71    private const string MaximumEvaluatedSolutionsParameterName = "MaximumEvaluatedSolutions";
72    private const string RandomParameterName = "Random";
73    private const string AnalyzerParameterName = "Analyzer";
74    // MOEA-D parameters
75    private const string NeighbourSizeParameterName = "NeighbourSize";
76    private const string NeighbourhoodSelectionProbabilityParameterName = "NeighbourhoodSelectionProbability";
77    private const string MaximumNumberOfReplacedSolutionsParameterName = "MaximumNumberOfReplacedSolutions";
78    private const string FunctionTypeParameterName = "FunctionType";
79
80    public IValueParameter<MultiAnalyzer> AnalyzerParameter {
81      get { return (ValueParameter<MultiAnalyzer>)Parameters[AnalyzerParameterName]; }
82    }
83
84    public IConstrainedValueParameter<StringValue> FunctionTypeParameter {
85      get { return (IConstrainedValueParameter<StringValue>)Parameters[FunctionTypeParameterName]; }
86    }
87    public IFixedValueParameter<IntValue> NeighbourSizeParameter {
88      get { return (IFixedValueParameter<IntValue>)Parameters[NeighbourSizeParameterName]; }
89    }
90    public IFixedValueParameter<IntValue> MaximumNumberOfReplacedSolutionsParameter {
91      get { return (IFixedValueParameter<IntValue>)Parameters[MaximumNumberOfReplacedSolutionsParameterName]; }
92    }
93    public IFixedValueParameter<DoubleValue> NeighbourhoodSelectionProbabilityParameter {
94      get { return (IFixedValueParameter<DoubleValue>)Parameters[NeighbourhoodSelectionProbabilityParameterName]; }
95    }
96    public IFixedValueParameter<IntValue> SeedParameter {
97      get { return (IFixedValueParameter<IntValue>)Parameters[SeedParameterName]; }
98    }
99    public IFixedValueParameter<BoolValue> SetSeedRandomlyParameter {
100      get { return (IFixedValueParameter<BoolValue>)Parameters[SetSeedRandomlyParameterName]; }
101    }
102    private IValueParameter<IntValue> PopulationSizeParameter {
103      get { return (IValueParameter<IntValue>)Parameters[PopulationSizeParameterName]; }
104    }
105    private IValueParameter<IntValue> ResultPopulationSizeParameter {
106      get { return (IValueParameter<IntValue>)Parameters[ResultPopulationSizeParameterName]; }
107    }
108    public IValueParameter<PercentValue> CrossoverProbabilityParameter {
109      get { return (IValueParameter<PercentValue>)Parameters[CrossoverProbabilityParameterName]; }
110    }
111    public IConstrainedValueParameter<ICrossover> CrossoverParameter {
112      get { return (IConstrainedValueParameter<ICrossover>)Parameters[CrossoverParameterName]; }
113    }
114    public IValueParameter<PercentValue> MutationProbabilityParameter {
115      get { return (IValueParameter<PercentValue>)Parameters[MutationProbabilityParameterName]; }
116    }
117    public IConstrainedValueParameter<IManipulator> MutatorParameter {
118      get { return (IConstrainedValueParameter<IManipulator>)Parameters[MutatorParameterName]; }
119    }
120    public IValueParameter<IntValue> MaximumEvaluatedSolutionsParameter {
121      get { return (IValueParameter<IntValue>)Parameters[MaximumEvaluatedSolutionsParameterName]; }
122    }
123    public IValueParameter<IRandom> RandomParameter {
124      get { return (IValueParameter<IRandom>)Parameters[RandomParameterName]; }
125    }
126    #endregion
127
128    #region parameter properties
129    public new IMultiObjectiveHeuristicOptimizationProblem Problem {
130      get { return (IMultiObjectiveHeuristicOptimizationProblem)base.Problem; }
131    }
132    public int Seed {
133      get { return SeedParameter.Value.Value; }
134      set { SeedParameter.Value.Value = value; }
135    }
136    public bool SetSeedRandomly {
137      get { return SetSeedRandomlyParameter.Value.Value; }
138      set { SetSeedRandomlyParameter.Value.Value = value; }
139    }
140    public IntValue PopulationSize {
141      get { return PopulationSizeParameter.Value; }
142      set { PopulationSizeParameter.Value = value; }
143    }
144    public IntValue ResultPopulationSize {
145      get { return ResultPopulationSizeParameter.Value; }
146      set { ResultPopulationSizeParameter.Value = value; }
147    }
148    public PercentValue CrossoverProbability {
149      get { return CrossoverProbabilityParameter.Value; }
150      set { CrossoverProbabilityParameter.Value = value; }
151    }
152    public ICrossover Crossover {
153      get { return CrossoverParameter.Value; }
154      set { CrossoverParameter.Value = value; }
155    }
156    public PercentValue MutationProbability {
157      get { return MutationProbabilityParameter.Value; }
158      set { MutationProbabilityParameter.Value = value; }
159    }
160    public IManipulator Mutator {
161      get { return MutatorParameter.Value; }
162      set { MutatorParameter.Value = value; }
163    }
164    public MultiAnalyzer Analyzer {
165      get { return AnalyzerParameter.Value; }
166      set { AnalyzerParameter.Value = value; }
167    }
168    public IntValue MaximumEvaluatedSolutions {
169      get { return MaximumEvaluatedSolutionsParameter.Value; }
170      set { MaximumEvaluatedSolutionsParameter.Value = value; }
171    }
172    public int NeighbourSize {
173      get { return NeighbourSizeParameter.Value.Value; }
174      set { NeighbourSizeParameter.Value.Value = value; }
175    }
176    public int MaximumNumberOfReplacedSolutions {
177      get { return MaximumNumberOfReplacedSolutionsParameter.Value.Value; }
178      set { MaximumNumberOfReplacedSolutionsParameter.Value.Value = value; }
179    }
180    public double NeighbourhoodSelectionProbability {
181      get { return NeighbourhoodSelectionProbabilityParameter.Value.Value; }
182      set { NeighbourhoodSelectionProbabilityParameter.Value.Value = value; }
183    }
184    #endregion
185
186    #region constructors
187    public MOEADAlgorithmBase() {
188      Parameters.Add(new FixedValueParameter<IntValue>(SeedParameterName, "The random seed used to initialize the new pseudo random number generator.", new IntValue(0)));
189      Parameters.Add(new FixedValueParameter<BoolValue>(SetSeedRandomlyParameterName, "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true)));
190      Parameters.Add(new ValueParameter<IntValue>(PopulationSizeParameterName, "The size of the population of solutions.", new IntValue(100)));
191      Parameters.Add(new ValueParameter<IntValue>(ResultPopulationSizeParameterName, "The size of the population of solutions.", new IntValue(100)));
192      Parameters.Add(new ValueParameter<PercentValue>(CrossoverProbabilityParameterName, "The probability that the crossover operator is applied.", new PercentValue(0.9)));
193      Parameters.Add(new ConstrainedValueParameter<ICrossover>(CrossoverParameterName, "The operator used to cross solutions."));
194      Parameters.Add(new ValueParameter<PercentValue>(MutationProbabilityParameterName, "The probability that the mutation operator is applied on a solution.", new PercentValue(0.25)));
195      Parameters.Add(new ConstrainedValueParameter<IManipulator>(MutatorParameterName, "The operator used to mutate solutions."));
196      Parameters.Add(new ValueParameter<MultiAnalyzer>("Analyzer", "The operator used to analyze each generation.", new MultiAnalyzer()));
197      Parameters.Add(new ValueParameter<IntValue>(MaximumEvaluatedSolutionsParameterName, "The maximum number of evaluated solutions (approximately).", new IntValue(100_000)));
198      Parameters.Add(new ValueParameter<IRandom>(RandomParameterName, new MersenneTwister()));
199      Parameters.Add(new FixedValueParameter<IntValue>(NeighbourSizeParameterName, new IntValue(20)));
200      Parameters.Add(new FixedValueParameter<IntValue>(MaximumNumberOfReplacedSolutionsParameterName, new IntValue(2)));
201      Parameters.Add(new FixedValueParameter<DoubleValue>(NeighbourhoodSelectionProbabilityParameterName, new DoubleValue(0.1)));
202
203      var functionTypeParameter = new ConstrainedValueParameter<StringValue>(FunctionTypeParameterName);
204      foreach (var s in new[] { "Chebyshev", "PBI", "Weighted Sum" }) {
205        functionTypeParameter.ValidValues.Add(new StringValue(s));
206      }
207      Parameters.Add(functionTypeParameter);
208    }
209
210    protected MOEADAlgorithmBase(MOEADAlgorithmBase original, Cloner cloner) : base(original, cloner) {
211      functionType = original.functionType;
212      evaluatedSolutions = original.evaluatedSolutions;
213
214      if (original.IdealPoint != null) {
215        IdealPoint = (double[])original.IdealPoint.Clone();
216      }
217
218      if (original.NadirPoint != null) {
219        NadirPoint = (double[])original.NadirPoint.Clone();
220      }
221
222      if (original.lambda != null) {
223        lambda = (double[][])original.lambda.Clone();
224      }
225
226      if (original.neighbourhood != null) {
227        neighbourhood = (int[][])original.neighbourhood.Clone();
228      }
229
230      if (original.solutions != null) {
231        solutions = original.solutions.Select(cloner.Clone).ToArray();
232      }
233
234      if (original.population != null) {
235        population = original.population.Select(cloner.Clone).ToList();
236      }
237
238      if (original.offspringPopulation != null) {
239        offspringPopulation = original.offspringPopulation.Select(cloner.Clone).ToList();
240      }
241
242      if (original.jointPopulation != null) {
243        jointPopulation = original.jointPopulation.Select(x => cloner.Clone(x)).ToList();
244      }
245
246      if (original.executionContext != null) {
247        executionContext = cloner.Clone(original.executionContext);
248      }
249
250      if (original.globalScope != null) {
251        globalScope = cloner.Clone(original.globalScope);
252      }
253    }
254
255    [StorableConstructor]
256    protected MOEADAlgorithmBase(bool deserializing) : base(deserializing) { }
257    #endregion
258
259    private void InitializePopulation(ExecutionContext executionContext, CancellationToken cancellationToken, IRandom random, bool[] maximization) {
260      var creator = Problem.SolutionCreator;
261      var evaluator = Problem.Evaluator;
262
263      var dimensions = maximization.Length;
264      var populationSize = PopulationSize.Value;
265      population = new List<IMOEADSolution>(populationSize);
266
267      var parentScope = executionContext.Scope;
268      // first, create all individuals
269      for (int i = 0; i < populationSize; ++i) {
270        var childScope = new Scope(i.ToString()) { Parent = parentScope };
271        ExecuteOperation(executionContext, cancellationToken, executionContext.CreateChildOperation(creator, childScope));
272        parentScope.SubScopes.Add(childScope);
273      }
274
275      // then, evaluate them and update qualities
276      for (int i = 0; i < populationSize; ++i) {
277        var childScope = parentScope.SubScopes[i];
278        ExecuteOperation(executionContext, cancellationToken, executionContext.CreateChildOperation(evaluator, childScope));
279
280        var qualities = (DoubleArray)childScope.Variables["Qualities"].Value;
281        var solution = new MOEADSolution(childScope, dimensions, 0);
282        for (int j = 0; j < dimensions; ++j) {
283          solution.Qualities[j] = maximization[j] ? 1 - qualities[j] : qualities[j];
284        }
285        population.Add(solution);
286      }
287    }
288
289    public override void Prepare() {
290      base.Prepare();
291    }
292
293    protected override void Initialize(CancellationToken cancellationToken) {
294      globalScope = new Scope("Global Scope");
295      executionContext = new ExecutionContext(null, this, globalScope);
296
297      // set the execution context for parameters to allow lookup
298      foreach (var parameter in Problem.Parameters.OfType<IValueParameter>()) {
299        // we need all of these in order for the wiring of the operators to work
300        globalScope.Variables.Add(new Variable(parameter.Name, parameter.Value));
301      }
302      globalScope.Variables.Add(new Variable("Results", Results)); // make results available as a parameter for analyzers etc.
303
304      var rand = RandomParameter.Value;
305      if (SetSeedRandomly) Seed = RandomSeedGenerator.GetSeed();
306      rand.Reset(Seed);
307
308      bool[] maximization = ((BoolArray)Problem.MaximizationParameter.ActualValue).CloneAsArray();
309      var dimensions = maximization.Length;
310
311      var populationSize = PopulationSize.Value;
312
313      InitializePopulation(executionContext, cancellationToken, rand, maximization);
314      InitializeUniformWeights(rand, populationSize, dimensions);
315      InitializeNeighbourHood(lambda, populationSize, NeighbourSize);
316
317      IdealPoint = new double[dimensions];
318      IdealPoint.UpdateIdeal(population);
319
320      NadirPoint = new double[dimensions];
321      NadirPoint.UpdateNadir(population);
322
323      var functionTypeString = FunctionTypeParameter.Value.Value;
324      switch (functionTypeString) {
325        case "Chebyshev":
326          functionType = FunctionType.TCHE;
327          break;
328        case "PBI":
329          functionType = FunctionType.PBI;
330          break;
331        case "Weighted Sum":
332          functionType = FunctionType.AGG;
333          break;
334      }
335
336      evaluatedSolutions = populationSize;
337
338      base.Initialize(cancellationToken);
339    }
340
341    public override bool SupportsPause => true;
342
343    protected void InitializeUniformWeights(IRandom random, int populationSize, int dimensions) {
344      if (dimensions > 2) {
345        throw new ArgumentException("The current implementation doesn't support more than 2 dimensions.");
346      }
347
348      lambda = new double[populationSize][];
349      var values = SequenceGenerator.GenerateSteps(0m, 1m, 1m / populationSize).ToArray();
350
351      for (int i = 0; i < populationSize; ++i) {
352        var w = (double)values[i];
353        lambda[i] = new[] { w, 1 - w };
354      }
355      lambda.ShuffleInPlace(random);
356    }
357
358    protected void InitializeNeighbourHood(double[][] lambda, int populationSize, int neighbourSize) {
359      neighbourhood = new int[populationSize][];
360
361      var x = new double[populationSize];
362      var idx = new int[populationSize];
363
364      for (int i = 0; i < populationSize; ++i) {
365        for (int j = 0; j < populationSize; ++j) {
366          x[j] = MOEADUtil.EuclideanDistance(lambda[i], lambda[j]);
367          idx[j] = j;
368        }
369
370        MOEADUtil.MinFastSort(x, idx, populationSize, neighbourSize);
371        neighbourhood[i] = (int[])idx.Clone();
372      }
373    }
374
375    protected NeighborType ChooseNeighborType(IRandom random, double neighbourhoodSelectionProbability) {
376      return random.NextDouble() < neighbourhoodSelectionProbability
377        ? NeighborType.NEIGHBOR
378        : NeighborType.POPULATION;
379    }
380
381    protected IList<IMOEADSolution> ParentSelection(IRandom random, int subProblemId, NeighborType neighbourType) {
382      List<int> matingPool = MatingSelection(random, subProblemId, 2, neighbourType);
383
384      var parents = new IMOEADSolution[3];
385
386      parents[0] = population[matingPool[0]];
387      parents[1] = population[matingPool[1]];
388      parents[2] = population[subProblemId];
389
390      return parents;
391    }
392
393    protected List<int> MatingSelection(IRandom random, int subproblemId, int numberOfSolutionsToSelect, NeighborType neighbourType) {
394      int populationSize = PopulationSize.Value;
395
396      var listOfSolutions = new List<int>(numberOfSolutionsToSelect);
397
398      int neighbourSize = neighbourhood[subproblemId].Length;
399      while (listOfSolutions.Count < numberOfSolutionsToSelect) {
400        var selectedSolution = neighbourType == NeighborType.NEIGHBOR
401          ? neighbourhood[subproblemId][random.Next(neighbourSize)]
402          : random.Next(populationSize);
403
404        bool flag = true;
405        foreach (int individualId in listOfSolutions) {
406          if (individualId == selectedSolution) {
407            flag = false;
408            break;
409          }
410        }
411
412        if (flag) {
413          listOfSolutions.Add(selectedSolution);
414        }
415      }
416
417      return listOfSolutions;
418    }
419
420    protected void UpdateNeighbourHood(IRandom random, IMOEADSolution individual, int subProblemId, NeighborType neighbourType) {
421      int replacedSolutions = 0;
422      int size = neighbourType == NeighborType.NEIGHBOR ? NeighbourSize : population.Count;
423
424      foreach (var i in Enumerable.Range(0, size).Shuffle(random)) {
425        int k = neighbourType == NeighborType.NEIGHBOR
426          ? neighbourhood[subProblemId][i]
427          : i;
428
429        double f1 = CalculateFitness(population[k].Qualities, lambda[k]);
430        double f2 = CalculateFitness(individual.Qualities, lambda[k]);
431
432        if (f2 < f1) {
433          population[k] = (IMOEADSolution)individual.Clone();
434          replacedSolutions++;
435        }
436
437        if (replacedSolutions >= MaximumNumberOfReplacedSolutions) {
438          return;
439        }
440      }
441    }
442
443    private double CalculateFitness(double[] qualities, double[] lambda) {
444      double fitness;
445      int dim = qualities.Length;
446      switch (functionType) {
447        case FunctionType.TCHE: {
448            double maxFun = -1.0e+30;
449
450            for (int n = 0; n < dim; n++) {
451              double diff = Math.Abs(qualities[n] - IdealPoint[n]);
452
453              double feval = lambda[n] == 0 ? 0.0001 * diff : diff * lambda[n];
454              if (feval > maxFun) {
455                maxFun = feval;
456              }
457            }
458
459            fitness = maxFun;
460            return fitness;
461          }
462        case FunctionType.AGG: {
463            double sum = 0.0;
464            for (int n = 0; n < dim; n++) {
465              sum += lambda[n] * qualities[n];
466            }
467
468            fitness = sum;
469            return fitness;
470          }
471        case FunctionType.PBI: {
472            double d1, d2, nl;
473            double theta = 5.0;
474            int dimensions = dim;
475
476            d1 = d2 = nl = 0.0;
477
478            for (int i = 0; i < dimensions; i++) {
479              d1 += (qualities[i] - IdealPoint[i]) * lambda[i];
480              nl += Math.Pow(lambda[i], 2.0);
481            }
482            nl = Math.Sqrt(nl);
483            d1 = Math.Abs(d1) / nl;
484
485            for (int i = 0; i < dimensions; i++) {
486              d2 += Math.Pow((qualities[i] - IdealPoint[i]) - d1 * (lambda[i] / nl), 2.0);
487            }
488            d2 = Math.Sqrt(d2);
489
490            fitness = (d1 + theta * d2);
491            return fitness;
492          }
493        default: {
494            throw new ArgumentException($"Unknown function type: {functionType}");
495          }
496      }
497    }
498
499    public IList<IMOEADSolution> GetResult(IRandom random) {
500      var populationSize = PopulationSize.Value;
501      var resultPopulationSize = ResultPopulationSize.Value;
502
503      if (populationSize > resultPopulationSize) {
504        return MOEADUtil.GetSubsetOfEvenlyDistributedSolutions(random, population, resultPopulationSize);
505      } else {
506        return population;
507      }
508    }
509
510    protected void UpdateParetoFronts() {
511      bool dominates(Point2D<double> x, Point2D<double> y) => x.X <= y.X && x.Y <= y.Y;
512      // get all non-dominated points
513      var points = population.Select(x => new Point2D<double>(Math.Round(x.Qualities[0], 6), Math.Round(x.Qualities[1], 6))).OrderBy(_ => _.X).ThenBy(_ => _.Y).ToArray();
514      var dominated = new bool[points.Length];
515
516      for (int i = 0; i < points.Length; ++i) {
517        if (dominated[i]) { continue; }
518        for (int j = 0; j < points.Length; ++j) {
519          if (i == j) { continue; }
520          if (dominated[j]) { continue; }
521          dominated[j] = dominates(points[i], points[j]);
522        }
523      }
524
525      var pf = Enumerable.Range(0, dominated.Length).Where(x => !dominated[x]).Select(x => points[x]);
526
527      ScatterPlot sp;
528      if (!Results.ContainsKey("Pareto Front")) {
529        sp = new ScatterPlot();
530        sp.Rows.Add(new ScatterPlotDataRow("Pareto Front", "", pf) { VisualProperties = { PointSize = 5 } });
531        Results.AddOrUpdateResult("Pareto Front", sp);
532      } else {
533        sp = (ScatterPlot)Results["Pareto Front"].Value;
534        sp.Rows["Pareto Front"].Points.Replace(pf);
535      }
536    }
537
538    #region operator wiring and events
539    protected void ExecuteOperation(ExecutionContext executionContext, CancellationToken cancellationToken, IOperation operation) {
540      Stack<IOperation> executionStack = new Stack<IOperation>();
541      executionStack.Push(operation);
542      while (executionStack.Count > 0) {
543        cancellationToken.ThrowIfCancellationRequested();
544        IOperation next = executionStack.Pop();
545        if (next is OperationCollection) {
546          OperationCollection coll = (OperationCollection)next;
547          for (int i = coll.Count - 1; i >= 0; i--)
548            if (coll[i] != null) executionStack.Push(coll[i]);
549        } else if (next is IAtomicOperation) {
550          IAtomicOperation op = (IAtomicOperation)next;
551          next = op.Operator.Execute((IExecutionContext)op, cancellationToken);
552          if (next != null) executionStack.Push(next);
553        }
554      }
555    }
556
557    private void UpdateAnalyzers() {
558      Analyzer.Operators.Clear();
559      if (Problem != null) {
560        foreach (IAnalyzer analyzer in Problem.Operators.OfType<IAnalyzer>()) {
561          foreach (IScopeTreeLookupParameter param in analyzer.Parameters.OfType<IScopeTreeLookupParameter>())
562            param.Depth = 1;
563          Analyzer.Operators.Add(analyzer, analyzer.EnabledByDefault);
564        }
565      }
566    }
567
568    private void UpdateCrossovers() {
569      ICrossover oldCrossover = CrossoverParameter.Value;
570      CrossoverParameter.ValidValues.Clear();
571      ICrossover defaultCrossover = Problem.Operators.OfType<ICrossover>().FirstOrDefault();
572
573      foreach (ICrossover crossover in Problem.Operators.OfType<ICrossover>().OrderBy(x => x.Name))
574        CrossoverParameter.ValidValues.Add(crossover);
575
576      if (oldCrossover != null) {
577        ICrossover crossover = CrossoverParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldCrossover.GetType());
578        if (crossover != null) CrossoverParameter.Value = crossover;
579        else oldCrossover = null;
580      }
581      if (oldCrossover == null && defaultCrossover != null)
582        CrossoverParameter.Value = defaultCrossover;
583    }
584
585    private void UpdateMutators() {
586      IManipulator oldMutator = MutatorParameter.Value;
587      MutatorParameter.ValidValues.Clear();
588      IManipulator defaultMutator = Problem.Operators.OfType<IManipulator>().FirstOrDefault();
589
590      foreach (IManipulator mutator in Problem.Operators.OfType<IManipulator>().OrderBy(x => x.Name))
591        MutatorParameter.ValidValues.Add(mutator);
592
593      if (oldMutator != null) {
594        IManipulator mutator = MutatorParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldMutator.GetType());
595        if (mutator != null) MutatorParameter.Value = mutator;
596        else oldMutator = null;
597      }
598
599      if (oldMutator == null && defaultMutator != null)
600        MutatorParameter.Value = defaultMutator;
601    }
602
603    protected override void OnProblemChanged() {
604      UpdateCrossovers();
605      UpdateMutators();
606      UpdateAnalyzers();
607      base.OnProblemChanged();
608    }
609
610    protected override void OnStopped() {
611      if (solutions != null) {
612        solutions.Clear();
613      }
614      if (population != null) {
615        population.Clear();
616      }
617      if (offspringPopulation != null) {
618        offspringPopulation.Clear();
619      }
620      if (jointPopulation != null) {
621        jointPopulation.Clear();
622      }
623      base.OnStopped();
624    }
625    #endregion
626  }
627}
Note: See TracBrowser for help on using the repository browser.