Free cookie consent management tool by TermsFeed Policy Generator

source: branches/VNS/HeuristicLab.Algorithms.LocalSearch/3.3/LocalSearchImprovementOperator.cs @ 5735

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

Implemented review comments of swagner (#1425)

File size: 13.0 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("LocalIterations", "BestLocalQuality");
107
108        ResultsCollector rc = ((loop.OperatorGraph.InitialOperator as SingleSuccessorOperator).Successor
109          as SingleSuccessorOperator).Successor as ResultsCollector;
110        rc.CollectedValues.Remove("BestLocalQuality");
111
112        qualityAnalyzer = new BestAverageWorstQualityAnalyzer();
113
114        Parameters.Add(new ConstrainedValueParameter<IMoveGenerator>("MoveGenerator", "The operator used to generate moves to the neighborhood of the current solution."));
115        Parameters.Add(new ConstrainedValueParameter<IMoveMaker>("MoveMaker", "The operator used to perform a move."));
116        Parameters.Add(new ConstrainedValueParameter<ISingleObjectiveMoveEvaluator>("MoveEvaluator", "The operator used to evaluate a move."));
117        Parameters.Add(new ValueParameter<IntValue>("MaximumIterations", "The maximum number of generations which should be processed.", new IntValue(150)));
118        Parameters.Add(new ValueParameter<IntValue>("SampleSize", "Number of moves that MultiMoveGenerators should create. This is ignored for Exhaustive- and SingleMoveGenerators.", new IntValue(1500)));
119        Parameters.Add(new LookupParameter<IntValue>("EvaluatedSolutions", "The number of evaluated moves."));
120        Parameters.Add(new ValueParameter<MultiAnalyzer>("Analyzer", "The operator used to analyze the solution.", new MultiAnalyzer()));
121
122        Initialize();
123    }
124
125    private void Initialize() {
126      MoveGeneratorParameter.ValueChanged += new EventHandler(MoveGeneratorParameter_ValueChanged);
127    }
128
129    public void OnProblemChanged(IProblem problem) {
130      UpdateMoveOperators(problem);
131      ChooseMoveOperators();
132
133      ParameterizeMoveGenerators(problem as ISingleObjectiveProblem);
134      ParameterizeMoveEvaluators(problem as ISingleObjectiveProblem);
135      ParameterizeMoveMakers(problem as ISingleObjectiveProblem);
136
137      ParameterizeAnalyzers(problem as ISingleObjectiveProblem);
138      UpdateAnalyzers(problem as ISingleObjectiveProblem);
139    }
140
141    void ParameterizeAnalyzers(ISingleObjectiveProblem problem) {
142      qualityAnalyzer.ResultsParameter.ActualName = "Results";
143      if (problem != null) {
144        qualityAnalyzer.MaximizationParameter.ActualName = problem.MaximizationParameter.Name;
145        if (MoveEvaluator != null)
146          qualityAnalyzer.QualityParameter.ActualName = MoveEvaluator.MoveQualityParameter.ActualName;
147        qualityAnalyzer.BestKnownQualityParameter.ActualName = problem.BestKnownQualityParameter.Name;
148      }
149    }
150
151    void UpdateAnalyzers(ISingleObjectiveProblem problem) {
152      Analyzer.Operators.Clear();
153      if (problem != null) {
154        foreach (IAnalyzer analyzer in problem.Operators.OfType<IAnalyzer>()) {
155          IAnalyzer clone = analyzer.Clone() as IAnalyzer;
156          foreach (IScopeTreeLookupParameter param in clone.Parameters.OfType<IScopeTreeLookupParameter>())
157            param.Depth = 0;
158          Analyzer.Operators.Add(clone);
159        }
160      }
161      Analyzer.Operators.Add(qualityAnalyzer);
162    }
163
164    void MoveGeneratorParameter_ValueChanged(object sender, EventArgs e) {
165      ChooseMoveOperators();
166    }
167
168    private void UpdateMoveOperators(IProblem problem) {
169      IMoveGenerator oldMoveGenerator = MoveGenerator;
170      IMoveMaker oldMoveMaker = MoveMaker;
171      ISingleObjectiveMoveEvaluator oldMoveEvaluator = MoveEvaluator;
172
173      ClearMoveParameters();
174
175      if (problem != null) {
176        foreach (IMoveGenerator generator in problem.Operators.OfType<IMoveGenerator>().OrderBy(x => x.Name))
177          MoveGeneratorParameter.ValidValues.Add(generator);
178
179        foreach (IMoveMaker maker in problem.Operators.OfType<IMoveMaker>().OrderBy(x => x.Name))
180          MoveMakerParameter.ValidValues.Add(maker);
181
182        foreach (ISingleObjectiveMoveEvaluator evaluator in problem.Operators.OfType<ISingleObjectiveMoveEvaluator>().OrderBy(x => x.Name))
183          MoveEvaluatorParameter.ValidValues.Add(evaluator);
184      }
185
186      if (oldMoveGenerator != null) {
187        IMoveGenerator newMoveGenerator = MoveGeneratorParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldMoveGenerator.GetType());
188        if (newMoveGenerator != null) MoveGenerator = newMoveGenerator;
189      }
190      if (MoveGenerator == null) {
191        ClearMoveParameters();
192      }
193
194      if (oldMoveMaker != null) {
195        IMoveMaker mm = MoveMakerParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldMoveMaker.GetType());
196        if (mm != null) MoveMaker = mm;
197      }
198
199      if (oldMoveEvaluator != null) {
200        ISingleObjectiveMoveEvaluator me = MoveEvaluatorParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldMoveEvaluator.GetType());
201        if (me != null) MoveEvaluator = me;
202      }
203    }
204
205    private void ChooseMoveOperators() {
206      IMoveMaker oldMoveMaker = MoveMaker;
207      ISingleObjectiveMoveEvaluator oldMoveEvaluator = MoveEvaluator;
208
209      if (MoveGenerator != null) {
210        List<Type> moveTypes = MoveGenerator.GetType().GetInterfaces().Where(x => typeof(IMoveOperator).IsAssignableFrom(x)).ToList();
211        foreach (Type type in moveTypes.ToList()) {
212          if (moveTypes.Any(t => t != type && type.IsAssignableFrom(t)))
213            moveTypes.Remove(type);
214        }
215        List<IMoveMaker> validMoveMakers = new List<IMoveMaker>();
216        List<ISingleObjectiveMoveEvaluator> validMoveEvaluators = new List<ISingleObjectiveMoveEvaluator>();
217
218        foreach (Type type in moveTypes) {
219          var moveMakers = MoveMakerParameter.ValidValues.Where(x => type.IsAssignableFrom(x.GetType())).OrderBy(x => x.Name);
220          foreach (IMoveMaker moveMaker in moveMakers)
221            validMoveMakers.Add(moveMaker);
222
223          var moveEvaluators = MoveEvaluatorParameter.ValidValues.Where(x => type.IsAssignableFrom(x.GetType())).OrderBy(x => x.Name);
224          foreach (ISingleObjectiveMoveEvaluator moveEvaluator in moveEvaluators)
225            validMoveEvaluators.Add(moveEvaluator);
226        }
227        if (oldMoveMaker != null) {
228          IMoveMaker mm = validMoveMakers.FirstOrDefault(x => x.GetType() == oldMoveMaker.GetType());
229          if (mm != null) MoveMaker = mm;
230          else MoveMaker = validMoveMakers.FirstOrDefault();
231        }
232
233        if (oldMoveEvaluator != null) {
234          ISingleObjectiveMoveEvaluator me = validMoveEvaluators.FirstOrDefault(x => x.GetType() == oldMoveEvaluator.GetType());
235          if (me != null) MoveEvaluator = me;
236          else MoveEvaluator = validMoveEvaluators.FirstOrDefault();
237        }
238      }
239    }
240
241    private void ClearMoveParameters() {
242      MoveGeneratorParameter.ValidValues.Clear();
243      MoveMakerParameter.ValidValues.Clear();
244      MoveEvaluatorParameter.ValidValues.Clear();
245    }
246
247    private void ParameterizeMoveGenerators(ISingleObjectiveProblem problem) {
248      if (problem != null) {
249        foreach (IMultiMoveGenerator generator in problem.Operators.OfType<IMultiMoveGenerator>())
250          generator.SampleSizeParameter.ActualName = SampleSizeParameter.Name;
251      }
252    }
253    private void ParameterizeMoveEvaluators(ISingleObjectiveProblem problem) {
254      foreach (ISingleObjectiveMoveEvaluator op in problem.Operators.OfType<ISingleObjectiveMoveEvaluator>()) {
255        op.QualityParameter.ActualName = problem.Evaluator.QualityParameter.ActualName;
256      }
257    }
258    private void ParameterizeMoveMakers(ISingleObjectiveProblem problem) {
259      foreach (IMoveMaker op in problem.Operators.OfType<IMoveMaker>()) {
260        op.QualityParameter.ActualName = problem.Evaluator.QualityParameter.ActualName;
261        if (MoveEvaluator != null)
262          op.MoveQualityParameter.ActualName = MoveEvaluator.MoveQualityParameter.ActualName;
263      }
264    }
265
266    public override IOperation Apply() {
267      Scope subScope = new Scope();
268      Scope individual = new Scope();
269
270      foreach (Variable var in ExecutionContext.Scope.Variables) {
271        individual.Variables.Add(var);
272      }
273      subScope.SubScopes.Add(individual);
274
275      ExecutionContext.Scope.SubScopes.Add(subScope);
276      int index = subScope.Parent.SubScopes.IndexOf(subScope);
277
278      SubScopesProcessor processor = new SubScopesProcessor();
279      SubScopesRemover remover = new SubScopesRemover();
280
281      remover.RemoveAllSubScopes = false;
282      remover.SubScopeIndexParameter.Value = new IntValue(index);
283
284      for (int i = 0; i < index; i++) {
285        processor.Operators.Add(new EmptyOperator());
286      }
287
288      loop.EvaluatedMovesParameter.ActualName = EvaluatedSolutionsParameter.ActualName;
289
290      processor.Operators.Add(loop);
291      processor.Successor = remover;
292
293      IOperation next = base.Apply();
294      if (next as ExecutionContext != null) {
295        remover.Successor = (next as ExecutionContext).Operator;
296      }
297
298      return ExecutionContext.CreateChildOperation(processor);
299    }
300  }
301}
Note: See TracBrowser for help on using the repository browser.