using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Encodings.RealVectorEncoding; using HeuristicLab.Parameters; using HeuristicLab.PDPSimulation.DomainModel; using HeuristicLab.PDPSimulation.Operators; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.PDPSimulation { [Item("PriorityDispatching", "")] [StorableClass] public abstract class PriorityDispatching : Dispatching { [StorableConstructor] protected PriorityDispatching(bool deserializing) : base(deserializing) { } protected PriorityDispatching(PriorityDispatching original, Cloner cloner) : base(original, cloner) { } protected PriorityDispatching() { } protected abstract double CalculatePriority(IDictionary variables); protected override void GetHighestPriorityOrder(DynPDPProblemInstance instance, Vehicle vehicle, IEnumerable orders, out Order order, out double priority) { Order best = null; double bestPriority = double.MinValue; var pickupOrdersByLocation = (from o in orders where IsPickup(o, instance) group o by new { X = o.PickupXCoord, Y = o.PickupYCoord }) .ToDictionary(x => new XY(x.Key.X, x.Key.Y), y => y.ToArray(), new XYEqComparer()); var deliveryOrdersByLocation = (from o in orders where !IsPickup(o, instance) && o.Vehicle == vehicle.Id group o by new { X = o.DeliveryXCoord, Y = o.DeliveryYCoord }) .ToDictionary(x => new XY(x.Key.X, x.Key.Y), y => y.ToArray(), new XYEqComparer()); var destinations = deliveryOrdersByLocation.Keys.ToArray(); foreach (var o in orders) { if (IsPickup(o, instance) && o.Demand > vehicle.Capacity) continue; double prio; if (!IsPickup(o, instance) && vehicle.TargetPositionX == o.DeliveryXCoord && vehicle.TargetPositionY == o.DeliveryYCoord) { prio = double.MaxValue; } else { var target = new XY(o.PickupXCoord, o.PickupYCoord); if (!IsPickup(o, instance)) target = new XY(o.DeliveryXCoord, o.DeliveryYCoord); var destinationDifference = destinations.Select(x => scenario.DistanceMeasure.GetDistance(target.X, target.Y, x.X, x.Y)).ToArray(); var courierDifference = GetVehicles().Where(x => x != vehicle).Select(x => new XY(x.TargetPositionX, x.TargetPositionY)) .Select(x => scenario.DistanceMeasure.GetDistance(target.X, target.Y, x.X, x.Y)).ToArray(); var commonDestinations = orders.Where(x => !IsPickup(x, instance) && x.Vehicle == vehicle.Id && x.DeliveryXCoord == o.PickupXCoord && x.DeliveryYCoord == o.PickupYCoord); var variables = new Dictionary(); variables.Add("Distance", scenario.DistanceMeasure.GetDistance(vehicle.TargetPositionX, vehicle.TargetPositionY, target.X, target.Y)); variables.Add("EarliestTimeOfArrival", vehicle.ReadyTime + variables["Distance"]); variables.Add("DueDate", o.DeliveryDueTime - GetSimulationTime()); variables.Add("StartDate", IsPickup(o, instance) ? o.PickupReadyTime - GetSimulationTime() : 0); variables.Add("PickupOrdersAtTarget", pickupOrdersByLocation.ContainsKey(target) ? pickupOrdersByLocation[target].Count() : 0); variables.Add("PickupOrderItemsAtTarget", pickupOrdersByLocation.ContainsKey(target) ? pickupOrdersByLocation[target].Sum(x => x.Demand) : 0); variables.Add("DeliveryOrdersAtTarget", deliveryOrdersByLocation.ContainsKey(target) ? deliveryOrdersByLocation[target].Count() : 0); variables.Add("DeliveryOrderItemsAtTarget", deliveryOrdersByLocation.ContainsKey(target) ? deliveryOrdersByLocation[target].Sum(x => x.Demand) : 0); variables.Add("AverageDistanceToDestinations", destinationDifference.Any() ? destinationDifference.Average() : 0); variables.Add("MinimumDistanceToDestinations", destinationDifference.Any() ? destinationDifference.Min() : 0); variables.Add("MaximumDistanceToDestinations", destinationDifference.Any() ? destinationDifference.Max() : 0); variables.Add("NumberOfOtherCouriersToTarget", GetVehicles().Count > 2 ? GetVehicles().Where(x => x != vehicle).Count(x => target.X == x.TargetPositionX && target.Y == x.TargetPositionY) : 0); variables.Add("AverageDistanceToOtherCouriers", courierDifference.Any() ? courierDifference.Average() : 0); variables.Add("MinimumDistanceToOtherCouriers", courierDifference.Any() ? courierDifference.Min() : 0); variables.Add("MaximumDistanceToOtherCouriers", courierDifference.Any() ? courierDifference.Max() : 0); variables.Add("DemandSize", o.Demand); variables.Add("EDD", commonDestinations.Any() ? commonDestinations.Min(d => d.DeliveryDueTime - scenario.DistanceMeasure.GetDistance(vehicle.TargetPositionX, vehicle.TargetPositionY, d.DeliveryXCoord, d.DeliveryYCoord) - GetSimulationTime()) : 0); variables.Add("LeadTime", o.PickupReadyTime - GetSimulationTime()); prio = CalculatePriority(variables); } if (prio > bestPriority) { bestPriority = prio; best = o; } } order = best != null ? best : orders.First(); priority = bestPriority; } } }