Free cookie consent management tool by TermsFeed Policy Generator

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

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

Improved coordination between optimization and simulation thread (#1955)

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