Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Algorithms.EvolutionStrategy/3.3/EvolutionStrategy.cs @ 3183

Last change on this file since 3183 was 3183, checked in by abeham, 14 years ago

Updated evolution strategy to include mutation strength adjustment (doh!) #932
Also added self adaptive crossover

  • Property svn:mime-type set to application/octet-stream
File size: 41.4 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 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 HeuristicLab.Core;
26using HeuristicLab.Data;
27using HeuristicLab.Encodings.RealVectorEncoding;
28using HeuristicLab.Operators;
29using HeuristicLab.Optimization;
30using HeuristicLab.Optimization.Operators;
31using HeuristicLab.Parameters;
32using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
33using HeuristicLab.PluginInfrastructure;
34
35namespace HeuristicLab.Algorithms.EvolutionStrategy {
36  /// <summary>
37  /// A standard genetic algorithm.
38  /// </summary>
39  [Item("Evolution Strategy", "An evolution strategy.")]
40  [Creatable("Algorithms")]
41  [StorableClass]
42  public sealed class EvolutionStrategy : EngineAlgorithm {
43    [Storable]
44    private SelfAdaptiveCrossover selfAdaptiveCrossover;
45
46    #region Problem Properties
47    public override Type ProblemType {
48      get { return typeof(ISingleObjectiveProblem); }
49    }
50    public new ISingleObjectiveProblem Problem {
51      get { return (ISingleObjectiveProblem)base.Problem; }
52      set { base.Problem = value; }
53    }
54    #endregion
55
56    #region Parameter Properties
57    private ValueParameter<IntValue> SeedParameter {
58      get { return (ValueParameter<IntValue>)Parameters["Seed"]; }
59    }
60    private ValueParameter<BoolValue> SetSeedRandomlyParameter {
61      get { return (ValueParameter<BoolValue>)Parameters["SetSeedRandomly"]; }
62    }
63    private ValueParameter<IntValue> PopulationSizeParameter {
64      get { return (ValueParameter<IntValue>)Parameters["PopulationSize"]; }
65    }
66    private ValueParameter<IntValue> ParentsPerChildParameter {
67      get { return (ValueParameter<IntValue>)Parameters["ParentsPerChild"]; }
68    }
69    private ValueParameter<IntValue> ChildrenParameter {
70      get { return (ValueParameter<IntValue>)Parameters["Children"]; }
71    }
72    private ValueParameter<IntValue> MaximumGenerationsParameter {
73      get { return (ValueParameter<IntValue>)Parameters["MaximumGenerations"]; }
74    }
75    private ValueParameter<DoubleMatrix> StrategyVectorBoundsParameter {
76      get { return (ValueParameter<DoubleMatrix>)Parameters["StrategyVectorBounds"]; }
77    }
78    private ValueParameter<IntValue> ProblemDimensionParameter {
79      get { return (ValueParameter<IntValue>)Parameters["ProblemDimension"]; }
80    }
81    private ValueParameter<DoubleValue> GeneralLearningRateParameter {
82      get { return (ValueParameter<DoubleValue>)Parameters["GeneralLearningRate"]; }
83    }
84    private ValueParameter<DoubleValue> LearningRateParameter {
85      get { return (ValueParameter<DoubleValue>)Parameters["LearningRate"]; }
86    }
87    private ValueParameter<BoolValue> PlusSelectionParameter {
88      get { return (ValueParameter<BoolValue>)Parameters["PlusSelection"]; }
89    }
90    private ConstrainedValueParameter<IManipulator> MutatorParameter {
91      get { return (ConstrainedValueParameter<IManipulator>)Parameters["Mutator"]; }
92    }
93    private OptionalConstrainedValueParameter<ICrossover> RecombinatorParameter {
94      get { return (OptionalConstrainedValueParameter<ICrossover>)Parameters["Recombinator"]; }
95    }
96    #endregion
97
98    #region Properties
99    public IntValue Seed {
100      get { return SeedParameter.Value; }
101      set { SeedParameter.Value = value; }
102    }
103    public BoolValue SetSeedRandomly {
104      get { return SetSeedRandomlyParameter.Value; }
105      set { SetSeedRandomlyParameter.Value = value; }
106    }
107    public IntValue PopulationSize {
108      get { return PopulationSizeParameter.Value; }
109      set { PopulationSizeParameter.Value = value; }
110    }
111    public IntValue ParentsPerChild {
112      get { return ParentsPerChildParameter.Value; }
113      set { ParentsPerChildParameter.Value = value; }
114    }
115    public IntValue Children {
116      get { return ChildrenParameter.Value; }
117      set { ChildrenParameter.Value = value; }
118    }
119    public IntValue MaximumGenerations {
120      get { return MaximumGenerationsParameter.Value; }
121      set { MaximumGenerationsParameter.Value = value; }
122    }
123    private DoubleMatrix StrategyVectorBounds {
124      get { return StrategyVectorBoundsParameter.Value; }
125      set { StrategyVectorBoundsParameter.Value = value; }
126    }
127    private IntValue ProblemDimension {
128      get { return ProblemDimensionParameter.Value; }
129      set { ProblemDimensionParameter.Value = value; }
130    }
131    private DoubleValue GeneralLearningRate {
132      get { return GeneralLearningRateParameter.Value; }
133      set { GeneralLearningRateParameter.Value = value; }
134    }
135    private DoubleValue LearningRate {
136      get { return LearningRateParameter.Value; }
137      set { LearningRateParameter.Value = value; }
138    }
139    private BoolValue PlusSelection {
140      get { return PlusSelectionParameter.Value; }
141      set { PlusSelectionParameter.Value = value; }
142    }
143    public IManipulator Mutator {
144      get { return MutatorParameter.Value; }
145      set { MutatorParameter.Value = value; }
146    }
147    public ICrossover Recombinator {
148      get { return RecombinatorParameter.Value; }
149      set { RecombinatorParameter.Value = value; }
150    }
151
152    private RandomCreator RandomCreator {
153      get { return (RandomCreator)OperatorGraph.InitialOperator; }
154    }
155    private SolutionsCreator SolutionsCreator {
156      get { return (SolutionsCreator)RandomCreator.Successor; }
157    }
158    private EvolutionStrategyMainLoop MainLoop {
159      get { return (EvolutionStrategyMainLoop)((UniformSequentialSubScopesProcessor)SolutionsCreator.Successor).Successor; }
160    }
161    #endregion
162
163    [StorableConstructor]
164    private EvolutionStrategy(bool deserializing) : base() { }
165    public EvolutionStrategy()
166      : base() {
167      Parameters.Add(new ValueParameter<IntValue>("Seed", "The random seed used to initialize the new pseudo random number generator.", new IntValue(0)));
168      Parameters.Add(new ValueParameter<BoolValue>("SetSeedRandomly", "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true)));
169      Parameters.Add(new ValueParameter<IntValue>("PopulationSize", "µ (mu) - the size of the population.", new IntValue(5)));
170      Parameters.Add(new ValueParameter<IntValue>("ParentsPerChild", "ρ (rho) - how many parents should be recombined.", new IntValue(1)));
171      Parameters.Add(new ValueParameter<IntValue>("Children", "λ (lambda) - the size of the offspring population.", new IntValue(10)));
172      Parameters.Add(new ValueParameter<IntValue>("MaximumGenerations", "The maximum number of generations which should be processed.", new IntValue(1000)));
173      Parameters.Add(new ValueParameter<DoubleMatrix>("StrategyVectorBounds", "2 column matrix with one row for each dimension specifying upper and lower bound for the strategy vector. If there are less rows than dimensions, the strategy vector will be read in a cycle.", new DoubleMatrix(new double[,] { {0.1, 5} })));
174      Parameters.Add(new ValueParameter<IntValue>("ProblemDimension", "The problem dimension (length of the strategy vector.", new IntValue(1)));
175      Parameters.Add(new ValueParameter<DoubleValue>("GeneralLearningRate", "τ0 (tau0) - the factor with which adjustments in the strategy vector is dampened over all dimensions. Recommendation is to use 1/Sqrt(2*ProblemDimension).", new DoubleValue(0.707106)));
176      Parameters.Add(new ValueParameter<DoubleValue>("LearningRate", "τ (tau) - the factor with which adjustments in the strategy vector are dampened in a single dimension. Recommendation is to use 1/Sqrt(2*Sqrt(ProblemDimension)).", new DoubleValue(0.707106)));
177      Parameters.Add(new ValueParameter<BoolValue>("PlusSelection", "True for plus selection (elitist population), false for comma selection (non-elitist population).", new BoolValue(true)));
178      Parameters.Add(new OptionalConstrainedValueParameter<ICrossover>("Recombinator", "The operator used to cross solutions."));
179      Parameters.Add(new ConstrainedValueParameter<IManipulator>("Mutator", "The operator used to mutate solutions."));
180
181      RandomCreator randomCreator = new RandomCreator();
182      SolutionsCreator solutionsCreator = new SolutionsCreator();
183      UniformSequentialSubScopesProcessor strategyVectorProcessor = new UniformSequentialSubScopesProcessor();
184      UniformRandomRealVectorCreator strategyVectorCreator = new UniformRandomRealVectorCreator();
185      EvolutionStrategyMainLoop mainLoop = new EvolutionStrategyMainLoop();
186      OperatorGraph.InitialOperator = randomCreator;
187
188      randomCreator.RandomParameter.ActualName = "Random";
189      randomCreator.SeedParameter.ActualName = SeedParameter.Name;
190      randomCreator.SeedParameter.Value = null;
191      randomCreator.SetSeedRandomlyParameter.ActualName = SetSeedRandomlyParameter.Name;
192      randomCreator.SetSeedRandomlyParameter.Value = null;
193      randomCreator.Successor = solutionsCreator;
194
195      solutionsCreator.NumberOfSolutionsParameter.ActualName = PopulationSizeParameter.Name;
196      solutionsCreator.Successor = strategyVectorProcessor;
197
198      strategyVectorProcessor.Operator = strategyVectorCreator;
199      strategyVectorProcessor.Successor = mainLoop;
200
201      strategyVectorCreator.BoundsParameter.ActualName = StrategyVectorBoundsParameter.Name;
202      strategyVectorCreator.LengthParameter.ActualName = ProblemDimensionParameter.Name;
203      strategyVectorCreator.RandomParameter.ActualName = "Random";
204      strategyVectorCreator.RealVectorParameter.ActualName = "StrategyVector";
205
206      mainLoop.RandomParameter.ActualName = RandomCreator.RandomParameter.ActualName;
207      mainLoop.PopulationSizeParameter.ActualName = PopulationSizeParameter.Name;
208      mainLoop.ParentsPerChildParameter.ActualName = ParentsPerChildParameter.Name;
209      mainLoop.ChildrenParameter.ActualName = ChildrenParameter.Name;
210      mainLoop.MaximumGenerationsParameter.ActualName = MaximumGenerationsParameter.Name;
211      mainLoop.MutatorParameter.ActualName = MutatorParameter.Name;
212      mainLoop.RecombinatorParameter.ActualName = RecombinatorParameter.Name;
213      mainLoop.ResultsParameter.ActualName = "Results";
214
215      selfAdaptiveCrossover = new SelfAdaptiveCrossover();
216      ParameterizeSelfAdapativeCrossover();
217
218      Initialze();
219    }
220
221    public override IDeepCloneable Clone(Cloner cloner) {
222      EvolutionStrategy clone = (EvolutionStrategy)base.Clone(cloner);
223      clone.Initialze();
224      return clone;
225    }
226
227    #region Events
228    protected override void OnProblemChanged() {
229      ParameterizeStochasticOperator(Problem.SolutionCreator);
230      ParameterizeStochasticOperator(Problem.Evaluator);
231      ParameterizeStochasticOperator(Problem.Visualizer);
232      foreach (IOperator op in Problem.Operators) ParameterizeStochasticOperator(op);
233      ParameterizeSolutionsCreator();
234      ParameterizeMainLoop();
235      UpdateRecombinators();
236      UpdateMutators();
237      Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
238      base.OnProblemChanged();
239    }
240    protected override void Problem_SolutionCreatorChanged(object sender, EventArgs e) {
241      ParameterizeStochasticOperator(Problem.SolutionCreator);
242      ParameterizeSolutionsCreator();
243      base.Problem_SolutionCreatorChanged(sender, e);
244    }
245    protected override void Problem_EvaluatorChanged(object sender, EventArgs e) {
246      ParameterizeStochasticOperator(Problem.Evaluator);
247      ParameterizeSolutionsCreator();
248      ParameterizeMainLoop();
249      Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
250      base.Problem_EvaluatorChanged(sender, e);
251    }
252    protected override void Problem_VisualizerChanged(object sender, EventArgs e) {
253      ParameterizeStochasticOperator(Problem.Visualizer);
254      ParameterizeMainLoop();
255      base.Problem_VisualizerChanged(sender, e);
256    }
257    protected override void Problem_OperatorsChanged(object sender, EventArgs e) {
258      foreach (IOperator op in Problem.Operators) ParameterizeStochasticOperator(op);
259      UpdateRecombinators();
260      UpdateMutators();
261      base.Problem_OperatorsChanged(sender, e);
262    }
263    private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) {
264      ParameterizeMainLoop();
265    }
266    private void PopulationSizeParameter_ValueChanged(object sender, EventArgs e) {
267      PopulationSize.ValueChanged += new EventHandler(PopulationSize_ValueChanged);
268      PopulationSize_ValueChanged(null, EventArgs.Empty);
269    }
270    private void PopulationSize_ValueChanged(object sender, EventArgs e) {
271      if (PopulationSize.Value <= 0) PopulationSize.Value = 1;
272      if (!PlusSelection.Value && Children.Value < PopulationSize.Value)
273        Children.Value = PopulationSize.Value;
274    }
275    private void ParentsPerChildParameter_ValueChanged(object sender, EventArgs e) {
276      ParentsPerChild.ValueChanged += new EventHandler(ParentsPerChild_ValueChanged);
277      ParentsPerChild_ValueChanged(null, EventArgs.Empty);
278    }
279    private void ParentsPerChild_ValueChanged(object sender, EventArgs e) {
280      if (ParentsPerChild.Value < 1 || ParentsPerChild.Value > 1 && RecombinatorParameter.ValidValues.Count == 0)
281        ParentsPerChild.Value = 1;
282      if (ParentsPerChild.Value > 1 && Recombinator == null) Recombinator = RecombinatorParameter.ValidValues.First();
283      if (ParentsPerChild.Value > 1 && ParentsPerChild.Value > PopulationSize.Value)
284        PopulationSize.Value = ParentsPerChild.Value;
285    }
286    private void ChildrenParameter_ValueChanged(object sender, EventArgs e) {
287      Children.ValueChanged += new EventHandler(Children_ValueChanged);
288      Children_ValueChanged(null, EventArgs.Empty);
289    }
290    private void Children_ValueChanged(object sender, EventArgs e) {
291      if (Children.Value <= 0) Children.Value = 1;
292      if (!PlusSelection.Value && Children.Value < PopulationSize.Value)
293        PopulationSize.Value = Children.Value;
294    }
295    private void PlusSelectionParameter_ValueChanged(object sender, EventArgs e) {
296      PlusSelection.ValueChanged += new EventHandler(PlusSelection_ValueChanged);
297      PlusSelection_ValueChanged(null, EventArgs.Empty);
298    }
299    private void PlusSelection_ValueChanged(object sender, EventArgs e) {
300      if (!PlusSelection.Value && Children.Value < PopulationSize.Value)
301        Children.Value = PopulationSize.Value;
302    }
303    private void RecombinatorParameter_ValueChanged(object sender, EventArgs e) {
304      if (Recombinator == null && ParentsPerChild.Value > 1) ParentsPerChild.Value = 1;
305      else if (Recombinator != null && ParentsPerChild.Value == 1) ParentsPerChild.Value = 2;
306    }
307    private void ProblemDimensionParameter_ValueChanged(object sender, EventArgs e) {
308      ProblemDimension.ValueChanged += new EventHandler(ProblemDimension_ValueChanged);
309      ProblemDimension_ValueChanged(null, EventArgs.Empty);
310    }
311    private void ProblemDimension_ValueChanged(object sender, EventArgs e) {
312      if (ProblemDimension.Value < 1) ProblemDimension.Value = 1;
313      GeneralLearningRate.Value = 1.0 / Math.Sqrt(2 * ProblemDimension.Value);
314      LearningRate.Value = 1.0 / Math.Sqrt(2 * Math.Sqrt(ProblemDimension.Value));
315    }
316    private void selfAdaptiveCrossover_StrategyVectorCrossoverParameter_ValueChanged(object sender, EventArgs e) {
317      ParameterizeSelfAdapativeCrossover();
318    }
319    #endregion
320
321    #region Helpers
322    [StorableHook(HookType.AfterDeserialization)]
323    private void Initialze() {
324      PopulationSizeParameter.ValueChanged += new EventHandler(PopulationSizeParameter_ValueChanged);
325      PopulationSize.ValueChanged += new EventHandler(PopulationSize_ValueChanged);
326      ParentsPerChildParameter.ValueChanged += new EventHandler(ParentsPerChildParameter_ValueChanged);
327      ParentsPerChild.ValueChanged += new EventHandler(ParentsPerChild_ValueChanged);
328      ChildrenParameter.ValueChanged += new EventHandler(ChildrenParameter_ValueChanged);
329      Children.ValueChanged += new EventHandler(Children_ValueChanged);
330      PlusSelectionParameter.ValueChanged += new EventHandler(PlusSelectionParameter_ValueChanged);
331      PlusSelection.ValueChanged += new EventHandler(PlusSelection_ValueChanged);
332      RecombinatorParameter.ValueChanged += new EventHandler(RecombinatorParameter_ValueChanged);
333      ProblemDimensionParameter.ValueChanged += new EventHandler(ProblemDimensionParameter_ValueChanged);
334      ProblemDimension.ValueChanged += new EventHandler(ProblemDimension_ValueChanged);
335      selfAdaptiveCrossover.StrategyVectorCrossoverParameter.ValueChanged += new EventHandler(selfAdaptiveCrossover_StrategyVectorCrossoverParameter_ValueChanged);
336      if (Problem != null)
337        Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
338    }
339    private void ParameterizeSolutionsCreator() {
340      SolutionsCreator.EvaluatorParameter.ActualName = Problem.EvaluatorParameter.Name;
341      SolutionsCreator.SolutionCreatorParameter.ActualName = Problem.SolutionCreatorParameter.Name;
342    }
343    private void ParameterizeMainLoop() {
344      MainLoop.BestKnownQualityParameter.ActualName = Problem.BestKnownQualityParameter.Name;
345      MainLoop.EvaluatorParameter.ActualName = Problem.EvaluatorParameter.Name;
346      MainLoop.MaximizationParameter.ActualName = Problem.MaximizationParameter.Name;
347      MainLoop.QualityParameter.ActualName = Problem.Evaluator.QualityParameter.ActualName;
348      MainLoop.VisualizerParameter.ActualName = Problem.VisualizerParameter.Name;
349      if (Problem.Visualizer != null)
350        MainLoop.VisualizationParameter.ActualName = Problem.Visualizer.VisualizationParameter.ActualName;
351    }
352    private void ParameterizeStochasticOperator(IOperator op) {
353      if (op is IStochasticOperator)
354        ((IStochasticOperator)op).RandomParameter.ActualName = RandomCreator.RandomParameter.ActualName;
355    }
356    private void ParameterizeSelfAdapativeCrossover() {
357      selfAdaptiveCrossover.RandomParameter.ActualName = RandomCreator.RandomParameter.ActualName;
358      selfAdaptiveCrossover.StrategyVectorCrossover.ParentsParameter.ActualName = "StrategyVector";
359      selfAdaptiveCrossover.StrategyVectorCrossover.ChildParameter.ActualName = "StrategyVector";
360      selfAdaptiveCrossover.StrategyVectorCrossover.BoundsParameter.ActualName = "StrategyVectorBounds";
361    }
362    private void UpdateRecombinators() {
363      ICrossover oldRecombinator = RecombinatorParameter.Value;
364      ICrossover oldSARecombinator = selfAdaptiveCrossover.Crossover;
365      selfAdaptiveCrossover.CrossoverParameter.ValidValues.Clear();
366      RecombinatorParameter.ValidValues.Clear();
367      RecombinatorParameter.ValidValues.Add(selfAdaptiveCrossover);
368      foreach (ICrossover recombinator in Problem.Operators.OfType<ICrossover>().OrderBy(x => x.Name)) {
369        RecombinatorParameter.ValidValues.Add(recombinator);
370        selfAdaptiveCrossover.CrossoverParameter.ValidValues.Add(recombinator);
371      }
372      if (oldRecombinator != null) {
373        ICrossover recombinator = RecombinatorParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldRecombinator.GetType());
374        if (recombinator != null) RecombinatorParameter.Value = recombinator;
375      }
376      if (oldSARecombinator != null) {
377        ICrossover saRecombinator = selfAdaptiveCrossover.CrossoverParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldSARecombinator.GetType());
378        if (saRecombinator != null) selfAdaptiveCrossover.Crossover = saRecombinator;
379      }
380    }
381    private void UpdateMutators() {
382      IManipulator oldMutator = MutatorParameter.Value;
383      MutatorParameter.ValidValues.Clear();
384      foreach (IManipulator mutator in Problem.Operators.OfType<IManipulator>().OrderBy(x => x.Name))
385        MutatorParameter.ValidValues.Add(mutator);
386      if (oldMutator != null) {
387        IManipulator mutator = MutatorParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldMutator.GetType());
388        if (mutator != null) MutatorParameter.Value = mutator;
389      }
390    }
391    #endregion
392  }
393}
Note: See TracBrowser for help on using the repository browser.