Free cookie consent management tool by TermsFeed Policy Generator

source: stable/HeuristicLab.Problems.VehicleRouting/3.4/VehicleRoutingProblem.cs @ 17105

Last change on this file since 17105 was 17105, checked in by mkommend, 5 years ago

#2520: Merged 16584, 16585,16594,16595, 16625, 16658, 16659, 16672, 16707, 16729, 16792, 16796, 16797, 16799, 16819, 16906, 16907, 16908, 16933, 16945, 16992, 16994, 16995, 16996, 16997, 17014, 17015, 17017, 17020, 17021, 17022, 17023, 17024, 17029, 17086, 17087, 17088, 17089 into stable.

File size: 16.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2019 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.Drawing;
25using System.Linq;
26using HeuristicLab.Analysis;
27using HeuristicLab.Common;
28using HeuristicLab.Core;
29using HeuristicLab.Data;
30using HeuristicLab.Optimization;
31using HeuristicLab.Optimization.Operators;
32using HeuristicLab.Parameters;
33using HEAL.Attic;
34using HeuristicLab.PluginInfrastructure;
35using HeuristicLab.Problems.Instances;
36using HeuristicLab.Problems.VehicleRouting.Encodings.Alba;
37using HeuristicLab.Problems.VehicleRouting.Interfaces;
38using HeuristicLab.Problems.VehicleRouting.Interpreters;
39using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
40using HeuristicLab.Problems.VehicleRouting.Variants;
41
42namespace HeuristicLab.Problems.VehicleRouting {
43  [Item("Vehicle Routing Problem (VRP)", "Represents a Vehicle Routing Problem.")]
44  [Creatable(CreatableAttribute.Categories.CombinatorialProblems, Priority = 110)]
45  [StorableType("95137523-AE3B-4638-958C-E86829D54CE3")]
46  public sealed class VehicleRoutingProblem : Problem, ISingleObjectiveHeuristicOptimizationProblem, IStorableContent, IProblemInstanceConsumer<IVRPData> {
47    public string Filename { get; set; }
48
49    public static new Image StaticItemImage {
50      get { return HeuristicLab.Common.Resources.VSImageLibrary.Type; }
51    }
52
53    #region Parameter Properties
54    public ValueParameter<BoolValue> MaximizationParameter {
55      get { return (ValueParameter<BoolValue>)Parameters["Maximization"]; }
56    }
57    IParameter ISingleObjectiveHeuristicOptimizationProblem.MaximizationParameter {
58      get { return MaximizationParameter; }
59    }
60    public ValueParameter<IVRPProblemInstance> ProblemInstanceParameter {
61      get { return (ValueParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
62    }
63    public OptionalValueParameter<DoubleValue> BestKnownQualityParameter {
64      get { return (OptionalValueParameter<DoubleValue>)Parameters["BestKnownQuality"]; }
65    }
66    IParameter ISingleObjectiveHeuristicOptimizationProblem.BestKnownQualityParameter {
67      get { return BestKnownQualityParameter; }
68    }
69    public OptionalValueParameter<VRPSolution> BestKnownSolutionParameter {
70      get { return (OptionalValueParameter<VRPSolution>)Parameters["BestKnownSolution"]; }
71    }
72    public IConstrainedValueParameter<IVRPCreator> SolutionCreatorParameter {
73      get { return (IConstrainedValueParameter<IVRPCreator>)Parameters["SolutionCreator"]; }
74    }
75    IParameter IHeuristicOptimizationProblem.SolutionCreatorParameter {
76      get { return SolutionCreatorParameter; }
77    }
78    public IValueParameter<IVRPEvaluator> EvaluatorParameter {
79      get { return (IValueParameter<IVRPEvaluator>)Parameters["Evaluator"]; }
80    }
81    IParameter IHeuristicOptimizationProblem.EvaluatorParameter {
82      get { return EvaluatorParameter; }
83    }
84    #endregion
85
86    #region Properties
87    public IVRPProblemInstance ProblemInstance {
88      get { return ProblemInstanceParameter.Value; }
89      set { ProblemInstanceParameter.Value = value; }
90    }
91
92    public VRPSolution BestKnownSolution {
93      get { return BestKnownSolutionParameter.Value; }
94      set { BestKnownSolutionParameter.Value = value; }
95    }
96
97    public DoubleValue BestKnownQuality {
98      get { return BestKnownQualityParameter.Value; }
99      set { BestKnownQualityParameter.Value = value; }
100    }
101
102    public ISingleObjectiveEvaluator Evaluator {
103      get { return EvaluatorParameter.Value; }
104    }
105
106    IEvaluator IHeuristicOptimizationProblem.Evaluator {
107      get { return this.Evaluator; }
108    }
109
110    ISolutionCreator IHeuristicOptimizationProblem.SolutionCreator {
111      get { return SolutionCreatorParameter.Value; }
112    }
113    public IVRPCreator SolutionCreator {
114      get { return SolutionCreatorParameter.Value; }
115      set { SolutionCreatorParameter.Value = value; }
116    }
117    #endregion
118
119    [StorableConstructor]
120    private VehicleRoutingProblem(StorableConstructorFlag _) : base(_) { }
121    public VehicleRoutingProblem()
122      : base() {
123      Parameters.Add(new ValueParameter<BoolValue>("Maximization", "Set to false as the Vehicle Routing Problem is a minimization problem.", new BoolValue(false)));
124      Parameters.Add(new ValueParameter<IVRPProblemInstance>("ProblemInstance", "The VRP problem instance"));
125      Parameters.Add(new OptionalValueParameter<DoubleValue>("BestKnownQuality", "The quality of the best known solution of this VRP instance."));
126      Parameters.Add(new OptionalValueParameter<VRPSolution>("BestKnownSolution", "The best known solution of this VRP instance."));
127
128      Parameters.Add(new ConstrainedValueParameter<IVRPCreator>("SolutionCreator", "The operator which should be used to create new VRP solutions."));
129      Parameters.Add(new ValueParameter<IVRPEvaluator>("Evaluator", "The operator which should be used to evaluate VRP solutions."));
130
131      EvaluatorParameter.Hidden = true;
132
133      InitializeRandomVRPInstance();
134      InitializeOperators();
135
136      AttachEventHandlers();
137      AttachProblemInstanceEventHandlers();
138
139      EvaluatorParameter.Value = ProblemInstance.SolutionEvaluator;
140    }
141
142    public override IDeepCloneable Clone(Cloner cloner) {
143      cloner.Clone(ProblemInstance);
144      return new VehicleRoutingProblem(this, cloner);
145    }
146
147    private VehicleRoutingProblem(VehicleRoutingProblem original, Cloner cloner)
148      : base(original, cloner) {
149      this.AttachEventHandlers();
150      this.AttachProblemInstanceEventHandlers();
151
152      ProblemInstance.SolutionEvaluator = EvaluatorParameter.Value;
153    }
154
155    #region Events
156    public event EventHandler SolutionCreatorChanged;
157    private void OnSolutionCreatorChanged() {
158      EventHandler handler = SolutionCreatorChanged;
159      if (handler != null) handler(this, EventArgs.Empty);
160    }
161    public event EventHandler EvaluatorChanged;
162    private void OnEvaluatorChanged() {
163      EventHandler handler = EvaluatorChanged;
164      if (handler != null) handler(this, EventArgs.Empty);
165    }
166    #endregion
167
168    #region Helpers
169    [StorableHook(HookType.AfterDeserialization)]
170    private void AfterDeserialization() {
171      AttachEventHandlers();
172      AttachProblemInstanceEventHandlers();
173
174      ProblemInstance.SolutionEvaluator = EvaluatorParameter.Value;
175    }
176
177    [Storable(OldName = "operators")]
178    private List<IOperator> StorableOperators {
179      set { Operators.AddRange(value); }
180    }
181
182    private void AttachEventHandlers() {
183      ProblemInstanceParameter.ValueChanged += new EventHandler(ProblemInstanceParameter_ValueChanged);
184      BestKnownSolutionParameter.ValueChanged += new EventHandler(BestKnownSolutionParameter_ValueChanged);
185      EvaluatorParameter.ValueChanged += new EventHandler(EvaluatorParameter_ValueChanged);
186      SolutionCreatorParameter.ValueChanged += new EventHandler(SolutionCreatorParameter_ValueChanged);
187    }
188
189    private void AttachProblemInstanceEventHandlers() {
190      if (ProblemInstance != null) {
191        ProblemInstance.EvaluationChanged += new EventHandler(ProblemInstance_EvaluationChanged);
192      }
193    }
194
195    private void EvalBestKnownSolution() {
196      if (BestKnownSolution == null) return;
197      try {
198        //call evaluator
199        BestKnownQuality = new DoubleValue(ProblemInstance.Evaluate(BestKnownSolution.Solution).Quality);
200        BestKnownSolution.Quality = BestKnownQuality;
201      } catch {
202        BestKnownQuality = null;
203        BestKnownSolution = null;
204      }
205    }
206
207    void BestKnownSolutionParameter_ValueChanged(object sender, EventArgs e) {
208      EvalBestKnownSolution();
209    }
210
211    void ProblemInstance_EvaluationChanged(object sender, EventArgs e) {
212      BestKnownQuality = null;
213      if (BestKnownSolution != null) {
214        // the tour is not valid if there are more vehicles in it than allowed
215        if (ProblemInstance.Vehicles.Value < BestKnownSolution.Solution.GetTours().Count) {
216          BestKnownSolution = null;
217        } else EvalBestKnownSolution();
218      }
219    }
220
221    void ProblemInstanceParameter_ValueChanged(object sender, EventArgs e) {
222      InitializeOperators();
223      AttachProblemInstanceEventHandlers();
224
225      EvaluatorParameter.Value = ProblemInstance.SolutionEvaluator;
226
227      OnSolutionCreatorChanged();
228      OnEvaluatorChanged();
229      OnOperatorsChanged();
230    }
231
232    public void SetProblemInstance(IVRPProblemInstance instance) {
233      ProblemInstanceParameter.ValueChanged -= new EventHandler(ProblemInstanceParameter_ValueChanged);
234
235      ProblemInstance = instance;
236      AttachProblemInstanceEventHandlers();
237
238      OnSolutionCreatorChanged();
239      OnEvaluatorChanged();
240
241      ProblemInstanceParameter.ValueChanged += new EventHandler(ProblemInstanceParameter_ValueChanged);
242    }
243
244    private void SolutionCreatorParameter_ValueChanged(object sender, EventArgs e) {
245      OnSolutionCreatorChanged();
246    }
247    private void EvaluatorParameter_ValueChanged(object sender, EventArgs e) {
248      if (ProblemInstance != null)
249        ProblemInstance.SolutionEvaluator = EvaluatorParameter.Value;
250      OnEvaluatorChanged();
251    }
252
253    private void InitializeOperators() {
254      var solutionCreatorParameter = SolutionCreatorParameter as ConstrainedValueParameter<IVRPCreator>;
255      solutionCreatorParameter.ValidValues.Clear();
256
257      Operators.Clear();
258
259      if (ProblemInstance != null) {
260        Operators.AddRange(
261        ProblemInstance.Operators.Concat(
262          ApplicationManager.Manager.GetInstances<IGeneralVRPOperator>().Cast<IOperator>()).OrderBy(op => op.Name));
263        Operators.Add(new VRPSimilarityCalculator());
264        Operators.Add(new QualitySimilarityCalculator());
265        Operators.Add(new PopulationSimilarityAnalyzer(Operators.OfType<ISolutionSimilarityCalculator>()));
266
267        IVRPCreator defaultCreator = null;
268        foreach (IVRPCreator creator in Operators.Where(o => o is IVRPCreator)) {
269          solutionCreatorParameter.ValidValues.Add(creator);
270          if (creator is Encodings.Alba.RandomCreator)
271            defaultCreator = creator;
272        }
273        Operators.Add(new AlbaLambdaInterchangeLocalImprovementOperator());
274        if (defaultCreator != null)
275          solutionCreatorParameter.Value = defaultCreator;
276      }
277
278      ParameterizeOperators();
279    }
280
281    private void ParameterizeOperators() {
282      foreach (IOperator op in Operators.OfType<IOperator>()) {
283        if (op is IMultiVRPOperator) {
284          (op as IMultiVRPOperator).SetOperators(Operators.OfType<IOperator>());
285        }
286      }
287      if (ProblemInstance != null) {
288        foreach (ISingleObjectiveImprovementOperator op in Operators.OfType<ISingleObjectiveImprovementOperator>()) {
289          op.SolutionParameter.ActualName = SolutionCreator.VRPToursParameter.ActualName;
290          op.SolutionParameter.Hidden = true;
291        }
292        foreach (ISingleObjectivePathRelinker op in Operators.OfType<ISingleObjectivePathRelinker>()) {
293          op.ParentsParameter.ActualName = SolutionCreator.VRPToursParameter.ActualName;
294          op.ParentsParameter.Hidden = true;
295        }
296        foreach (ISolutionSimilarityCalculator op in Operators.OfType<ISolutionSimilarityCalculator>()) {
297          op.SolutionVariableName = SolutionCreator.VRPToursParameter.ActualName;
298          op.QualityVariableName = ProblemInstance.SolutionEvaluator.QualityParameter.ActualName;
299          var calc = op as VRPSimilarityCalculator;
300          if (calc != null) calc.ProblemInstance = ProblemInstance;
301        }
302      }
303    }
304
305    #endregion
306
307    private void InitializeRandomVRPInstance() {
308      System.Random rand = new System.Random();
309
310      CVRPTWProblemInstance problem = new CVRPTWProblemInstance();
311      int cities = 100;
312
313      problem.Coordinates = new DoubleMatrix(cities + 1, 2);
314      problem.Demand = new DoubleArray(cities + 1);
315      problem.DueTime = new DoubleArray(cities + 1);
316      problem.ReadyTime = new DoubleArray(cities + 1);
317      problem.ServiceTime = new DoubleArray(cities + 1);
318
319      problem.Vehicles.Value = 100;
320      problem.Capacity.Value = 200;
321
322      for (int i = 0; i <= cities; i++) {
323        problem.Coordinates[i, 0] = rand.Next(0, 100);
324        problem.Coordinates[i, 1] = rand.Next(0, 100);
325
326        if (i == 0) {
327          problem.Demand[i] = 0;
328          problem.DueTime[i] = Int16.MaxValue;
329          problem.ReadyTime[i] = 0;
330          problem.ServiceTime[i] = 0;
331        } else {
332          problem.Demand[i] = rand.Next(10, 50);
333          problem.DueTime[i] = rand.Next((int)Math.Ceiling(problem.GetDistance(0, i, null)), 1200);
334          problem.ReadyTime[i] = problem.DueTime[i] - rand.Next(0, 100);
335          problem.ServiceTime[i] = 90;
336        }
337      }
338
339      this.ProblemInstance = problem;
340    }
341
342    public void ImportSolution(string solutionFileName) {
343      SolutionParser parser = new SolutionParser(solutionFileName);
344      parser.Parse();
345
346      HeuristicLab.Problems.VehicleRouting.Encodings.Potvin.PotvinEncoding encoding = new Encodings.Potvin.PotvinEncoding(ProblemInstance);
347
348      int cities = 0;
349      foreach (List<int> route in parser.Routes) {
350        Tour tour = new Tour();
351        tour.Stops.AddRange(route);
352        cities += tour.Stops.Count;
353
354        encoding.Tours.Add(tour);
355      }
356
357      if (cities != ProblemInstance.Coordinates.Rows - 1)
358        ErrorHandling.ShowErrorDialog(new Exception("The optimal solution does not seem to correspond with the problem data"));
359      else {
360        VRPSolution solution = new VRPSolution(ProblemInstance, encoding, new DoubleValue(0));
361        BestKnownSolutionParameter.Value = solution;
362      }
363    }
364
365    #region Instance Consuming
366    public void Load(IVRPData data, IVRPDataInterpreter interpreter) {
367      VRPInstanceDescription instance = interpreter.Interpret(data);
368
369      Name = instance.Name;
370      Description = instance.Description;
371
372      BestKnownQuality = null;
373      BestKnownSolution = null;
374
375      if (ProblemInstance != null && instance.ProblemInstance != null &&
376        instance.ProblemInstance.GetType() == ProblemInstance.GetType())
377        SetProblemInstance(instance.ProblemInstance);
378      else
379        ProblemInstance = instance.ProblemInstance;
380
381      OnReset();
382
383      if (instance.BestKnownQuality != null) {
384        BestKnownQuality = new DoubleValue((double)instance.BestKnownQuality);
385      }
386
387      if (instance.BestKnownSolution != null) {
388        VRPSolution solution = new VRPSolution(ProblemInstance, instance.BestKnownSolution, new DoubleValue(0));
389        BestKnownSolution = solution;
390      }
391    }
392    #endregion
393
394    #region IProblemInstanceConsumer<VRPData> Members
395
396    public void Load(IVRPData data) {
397      var interpreterDataType = data.GetType();
398      var interpreterType = typeof(IVRPDataInterpreter<>).MakeGenericType(interpreterDataType);
399
400      var interpreters = ApplicationManager.Manager.GetTypes(interpreterType);
401
402      var concreteInterpreter = interpreters.Single(t => GetInterpreterDataType(t) == interpreterDataType);
403
404      Load(data, (IVRPDataInterpreter)Activator.CreateInstance(concreteInterpreter));
405    }
406
407    private Type GetInterpreterDataType(Type type) {
408      var parentInterfaces = type.BaseType.GetInterfaces();
409      var interfaces = type.GetInterfaces().Except(parentInterfaces);
410
411      var interpreterInterface = interfaces.Single(i => typeof(IVRPDataInterpreter).IsAssignableFrom(i));
412      return interpreterInterface.GetGenericArguments()[0];
413    }
414
415    #endregion
416  }
417}
Note: See TracBrowser for help on using the repository browser.