Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Algorithms.VariableNeighborhoodSearch/3.3/VariableNeighborhoodSearch.cs @ 6042

Last change on this file since 6042 was 6042, checked in by abeham, 13 years ago

#1425

  • Changed LocalImprovementOperators
    • Changed interface (made Problem a property, added a property that denotes the type of the problem that it can be applied on, added some general parameters)
    • Added some parameters and wiring
    • Changed move discovery and parameterization and added a helper class to ease finding compatible move operators
    • Discovering only IMultiMoveOperators and IExhaustiveMoveOperators and putting the multi move ones first
    • Fixed bug in Apply method that could create an endless string of nested execution contexts
    • Removed all problem specific analyzers in the two local improvement operators and only left the BestAverageWorstQualityAnalyzer since it doesn't make any sense to perform diversity or allele analysis during local improvement in the most common case and those analyzers take a lot of time (one can always add them manually should he/she be interested). The analyzers in the VNS's Analyzer parameter are left untouched.
  • Removed shaking operator and interface from VNS plugin and added that to Optimization and Optimization.Operators
  • Changed some ValueParameters to ConstrainedValueParameters and added type discovery to fill them (using the ProblemType property to get compatible local improvement operators)
  • Added missing GPL license headers
  • Changed some ValueParameters to the new FixedValueParameters
  • Added an additional encoding specific ShakingOperator to each encoding and added that to each problem
    • reason is that only the problem/encoding can really decide if a shaking operator is meaningful or not
  • Fixed an unrelated bug in the BestAverageWorstQualityAnalyzer that I encountered (and made the fix backwards compatible)
    • Also added a snippet for creating the backwards compatible comment marker and region
  • Fixed the operator graph of the VNS main loop
    • The condition to continue only when the local search was not successful is not necessary and is not part of the VNS definition as far as I know it (only condition to break the inner loop is when k reaches k_max)
  • Changed the ShakingOperator to input current index and output the maximum number of neighborhoods instead of a boolean that indicates that the last index has been reached since the maximum number is a little more generally useful and equally powerful in modeling
    • Remodeled the VNS main loop to check for k < k_max in order to continue the inner loop
  • other changes that I forgot...

Still necessary

  • test, test, test
  • check for backwards compatible breakers
  • add a maximum evaluated solutions stop criterion
  • optionally: implement fast problem specific local search improvement operators that do not build on the whole generic overhead (e.g. a 2-opt TSP specific local search operator). The idea of VNS is really to converge to a local optimum which is difficult to achieve using the current rather limited termination options
File size: 14.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 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 HeuristicLab.Analysis;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.Operators;
29using HeuristicLab.Optimization;
30using HeuristicLab.Optimization.Operators;
31using HeuristicLab.Parameters;
32using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
33using HeuristicLab.PluginInfrastructure;
34using HeuristicLab.Random;
35
36namespace HeuristicLab.Algorithms.VariableNeighborhoodSearch {
37  [Item("Variable Neighborhood Search", "A variable neighborhood search algorithm.")]
38  [Creatable("Algorithms")]
39  [StorableClass]
40  public sealed class VariableNeighborhoodSearch : HeuristicOptimizationEngineAlgorithm, IStorableContent {
41    public string Filename { get; set; }
42
43    #region Problem Properties
44    public override Type ProblemType {
45      get { return typeof(ISingleObjectiveHeuristicOptimizationProblem); }
46    }
47    public new ISingleObjectiveHeuristicOptimizationProblem Problem {
48      get { return (ISingleObjectiveHeuristicOptimizationProblem)base.Problem; }
49      set { base.Problem = value; }
50    }
51    #endregion
52
53    #region Parameter Properties
54    private FixedValueParameter<IntValue> SeedParameter {
55      get { return (FixedValueParameter<IntValue>)Parameters["Seed"]; }
56    }
57    private FixedValueParameter<BoolValue> SetSeedRandomlyParameter {
58      get { return (FixedValueParameter<BoolValue>)Parameters["SetSeedRandomly"]; }
59    }
60    private ConstrainedValueParameter<ILocalImprovementOperator> LocalImprovementParameter {
61      get { return (ConstrainedValueParameter<ILocalImprovementOperator>)Parameters["LocalImprovement"]; }
62    }
63    private ConstrainedValueParameter<IMultiNeighborhoodShakingOperator> ShakingOperatorParameter {
64      get { return (ConstrainedValueParameter<IMultiNeighborhoodShakingOperator>)Parameters["ShakingOperator"]; }
65    }
66    private FixedValueParameter<IntValue> MaximumIterationsParameter {
67      get { return (FixedValueParameter<IntValue>)Parameters["MaximumIterations"]; }
68    }
69    private ValueParameter<MultiAnalyzer> AnalyzerParameter {
70      get { return (ValueParameter<MultiAnalyzer>)Parameters["Analyzer"]; }
71    }
72    public FixedValueParameter<IntValue> LocalImprovementMaximumIterationsParameter {
73      get { return (FixedValueParameter<IntValue>)Parameters["LocalImprovementMaximumIterations"]; }
74    }
75    #endregion
76
77    #region Properties
78    private RandomCreator RandomCreator {
79      get { return (RandomCreator)OperatorGraph.InitialOperator; }
80    }
81    public MultiAnalyzer Analyzer {
82      get { return AnalyzerParameter.Value; }
83      set { AnalyzerParameter.Value = value; }
84    }
85    private SolutionsCreator SolutionsCreator {
86      get { return (SolutionsCreator)RandomCreator.Successor; }
87    }
88    private VariableNeighborhoodSearchMainLoop MainLoop {
89      get { return FindMainLoop(SolutionsCreator.Successor); }
90    }
91    #endregion
92
93    [Storable]
94    private BestAverageWorstQualityAnalyzer qualityAnalyzer;
95
96    [StorableConstructor]
97    private VariableNeighborhoodSearch(bool deserializing) : base(deserializing) { }
98    private VariableNeighborhoodSearch(VariableNeighborhoodSearch original, Cloner cloner)
99      : base(original, cloner) {
100      qualityAnalyzer = cloner.Clone(original.qualityAnalyzer);
101      RegisterEventHandlers();
102    }
103    public VariableNeighborhoodSearch()
104      : base() {
105      Parameters.Add(new FixedValueParameter<IntValue>("Seed", "The random seed used to initialize the new pseudo random number generator.", new IntValue(0)));
106      Parameters.Add(new FixedValueParameter<BoolValue>("SetSeedRandomly", "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true)));
107      Parameters.Add(new ConstrainedValueParameter<ILocalImprovementOperator>("LocalImprovement", "The local improvement operation"));
108      Parameters.Add(new ConstrainedValueParameter<IMultiNeighborhoodShakingOperator>("ShakingOperator", "The operator that performs the shaking of solutions."));
109      Parameters.Add(new FixedValueParameter<IntValue>("MaximumIterations", "The maximum number of iterations which should be processed.", new IntValue(50)));
110      Parameters.Add(new FixedValueParameter<IntValue>("LocalImprovementMaximumIterations", "The maximum number of iterations which should be performed in the local improvement phase.", new IntValue(50)));
111      Parameters.Add(new ValueParameter<MultiAnalyzer>("Analyzer", "The operator used to analyze the solution and moves.", new MultiAnalyzer()));
112
113      RandomCreator randomCreator = new RandomCreator();
114      SolutionsCreator solutionsCreator = new SolutionsCreator();
115      VariableCreator variableCreator = new VariableCreator();
116      ResultsCollector resultsCollector = new ResultsCollector();
117      VariableNeighborhoodSearchMainLoop mainLoop = new VariableNeighborhoodSearchMainLoop();
118      OperatorGraph.InitialOperator = randomCreator;
119
120      randomCreator.RandomParameter.ActualName = "Random";
121      randomCreator.SeedParameter.ActualName = SeedParameter.Name;
122      randomCreator.SeedParameter.Value = null;
123      randomCreator.SetSeedRandomlyParameter.ActualName = SetSeedRandomlyParameter.Name;
124      randomCreator.SetSeedRandomlyParameter.Value = null;
125      randomCreator.Successor = solutionsCreator;
126
127      solutionsCreator.NumberOfSolutions = new IntValue(1);
128      solutionsCreator.Successor = variableCreator;
129
130      variableCreator.Name = "Initialize Evaluated Solutions";
131
132      variableCreator.CollectedValues.Add(new ValueParameter<IntValue>("Iterations", new IntValue(0)));
133      variableCreator.CollectedValues.Add(new ValueParameter<IntValue>("EvaluatedSolutions", new IntValue(0)));
134      variableCreator.CollectedValues.Add(new ValueParameter<IntValue>("CurrentNeighborhoodIndex", new IntValue(0)));
135      variableCreator.CollectedValues.Add(new ValueParameter<IntValue>("NeighborhoodCount", new IntValue(0)));
136      variableCreator.Successor = resultsCollector;
137
138      resultsCollector.CollectedValues.Add(new LookupParameter<IntValue>("Evaluated Solutions", null, "EvaluatedSolutions"));
139      resultsCollector.CollectedValues.Add(new LookupParameter<IntValue>("Iterations"));
140      resultsCollector.ResultsParameter.ActualName = "Results";
141      resultsCollector.Successor = mainLoop;
142
143      mainLoop.IterationsParameter.ActualName = "Iterations";
144      mainLoop.CurrentNeighborhoodIndexParameter.ActualName = "CurrentNeighborhoodIndex";
145      mainLoop.NeighborhoodCountParameter.ActualName = "NeighborhoodCount";
146      mainLoop.LocalImprovementParameter.ActualName = LocalImprovementParameter.Name;
147      mainLoop.ShakingOperatorParameter.ActualName = ShakingOperatorParameter.Name;
148      mainLoop.MaximumIterationsParameter.ActualName = MaximumIterationsParameter.Name;
149      mainLoop.RandomParameter.ActualName = RandomCreator.RandomParameter.ActualName;
150      mainLoop.ResultsParameter.ActualName = "Results";
151      mainLoop.AnalyzerParameter.ActualName = AnalyzerParameter.Name;
152      mainLoop.EvaluatedSolutionsParameter.ActualName = "EvaluatedSolutions";
153
154      InitializeLocalImprovementOperators();
155      qualityAnalyzer = new BestAverageWorstQualityAnalyzer();
156      ParameterizeAnalyzers();
157      UpdateAnalyzers();
158
159      RegisterEventHandlers();
160    }
161
162    public override IDeepCloneable Clone(Cloner cloner) {
163      return new VariableNeighborhoodSearch(this, cloner);
164    }
165
166    [StorableHook(HookType.AfterDeserialization)]
167    private void AfterDeserialization() {
168      RegisterEventHandlers();
169    }
170
171    public override void Prepare() {
172      if (Problem != null) base.Prepare();
173    }
174
175    private void RegisterEventHandlers() {
176      LocalImprovementParameter.ValueChanged += new EventHandler(LocalImprovementParameter_ValueChanged);
177      if (Problem != null) {
178        Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
179      }
180    }
181
182    #region Events
183    protected override void OnProblemChanged() {
184      InitializeLocalImprovementOperators();
185      UpdateShakingOperators();
186      UpdateAnalyzers();
187
188      ParameterizeStochasticOperator(Problem.SolutionCreator);
189      ParameterizeStochasticOperator(Problem.Evaluator);
190      foreach (IOperator op in Problem.Operators) ParameterizeStochasticOperator(op);
191      ParameterizeSolutionsCreator();
192      ParameterizeMainLoop();
193      ParameterizeAnalyzers();
194      ParameterizeIterationBasedOperators();
195      ParameterizeLocalImprovementOperators();
196      Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
197      base.OnProblemChanged();
198    }
199    protected override void Problem_SolutionCreatorChanged(object sender, EventArgs e) {
200      ParameterizeStochasticOperator(Problem.SolutionCreator);
201      ParameterizeSolutionsCreator();
202      base.Problem_SolutionCreatorChanged(sender, e);
203    }
204    protected override void Problem_EvaluatorChanged(object sender, EventArgs e) {
205      ParameterizeStochasticOperator(Problem.Evaluator);
206      ParameterizeSolutionsCreator();
207      ParameterizeMainLoop();
208      ParameterizeAnalyzers();
209      Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
210      base.Problem_EvaluatorChanged(sender, e);
211    }
212    protected override void Problem_OperatorsChanged(object sender, EventArgs e) {
213      UpdateShakingOperators();
214      UpdateAnalyzers();
215      foreach (IOperator op in Problem.Operators) ParameterizeStochasticOperator(op);
216      ParameterizeIterationBasedOperators();
217      base.Problem_OperatorsChanged(sender, e);
218    }
219    private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) {
220      ParameterizeMainLoop();
221      ParameterizeAnalyzers();
222    }
223    private void LocalImprovementParameter_ValueChanged(object sender, EventArgs e) {
224      ParameterizeLocalImprovementOperators();
225    }
226    #endregion
227
228    #region Helpers
229    private void ParameterizeSolutionsCreator() {
230      SolutionsCreator.EvaluatorParameter.ActualName = Problem.EvaluatorParameter.Name;
231      SolutionsCreator.SolutionCreatorParameter.ActualName = Problem.SolutionCreatorParameter.Name;
232    }
233    private void ParameterizeStochasticOperator(IOperator op) {
234      if (op is IStochasticOperator)
235        ((IStochasticOperator)op).RandomParameter.ActualName = RandomCreator.RandomParameter.ActualName;
236    }
237    private void ParameterizeMainLoop() {
238      MainLoop.EvaluatorParameter.ActualName = Problem.EvaluatorParameter.Name;
239      MainLoop.MaximizationParameter.ActualName = Problem.MaximizationParameter.Name;
240      MainLoop.QualityParameter.ActualName = Problem.Evaluator.QualityParameter.ActualName;
241    }
242    private void ParameterizeAnalyzers() {
243      qualityAnalyzer.ResultsParameter.ActualName = "Results";
244      if (Problem != null) {
245        qualityAnalyzer.MaximizationParameter.ActualName = Problem.MaximizationParameter.Name;
246        qualityAnalyzer.QualityParameter.ActualName = Problem.Evaluator.QualityParameter.ActualName;
247        qualityAnalyzer.QualityParameter.Depth = 1;
248        qualityAnalyzer.BestKnownQualityParameter.ActualName = Problem.BestKnownQualityParameter.Name;
249      }
250    }
251    private void ParameterizeIterationBasedOperators() {
252      if (Problem != null) {
253        foreach (IIterationBasedOperator op in Problem.Operators.OfType<IIterationBasedOperator>()) {
254          op.IterationsParameter.ActualName = "Iterations";
255          op.MaximumIterationsParameter.ActualName = MaximumIterationsParameter.Name;
256        }
257      }
258    }
259    private void ParameterizeLocalImprovementOperators() {
260      foreach (ILocalImprovementOperator op in LocalImprovementParameter.ValidValues) {
261        if (op != LocalImprovementParameter.Value) op.Problem = null;
262        op.MaximumIterationsParameter.Value = null;
263        op.MaximumIterationsParameter.ActualName = LocalImprovementMaximumIterationsParameter.Name;
264      }
265      if (LocalImprovementParameter.Value != null)
266        LocalImprovementParameter.Value.Problem = Problem;
267    }
268    private void InitializeLocalImprovementOperators() {
269      if (Problem == null) {
270        LocalImprovementParameter.ValidValues.Clear();
271      } else {
272        LocalImprovementParameter.ValidValues.RemoveWhere(x => !x.ProblemType.IsAssignableFrom(Problem.GetType()));
273        foreach (ILocalImprovementOperator op in ApplicationManager.Manager.GetInstances<ILocalImprovementOperator>().Where(x => x.ProblemType.IsAssignableFrom(Problem.GetType()))) {
274          if (!LocalImprovementParameter.ValidValues.Any(x => x.GetType() == op.GetType()))
275            LocalImprovementParameter.ValidValues.Add(op);
276        }
277      }
278    }
279    private void UpdateShakingOperators() {
280      ShakingOperatorParameter.ValidValues.Clear();
281      foreach (IMultiNeighborhoodShakingOperator op in Problem.Operators.OfType<IMultiNeighborhoodShakingOperator>()) {
282        ShakingOperatorParameter.ValidValues.Add(op);
283        op.CurrentNeighborhoodIndexParameter.ActualName = "CurrentNeighborhoodIndex";
284        op.NeighborhoodCountParameter.ActualName = "NeighborhoodCount";
285      }
286    }
287    private void UpdateAnalyzers() {
288      Analyzer.Operators.Clear();
289      if (Problem != null) {
290        foreach (IAnalyzer analyzer in Problem.Operators.OfType<IAnalyzer>()) {
291          foreach (IScopeTreeLookupParameter param in analyzer.Parameters.OfType<IScopeTreeLookupParameter>())
292            param.Depth = 1;
293          Analyzer.Operators.Add(analyzer);
294        }
295      }
296      Analyzer.Operators.Add(qualityAnalyzer);
297    }
298    private VariableNeighborhoodSearchMainLoop FindMainLoop(IOperator start) {
299      IOperator mainLoop = start;
300      while (mainLoop != null && !(mainLoop is VariableNeighborhoodSearchMainLoop))
301        mainLoop = ((SingleSuccessorOperator)mainLoop).Successor;
302      if (mainLoop == null) return null;
303      else return (VariableNeighborhoodSearchMainLoop)mainLoop;
304    }
305    #endregion
306  }
307}
Note: See TracBrowser for help on using the repository browser.