1 | using System;
|
---|
2 | using System.Collections.Generic;
|
---|
3 | using System.Diagnostics;
|
---|
4 | using System.Linq;
|
---|
5 | using HeuristicLab.Common;
|
---|
6 | using HeuristicLab.Core;
|
---|
7 | using HeuristicLab.Encodings.RealVectorEncoding;
|
---|
8 | using HeuristicLab.Parameters;
|
---|
9 | using HeuristicLab.PDPSimulation.DomainModel;
|
---|
10 | using HeuristicLab.PDPSimulation.Operators;
|
---|
11 | using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
|
---|
12 |
|
---|
13 | namespace HeuristicLab.PDPSimulation {
|
---|
14 | [Item("Dispatching", "")]
|
---|
15 | [StorableClass]
|
---|
16 | public abstract class Dispatching : DynamicPDPOptimization {
|
---|
17 |
|
---|
18 | private bool IsIdle(Vehicle v) {
|
---|
19 | return v.CurrentOrder == Guid.Empty;
|
---|
20 | }
|
---|
21 |
|
---|
22 | protected override bool OptimizationRequired(ChangeInformation changeInformation) {
|
---|
23 | // either there are vehicles waiting and there are orders to dispatch
|
---|
24 | // or there are new orders and waiting vehicles
|
---|
25 | return (GetVehicles().Any(x => IsIdle(x))
|
---|
26 | && GetOrders().Any(x => x.AssignedVehicle == Guid.Empty || GetVehicles().Any(y => IsIdle(y) && x.AssignedVehicle == y.Id)));
|
---|
27 | }
|
---|
28 |
|
---|
29 |
|
---|
30 | [StorableConstructor]
|
---|
31 | protected Dispatching(bool deserializing) : base(deserializing) { }
|
---|
32 | protected Dispatching(Dispatching original, Cloner cloner) : base(original, cloner) { }
|
---|
33 | protected Dispatching() {
|
---|
34 | }
|
---|
35 |
|
---|
36 | protected override bool PerformOptimization(DynamicPDProblemInstance instance, ChangeInformation changeInformation) {
|
---|
37 | var waitingVehicles = GetVehicles().Where(x => IsIdle(x)).ToList();
|
---|
38 | var waitingOrders = GetOrders().Where(x => x.AssignedVehicle == Guid.Empty).ToList();
|
---|
39 |
|
---|
40 | while (waitingVehicles.Any() && (waitingOrders.Any()
|
---|
41 | || GetOrders().Any(x => x.OrderState == OrderState.PickedUp && waitingVehicles.Any(y => y.Id == x.AssignedVehicle)))) {
|
---|
42 | var tmp = new Dictionary<Vehicle, Tuple<Order, double>>();
|
---|
43 | foreach (var vehicle in waitingVehicles) {
|
---|
44 | var pickedupOrders = GetOrders().Where(x => x.OrderState == OrderState.PickedUp && x.AssignedVehicle == vehicle.Id);
|
---|
45 | var orders = waitingOrders.Concat(pickedupOrders);
|
---|
46 | if (orders.Any()) {
|
---|
47 | Order selectedOrder;
|
---|
48 | double priority;
|
---|
49 | GetHighestPriorityOrder((DynPDPProblemInstance)instance.StaticInstance, vehicle, orders, out selectedOrder, out priority);
|
---|
50 | tmp[vehicle] = Tuple.Create(selectedOrder, priority);
|
---|
51 | }
|
---|
52 | }
|
---|
53 | var assignment = tmp.GroupBy(x => x.Value.Item1, x => new { Vehicle = x.Key, Priority = x.Value.Item2 });
|
---|
54 | foreach (var a in assignment) {
|
---|
55 | var bestVehicle = a.MaxItems(x => x.Priority).Select(x => x.Vehicle).First();
|
---|
56 | var order = a.Key;
|
---|
57 |
|
---|
58 | bool first = true;
|
---|
59 |
|
---|
60 | XY target;
|
---|
61 | MoveVehicleAction action;
|
---|
62 | if (order.OrderState == OrderState.Waiting) {
|
---|
63 | target = new XY(order.PickupXCoord, order.PickupYCoord);
|
---|
64 | action = new MoveVehicleAction(bestVehicle.Id, order.PickupXCoord, order.PickupYCoord, VehicleAction.Pickup, order, scenario.AllowDiversion, scenario.DistanceMeasure);
|
---|
65 | } else {
|
---|
66 | target = new XY(order.DeliveryXCoord, order.DeliveryYCoord);
|
---|
67 | action = new MoveVehicleAction(bestVehicle.Id, order.DeliveryXCoord, order.DeliveryYCoord, VehicleAction.Deliver, order, scenario.AllowDiversion, scenario.DistanceMeasure);
|
---|
68 | }
|
---|
69 | var pickedupOrders = GetOrders().Where(x => x.OrderState == OrderState.PickedUp && x.AssignedVehicle == bestVehicle.Id);
|
---|
70 | var pickedupOrdersAtDestination = pickedupOrders.Where(o => o.DeliveryXCoord == target.X && o.DeliveryYCoord == target.Y);
|
---|
71 | List<MoveVehicleAction> deliveryActions = new List<MoveVehicleAction>();
|
---|
72 | foreach (var pickedupOrder in pickedupOrdersAtDestination) {
|
---|
73 | if (pickedupOrder != order) {
|
---|
74 | MoveVehicleAction deliveryAction = new MoveVehicleAction(bestVehicle.Id, pickedupOrder.DeliveryXCoord, pickedupOrder.DeliveryYCoord, VehicleAction.Deliver, pickedupOrder, scenario.AllowDiversion, scenario.DistanceMeasure);
|
---|
75 | if (first) {
|
---|
76 | SetAction(deliveryAction);
|
---|
77 | first = false;
|
---|
78 | } else {
|
---|
79 | AppendAction(deliveryAction);
|
---|
80 | }
|
---|
81 | waitingOrders.Remove(pickedupOrder);
|
---|
82 | }
|
---|
83 | }
|
---|
84 |
|
---|
85 | if (first) {
|
---|
86 | SetAction(action);
|
---|
87 | first = false;
|
---|
88 | } else {
|
---|
89 | AppendAction(action);
|
---|
90 | }
|
---|
91 | waitingVehicles.Remove(bestVehicle);
|
---|
92 | waitingOrders.Remove(order);
|
---|
93 |
|
---|
94 | foreach (var assignedOrder in GetOrders().Where(o => o.AssignedVehicle == bestVehicle.Id && o.OrderState == OrderState.Waiting))
|
---|
95 | assignedOrder.AssignedVehicle = Guid.Empty;
|
---|
96 |
|
---|
97 | order.AssignedVehicle = bestVehicle.Id;
|
---|
98 | }
|
---|
99 | }
|
---|
100 | return true;
|
---|
101 | }
|
---|
102 |
|
---|
103 | protected abstract void GetHighestPriorityOrder(DynPDPProblemInstance instance, Vehicle vehicle, IEnumerable<Order> orders, out Order order, out double priority);
|
---|
104 |
|
---|
105 | protected bool IsPickup(Order o, DynPDPProblemInstance instance) {
|
---|
106 | return instance.Demand[Instance.GetStops(o.Id).First()] > 0;
|
---|
107 | }
|
---|
108 |
|
---|
109 | protected struct XY {
|
---|
110 | public double X { get; private set; }
|
---|
111 | public double Y { get; private set; }
|
---|
112 |
|
---|
113 | public XY(double x, double y)
|
---|
114 | : this() {
|
---|
115 | X = x;
|
---|
116 | Y = y;
|
---|
117 | }
|
---|
118 | }
|
---|
119 |
|
---|
120 | protected class XYEqComparer : EqualityComparer<XY> {
|
---|
121 | public override bool Equals(XY x, XY y) {
|
---|
122 | return x.X == y.X && x.Y == y.Y;
|
---|
123 | }
|
---|
124 |
|
---|
125 | public override int GetHashCode(XY obj) {
|
---|
126 | return obj.X.GetHashCode() ^ obj.Y.GetHashCode();
|
---|
127 | }
|
---|
128 | }
|
---|
129 | }
|
---|
130 | }
|
---|