Free cookie consent management tool by TermsFeed Policy Generator

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

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

Integrated VNS into trunk (#1425)

File size: 13.0 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using HeuristicLab.Core;
6using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
7using HeuristicLab.Common;
8using HeuristicLab.Optimization;
9using HeuristicLab.Parameters;
10using HeuristicLab.Data;
11using HeuristicLab.Analysis;
12using HeuristicLab.Random;
13using HeuristicLab.Optimization.Operators;
14using HeuristicLab.Operators;
15using HeuristicLab.Algorithms.LocalSearch;
16
17namespace HeuristicLab.Algorithms.VariableNeighborhoodSearch {
18  [Item("Variable Neighborhood Search", "A variable neighborhood search algorithm.")]
19  [Creatable("Algorithms")]
20  [StorableClass]
21  public sealed class VariableNeighborhoodSearch : EngineAlgorithm, IStorableContent {
22    public string Filename { get; set; }
23
24    #region Problem Properties
25    public override Type ProblemType {
26      get { return typeof(ISingleObjectiveProblem); }
27    }
28    public new ISingleObjectiveProblem Problem {
29      get { return (ISingleObjectiveProblem)base.Problem; }
30      set { base.Problem = value; }
31    }
32    #endregion
33
34    #region Parameter Properties
35    private ValueParameter<IntValue> SeedParameter {
36      get { return (ValueParameter<IntValue>)Parameters["Seed"]; }
37    }
38    private ValueParameter<BoolValue> SetSeedRandomlyParameter {
39      get { return (ValueParameter<BoolValue>)Parameters["SetSeedRandomly"]; }
40    }
41    private ValueParameter<ILocalImprovementOperator> LocalImprovementParameter {
42      get { return (ValueParameter<ILocalImprovementOperator>)Parameters["LocalImprovement"]; }
43    }
44    private ValueParameter<IShakingOperator> ShakingParameter {
45      get { return (ValueParameter<IShakingOperator>)Parameters["Shaking"]; }
46    }
47    private ValueParameter<IntValue> MaximumIterationsParameter {
48      get { return (ValueParameter<IntValue>)Parameters["MaximumIterations"]; }
49    }
50    private ValueParameter<MultiAnalyzer> AnalyzerParameter {
51      get { return (ValueParameter<MultiAnalyzer>)Parameters["Analyzer"]; }
52    }
53    private VariableNeighborhoodSearchMainLoop VNSMainLoop {
54      get { return FindMainLoop(SolutionsCreator.Successor); }
55    }
56    #endregion
57
58    #region Properties
59    private RandomCreator RandomCreator {
60      get { return (RandomCreator)OperatorGraph.InitialOperator; }
61    }
62    public MultiAnalyzer Analyzer {
63      get { return AnalyzerParameter.Value; }
64      set { AnalyzerParameter.Value = value; }
65    }
66    private SolutionsCreator SolutionsCreator {
67      get { return (SolutionsCreator)RandomCreator.Successor; }
68    }
69    #endregion
70
71    [Storable]
72    private BestAverageWorstQualityAnalyzer qualityAnalyzer;
73
74    [StorableConstructor]
75    private VariableNeighborhoodSearch(bool deserializing) : base(deserializing) { }
76    [StorableHook(HookType.AfterDeserialization)]
77    private void AfterDeserialization() {
78
79    }
80    private VariableNeighborhoodSearch(VariableNeighborhoodSearch original, Cloner cloner)
81      : base(original, cloner) {
82      qualityAnalyzer = cloner.Clone(original.qualityAnalyzer);
83      Initialize();
84    }
85    public override IDeepCloneable Clone(Cloner cloner) {
86      return new VariableNeighborhoodSearch(this, cloner);
87    }
88    public VariableNeighborhoodSearch()
89      : base() {
90      Parameters.Add(new ValueParameter<IntValue>("Seed", "The random seed used to initialize the new pseudo random number generator.", new IntValue(0)));
91      Parameters.Add(new ValueParameter<BoolValue>("SetSeedRandomly", "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true)));
92      Parameters.Add(new ValueParameter<ILocalImprovementOperator>("LocalImprovement", "The local improvement operation", new LocalSearchImprovementOperator()));
93      Parameters.Add(new ValueParameter<IShakingOperator>("Shaking", "The shaking operation"));
94      Parameters.Add(new ValueParameter<IntValue>("MaximumIterations", "The maximum number of generations which should be processed.", new IntValue(1000)));
95      Parameters.Add(new ValueParameter<MultiAnalyzer>("Analyzer", "The operator used to analyze the solution and moves.", new MultiAnalyzer()));
96
97      RandomCreator randomCreator = new RandomCreator();
98      SolutionsCreator solutionsCreator = new SolutionsCreator();
99      VariableCreator variableCreator = new VariableCreator();
100      ResultsCollector resultsCollector = new ResultsCollector();
101      VariableNeighborhoodSearchMainLoop mainLoop = new VariableNeighborhoodSearchMainLoop();
102      OperatorGraph.InitialOperator = randomCreator;
103
104      randomCreator.RandomParameter.ActualName = "Random";
105      randomCreator.SeedParameter.ActualName = SeedParameter.Name;
106      randomCreator.SeedParameter.Value = null;
107      randomCreator.SetSeedRandomlyParameter.ActualName = SetSeedRandomlyParameter.Name;
108      randomCreator.SetSeedRandomlyParameter.Value = null;
109      randomCreator.Successor = solutionsCreator;
110
111      solutionsCreator.NumberOfSolutions = new IntValue(1);
112      solutionsCreator.Successor = variableCreator;
113
114      variableCreator.Name = "Initialize Evaluated Solutions";
115      variableCreator.CollectedValues.Add(new ValueParameter<IntValue>("EvaluatedSolutions", new IntValue()));
116      variableCreator.Successor = resultsCollector;
117
118      resultsCollector.CollectedValues.Add(new LookupParameter<IntValue>("Evaluated Solutions", null, "EvaluatedSolutions"));
119      resultsCollector.ResultsParameter.ActualName = "Results";
120      resultsCollector.Successor = mainLoop;
121
122      mainLoop.LocalImprovementParameter.ActualName = LocalImprovementParameter.Name;
123      mainLoop.ShakingParameter.ActualName = ShakingParameter.Name;
124      mainLoop.MaximumIterationsParameter.ActualName = MaximumIterationsParameter.Name;
125      mainLoop.RandomParameter.ActualName = RandomCreator.RandomParameter.ActualName;
126      mainLoop.ResultsParameter.ActualName = "Results";
127      mainLoop.AnalyzerParameter.ActualName = AnalyzerParameter.Name;
128      mainLoop.EvaluatedSolutionsParameter.ActualName = "EvaluatedSolutions";
129
130      qualityAnalyzer = new BestAverageWorstQualityAnalyzer();
131      ParameterizeAnalyzers();
132      UpdateAnalyzers();
133
134      Initialize();
135    }
136
137    public override void Prepare() {
138      if (Problem != null) base.Prepare();
139    }
140
141    private void Initialize() {
142      if (Problem != null) {
143        Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
144      }
145      LocalImprovementParameter.ValueChanged += new EventHandler(LocalImprovementParameter_ValueChanged);
146    }
147
148    #region Events
149    protected override void OnProblemChanged() {
150      ParameterizeStochasticOperator(Problem.SolutionCreator);
151      ParameterizeStochasticOperator(Problem.Evaluator);
152      foreach (IOperator op in Problem.Operators) ParameterizeStochasticOperator(op);
153      ParameterizeSolutionsCreator();
154      ParameterizeVNSMainLoop();
155      ParameterizeAnalyzers();
156      ParameterizeIterationBasedOperators();
157      UpdateShakingOperator();
158      UpdateLocalImprovementOperator();
159      UpdateAnalyzers();
160      Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
161      base.OnProblemChanged();
162    }
163
164    protected override void Problem_SolutionCreatorChanged(object sender, EventArgs e) {
165      ParameterizeStochasticOperator(Problem.SolutionCreator);
166      ParameterizeSolutionsCreator();
167      base.Problem_SolutionCreatorChanged(sender, e);
168    }
169    protected override void Problem_EvaluatorChanged(object sender, EventArgs e) {
170      ParameterizeStochasticOperator(Problem.Evaluator);
171      ParameterizeSolutionsCreator();
172      ParameterizeVNSMainLoop();
173      ParameterizeAnalyzers();
174      Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
175      base.Problem_EvaluatorChanged(sender, e);
176    }
177    protected override void Problem_OperatorsChanged(object sender, EventArgs e) {
178      foreach (IOperator op in Problem.Operators) ParameterizeStochasticOperator(op);
179      ParameterizeIterationBasedOperators();
180      UpdateShakingOperator();
181      UpdateLocalImprovementOperator();
182      UpdateAnalyzers();
183      base.Problem_OperatorsChanged(sender, e);
184    }
185
186    private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) {
187      ParameterizeVNSMainLoop();
188      ParameterizeAnalyzers();
189    }
190
191    void LocalImprovementParameter_ValueChanged(object sender, EventArgs e) {
192      if (LocalImprovementParameter.Value != null)
193        LocalImprovementParameter.Value.OnProblemChanged(Problem);
194    }
195    #endregion
196
197    #region Helpers
198    private void ParameterizeSolutionsCreator() {
199      SolutionsCreator.EvaluatorParameter.ActualName = Problem.EvaluatorParameter.Name;
200      SolutionsCreator.SolutionCreatorParameter.ActualName = Problem.SolutionCreatorParameter.Name;
201    }
202    private void ParameterizeStochasticOperator(IOperator op) {
203      if (op is IStochasticOperator)
204        ((IStochasticOperator)op).RandomParameter.ActualName = RandomCreator.RandomParameter.ActualName;
205    }
206    private void ParameterizeVNSMainLoop() {
207      VNSMainLoop.EvaluatorParameter.ActualName = Problem.EvaluatorParameter.Name;
208      VNSMainLoop.MaximizationParameter.ActualName = Problem.MaximizationParameter.Name;
209      VNSMainLoop.QualityParameter.ActualName = Problem.Evaluator.QualityParameter.ActualName;
210    }
211    private void ParameterizeAnalyzers() {
212      qualityAnalyzer.ResultsParameter.ActualName = "Results";
213      if (Problem != null) {
214        qualityAnalyzer.MaximizationParameter.ActualName = Problem.MaximizationParameter.Name;
215        qualityAnalyzer.QualityParameter.ActualName = Problem.Evaluator.QualityParameter.ActualName;
216        qualityAnalyzer.QualityParameter.Depth = 1;
217        qualityAnalyzer.BestKnownQualityParameter.ActualName = Problem.BestKnownQualityParameter.Name;
218      }
219    }
220    private void ParameterizeIterationBasedOperators() {
221      if (Problem != null) {
222        foreach (IIterationBasedOperator op in Problem.Operators.OfType<IIterationBasedOperator>()) {
223          op.IterationsParameter.ActualName = "Iterations";
224          op.MaximumIterationsParameter.ActualName = "MaximumIterations";
225        }
226      }
227    }
228    private void UpdateShakingOperator() {
229      Type manipulatorType = typeof(IManipulator);
230      List<Type> manipulatorInterfaces = new List<Type>();
231
232      foreach (IManipulator mutator in Problem.Operators.OfType<IManipulator>().OrderBy(x => x.Name)) {
233        Type t = mutator.GetType();
234        Type[] interfaces = t.GetInterfaces();
235
236        for(int i = 0; i < interfaces.Length; i++) {
237          if (manipulatorType.IsAssignableFrom(interfaces[i])) {
238            bool assignable = false;
239            for (int j = 0; j < interfaces.Length; j++) {
240              if (i != j && interfaces[i].IsAssignableFrom(interfaces[j])) {
241                assignable = true;
242                break;
243              }
244            }
245
246            if(!assignable)
247              manipulatorInterfaces.Add(interfaces[i]);
248          }         
249        }
250      }
251
252      foreach (Type manipulatorInterface in manipulatorInterfaces) {
253        //manipulatorInterface is more specific
254        if (manipulatorType.IsAssignableFrom(manipulatorInterface)) {
255          //and compatible to all other found manipulator types
256          bool compatible = true;
257          foreach (Type manipulatorInterface2 in manipulatorInterfaces) {
258            if (!manipulatorInterface.IsAssignableFrom(manipulatorInterface2)) {
259              compatible = false;
260              break;
261            }
262          }
263
264          if (compatible)
265            manipulatorType = manipulatorInterface;
266        }
267      }
268     
269      Type genericType = typeof(ShakingOperator<>).MakeGenericType(manipulatorType);
270      ShakingParameter.Value = (IShakingOperator)Activator.CreateInstance(genericType, new object[]{});
271
272      ShakingParameter.Value.OnProblemChanged(Problem);
273    }
274    private void UpdateLocalImprovementOperator() {
275      LocalImprovementParameter.Value.OnProblemChanged(Problem);
276    }
277    private void UpdateAnalyzers() {
278      Analyzer.Operators.Clear();
279      if (Problem != null) {
280        foreach (IAnalyzer analyzer in Problem.Operators.OfType<IAnalyzer>()) {
281          foreach (IScopeTreeLookupParameter param in analyzer.Parameters.OfType<IScopeTreeLookupParameter>())
282            param.Depth = 1;
283          Analyzer.Operators.Add(analyzer);
284        }
285      }
286      Analyzer.Operators.Add(qualityAnalyzer);
287    }
288    private VariableNeighborhoodSearchMainLoop FindMainLoop(IOperator start) {
289      IOperator mainLoop = start;
290      while (mainLoop != null && !(mainLoop is VariableNeighborhoodSearchMainLoop))
291        mainLoop = ((SingleSuccessorOperator)mainLoop).Successor;
292      if (mainLoop == null) return null;
293      else return (VariableNeighborhoodSearchMainLoop)mainLoop;
294    }
295    #endregion
296  }
297}
Note: See TracBrowser for help on using the repository browser.