Free cookie consent management tool by TermsFeed Policy Generator

source: branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliverySimulation.cs @ 8941

Last change on this file since 8941 was 8792, checked in by svonolfe, 12 years ago

Improved performance when small time steps are used (#1955)

File size: 18.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.PDPSimulation.SimulationCore;
29using HeuristicLab.Parameters;
30using HeuristicLab.Data;
31using System.Threading;
32using HeuristicLab.Common;
33using HeuristicLab.PDPSimulation.DomainModel;
34using HeuristicLab.Optimization;
35using HeuristicLab.Analysis;
36
37namespace HeuristicLab.PDPSimulation {
38  [Item("PickupDeliverySimulation", "A pickup and delivery simulation.")]
39  [Creatable("Simulations")]
40  [StorableClass]
41  public sealed class PickupDeliverySimulation: Simulation {
42    #region parameters
43    public OptionalValueParameter<PickupDeliveryOptimization> OptimizationParameter {
44      get { return (OptionalValueParameter<PickupDeliveryOptimization>)Parameters["PickupDeliveryOptimization"]; }
45    }
46
47    public OptionalValueParameter<WaitingStrategy> WaitingStrategyParameter {
48      get { return (OptionalValueParameter<WaitingStrategy>)Parameters["WaitingStrategy"]; }
49    }
50
51    public OptionalValueParameter<PickupDeliveryAnalyzer> AnalyzerParameter {
52      get { return (OptionalValueParameter<PickupDeliveryAnalyzer>)Parameters["Analyzer"]; }
53    }
54
55    public ValueParameter<DoubleValue> TimeStepParameter {
56      get { return (ValueParameter<DoubleValue>)Parameters["TimeStep"]; }
57    }
58
59    public ValueParameter<DoubleValue> ResultCollectionIntervalParameter {
60      get { return (ValueParameter<DoubleValue>)Parameters["ResultCollectionInterval"]; }
61    }
62
63
64    public ValueParameter<BoolValue> SynchronizedParameter {
65      get { return (ValueParameter<BoolValue>)Parameters["Synchronized"]; }
66    }
67    public ValueParameter<IntValue> DelayParameter {
68      get { return (ValueParameter<IntValue>)Parameters["Delay"]; }
69    }
70    public ValueParameter<IntValue> InitialDelayParameter {
71      get { return (ValueParameter<IntValue>)Parameters["InitialDelay"]; }
72    }
73
74    private ValueParameter<IntValue> SeedParameter {
75      get { return (ValueParameter<IntValue>)Parameters["Seed"]; }
76    }
77    private ValueParameter<BoolValue> SetSeedRandomlyParameter {
78      get { return (ValueParameter<BoolValue>)Parameters["SetSeedRandomly"]; }
79    }
80    #endregion
81
82    #region properties
83    public double SimulationTime {
84      get {
85        return simulationTime;
86      }
87
88      private set {
89        simulationTime = value;
90      }
91    }
92
93    public double TimeStep {
94      get {
95        return TimeStepParameter.Value.Value;
96      }
97    }
98
99    private double ResultCollectionInterval {
100      get {
101        return ResultCollectionIntervalParameter.Value.Value;
102      }
103    }
104
105    private bool Synchronized {
106      get {
107        return SynchronizedParameter.Value.Value;
108      }
109    }
110
111    private int Delay {
112      get {
113        return DelayParameter.Value.Value;
114      }
115    }
116
117    public override Type ProblemType {
118      get { return typeof(PickupDeliveryScenario); }
119    }
120
121    private PickupDeliveryScenario Scenario {
122      get {
123        return Problem as PickupDeliveryScenario;
124      }
125    }
126
127    private PickupDeliveryOptimization Optimization {
128      get { return OptimizationParameter.Value;  }
129    }
130
131    private WaitingStrategy WaitingStrategy {
132      get { return WaitingStrategyParameter.Value; }
133    }
134
135    private PickupDeliveryAnalyzer Analyzer {
136      get { return AnalyzerParameter.Value; }
137    }
138    #endregion
139
140    #region constructors
141    public PickupDeliverySimulation()
142      : base() {
143      Parameters.Add(new OptionalValueParameter<PickupDeliveryOptimization>("PickupDeliveryOptimization", new BestInsertion()));
144      Parameters.Add(new OptionalValueParameter<WaitingStrategy>("WaitingStrategy", new DriveFirstWaitingStrategy()));
145      Parameters.Add(new OptionalValueParameter<PickupDeliveryAnalyzer>("Analyzer", new PickupDeliveryAnalyzer()));
146      Parameters.Add(new ValueParameter<DoubleValue>("TimeStep", "The time progress after every tick", new DoubleValue(1)));
147      Parameters.Add(new ValueParameter<DoubleValue>("ResultCollectionInterval", "The result collection interval", new DoubleValue(1)));
148      Parameters.Add(new ValueParameter<BoolValue>("Synchronized", "Indicates if the simulation and optimization should be synchronized", new BoolValue(true)));
149      Parameters.Add(new ValueParameter<IntValue>("Delay", "The delay after each tick", new IntValue(0)));
150      Parameters.Add(new ValueParameter<IntValue>("InitialDelay", "The initial delay", new IntValue(0)));
151      Parameters.Add(new ValueParameter<IntValue>("Seed", "The random seed used to initialize the new pseudo random number generator.", new IntValue(0)));
152      Parameters.Add(new ValueParameter<BoolValue>("SetSeedRandomly", "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true)));
153
154      OptimizationParameter.GetsCollected = false;
155
156      orders = new List<Order>();
157      vehicles = new List<Vehicle>();
158
159      AttachEventHandlers();
160      SetOptimizationSimulation();
161      SetOptimizationScenario();
162      SetWaitingStrategy();
163      SetWaitingStrategyScenario();
164    }
165    [StorableConstructor]
166    private PickupDeliverySimulation(bool deserializing) : base(deserializing) {
167    }
168
169    [StorableHook(HookType.AfterDeserialization)]
170    private void AfterDeserialization() {
171      AttachEventHandlers();
172    }
173
174    private PickupDeliverySimulation(PickupDeliverySimulation original, Cloner cloner)
175      : base(original, cloner) {
176      orders = new List<Order>();
177      foreach (Order order in original.orders) {
178        orders.Add(cloner.Clone<Order>(order));
179      }
180
181      vehicles = new List<Vehicle>();
182      foreach (Vehicle vehicle in original.vehicles) {
183        vehicles.Add(cloner.Clone<Vehicle>(vehicle));
184      }
185
186      simulationTime = original.simulationTime;
187      newSimulationTime = original.newSimulationTime;
188      lastResultCollection = original.lastResultCollection;
189      simulationObject = cloner.Clone<SimulationObject>(original.simulationObject);
190
191      AttachEventHandlers();
192    }
193    public override IDeepCloneable Clone(Cloner cloner) {
194      return new PickupDeliverySimulation(this, cloner);
195    }
196
197    [StorableHook(HookType.AfterDeserialization)]
198    private void AttachEventHandlers() {
199      OptimizationParameter.ValueChanged += new EventHandler(OptimizationParameter_ValueChanged);
200      WaitingStrategyParameter.ValueChanged += new EventHandler(WaitingStrategyParameter_ValueChanged);
201
202      if(Scenario != null)
203        Scenario.ScenarioChanged += new EventHandler(Scenario_ScenarioChanged);
204    }
205
206    void Scenario_ScenarioChanged(object sender, EventArgs e) {
207      SetOptimizationScenario();
208      SetWaitingStrategy();
209      SetWaitingStrategyScenario();
210
211      Prepare();
212    }
213
214    void WaitingStrategyParameter_ValueChanged(object sender, EventArgs e) {
215      SetWaitingStrategy();
216      SetWaitingStrategyScenario();
217    }
218
219    void OptimizationParameter_ValueChanged(object sender, EventArgs e) {
220      SetOptimizationSimulation();
221      SetOptimizationScenario();
222      SetWaitingStrategy();
223    }
224
225    protected override void OnProblemChanged() {
226      base.OnProblemChanged();
227
228      SetOptimizationScenario();
229      SetWaitingStrategy();
230      SetWaitingStrategyScenario();
231
232      if (Scenario != null)
233        Scenario.ScenarioChanged += new EventHandler(Scenario_ScenarioChanged);
234    }
235    #endregion
236
237    #region state
238    [Storable]
239    private List<Order> orders;
240
241    public List<Order> Orders {
242      get {
243        lock (orders) {
244          return new List<Order>(orders);
245        }
246      }
247    }
248
249    public Order GetOrder(Guid orderId) {
250      lock (orders) {
251        return orders.FirstOrDefault(o => o.Id == orderId);
252      }
253    }
254
255    public double OrderRangeX {
256      get { return Scenario.OrderRangeX(); }
257    }
258
259    public double OrderRangeY {
260      get { return Scenario.OrderRangeY(); }
261    }
262
263    private bool AllOrdersDelivered() {
264      bool delivered = true;
265
266      foreach(Order order in orders) {
267        if (order.OrderState != OrderState.Delivered) {
268          delivered = false;
269          break;
270        }
271      }
272
273      return delivered;
274    }
275
276    [Storable]
277    private List<Vehicle> vehicles;
278
279    public List<Vehicle> Vehicles {
280      get {
281        return new List<Vehicle>(vehicles);
282      }
283    }
284
285    public Vehicle GetVehicle(Guid vehicleId) {
286      return vehicles.FirstOrDefault(v => v.Id == vehicleId);
287    }
288
289    private bool AllVehiclesAtDepot() {
290      bool atDepot = true;
291
292      foreach (Vehicle vehicle in vehicles) {
293        if ((vehicle.VehicleState != VehicleState.Parked && vehicle.VehicleState != VehicleState.Waiting) ||
294          vehicle.PositionX != vehicle.DepotX ||
295          vehicle.PositionY != vehicle.DepotY) {
296          atDepot = false;
297          break;
298        }
299      }
300
301      return atDepot;
302    }
303
304    public PDAction GetAction(Vehicle vehicle) {
305      if (Optimization != null)
306        return Optimization.GetAction(vehicle);
307      else
308        return null;
309    }
310
311    [Storable]
312    private double newSimulationTime;
313
314    [Storable]
315    private double simulationTime;
316
317    [Storable]
318    private double lastResultCollection;
319
320    [Storable]
321    private SimulationObject simulationObject;
322    #endregion
323
324    #region events
325
326    public delegate void SimulationStateChangedHandler(BaseObject obj, SimulationStateChange change);
327    public event SimulationStateChangedHandler SimulationStateChanged;
328
329    private void OnSimulationStateChanged(BaseObject obj, SimulationStateChange change) {
330      SimulationStateChangedHandler handler = SimulationStateChanged;
331      if (handler != null)
332        handler(obj, change);
333    }
334    #endregion
335
336    #region synchronization
337    private EventWaitHandle wh;
338    private void InitWaitHandle() {
339      if(wh != null)
340        wh.Dispose();
341
342      wh = null;
343      if (Synchronized)
344        wh = new EventWaitHandle(false, EventResetMode.AutoReset);
345    }
346    private void SignalWaitHandle() {
347      if (wh != null)
348        wh.Set();
349    }
350    public void WaitForSimulation() {
351      if (wh != null)
352        wh.WaitOne();
353    }
354    private void WaitForOptimization() {
355      if (Optimization != null)
356        Optimization.WaitForOptimization();
357    }
358    #endregion
359
360    #region simulation logic
361    private void UpdateVisualization() {
362      if (Analyzer != null)
363        Analyzer.UpdateVisualization(this, Scenario, Results);
364    }
365
366    private void UpdateSimulationState() {
367      if (Optimization != null) {
368        foreach (PDAction action in Optimization.GetActions()) {
369          BaseObject obj = vehicles.FirstOrDefault(v => v.Id == action.BaseObjectId);
370          if(obj == null)
371            obj = orders.FirstOrDefault(o => o.Id == action.BaseObjectId);
372
373          List<PDChange> changes = action.Perform(obj, SimulationTime, TimeStep);
374
375          foreach (PDChange change in changes)
376            OnSimulationStateChanged(change.BaseObject, change.ChangeType);
377        }
378      }
379    }
380
381    private void UpdateResults(bool stopped) {
382      if (stopped || SimulationTime == 0 ||
383         (SimulationTime - lastResultCollection) >= ResultCollectionInterval) {
384        UpdateVisualization();   
385        if (Analyzer != null) {
386          Analyzer.Analyze(this, Scenario, Results);
387        }
388
389        lastResultCollection = SimulationTime;
390      }
391      if (Analyzer != null) {
392        Analyzer.Tick(this, Scenario, Results);
393      }
394    }
395
396    private void UpdateOrders() {
397      lock (orders) {
398        IEnumerable<Order> newOrders = Scenario.GetOrders(SimulationTime, newSimulationTime);
399        foreach (Order order in newOrders) {
400          orders.Add(order);
401          OnSimulationStateChanged(order, SimulationStateChange.OrderCreated);
402        }
403
404        if (!Scenario.MoreOrders(newSimulationTime))
405          OnSimulationStateChanged(simulationObject, SimulationStateChange.NoMoreOrders);
406      }
407    }
408
409    private void CreateSimulation() {
410      vehicles.Clear();
411      orders.Clear();
412
413      simulationObject = new SimulationObject();
414      lastResultCollection = 0;
415      simulationTime = 0;
416      newSimulationTime = 0;
417
418      //create vehicles
419      for (int i = 0; i < Scenario.VehicleCapacitiesParameter.Value.Length; i++) {
420        Vehicle v = new Vehicle();
421        v.VehicleState = VehicleState.Parked;
422        v.Availibility = 1;
423        v.DepotX = v.PositionX = v.TargetPositionX = Scenario.DepotCoordinatesParameter.Value[i, 0];
424        v.DepotY = v.PositionY = v.TargetPositionY = Scenario.DepotCoordinatesParameter.Value[i, 1];
425        v.Capacity = v.TotalCapacity = Scenario.VehicleCapacitiesParameter.Value[i];
426        v.ReadyTime = Scenario.VehicleReadyTimesParameter.Value[i];
427        v.DueTime = Scenario.VehicleDueTimesParameter.Value[i];
428
429        vehicles.Add(v);
430        OnSimulationStateChanged(v, SimulationStateChange.VehicleCreated);
431      }
432
433      //create initial orders
434      UpdateOrders();
435      UpdateResults(false);
436
437      UpdateVisualization();
438    }
439
440    protected override void OnPrepared() {
441      base.OnPrepared();
442      PrepareOptimization();
443      simulationTime = 0;
444      newSimulationTime = 0;
445    }
446
447    private void InitSimulation() {
448      pausePending = false;
449      stopPending = false;
450      InitWaitHandle();
451
452      if (simulationTime == 0) {
453        PrepareOptimization();
454        CreateSimulation();
455
456        SignalWaitHandle();
457        if (OptimizationRequired()) {
458          StartOptimization();
459          Thread.Sleep(InitialDelayParameter.Value.Value);
460          WaitForOptimization();
461        } else {
462          Thread.Sleep(InitialDelayParameter.Value.Value);
463        }
464
465        Step();
466      }
467    }
468
469    private void StartOptimization() {
470      if (Optimization != null) {
471        Optimization.Start(Synchronized);
472      }
473    }
474
475    private void StopOptimization() {
476      if (Optimization != null)
477        Optimization.Stop();
478    }
479
480    private void PrepareOptimization() {
481      if (Optimization != null)
482        Optimization.Prepare();
483    }
484
485    private void SetOptimizationScenario() {
486      if (Optimization != null)
487        Optimization.SetScenario(Scenario);
488    }
489
490    private void SetOptimizationSimulation() {
491      if (Optimization != null)
492        Optimization.SetSimulation(this);
493    }
494
495    private void SetWaitingStrategyScenario() {
496      if (WaitingStrategy != null)
497        WaitingStrategy.SetScenario(Scenario);
498    }
499
500    private void SetWaitingStrategy() {
501      if (Optimization != null)
502        Optimization.SetWaitingStrategy(WaitingStrategyParameter.Value);
503    }
504
505    private bool OptimizationRunning() {
506      bool running = false;
507
508      if (Optimization != null)
509        running = Optimization.Running();
510
511      return running;
512    }
513
514    private void RelocateVehicles() {
515      if (Optimization != null)
516        Optimization.RelocateVehicles();
517    }
518
519    private bool OptimizationRequired() {
520      bool required = false;
521
522      if (Optimization != null)
523        required = Optimization.OptimizationRequired();
524
525      return required;
526    }
527
528    private void WaitForOptimizationExit() {
529      if (Optimization != null) {
530        while (Optimization.Running()) {
531          Thread.Sleep(100);
532          SignalWaitHandle();
533        }
534        Optimization.Exit();
535      }
536    }
537
538    private void StopSimulation() {
539      SignalWaitHandle();
540      StopOptimization();
541    }
542
543    private bool pausePending;
544    public override void Pause() {
545      base.Pause();
546      pausePending = true;
547    }
548
549    private bool stopPending;
550    public override void Stop() {
551      base.Stop();
552      stopPending = true;
553    }
554
555    private void Step() {
556      //next step
557      SimulationTime = newSimulationTime;
558      newSimulationTime = SimulationTime + TimeStep;
559    }
560
561    protected override void Run(CancellationToken cancellationToken) {
562      InitSimulation();
563
564      while (!AllOrdersDelivered() || Scenario.MoreOrders(SimulationTime) || (Scenario.RelocateBackToDepot && !AllVehiclesAtDepot())) {
565        //perform actions
566        UpdateSimulationState();
567        UpdateOrders();
568        UpdateResults(false);
569
570        Step();
571
572        if (OptimizationRequired()) {
573          SignalWaitHandle();
574
575          if (!OptimizationRunning() && !(pausePending || stopPending)) {
576            SignalWaitHandle();
577            StartOptimization();
578          }
579
580          WaitForOptimization();
581        } else {
582          RelocateVehicles();
583        }
584
585        if (pausePending || stopPending) {
586          if (!OptimizationRunning()) {
587            cancellationToken.ThrowIfCancellationRequested();
588          } else
589            StopOptimization();
590        }
591
592        Thread.Sleep(Delay);
593      }
594
595      if (Optimization != null)
596        Optimization.RemoveCompletedActions();
597      UpdateResults(true);
598
599      Results.Add(new Result("Finished", new BoolValue(true)));
600
601      Thread.Sleep(500);
602      StopSimulation();
603      WaitForOptimizationExit();
604    }
605  }
606  #endregion
607}
Note: See TracBrowser for help on using the repository browser.