Free cookie consent management tool by TermsFeed Policy Generator

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

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

Fixed a bug in the evolution strategy and included some parameter sanity checks #932

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