Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Algorithms.SimulatedAnnealing/3.3/SimulatedAnnealing.cs @ 3132

Last change on this file since 3132 was 3131, checked in by abeham, 15 years ago

fixed wiring in LS, SA, and TS when problem is changed MoveGenerator becomes null which resulted in a NullReferenceException #933

File size: 17.9 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.Optimization;
28using HeuristicLab.Operators;
29using HeuristicLab.Optimization.Operators;
30using HeuristicLab.Parameters;
31using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
32using HeuristicLab.PluginInfrastructure;
33
34namespace HeuristicLab.Algorithms.SimulatedAnnealing {
35  [Item("Simulated Annealing", "A simulated annealing algorithm.")]
36  [Creatable("Algorithms")]
37  public class SimulatedAnnealing : EngineAlgorithm {
38    #region Problem Properties
39    public override Type ProblemType {
40      get { return typeof(ISingleObjectiveProblem); }
41    }
42    public new ISingleObjectiveProblem Problem {
43      get { return (ISingleObjectiveProblem)base.Problem; }
44      set { base.Problem = value; }
45    }
46    #endregion
47
48    #region Parameter Properties
49    private ValueParameter<IntValue> SeedParameter {
50      get { return (ValueParameter<IntValue>)Parameters["Seed"]; }
51    }
52    private ValueParameter<BoolValue> SetSeedRandomlyParameter {
53      get { return (ValueParameter<BoolValue>)Parameters["SetSeedRandomly"]; }
54    }
55    private ConstrainedValueParameter<IMultiMoveGenerator> MoveGeneratorParameter {
56      get { return (ConstrainedValueParameter<IMultiMoveGenerator>)Parameters["MoveGenerator"]; }
57    }
58    private ConstrainedValueParameter<IMoveMaker> MoveMakerParameter {
59      get { return (ConstrainedValueParameter<IMoveMaker>)Parameters["MoveMaker"]; }
60    }
61    private ConstrainedValueParameter<ISingleObjectiveMoveEvaluator> MoveEvaluatorParameter {
62      get { return (ConstrainedValueParameter<ISingleObjectiveMoveEvaluator>)Parameters["MoveEvaluator"]; }
63    }
64    private ConstrainedValueParameter<IDiscreteDoubleValueModifier> AnnealingOperatorParameter {
65      get { return (ConstrainedValueParameter<IDiscreteDoubleValueModifier>)Parameters["AnnealingOperator"]; }
66    }
67    private ValueParameter<IntValue> MaximumIterationsParameter {
68      get { return (ValueParameter<IntValue>)Parameters["MaximumIterations"]; }
69    }
70    private ValueParameter<IntValue> InnerIterationsParameter {
71      get { return (ValueParameter<IntValue>)Parameters["InnerIterations"]; }
72    }
73    private ValueParameter<DoubleValue> StartTemperatureParameter {
74      get { return (ValueParameter<DoubleValue>)Parameters["StartTemperature"]; }
75    }
76    private ValueParameter<DoubleValue> EndTemperatureParameter {
77      get { return (ValueParameter<DoubleValue>)Parameters["EndTemperature"]; }
78    }
79    #endregion
80
81    #region Properties
82    public IntValue Seed {
83      get { return SeedParameter.Value; }
84      set { SeedParameter.Value = value; }
85    }
86    public BoolValue SetSeedRandomly {
87      get { return SetSeedRandomlyParameter.Value; }
88      set { SetSeedRandomlyParameter.Value = value; }
89    }
90    public IMultiMoveGenerator MoveGenerator {
91      get { return MoveGeneratorParameter.Value; }
92      set { MoveGeneratorParameter.Value = value; }
93    }
94    public IMoveMaker MoveMaker {
95      get { return MoveMakerParameter.Value; }
96      set { MoveMakerParameter.Value = value; }
97    }
98    public ISingleObjectiveMoveEvaluator MoveEvaluator {
99      get { return MoveEvaluatorParameter.Value; }
100      set { MoveEvaluatorParameter.Value = value; }
101    }
102    public IntValue MaximumIterations {
103      get { return MaximumIterationsParameter.Value; }
104      set { MaximumIterationsParameter.Value = value; }
105    }
106    public IntValue InnerIterations {
107      get { return InnerIterationsParameter.Value; }
108      set { InnerIterationsParameter.Value = value; }
109    }
110    public DoubleValue StartTemperature {
111      get { return StartTemperatureParameter.Value; }
112      set { StartTemperatureParameter.Value = value; }
113    }
114    public DoubleValue EndTemperature {
115      get { return EndTemperatureParameter.Value; }
116      set { EndTemperatureParameter.Value = value; }
117    }
118    private RandomCreator RandomCreator {
119      get { return (RandomCreator)OperatorGraph.InitialOperator; }
120    }
121    private SolutionsCreator SolutionsCreator {
122      get { return (SolutionsCreator)RandomCreator.Successor; }
123    }
124    private SimulatedAnnealingMainLoop MainLoop {
125      get { return (SimulatedAnnealingMainLoop)SolutionsCreator.Successor; }
126    }
127
128    private List<IDiscreteDoubleValueModifier> annealingOperators;
129    private IEnumerable<IDiscreteDoubleValueModifier> AnnealingOperators {
130      get { return annealingOperators; }
131    }
132    #endregion
133
134    public SimulatedAnnealing()
135      : base() {
136      Parameters.Add(new ValueParameter<IntValue>("Seed", "The random seed used to initialize the new pseudo random number generator.", new IntValue(0)));
137      Parameters.Add(new ValueParameter<BoolValue>("SetSeedRandomly", "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true)));
138      Parameters.Add(new ConstrainedValueParameter<IMultiMoveGenerator>("MoveGenerator", "The operator used to generate moves to the neighborhood of the current solution."));
139      Parameters.Add(new ConstrainedValueParameter<ISingleObjectiveMoveEvaluator>("MoveEvaluator", "The operator used to evaluate a move."));
140      Parameters.Add(new ConstrainedValueParameter<IMoveMaker>("MoveMaker", "The operator used to perform a move."));
141      Parameters.Add(new ConstrainedValueParameter<IDiscreteDoubleValueModifier>("AnnealingOperator", "The operator used to modify the temperature."));
142      Parameters.Add(new ValueParameter<IntValue>("MaximumIterations", "The maximum number of generations which should be processed.", new IntValue(100)));
143      Parameters.Add(new ValueParameter<IntValue>("InnerIterations", "The amount of inner iterations (number of moves before temperature is adjusted again).", new IntValue(10)));
144      Parameters.Add(new ValueParameter<DoubleValue>("StartTemperature", "The initial temperature.", new DoubleValue(100)));
145      Parameters.Add(new ValueParameter<DoubleValue>("EndTemperature", "The final temperature which should be reached when iterations reaches maximum iterations.", new DoubleValue(1e-6)));
146
147      RandomCreator randomCreator = new RandomCreator();
148      SolutionsCreator solutionsCreator = new SolutionsCreator();
149      SimulatedAnnealingMainLoop mainLoop = new SimulatedAnnealingMainLoop();
150      OperatorGraph.InitialOperator = randomCreator;
151
152      randomCreator.RandomParameter.ActualName = "Random";
153      randomCreator.SeedParameter.ActualName = SeedParameter.Name;
154      randomCreator.SeedParameter.Value = null;
155      randomCreator.SetSeedRandomlyParameter.ActualName = SetSeedRandomlyParameter.Name;
156      randomCreator.SetSeedRandomlyParameter.Value = null;
157      randomCreator.Successor = solutionsCreator;
158
159      solutionsCreator.NumberOfSolutions = new IntValue(1);
160      solutionsCreator.Successor = mainLoop;
161
162      mainLoop.MoveGeneratorParameter.ActualName = MoveGeneratorParameter.Name;
163      mainLoop.MoveEvaluatorParameter.ActualName = MoveEvaluatorParameter.Name;
164      mainLoop.MoveMakerParameter.ActualName = MoveMakerParameter.Name;
165      mainLoop.AnnealingOperatorParameter.ActualName = AnnealingOperatorParameter.Name;
166      mainLoop.MaximumIterationsParameter.ActualName = MaximumIterationsParameter.Name;
167      mainLoop.StartTemperatureParameter.ActualName = StartTemperatureParameter.Name;
168      mainLoop.EndTemperatureParameter.ActualName = EndTemperatureParameter.Name;
169      mainLoop.RandomParameter.ActualName = RandomCreator.RandomParameter.ActualName;
170      mainLoop.ResultsParameter.ActualName = "Results";
171
172      Initialize();
173    }
174
175    [StorableConstructor]
176    private SimulatedAnnealing(bool deserializing) : base() { }
177
178    public override IDeepCloneable Clone(Cloner cloner) {
179      SimulatedAnnealing clone = (SimulatedAnnealing)base.Clone(cloner);
180      clone.Initialize();
181      return clone;
182    }
183
184    #region Events
185    protected override void OnProblemChanged() {
186      ParameterizeStochasticOperator(Problem.SolutionCreator);
187      ParameterizeStochasticOperator(Problem.Evaluator);
188      foreach (IOperator op in Problem.Operators) ParameterizeStochasticOperator(op);
189      foreach (ISingleObjectiveMoveEvaluator op in Problem.Operators.OfType<ISingleObjectiveMoveEvaluator>()) {
190        op.MoveQualityParameter.ActualNameChanged += new EventHandler(MoveEvaluator_MoveQualityParameter_ActualNameChanged);
191      }
192      ParameterizeSolutionsCreator();
193      ParameterizeMainLoop();
194      ParameterizeMoveEvaluators();
195      ParameterizeMoveMakers();
196      ParameterizeMoveGenerators();
197      UpdateMoveGenerator();
198      Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
199      base.OnProblemChanged();
200    }
201    protected override void Problem_SolutionCreatorChanged(object sender, EventArgs e) {
202      ParameterizeStochasticOperator(Problem.SolutionCreator);
203      ParameterizeSolutionsCreator();
204      base.Problem_SolutionCreatorChanged(sender, e);
205    }
206    protected override void Problem_EvaluatorChanged(object sender, EventArgs e) {
207      ParameterizeStochasticOperator(Problem.Evaluator);
208      ParameterizeSolutionsCreator();
209      ParameterizeMainLoop();
210      ParameterizeMoveEvaluators();
211      ParameterizeMoveMakers();
212      Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
213      base.Problem_EvaluatorChanged(sender, e);
214    }
215    protected override void Problem_OperatorsChanged(object sender, EventArgs e) {
216      foreach (IOperator op in Problem.Operators) ParameterizeStochasticOperator(op);
217      // This may seem pointless, but some operators already have the eventhandler registered, others don't
218      // FIXME: Is there another way to solve this problem?
219      foreach (ISingleObjectiveMoveEvaluator op in Problem.Operators.OfType<ISingleObjectiveMoveEvaluator>()) {
220        op.MoveQualityParameter.ActualNameChanged -= new EventHandler(MoveEvaluator_MoveQualityParameter_ActualNameChanged);
221        op.MoveQualityParameter.ActualNameChanged += new EventHandler(MoveEvaluator_MoveQualityParameter_ActualNameChanged);
222      }
223      IMultiMoveGenerator oldMoveGenerator = MoveGenerator;
224      UpdateMoveGenerator();
225      if (oldMoveGenerator == MoveGenerator) // in this case MoveGeneratorParameter_ValueChanged did not fire
226        UpdateMoveParameters();
227      ParameterizeMainLoop();
228      ParameterizeMoveEvaluators();
229      ParameterizeMoveMakers();
230      ParameterizeMoveGenerators();
231      base.Problem_OperatorsChanged(sender, e);
232    }
233    private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) {
234      ParameterizeMainLoop();
235      ParameterizeMoveEvaluators();
236      ParameterizeMoveMakers();
237    }
238    private void MoveGeneratorParameter_ValueChanged(object sender, EventArgs e) {
239      UpdateMoveParameters();
240    }
241    private void MoveEvaluatorParameter_ValueChanged(object sender, EventArgs e) {
242      ParameterizeMainLoop();
243      ParameterizeMoveEvaluators();
244      ParameterizeMoveMakers();
245    }
246    private void MoveEvaluator_MoveQualityParameter_ActualNameChanged(object sender, EventArgs e) {
247      ParameterizeMainLoop();
248      ParameterizeMoveEvaluators();
249      ParameterizeMoveMakers();
250    }
251    #endregion
252
253    #region Helpers
254    [StorableHook(HookType.AfterDeserialization)]
255    private void Initialize() {
256      if (Problem != null) {
257        Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
258        foreach (ISingleObjectiveMoveEvaluator op in Problem.Operators.OfType<ISingleObjectiveMoveEvaluator>()) {
259          op.MoveQualityParameter.ActualNameChanged += new EventHandler(MoveEvaluator_MoveQualityParameter_ActualNameChanged);
260        }
261      }
262      MoveGeneratorParameter.ValueChanged += new EventHandler(MoveGeneratorParameter_ValueChanged);
263      MoveEvaluatorParameter.ValueChanged += new EventHandler(MoveEvaluatorParameter_ValueChanged);
264      InitializeAnnealingOperators();
265    }
266    private void InitializeAnnealingOperators() {
267      annealingOperators = new List<IDiscreteDoubleValueModifier>();
268      if (ApplicationManager.Manager != null) {
269        annealingOperators.AddRange(ApplicationManager.Manager.GetInstances<IDiscreteDoubleValueModifier>().OrderBy(x => x.Name));
270        ParameterizeAnnealingOperators();
271      }
272      AnnealingOperatorParameter.ValidValues.Clear();
273      foreach (IDiscreteDoubleValueModifier op in annealingOperators)
274        AnnealingOperatorParameter.ValidValues.Add(op);
275    }
276    private void UpdateMoveGenerator() {
277      IMultiMoveGenerator oldMoveGenerator = MoveGenerator;
278      MoveGeneratorParameter.ValidValues.Clear();
279      if (Problem != null) {
280        foreach (IMultiMoveGenerator generator in Problem.Operators.OfType<IMultiMoveGenerator>().OrderBy(x => x.Name))
281          MoveGeneratorParameter.ValidValues.Add(generator);
282      }
283      if (oldMoveGenerator != null) {
284        IMultiMoveGenerator newMoveGenerator = MoveGeneratorParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldMoveGenerator.GetType());
285        if (newMoveGenerator != null) MoveGenerator = newMoveGenerator;
286      }
287      if (MoveGenerator == null) {
288        ClearMoveParameters();
289      }
290    }
291    private void UpdateMoveParameters() {
292      IMoveMaker oldMoveMaker = MoveMaker;
293      ISingleObjectiveMoveEvaluator oldMoveEvaluator = MoveEvaluator;
294      ClearMoveParameters();
295      if (MoveGenerator != null) {
296        List<Type> moveTypes = MoveGenerator.GetType().GetInterfaces().Where(x => typeof(IMoveOperator).IsAssignableFrom(x)).ToList();
297        foreach (Type type in moveTypes.ToList()) {
298          if (moveTypes.Any(t => t != type && type.IsAssignableFrom(t)))
299            moveTypes.Remove(type);
300        }
301        foreach (Type type in moveTypes) {
302          var operators = Problem.Operators.Where(x => type.IsAssignableFrom(x.GetType())).OrderBy(x => x.Name);
303          foreach (IMoveMaker moveMaker in operators.OfType<IMoveMaker>())
304            MoveMakerParameter.ValidValues.Add(moveMaker);
305          foreach (ISingleObjectiveMoveEvaluator moveEvaluator in operators.OfType<ISingleObjectiveMoveEvaluator>())
306            MoveEvaluatorParameter.ValidValues.Add(moveEvaluator);
307        }
308        if (oldMoveMaker != null) {
309          IMoveMaker mm = MoveMakerParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldMoveMaker.GetType());
310          if (mm != null) MoveMaker = mm;
311        }
312        if (oldMoveEvaluator != null) {
313          ISingleObjectiveMoveEvaluator me = MoveEvaluatorParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldMoveEvaluator.GetType());
314          if (me != null) MoveEvaluator = me;
315        }
316      }
317    }
318    private void ClearMoveParameters() {
319      MoveMakerParameter.ValidValues.Clear();
320      MoveEvaluatorParameter.ValidValues.Clear();
321    }
322    private void ParameterizeSolutionsCreator() {
323      SolutionsCreator.EvaluatorParameter.ActualName = Problem.EvaluatorParameter.Name;
324      SolutionsCreator.SolutionCreatorParameter.ActualName = Problem.SolutionCreatorParameter.Name;
325    }
326    private void ParameterizeMainLoop() {
327      MainLoop.MaximizationParameter.ActualName = Problem.MaximizationParameter.Name;
328      MainLoop.QualityParameter.ActualName = Problem.Evaluator.QualityParameter.ActualName;
329      if (MoveEvaluator != null)
330        MainLoop.MoveQualityParameter.ActualName = MoveEvaluator.MoveQualityParameter.ActualName;
331    }
332    private void ParameterizeStochasticOperator(IOperator op) {
333      if (op is IStochasticOperator)
334        ((IStochasticOperator)op).RandomParameter.ActualName = RandomCreator.RandomParameter.ActualName;
335    }
336    private void ParameterizeMoveEvaluators() {
337      foreach (ISingleObjectiveMoveEvaluator op in Problem.Operators.OfType<ISingleObjectiveMoveEvaluator>()) {
338        op.QualityParameter.ActualName = Problem.Evaluator.QualityParameter.ActualName;
339      }
340    }
341    private void ParameterizeMoveMakers() {
342      foreach (IMoveMaker op in Problem.Operators.OfType<IMoveMaker>()) {
343        op.QualityParameter.ActualName = Problem.Evaluator.QualityParameter.ActualName;
344        if (MoveEvaluator != null)
345          op.MoveQualityParameter.ActualName = MoveEvaluator.MoveQualityParameter.ActualName;
346      }
347    }
348    private void ParameterizeAnnealingOperators() {
349      foreach (IDiscreteDoubleValueModifier op in annealingOperators) {
350        op.IndexParameter.ActualName = "Iterations";
351        op.StartIndexParameter.Value = new IntValue(0);
352        op.EndIndexParameter.ActualName = MaximumIterationsParameter.Name;
353        op.ValueParameter.ActualName = "Temperature";
354        op.StartValueParameter.ActualName = StartTemperatureParameter.Name;
355        op.EndValueParameter.ActualName = EndTemperatureParameter.Name;
356        ParameterizeStochasticOperator(op);
357      }
358    }
359    private void ParameterizeMoveGenerators() {
360      foreach (IMultiMoveGenerator op in Problem.Operators.OfType<IMultiMoveGenerator>()) {
361        op.SampleSizeParameter.ActualName = InnerIterationsParameter.Name;
362      }
363    }
364    #endregion
365  }
366}
Note: See TracBrowser for help on using the repository browser.