Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2521_ProblemRefactoring/HeuristicLab.Algorithms.GeneticAlgorithm/3.3/CanonicalGeneticAlgorithm.cs @ 16147

Last change on this file since 16147 was 14429, checked in by abeham, 8 years ago

#2701, #2708: Made a new branch from ProblemRefactoring and removed ScopedBasicAlgorithm branch (which becomes MemPR branch)

File size: 9.4 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2016 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.Collections.Generic;
24using System.Linq;
25using System.Threading;
26using System.Threading.Tasks;
27using HeuristicLab.Analysis;
28using HeuristicLab.Common;
29using HeuristicLab.Core;
30using HeuristicLab.Data;
31using HeuristicLab.Optimization;
32using HeuristicLab.Optimization.Selection;
33using HeuristicLab.Optimization.Algorithms.SingleObjective;
34using HeuristicLab.Optimization.Crossover;
35using HeuristicLab.Optimization.Manipulation;
36using HeuristicLab.Parameters;
37using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
38
39namespace HeuristicLab.Algorithms.GeneticAlgorithm {
40  public class CanonicalGeneticAlgorithm<TProblem, TEncoding, TSolution> : HeuristicAlgorithm<EvolutionaryAlgorithmContext<TProblem, TEncoding, TSolution>, TProblem, TEncoding, TSolution>
41      where TProblem : class, ISingleObjectiveProblem<TEncoding, TSolution>, ISingleObjectiveProblemDefinition<TEncoding, TSolution>
42      where TEncoding : class, IEncoding<TSolution>
43      where TSolution : class, ISolution {
44
45    [Storable]
46    private IValueParameter<IntValue> populationSize;
47    public int PopulationSize {
48      get { return populationSize.Value.Value; }
49      set {
50        if (value < 2) throw new ArgumentException("PopulationSize cannot be smaller than 2");
51        populationSize.Value.Value = value;
52      }
53    }
54
55    [Storable]
56    private IConstrainedValueParameter<ISelector<EvolutionaryAlgorithmContext<TProblem, TEncoding, TSolution>>> selector;
57    public IConstrainedValueParameter<ISelector<EvolutionaryAlgorithmContext<TProblem, TEncoding, TSolution>>> SelectorParameter {
58      get { return selector; }
59    }
60    public ISelector<EvolutionaryAlgorithmContext<TProblem, TEncoding, TSolution>> Selector {
61      get { return selector.Value; }
62      set {
63        if (!selector.ValidValues.Contains(value))
64          selector.ValidValues.Add(value);
65        selector.Value = value;
66      }
67    }
68
69    [Storable]
70    private IConstrainedValueParameter<ICrossover<EvolutionaryAlgorithmContext<TProblem, TEncoding, TSolution>>> crossover;
71    public IConstrainedValueParameter<ICrossover<EvolutionaryAlgorithmContext<TProblem, TEncoding, TSolution>>> CrossoverParameter {
72      get { return crossover; }
73    }
74    public ICrossover<EvolutionaryAlgorithmContext<TProblem, TEncoding, TSolution>> Crossover {
75      get { return crossover.Value; }
76      set {
77        if (!crossover.ValidValues.Contains(value))
78          crossover.ValidValues.Add(value);
79        crossover.Value = value;
80      }
81    }
82
83    [Storable]
84    private IConstrainedValueParameter<IManipulator<EvolutionaryAlgorithmContext<TProblem, TEncoding, TSolution>>> mutator;
85    public IConstrainedValueParameter<IManipulator<EvolutionaryAlgorithmContext<TProblem, TEncoding, TSolution>>> MutatorParameter {
86      get { return mutator; }
87    }
88    public IManipulator<EvolutionaryAlgorithmContext<TProblem, TEncoding, TSolution>> Mutator {
89      get { return mutator.Value; }
90      set {
91        if (!mutator.ValidValues.Contains(value))
92          mutator.ValidValues.Add(value);
93        mutator.Value = value;
94      }
95    }
96
97    [Storable]
98    private IValueParameter<PercentValue> mutationProbability;
99    public double MutationProbability {
100      get { return mutationProbability.Value.Value; }
101      set { mutationProbability.Value.Value = value; }
102    }
103
104    [Storable]
105    private IValueParameter<IntValue> elitism;
106    public int Elitism {
107      get { return elitism.Value.Value; }
108      set {
109        if (value < 0) throw new ArgumentException("Elitism cannot be negative");
110        elitism.Value.Value = value;
111      }
112    }
113
114    [Storable]
115    protected BestAverageWorstQualityAnalyzer qualityAnalyzer;
116
117    [StorableConstructor]
118    protected CanonicalGeneticAlgorithm(bool deserializing) : base(deserializing) { }
119    protected CanonicalGeneticAlgorithm(CanonicalGeneticAlgorithm<TProblem, TEncoding, TSolution> original, Cloner cloner)
120      : base(original, cloner) {
121      populationSize = cloner.Clone(original.populationSize);
122      selector = cloner.Clone(original.selector);
123      crossover = cloner.Clone(original.crossover);
124      mutator = cloner.Clone(original.mutator);
125      mutationProbability = cloner.Clone(original.mutationProbability);
126      elitism = cloner.Clone(original.elitism);
127    }
128    public CanonicalGeneticAlgorithm() {
129      ProblemAnalyzer = new MultiAnalyzer();
130      AlgorithmAnalyzer = new MultiAnalyzer();
131      qualityAnalyzer = new BestAverageWorstQualityAnalyzer();
132      AlgorithmAnalyzer.Operators.Add(qualityAnalyzer, true);
133
134      Parameters.Add(populationSize = new ValueParameter<IntValue>("PopulationSize", "The number of individuals in the population", new IntValue(100)));
135      Parameters.Add(selector = new ConstrainedValueParameter<ISelector<EvolutionaryAlgorithmContext<TProblem, TEncoding, TSolution>>>("Selector", "The selection heuristic that creates the mating pool."));
136      Parameters.Add(crossover = new ConstrainedValueParameter<ICrossover<EvolutionaryAlgorithmContext<TProblem, TEncoding, TSolution>>>("Crossover", "The crossover heuristic that takes two parents and produces a child."));
137      Parameters.Add(mutator = new ConstrainedValueParameter<IManipulator<EvolutionaryAlgorithmContext<TProblem, TEncoding, TSolution>>>("Mutator", "The mutation heuristic that slightly alters an individual."));
138      Parameters.Add(mutationProbability = new ValueParameter<PercentValue>("MutationProbability", "The probability with which mutation will be applied to an individual after mating.", new PercentValue(0.05)));
139      Parameters.Add(elitism = new ValueParameter<IntValue>("Elitism", "The number of best solutions from the old population that will live in the next generation."));
140    }
141
142    public override IDeepCloneable Clone(Cloner cloner) {
143      return new CanonicalGeneticAlgorithm<TProblem, TEncoding, TSolution>(this, cloner);
144    }
145
146    protected override void OnProblemChanged() {
147      base.OnProblemChanged();
148      qualityAnalyzer.QualityParameter.ActualName = Problem.Evaluator.QualityParameter.ActualName;
149      qualityAnalyzer.QualityParameter.Depth = 1;
150      qualityAnalyzer.QualityParameter.Hidden = true;
151    }
152
153    protected override void PerformInitialize(CancellationToken token) {
154      for (var i = 0; i < PopulationSize; i++) {
155        var solutionScope = CreateEmptySolutionScope();
156        Context.Scope.SubScopes.Add(solutionScope);
157        RunOperator(Problem.Encoding.SolutionCreator, solutionScope, token);
158      }
159      EvaluatePopulation(Context.Scope.SubScopes.OfType<ISingleObjectiveSolutionScope<TSolution>>().ToList(), token);
160    }
161
162    protected override void PerformIterate(CancellationToken token) {
163      Selector.Select(Context, 2 * (PopulationSize - Elitism), true);
164      var pool = Context.MatingPool.ToList();
165
166      var nextGen = new List<ISingleObjectiveSolutionScope<TSolution>>(PopulationSize);
167      for (var i = 0; i < PopulationSize - Elitism; i++) {
168        Context.Parents = Tuple.Create(pool[2 * i], pool[2 * i + 1]);
169        Context.Child = CreateEmptySolutionScope();
170        Crossover.Cross(Context);
171        if (Context.Random.NextDouble() < MutationProbability)
172          Mutator.Manipulate(Context);
173        nextGen.Add(Context.Child);
174      }
175      EvaluatePopulation(nextGen, token);
176      if (Elitism > 0) {
177        nextGen.AddRange(Problem.Maximization
178          ? Context.Population.OrderByDescending(x => x.Fitness).Take(Elitism)
179          : Context.Population.OrderBy(x => x.Fitness).Take(Elitism));
180      }
181     
182      Context.Scope.SubScopes.Replace(nextGen);
183      Context.Iterations++;
184    }
185
186    private void EvaluatePopulation(ICollection<ISingleObjectiveSolutionScope<TSolution>> solutions, CancellationToken token) {
187      Parallel.ForEach(solutions, p => Evaluate(p, token));
188      Context.EvaluatedSolutions += solutions.Count;
189      var best = Problem.Maximization ? solutions.MaxItems(x => x.Fitness).First() : solutions.MinItems(x => x.Fitness).First();
190      if (IsBetter(Problem.Maximization, best.Fitness, Context.BestQuality)) {
191        Context.BestQuality = best.Fitness;
192        Context.BestSolution = (TSolution)best.Solution.Clone();
193      }
194    }
195
196    protected override void PerformAnalyze(CancellationToken token) {
197      base.PerformAnalyze(token);
198
199      IResult res;
200      if (!Results.TryGetValue("Generations", out res)) {
201        res = new Result("Generations", new IntValue(Context.Iterations));
202        Results.Add(res);
203      } else ((IntValue)res.Value).Value = Context.Iterations;
204    }
205  }
206}
Note: See TracBrowser for help on using the repository browser.