Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2521_ProblemRefactoring/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRPPDTWProblemInstance.cs @ 17954

Last change on this file since 17954 was 17717, checked in by abeham, 4 years ago

#2521: working on VRP (refactoring all the capabilities, features, and operator discovery)

File size: 13.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 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 HEAL.Attic;
26using HeuristicLab.Common;
27using HeuristicLab.Core;
28using HeuristicLab.Data;
29using HeuristicLab.Parameters;
30using HeuristicLab.Problems.VehicleRouting.Interfaces;
31
32namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
33  [Item("CVRPPDTWProblemInstance", "Represents a single depot CVRPPDTW instance.")]
34  [StorableType("6DC3F907-9CDC-4CDA-8C84-AC9ED248DB3B")]
35  public class CVRPPDTWProblemInstance : CVRPTWProblemInstance, IPickupAndDeliveryProblemInstance {
36    protected IValueParameter<IntArray> PickupDeliveryLocationParameter {
37      get { return (IValueParameter<IntArray>)Parameters["PickupDeliveryLocation"]; }
38    }
39    protected IValueParameter<DoubleValue> PickupViolationPenaltyParameter {
40      get { return (IValueParameter<DoubleValue>)Parameters["EvalPickupViolationPenalty"]; }
41    }
42
43    public IntArray PickupDeliveryLocation {
44      get { return PickupDeliveryLocationParameter.Value; }
45      set { PickupDeliveryLocationParameter.Value = value; }
46    }
47
48    protected IValueParameter<DoubleValue> CurrentPickupViolationPenaltyParameter {
49      get { return (IValueParameter<DoubleValue>)Parameters["CurrentPickupViolationPenalty"]; }
50    }
51
52    public DoubleValue PickupViolationPenalty {
53      get {
54        DoubleValue currentPickupViolationPenalty = CurrentPickupViolationPenaltyParameter.Value;
55        if (currentPickupViolationPenalty != null)
56          return currentPickupViolationPenalty;
57        else
58          return PickupViolationPenaltyParameter.Value;
59      }
60    }
61    DoubleValue IPickupAndDeliveryProblemInstance.CurrentPickupViolationPenalty {
62      get { return CurrentOverloadPenaltyParameter.Value; }
63      set { CurrentPickupViolationPenaltyParameter.Value = value; }
64    }
65
66    public int GetPickupDeliveryLocation(int city) {
67      return PickupDeliveryLocation[city];
68    }
69
70    public override IEnumerable<IOperator> FilterOperators(IEnumerable<IOperator> operators) {
71      return base.FilterOperators(operators)
72        .Where(x => !(x is INotPickupAndDeliveryOperator))
73        .Union(operators.Where(x => x is IPickupAndDeliveryOperator));
74    }
75
76    protected override VRPEvaluation CreateTourEvaluation() {
77      return new CVRPPDTWEvaluation();
78    }
79
80    protected override void EvaluateTour(VRPEvaluation eval, Tour tour, IVRPEncodedSolution solution) {
81      TourInsertionInfo tourInfo = new TourInsertionInfo(solution.GetVehicleAssignment(solution.GetTourIndex(tour)));
82      eval.InsertionInfo.AddTourInsertionInfo(tourInfo);
83      double originalQuality = eval.Quality;
84
85      double capacity = Capacity.Value;
86
87      double time = 0.0;
88      double waitingTime = 0.0;
89      double serviceTime = 0.0;
90      double tardiness = 0.0;
91      double overweight = 0.0;
92      double distance = 0.0;
93
94      double currentLoad = 0.0;
95      Dictionary<int, bool> stops = new Dictionary<int, bool>();
96      int pickupViolations = 0;
97
98      double tourStartTime = ReadyTime[0];
99      time = tourStartTime;
100
101      //simulate a tour, start and end at depot
102      for (int i = 0; i <= tour.Stops.Count; i++) {
103        int start = 0;
104        if (i > 0)
105          start = tour.Stops[i - 1];
106        int end = 0;
107        if (i < tour.Stops.Count)
108          end = tour.Stops[i];
109
110        //drive there
111        double currentDistace = GetDistance(start, end, solution);
112        time += currentDistace;
113        distance += currentDistace;
114
115        double arrivalTime = time;
116
117        //check if it was serviced on time
118        if (time > DueTime[end])
119          tardiness += time - DueTime[end];
120
121        //wait
122        double currentWaitingTime = 0.0;
123        if (time < ReadyTime[end])
124          currentWaitingTime = ReadyTime[end] - time;
125
126        double waitTime = ReadyTime[end] - time;
127
128        waitingTime += currentWaitingTime;
129        time += currentWaitingTime;
130
131        double spareTime = DueTime[end] - time;
132
133        //service
134        double currentServiceTime = ServiceTime[end];
135        serviceTime += currentServiceTime;
136        time += currentServiceTime;
137
138        //Pickup / deliver
139        double arrivalSpareCapacity = capacity - currentLoad;
140
141        bool validPickupDelivery =
142          validPickupDelivery =
143          ((Demand[end] >= 0) ||
144           (stops.ContainsKey(PickupDeliveryLocation[end])));
145
146        if (validPickupDelivery) {
147          currentLoad += Demand[end];
148        } else {
149          pickupViolations++;
150        }
151
152        if (currentLoad > capacity)
153          overweight += currentLoad - capacity;
154
155        double spareCapacity = capacity - currentLoad;
156        CVRPPDTWInsertionInfo stopInfo = new CVRPPDTWInsertionInfo(start, end, spareCapacity, tourStartTime,
157          arrivalTime, time, spareTime, waitTime, new List<int>(stops.Keys), arrivalSpareCapacity);
158        tourInfo.AddStopInsertionInfo(stopInfo);
159
160        stops.Add(end, true);
161      }
162
163      eval.Quality += FleetUsageFactor.Value;
164      eval.Quality += DistanceFactor.Value * distance;
165      eval.Distance += distance;
166      eval.VehicleUtilization += 1;
167
168      (eval as CVRPEvaluation).Overload += overweight;
169      double tourPenalty = 0;
170      double penalty = overweight * OverloadPenalty.Value;
171      eval.Penalty += penalty;
172      eval.Quality += penalty;
173      tourPenalty += penalty;
174
175      (eval as CVRPTWEvaluation).Tardiness += tardiness;
176      (eval as CVRPTWEvaluation).TravelTime += time;
177
178      penalty = tardiness * TardinessPenalty.Value;
179      eval.Penalty += penalty;
180      eval.Quality += penalty;
181      tourPenalty += penalty;
182
183      (eval as CVRPPDTWEvaluation).PickupViolations += pickupViolations;
184      penalty = pickupViolations * PickupViolationPenalty.Value;
185      eval.Penalty += penalty;
186      tourPenalty += penalty;
187
188      eval.Quality += penalty;
189      eval.Quality += time * TimeFactor.Value;
190      tourInfo.Penalty = tourPenalty;
191      tourInfo.Quality = eval.Quality - originalQuality;
192
193      eval.IsFeasible = overweight == 0 && tardiness == 0 && pickupViolations == 0;
194    }
195
196    protected override double GetTourInsertionCosts(IVRPEncodedSolution solution, TourInsertionInfo tourInsertionInfo, int index, int customer,
197      out bool feasible) {
198      CVRPPDTWInsertionInfo insertionInfo = tourInsertionInfo.GetStopInsertionInfo(index) as CVRPPDTWInsertionInfo;
199
200      double costs = 0;
201      feasible = tourInsertionInfo.Penalty < double.Epsilon;
202      bool tourFeasible = true;
203
204      double overloadPenalty = OverloadPenalty.Value;
205      double tardinessPenalty = TardinessPenalty.Value;
206      double pickupPenalty = PickupViolationPenalty.Value;
207
208      double distance = GetDistance(insertionInfo.Start, insertionInfo.End, solution);
209      double newDistance =
210        GetDistance(insertionInfo.Start, customer, solution) +
211        GetDistance(customer, insertionInfo.End, solution);
212      costs += DistanceFactor.Value * (newDistance - distance);
213
214      double demand = Demand[customer];
215      if (demand > insertionInfo.ArrivalSpareCapacity) {
216        tourFeasible = feasible = false;
217        if (insertionInfo.ArrivalSpareCapacity >= 0)
218          costs += (demand - insertionInfo.ArrivalSpareCapacity) * overloadPenalty;
219        else
220          costs += demand * overloadPenalty;
221      }
222      int destination = PickupDeliveryLocation[customer];
223
224      bool validPickup = true;
225      if (demand < 0 && !insertionInfo.Visited.Contains(destination)) {
226        tourFeasible = feasible = false;
227        validPickup = false;
228        costs += pickupPenalty;
229      }
230
231      double time = 0;
232      double tardiness = 0;
233
234      if (index > 0)
235        time = (tourInsertionInfo.GetStopInsertionInfo(index - 1) as CVRPTWInsertionInfo).LeaveTime;
236      else
237        time = insertionInfo.TourStartTime;
238
239      time += GetDistance(insertionInfo.Start, customer, solution);
240      if (time > DueTime[customer]) {
241        tardiness += time - DueTime[customer];
242      }
243      if (time < ReadyTime[customer])
244        time += ReadyTime[customer] - time;
245      time += ServiceTime[customer];
246      time += GetDistance(customer, insertionInfo.End, solution);
247
248      double additionalTime = time - (tourInsertionInfo.GetStopInsertionInfo(index) as CVRPTWInsertionInfo).ArrivalTime;
249      for (int i = index; i < tourInsertionInfo.GetStopCount(); i++) {
250        CVRPTWInsertionInfo nextStop = tourInsertionInfo.GetStopInsertionInfo(i) as CVRPTWInsertionInfo;
251
252        if (demand >= 0) {
253          if (nextStop.End == destination) {
254            demand = 0;
255            costs -= pickupPenalty;
256            if (tourInsertionInfo.Penalty == pickupPenalty && tourFeasible)
257              feasible = true;
258          } else if (nextStop.SpareCapacity < 0) {
259            costs += demand * overloadPenalty;
260          } else if (nextStop.SpareCapacity < demand) {
261            tourFeasible = feasible = false;
262            costs += (demand - nextStop.SpareCapacity) * overloadPenalty;
263          }
264        } else if (validPickup) {
265          if (nextStop.SpareCapacity < 0) {
266            costs += Math.Max(demand, nextStop.SpareCapacity) * overloadPenalty;
267          }
268        }
269
270        if (additionalTime < 0) {
271          //arrive earlier than before
272          //wait probably
273          if (nextStop.WaitingTime < 0) {
274            double wait = nextStop.WaitingTime - additionalTime;
275            if (wait > 0)
276              additionalTime += wait;
277          } else {
278            additionalTime = 0;
279          }
280
281          //check due date, decrease tardiness
282          if (nextStop.SpareTime < 0) {
283            costs += Math.Max(nextStop.SpareTime, additionalTime) * tardinessPenalty;
284          }
285        } else {
286          //arrive later than before, probably don't have to wait
287          if (nextStop.WaitingTime > 0) {
288            additionalTime -= Math.Min(additionalTime, nextStop.WaitingTime);
289          }
290
291          //check due date
292          if (nextStop.SpareTime > 0) {
293            double spare = nextStop.SpareTime - additionalTime;
294            if (spare < 0)
295              tardiness += -spare;
296          } else {
297            tardiness += additionalTime;
298          }
299        }
300      }
301
302      costs += additionalTime * TimeFactor.Value;
303
304      if (tardiness > 0) {
305        tourFeasible = feasible = false;
306      }
307
308      costs += tardiness * tardinessPenalty;
309
310      return costs;
311    }
312
313    [StorableConstructor]
314    protected CVRPPDTWProblemInstance(StorableConstructorFlag _) : base(_) { }
315
316    public CVRPPDTWProblemInstance() {
317      Parameters.Add(new ValueParameter<IntArray>("PickupDeliveryLocation", "The pickup and delivery location for each customer.", new IntArray()));
318
319      Parameters.Add(new ValueParameter<DoubleValue>("EvalPickupViolationPenalty", "The pickup violation penalty considered in the evaluation.", new DoubleValue(100)));
320      Parameters.Add(new OptionalValueParameter<DoubleValue>("CurrentPickupViolationPenalty", "The current pickup violation penalty considered in the evaluation.") { Hidden = true });
321
322      AttachEventHandlers();
323    }
324
325    public override IDeepCloneable Clone(Cloner cloner) {
326      return new CVRPPDTWProblemInstance(this, cloner);
327    }
328
329    protected CVRPPDTWProblemInstance(CVRPPDTWProblemInstance original, Cloner cloner)
330      : base(original, cloner) {
331      AttachEventHandlers();
332    }
333
334    [StorableHook(HookType.AfterDeserialization)]
335    private void AfterDeserialization() {
336      AttachEventHandlers();
337    }
338
339    private void AttachEventHandlers() {
340      PickupDeliveryLocationParameter.ValueChanged += PickupDeliveryLocationParameter_ValueChanged;
341      PickupDeliveryLocation.Reset += PickupDeliveryLocation_Changed;
342      PickupDeliveryLocation.ItemChanged += PickupDeliveryLocation_Changed;
343    }
344
345    public override void InitializeState() {
346      base.InitializeState();
347
348      CurrentPickupViolationPenaltyParameter.Value = null;
349    }
350
351    #region Event handlers
352    void PickupDeliveryLocationParameter_ValueChanged(object sender, EventArgs e) {
353      PickupDeliveryLocation.Reset += PickupDeliveryLocation_Changed;
354      PickupDeliveryLocation.ItemChanged += PickupDeliveryLocation_Changed;
355      EvalBestKnownSolution();
356    }
357    private void PickupDeliveryLocation_Changed(object sender, EventArgs e) {
358      EvalBestKnownSolution();
359    }
360    #endregion
361  }
362}
Note: See TracBrowser for help on using the repository browser.