Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Algorithms.LocalSearch/3.3/LocalSearchImprovementOperator.cs @ 5753

Last change on this file since 5753 was 5753, checked in by svonolfe, 13 years ago

Integrated VNS into trunk (#1425)

File size: 13.3 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.Collections.Generic;
24using System.Linq;
25using System.Text;
26using HeuristicLab.Core;
27using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
28using HeuristicLab.Operators;
29using HeuristicLab.Common;
30using HeuristicLab.Parameters;
31using HeuristicLab.Algorithms.LocalSearch;
32using HeuristicLab.Data;
33using HeuristicLab.Optimization;
34using HeuristicLab.Optimization.Operators;
35using HeuristicLab.Analysis;
36
37namespace HeuristicLab.Algorithms.LocalSearch {
38  /// <summary>
39  /// A local search improvement operator.
40  /// </summary>
41  [Item("LocalSearchImprovementOperator", "A local search improvement operator.")]
42  [StorableClass]
43  public class LocalSearchImprovementOperator: SingleSuccessorOperator, ILocalImprovementOperator {
44    [Storable]
45    private LocalSearchMainLoop loop;
46
47    [Storable]
48    private BestAverageWorstQualityAnalyzer qualityAnalyzer;
49   
50    private ConstrainedValueParameter<IMoveGenerator> MoveGeneratorParameter {
51      get { return (ConstrainedValueParameter<IMoveGenerator>)Parameters["MoveGenerator"]; }
52    }
53    private ConstrainedValueParameter<IMoveMaker> MoveMakerParameter {
54      get { return (ConstrainedValueParameter<IMoveMaker>)Parameters["MoveMaker"]; }
55    }
56    private ConstrainedValueParameter<ISingleObjectiveMoveEvaluator> MoveEvaluatorParameter {
57      get { return (ConstrainedValueParameter<ISingleObjectiveMoveEvaluator>)Parameters["MoveEvaluator"]; }
58    }
59    private ValueParameter<IntValue> MaximumIterationsParameter {
60      get { return (ValueParameter<IntValue>)Parameters["MaximumIterations"]; }
61    }
62    private ValueParameter<IntValue> SampleSizeParameter {
63      get { return (ValueParameter<IntValue>)Parameters["SampleSize"]; }
64    }
65    public LookupParameter<IntValue> EvaluatedSolutionsParameter {
66      get { return (LookupParameter<IntValue>)Parameters["EvaluatedSolutions"]; }
67    }
68    public ValueParameter<MultiAnalyzer> AnalyzerParameter {
69      get { return (ValueParameter<MultiAnalyzer>)Parameters["Analyzer"]; }
70    }
71
72    public IMoveGenerator MoveGenerator {
73      get { return MoveGeneratorParameter.Value; }
74      set { MoveGeneratorParameter.Value = value; }
75    }
76    public IMoveMaker MoveMaker {
77      get { return MoveMakerParameter.Value; }
78      set { MoveMakerParameter.Value = value; }
79    }
80    public ISingleObjectiveMoveEvaluator MoveEvaluator {
81      get { return MoveEvaluatorParameter.Value; }
82      set { MoveEvaluatorParameter.Value = value; }
83    }
84    public MultiAnalyzer Analyzer {
85      get { return AnalyzerParameter.Value; }
86      set { AnalyzerParameter.Value = value; }
87    }
88
89    [StorableConstructor]
90    protected LocalSearchImprovementOperator(bool deserializing) : base(deserializing) {}
91    [StorableHook(HookType.AfterDeserialization)]
92    private void AfterDeserialization() {
93      Initialize();
94    }
95    protected LocalSearchImprovementOperator(LocalSearchImprovementOperator original, Cloner cloner)
96      : base(original, cloner) {
97        this.loop = cloner.Clone(original.loop);
98        this.qualityAnalyzer = cloner.Clone(original.qualityAnalyzer);
99        Initialize();
100    }
101    public override IDeepCloneable Clone(Cloner cloner) {
102      return new LocalSearchImprovementOperator(this, cloner);
103    }
104    public LocalSearchImprovementOperator()
105      : base() {
106        loop = new LocalSearchMainLoop();
107       
108        ResultsCollector rc = (loop.OperatorGraph.InitialOperator as SingleSuccessorOperator).Successor as ResultsCollector;
109        rc.CollectedValues.Remove("BestLocalQuality");
110
111        qualityAnalyzer = new BestAverageWorstQualityAnalyzer();
112
113        Parameters.Add(new ConstrainedValueParameter<IMoveGenerator>("MoveGenerator", "The operator used to generate moves to the neighborhood of the current solution."));
114        Parameters.Add(new ConstrainedValueParameter<IMoveMaker>("MoveMaker", "The operator used to perform a move."));
115        Parameters.Add(new ConstrainedValueParameter<ISingleObjectiveMoveEvaluator>("MoveEvaluator", "The operator used to evaluate a move."));
116        Parameters.Add(new ValueParameter<IntValue>("MaximumIterations", "The maximum number of generations which should be processed.", new IntValue(150)));
117        Parameters.Add(new ValueParameter<IntValue>("SampleSize", "Number of moves that MultiMoveGenerators should create. This is ignored for Exhaustive- and SingleMoveGenerators.", new IntValue(1500)));
118        Parameters.Add(new LookupParameter<IntValue>("EvaluatedSolutions", "The number of evaluated moves."));
119        Parameters.Add(new ValueParameter<MultiAnalyzer>("Analyzer", "The operator used to analyze the solution.", new MultiAnalyzer()));
120
121        Initialize();
122    }
123
124    private void Initialize() {
125      MoveGeneratorParameter.ValueChanged += new EventHandler(MoveGeneratorParameter_ValueChanged);
126    }
127
128    public void OnProblemChanged(IProblem problem) {
129      UpdateMoveOperators(problem);
130      ChooseMoveOperators();
131
132      ParameterizeMoveGenerators(problem as ISingleObjectiveProblem);
133      ParameterizeMoveEvaluators(problem as ISingleObjectiveProblem);
134      ParameterizeMoveMakers(problem as ISingleObjectiveProblem);
135
136      ParameterizeAnalyzers(problem as ISingleObjectiveProblem);
137      UpdateAnalyzers(problem as ISingleObjectiveProblem);
138    }
139
140    void ParameterizeAnalyzers(ISingleObjectiveProblem problem) {
141      qualityAnalyzer.ResultsParameter.ActualName = "Results";
142      if (problem != null) {
143        qualityAnalyzer.MaximizationParameter.ActualName = problem.MaximizationParameter.Name;
144        if (MoveEvaluator != null)
145          qualityAnalyzer.QualityParameter.ActualName = MoveEvaluator.MoveQualityParameter.ActualName;
146        qualityAnalyzer.BestKnownQualityParameter.ActualName = problem.BestKnownQualityParameter.Name;
147      }
148    }
149
150    void UpdateAnalyzers(ISingleObjectiveProblem problem) {
151      Analyzer.Operators.Clear();
152      if (problem != null) {
153        foreach (IAnalyzer analyzer in problem.Operators.OfType<IAnalyzer>()) {
154          IAnalyzer clone = analyzer.Clone() as IAnalyzer;
155          foreach (IScopeTreeLookupParameter param in clone.Parameters.OfType<IScopeTreeLookupParameter>())
156            param.Depth = 0;
157          Analyzer.Operators.Add(clone);
158        }
159      }
160      Analyzer.Operators.Add(qualityAnalyzer);
161    }
162
163    void MoveGeneratorParameter_ValueChanged(object sender, EventArgs e) {
164      ChooseMoveOperators();
165    }
166
167    private void UpdateMoveOperators(IProblem problem) {
168      IMoveGenerator oldMoveGenerator = MoveGenerator;
169      IMoveMaker oldMoveMaker = MoveMaker;
170      ISingleObjectiveMoveEvaluator oldMoveEvaluator = MoveEvaluator;
171
172      ClearMoveParameters();
173
174      if (problem != null) {
175        foreach (IMoveGenerator generator in problem.Operators.OfType<IMoveGenerator>().OrderBy(x => x.Name))
176          MoveGeneratorParameter.ValidValues.Add(generator);
177
178        foreach (IMoveMaker maker in problem.Operators.OfType<IMoveMaker>().OrderBy(x => x.Name))
179          MoveMakerParameter.ValidValues.Add(maker);
180
181        foreach (ISingleObjectiveMoveEvaluator evaluator in problem.Operators.OfType<ISingleObjectiveMoveEvaluator>().OrderBy(x => x.Name))
182          MoveEvaluatorParameter.ValidValues.Add(evaluator);
183      }
184
185      if (oldMoveGenerator != null) {
186        IMoveGenerator newMoveGenerator = MoveGeneratorParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldMoveGenerator.GetType());
187        if (newMoveGenerator != null) MoveGenerator = newMoveGenerator;
188      }
189      if (MoveGenerator == null) {
190        ClearMoveParameters();
191      }
192
193      if (oldMoveMaker != null) {
194        IMoveMaker mm = MoveMakerParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldMoveMaker.GetType());
195        if (mm != null) MoveMaker = mm;
196      }
197
198      if (oldMoveEvaluator != null) {
199        ISingleObjectiveMoveEvaluator me = MoveEvaluatorParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldMoveEvaluator.GetType());
200        if (me != null) MoveEvaluator = me;
201      }
202    }
203
204    private void ChooseMoveOperators() {
205      IMoveMaker oldMoveMaker = MoveMaker;
206      ISingleObjectiveMoveEvaluator oldMoveEvaluator = MoveEvaluator;
207
208      if (MoveGenerator != null) {
209        List<Type> moveTypes = MoveGenerator.GetType().GetInterfaces().Where(x => typeof(IMoveOperator).IsAssignableFrom(x)).ToList();
210        foreach (Type type in moveTypes.ToList()) {
211          if (moveTypes.Any(t => t != type && type.IsAssignableFrom(t)))
212            moveTypes.Remove(type);
213        }
214        List<IMoveMaker> validMoveMakers = new List<IMoveMaker>();
215        List<ISingleObjectiveMoveEvaluator> validMoveEvaluators = new List<ISingleObjectiveMoveEvaluator>();
216
217        foreach (Type type in moveTypes) {
218          var moveMakers = MoveMakerParameter.ValidValues.Where(x => type.IsAssignableFrom(x.GetType())).OrderBy(x => x.Name);
219          foreach (IMoveMaker moveMaker in moveMakers)
220            validMoveMakers.Add(moveMaker);
221
222          var moveEvaluators = MoveEvaluatorParameter.ValidValues.Where(x => type.IsAssignableFrom(x.GetType())).OrderBy(x => x.Name);
223          foreach (ISingleObjectiveMoveEvaluator moveEvaluator in moveEvaluators)
224            validMoveEvaluators.Add(moveEvaluator);
225        }
226        if (oldMoveMaker != null) {
227          IMoveMaker mm = validMoveMakers.FirstOrDefault(x => x.GetType() == oldMoveMaker.GetType());
228          if (mm != null) MoveMaker = mm;
229          else MoveMaker = validMoveMakers.FirstOrDefault();
230        }
231
232        if (oldMoveEvaluator != null) {
233          ISingleObjectiveMoveEvaluator me = validMoveEvaluators.FirstOrDefault(x => x.GetType() == oldMoveEvaluator.GetType());
234          if (me != null) MoveEvaluator = me;
235          else MoveEvaluator = validMoveEvaluators.FirstOrDefault();
236        }
237      }
238    }
239
240    private void ClearMoveParameters() {
241      MoveGeneratorParameter.ValidValues.Clear();
242      MoveMakerParameter.ValidValues.Clear();
243      MoveEvaluatorParameter.ValidValues.Clear();
244    }
245
246    private void ParameterizeMoveGenerators(ISingleObjectiveProblem problem) {
247      if (problem != null) {
248        foreach (IMultiMoveGenerator generator in problem.Operators.OfType<IMultiMoveGenerator>())
249          generator.SampleSizeParameter.ActualName = SampleSizeParameter.Name;
250      }
251    }
252    private void ParameterizeMoveEvaluators(ISingleObjectiveProblem problem) {
253      foreach (ISingleObjectiveMoveEvaluator op in problem.Operators.OfType<ISingleObjectiveMoveEvaluator>()) {
254        op.QualityParameter.ActualName = problem.Evaluator.QualityParameter.ActualName;
255      }
256    }
257    private void ParameterizeMoveMakers(ISingleObjectiveProblem problem) {
258      foreach (IMoveMaker op in problem.Operators.OfType<IMoveMaker>()) {
259        op.QualityParameter.ActualName = problem.Evaluator.QualityParameter.ActualName;
260        if (MoveEvaluator != null)
261          op.MoveQualityParameter.ActualName = MoveEvaluator.MoveQualityParameter.ActualName;
262      }
263    }
264
265    public override IOperation Apply() {
266      Scope subScope = new Scope();
267      Scope individual = new Scope();
268
269      foreach (Variable var in ExecutionContext.Scope.Variables) {
270        individual.Variables.Add(var);
271      }
272      subScope.SubScopes.Add(individual);
273
274      ExecutionContext.Scope.SubScopes.Add(subScope);
275      int index = subScope.Parent.SubScopes.IndexOf(subScope);
276
277      SubScopesProcessor processor = new SubScopesProcessor();
278      SubScopesRemover remover = new SubScopesRemover();
279
280      remover.RemoveAllSubScopes = false;
281      remover.SubScopeIndexParameter.Value = new IntValue(index);
282
283      for (int i = 0; i < index; i++) {
284        processor.Operators.Add(new EmptyOperator());
285      }
286
287      VariableCreator variableCreator = new VariableCreator();
288      variableCreator.CollectedValues.Add(new ValueParameter<IntValue>("LocalIterations", new IntValue(0)));
289      variableCreator.CollectedValues.Add(new ValueParameter<DoubleValue>("BestLocalQuality", new DoubleValue(0)));
290
291      variableCreator.Successor = loop;
292
293      loop.EvaluatedMovesParameter.ActualName = EvaluatedSolutionsParameter.ActualName;
294
295      processor.Operators.Add(variableCreator);
296      processor.Successor = remover;
297
298      IOperation next = base.Apply();
299      if (next as ExecutionContext != null) {
300        remover.Successor = (next as ExecutionContext).Operator;
301      }
302
303      return ExecutionContext.CreateChildOperation(processor);
304    }
305  }
306}
Note: See TracBrowser for help on using the repository browser.