Free cookie consent management tool by TermsFeed Policy Generator

source: branches/ContextAlgorithms/HeuristicLab.Algorithms.GeneticAlgorithm/3.3/Model2/GeneticAlgorithm.cs @ 15625

Last change on this file since 15625 was 15625, checked in by abeham, 6 years ago

#2654: implemented generic context-based genetic algorithm

File size: 18.3 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2018 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
22using System;
23using System.Linq;
24using System.Threading;
25using System.Threading.Tasks;
26using HeuristicLab.Analysis;
27using HeuristicLab.Common;
28using HeuristicLab.Core;
29using HeuristicLab.Data;
30using HeuristicLab.Optimization;
31using HeuristicLab.Optimization.Model2;
32using HeuristicLab.Parameters;
33using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
34using HeuristicLab.PluginInfrastructure;
35
36namespace HeuristicLab.Algorithms.GeneticAlgorithm.Model2 {
37  /// <summary>
38  /// A genetic algorithm.
39  /// </summary>
40  [Item("Genetic Algorithm (GA) v2", "A genetic algorithm.")]
41  [Creatable(CreatableAttribute.Categories.PopulationBasedAlgorithms, Priority = 100)]
42  [StorableClass]
43  public sealed class GeneticAlgorithm : StochasticAlgorithm<PopulationContext<SolutionScope>> {
44    public override bool SupportsPause {
45      get { return true; }
46    }
47
48    #region Problem Properties
49    public override Type ProblemType {
50      get { return typeof(ISingleObjectiveHeuristicOptimizationProblem); }
51    }
52    public new ISingleObjectiveHeuristicOptimizationProblem Problem {
53      get { return (ISingleObjectiveHeuristicOptimizationProblem)base.Problem; }
54      set { base.Problem = value; }
55    }
56    #endregion
57
58    #region Parameter Properties
59    private FixedValueParameter<IntValue> PopulationSizeParameter {
60      get { return (FixedValueParameter<IntValue>)Parameters["PopulationSize"]; }
61    }
62    public IConstrainedValueParameter<ISelector> SelectorParameter {
63      get { return (IConstrainedValueParameter<ISelector>)Parameters["Selector"]; }
64    }
65    public IConstrainedValueParameter<ICrossover> CrossoverParameter {
66      get { return (IConstrainedValueParameter<ICrossover>)Parameters["Crossover"]; }
67    }
68    private FixedValueParameter<PercentValue> MutationProbabilityParameter {
69      get { return (FixedValueParameter<PercentValue>)Parameters["MutationProbability"]; }
70    }
71    public IConstrainedValueParameter<IManipulator> MutatorParameter {
72      get { return (IConstrainedValueParameter<IManipulator>)Parameters["Mutator"]; }
73    }
74    private FixedValueParameter<IntValue> ElitesParameter {
75      get { return (FixedValueParameter<IntValue>)Parameters["Elites"]; }
76    }
77    private IFixedValueParameter<BoolValue> ReevaluateElitesParameter {
78      get { return (IFixedValueParameter<BoolValue>)Parameters["ReevaluateElites"]; }
79    }
80    #endregion
81
82    #region Properties
83    public int PopulationSize {
84      get { return PopulationSizeParameter.Value.Value; }
85      set { PopulationSizeParameter.Value.Value = value; }
86    }
87    public ISelector Selector {
88      get { return SelectorParameter.Value; }
89      set { SelectorParameter.Value = value; }
90    }
91    public ICrossover Crossover {
92      get { return CrossoverParameter.Value; }
93      set { CrossoverParameter.Value = value; }
94    }
95    public double MutationProbability {
96      get { return MutationProbabilityParameter.Value.Value; }
97      set { MutationProbabilityParameter.Value.Value = value; }
98    }
99    public IManipulator Mutator {
100      get { return MutatorParameter.Value; }
101      set { MutatorParameter.Value = value; }
102    }
103    public int Elites {
104      get { return ElitesParameter.Value.Value; }
105      set { ElitesParameter.Value.Value = value; }
106    }
107    public bool ReevaluteElites {
108      get { return ReevaluateElitesParameter.Value.Value; }
109      set { ReevaluateElitesParameter.Value.Value = value; }
110    }
111
112    [Storable]
113    private BestAverageWorstQualityAnalyzer qualityAnalyzer;
114    #endregion
115
116    public GeneticAlgorithm()
117      : base() {
118      Parameters.Add(new FixedValueParameter<IntValue>("PopulationSize", "The size of the population of solutions.", new IntValue(100)));
119      Parameters.Add(new ConstrainedValueParameter<ISelector>("Selector", "The operator used to select solutions for reproduction."));
120      Parameters.Add(new ConstrainedValueParameter<ICrossover>("Crossover", "The operator used to cross solutions."));
121      Parameters.Add(new FixedValueParameter<PercentValue>("MutationProbability", "The probability that the mutation operator is applied on a solution.", new PercentValue(0.05)));
122      Parameters.Add(new ConstrainedValueParameter<IManipulator>("Mutator", "The operator used to mutate solutions."));
123      Parameters.Add(new FixedValueParameter<IntValue>("Elites", "The numer of elite solutions which are kept in each generation.", new IntValue(1)));
124      Parameters.Add(new FixedValueParameter<BoolValue>("ReevaluateElites", "Flag to determine if elite individuals should be reevaluated (i.e., if stochastic fitness functions are used.)", new BoolValue(false)) { Hidden = true });
125
126      Analyzer = new MultiAnalyzer();
127
128      foreach (ISelector selector in ApplicationManager.Manager.GetInstances<ISelector>().Where(x => !(x is IMultiObjectiveSelector)).OrderBy(x => x.Name))
129        SelectorParameter.ValidValues.Add(selector);
130      ISelector proportionalSelector = SelectorParameter.ValidValues.FirstOrDefault(x => x.GetType().Name.Equals("ProportionalSelector"));
131      if (proportionalSelector != null) SelectorParameter.Value = proportionalSelector;
132      ParameterizeSelectors();
133
134      qualityAnalyzer = new BestAverageWorstQualityAnalyzer();
135      ParameterizeAnalyzers();
136      UpdateAnalyzers();
137
138      RegisterEventHandlers();
139    }
140    [StorableConstructor]
141    private GeneticAlgorithm(bool deserializing) : base(deserializing) {
142      RegisterEventHandlers();
143    }
144
145    private GeneticAlgorithm(GeneticAlgorithm original, Cloner cloner)
146      : base(original, cloner) {
147      qualityAnalyzer = cloner.Clone(original.qualityAnalyzer);
148      RegisterEventHandlers();
149    }
150    public override IDeepCloneable Clone(Cloner cloner) {
151      return new GeneticAlgorithm(this, cloner);
152    }
153
154    protected override void Initialize(CancellationToken cancellationToken) {
155      base.Initialize(cancellationToken);
156      var max = ((IValueParameter<BoolValue>)Problem.MaximizationParameter).Value.Value;
157      Context.BestQuality = max ? double.MinValue : double.MaxValue;
158
159      for (var m = 0; m < PopulationSize; m++) {
160        Context.AddToPopulation(new SolutionScope(Problem.Evaluator.QualityParameter.ActualName));
161        Context.RunOperator(Problem.SolutionCreator, m, cancellationToken);
162      }
163
164      var locker = new object();
165      Parallel.For(0, PopulationSize, (i) => {
166        Context.RunOperator(Problem.Evaluator, Context.AtPopulation(i), cancellationToken);
167        var fit = Context.AtPopulation(i).Fitness;
168        if (max && Context.BestQuality < fit || !max && Context.BestQuality > fit) {
169          lock (locker) {
170            if (max && Context.BestQuality < fit || !max && Context.BestQuality > fit) {
171              Context.BestQuality = fit;
172            }
173          }
174        }
175      });
176
177      Context.EvaluatedSolutions += PopulationSize;
178
179      Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
180      Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
181      Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
182
183      Context.RunOperator(Analyzer, cancellationToken);
184    }
185
186    protected override void Run(CancellationToken cancellationToken) {
187      var lastUpdate = ExecutionTime;
188      var max = ((IValueParameter<BoolValue>)Problem.MaximizationParameter).Value.Value;
189
190      IResult result;
191      while (!StoppingCriterion()) {
192        Context.Iterations++;
193       
194        Context.RunOperator(Selector, cancellationToken);
195        var currentGen = Context.Scope.SubScopes[0];
196        var nextGen = Context.Scope.SubScopes[1];
197        for (var i = 0; i < PopulationSize - Elites; i++) {
198          var offspring = new SolutionScope(Problem.Evaluator.QualityParameter.ActualName);
199          var p1 = nextGen.SubScopes[0];
200          nextGen.SubScopes.RemoveAt(0);
201          offspring.SubScopes.Add(p1);
202          var p2 = nextGen.SubScopes[0];
203          nextGen.SubScopes.RemoveAt(0);
204          offspring.SubScopes.Add(p2);
205          nextGen.SubScopes.Add(offspring);
206
207          Context.RunOperator(Crossover, offspring, cancellationToken);
208          offspring.SubScopes.Clear();
209          if (Context.Random.NextDouble() < MutationProbability) {
210            Context.RunOperator(Mutator, offspring, cancellationToken);
211          }
212        }
213
214        var locker = new object();
215        Parallel.For(0, PopulationSize - Elites, (i) => {
216          Context.RunOperator(Problem.Evaluator, nextGen.SubScopes[i], cancellationToken);
217          var fit = ((ISolutionScope)nextGen.SubScopes[i]).Fitness;
218          if (max && Context.BestQuality < fit || !max && Context.BestQuality > fit) {
219            lock (locker) {
220              if (max && Context.BestQuality < fit || !max && Context.BestQuality > fit) {
221                Context.BestQuality = fit;
222              }
223            }
224          }
225        });
226        Context.EvaluatedSolutions += PopulationSize - Elites;
227        var elites = (max ? currentGen.SubScopes.OfType<SolutionScope>()
228          .OrderByDescending(x => x.Fitness).Take(Elites)
229          : currentGen.SubScopes.OfType<SolutionScope>()
230          .OrderBy(x => x.Fitness).Take(Elites)).ToList();
231        if (ReevaluteElites) {
232          Parallel.For(0, Elites, (i) => {
233            Context.RunOperator(Problem.Evaluator, elites[i], cancellationToken);
234          });
235          Context.EvaluatedSolutions += Elites;
236        }
237        nextGen.SubScopes.AddRange(elites);
238        Context.Scope.SubScopes.Replace(nextGen.SubScopes);
239
240        if (ExecutionTime - lastUpdate > TimeSpan.FromSeconds(1)) {
241          if (Results.TryGetValue("Iterations", out result))
242            ((IntValue)result.Value).Value = Context.Iterations;
243          else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
244          if (Results.TryGetValue("EvaluatedSolutions", out result))
245            ((IntValue)result.Value).Value = Context.EvaluatedSolutions;
246          else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
247          lastUpdate = ExecutionTime;
248        }
249        if (Results.TryGetValue("BestQuality", out result))
250          ((DoubleValue)result.Value).Value = Context.BestQuality;
251        else Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
252
253        Context.RunOperator(Analyzer, cancellationToken);
254
255        if (cancellationToken.IsCancellationRequested) break;
256      }
257
258      if (Results.TryGetValue("Iterations", out result))
259        ((IntValue)result.Value).Value = Context.Iterations;
260      else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
261      if (Results.TryGetValue("EvaluatedSolutions", out result))
262        ((IntValue)result.Value).Value = Context.EvaluatedSolutions;
263      else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
264     
265      if (Results.TryGetValue("BestQuality", out result))
266        ((DoubleValue) result.Value).Value = Context.BestQuality;
267      else Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
268    }
269
270    public override void Prepare() {
271      if (Problem != null) base.Prepare();
272    }
273
274    #region Events
275    protected override void OnProblemChanged() {
276      ParameterizeStochasticOperator(Problem.SolutionCreator);
277      ParameterizeStochasticOperator(Problem.Evaluator);
278      foreach (IOperator op in Problem.Operators.OfType<IOperator>()) ParameterizeStochasticOperator(op);
279      ParameterizeSelectors();
280      ParameterizeAnalyzers();
281      ParameterizeIterationBasedOperators();
282      UpdateCrossovers();
283      UpdateMutators();
284      UpdateAnalyzers();
285      Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
286      base.OnProblemChanged();
287    }
288   
289    protected override void Problem_OperatorsChanged(object sender, EventArgs e) {
290      foreach (IOperator op in Problem.Operators.OfType<IOperator>()) ParameterizeStochasticOperator(op);
291      ParameterizeIterationBasedOperators();
292      UpdateCrossovers();
293      UpdateMutators();
294      UpdateAnalyzers();
295      base.Problem_OperatorsChanged(sender, e);
296    }
297    private void Elites_ValueChanged(object sender, EventArgs e) {
298      ParameterizeSelectors();
299    }
300    private void PopulationSize_ValueChanged(object sender, EventArgs e) {
301      ParameterizeSelectors();
302    }
303    private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) {
304      ParameterizeSelectors();
305      ParameterizeAnalyzers();
306    }
307    #endregion
308
309    #region Helpers
310    private void RegisterEventHandlers() {
311      PopulationSizeParameter.Value.ValueChanged += new EventHandler(PopulationSize_ValueChanged);
312      ElitesParameter.Value.ValueChanged += new EventHandler(Elites_ValueChanged);
313      if (Problem != null) {
314        Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
315      }
316    }
317   
318    private void ParameterizeStochasticOperator(IOperator op) {
319      IStochasticOperator stochasticOp = op as IStochasticOperator;
320      if (stochasticOp != null) {
321        stochasticOp.RandomParameter.ActualName = nameof(Context.Random);
322        stochasticOp.RandomParameter.Hidden = true;
323      }
324    }
325    private void ParameterizeSelectors() {
326      foreach (ISelector selector in SelectorParameter.ValidValues) {
327        selector.CopySelected = new BoolValue(true);
328        selector.NumberOfSelectedSubScopesParameter.Value = new IntValue(2 * (PopulationSizeParameter.Value.Value - ElitesParameter.Value.Value));
329        selector.NumberOfSelectedSubScopesParameter.Hidden = true;
330        ParameterizeStochasticOperator(selector);
331      }
332      if (Problem != null) {
333        foreach (ISingleObjectiveSelector selector in SelectorParameter.ValidValues.OfType<ISingleObjectiveSelector>()) {
334          selector.MaximizationParameter.ActualName = Problem.MaximizationParameter.Name;
335          selector.MaximizationParameter.Hidden = true;
336          selector.QualityParameter.ActualName = Problem.Evaluator.QualityParameter.ActualName;
337          selector.QualityParameter.Hidden = true;
338        }
339      }
340    }
341    private void ParameterizeAnalyzers() {
342      qualityAnalyzer.ResultsParameter.ActualName = "Results";
343      qualityAnalyzer.ResultsParameter.Hidden = true;
344      if (Problem != null) {
345        qualityAnalyzer.MaximizationParameter.ActualName = Problem.MaximizationParameter.Name;
346        qualityAnalyzer.MaximizationParameter.Hidden = true;
347        qualityAnalyzer.QualityParameter.ActualName = Problem.Evaluator.QualityParameter.ActualName;
348        qualityAnalyzer.QualityParameter.Depth = 1;
349        qualityAnalyzer.QualityParameter.Hidden = true;
350        qualityAnalyzer.BestKnownQualityParameter.ActualName = Problem.BestKnownQualityParameter.Name;
351        qualityAnalyzer.BestKnownQualityParameter.Hidden = true;
352      }
353    }
354    private void ParameterizeIterationBasedOperators() {
355      if (Problem != null) {
356        foreach (IIterationBasedOperator op in Problem.Operators.OfType<IIterationBasedOperator>()) {
357          op.IterationsParameter.ActualName = "Generations";
358          op.IterationsParameter.Hidden = true;
359          op.MaximumIterationsParameter.ActualName = "MaximumGenerations";
360          op.MaximumIterationsParameter.Hidden = true;
361        }
362      }
363    }
364    private void UpdateCrossovers() {
365      ICrossover oldCrossover = CrossoverParameter.Value;
366      CrossoverParameter.ValidValues.Clear();
367      ICrossover defaultCrossover = Problem.Operators.OfType<ICrossover>().FirstOrDefault();
368
369      foreach (ICrossover crossover in Problem.Operators.OfType<ICrossover>().OrderBy(x => x.Name))
370        CrossoverParameter.ValidValues.Add(crossover);
371
372      if (oldCrossover != null) {
373        ICrossover crossover = CrossoverParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldCrossover.GetType());
374        if (crossover != null) CrossoverParameter.Value = crossover;
375        else oldCrossover = null;
376      }
377      if (oldCrossover == null && defaultCrossover != null)
378        CrossoverParameter.Value = defaultCrossover;
379    }
380    private void UpdateMutators() {
381      IManipulator oldMutator = MutatorParameter.Value;
382      MutatorParameter.ValidValues.Clear();
383      IManipulator defaultMutator = Problem.Operators.OfType<IManipulator>().FirstOrDefault();
384
385      foreach (IManipulator mutator in Problem.Operators.OfType<IManipulator>().OrderBy(x => x.Name))
386        MutatorParameter.ValidValues.Add(mutator);
387
388      if (oldMutator != null) {
389        IManipulator mutator = MutatorParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldMutator.GetType());
390        if (mutator != null) MutatorParameter.Value = mutator;
391        else oldMutator = null;
392      }
393
394      if (oldMutator == null && defaultMutator != null)
395        MutatorParameter.Value = defaultMutator;
396    }
397    private void UpdateAnalyzers() {
398      var multiAnalyzer = (MultiAnalyzer)Analyzer;
399      multiAnalyzer.Operators.Clear();
400      if (Problem != null) {
401        foreach (IAnalyzer analyzer in Problem.Operators.OfType<IAnalyzer>()) {
402          foreach (IScopeTreeLookupParameter param in analyzer.Parameters.OfType<IScopeTreeLookupParameter>())
403            param.Depth = 1;
404          multiAnalyzer.Operators.Add(analyzer, analyzer.EnabledByDefault);
405        }
406      }
407      multiAnalyzer.Operators.Add(qualityAnalyzer, qualityAnalyzer.EnabledByDefault);
408    }
409    #endregion
410  }
411}
Note: See TracBrowser for help on using the repository browser.