#region License Information /* HeuristicLab * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.Collections.Generic; using System.Linq; using System.Text; using HeuristicLab.Optimization; using HeuristicLab.Analysis; using HeuristicLab.Data; using HeuristicLab.PDPSimulation.DomainModel; using HeuristicLab.Core; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Common; using HeuristicLab.Problems.VehicleRouting; using HeuristicLab.PDPSimulation.Operators; using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin; namespace HeuristicLab.PDPSimulation { [Item("PickupDeliveryAnalyzer", "A pickup and delivery analyzer.")] [StorableClass] public class PickupDeliveryAnalyzer: ParameterizedNamedItem { public PickupDeliveryAnalyzer() : base() { } [StorableConstructor] protected PickupDeliveryAnalyzer(bool deserializing) : base(deserializing) { } protected PickupDeliveryAnalyzer(PickupDeliveryAnalyzer original, Cloner cloner) : base(original, cloner) { } public override IDeepCloneable Clone(Cloner cloner) { return new PickupDeliveryAnalyzer(this, cloner); } public virtual void UpdateVisualization(PickupDeliverySimulation simulation, PickupDeliveryScenario scenario, ResultCollection results) { if (!results.ContainsKey("Visualization")) results.Add(new Result("Visualization", new PickupDeliveryVisualization(simulation))); else (results["Visualization"].Value as PickupDeliveryVisualization).SetState(simulation); (results["Visualization"].Value as PickupDeliveryVisualization).Refresh(); } protected virtual void UpdateOrderResults(PickupDeliverySimulation simulation, PickupDeliveryScenario scenario, ResultCollection results) { if (!results.ContainsKey("OrderStatistics")) { DataTable data = new DataTable("OrderStatistics"); results.Add(new Result("OrderStatistics", data)); data.Rows.Add(new DataRow("WaitingOrders")); data.Rows.Add(new DataRow("PickedUpOrders")); data.Rows.Add(new DataRow("DeliveredOrders")); data.Rows.Add(new DataRow("CancelledOrders")); results.Add(new Result("AverageQueueLength", new DoubleValue(0))); } DataTable orderStatistics = results["OrderStatistics"].Value as DataTable; int currentWaiting = 0; int currentPickedUp = 0; int currentDelivered = 0; int currentCancelled = 0; foreach (Order order in simulation.Orders) { if (order.OrderState == OrderState.Waiting || order.OrderState == OrderState.PickingUp) currentWaiting++; else if (order.OrderState == OrderState.PickedUp || order.OrderState == OrderState.Delivering) currentPickedUp++; else if (order.OrderState == OrderState.Delivered) currentDelivered++; else if (order.OrderState == OrderState.Cancelled) currentCancelled++; } orderStatistics.Rows["WaitingOrders"].Values.Add(currentWaiting); orderStatistics.Rows["PickedUpOrders"].Values.Add(currentPickedUp); orderStatistics.Rows["DeliveredOrders"].Values.Add(currentDelivered); orderStatistics.Rows["CancelledOrders"].Values.Add(currentCancelled); DoubleValue queueLength = results["AverageQueueLength"].Value as DoubleValue; queueLength.Value = orderStatistics.Rows["WaitingOrders"].Values.Average(); } protected virtual void UpdateVehicleResults(PickupDeliverySimulation simulation, PickupDeliveryScenario scenario, ResultCollection results) { if (!results.ContainsKey("VehicleStatistics")) { DataTable data = new DataTable("VehicleStatistics"); results.Add(new Result("VehicleStatistics", data)); data.Rows.Add(new DataRow("UsedVehicles")); data.Rows.Add(new DataRow("DrivenDistance")); data.Rows.Add(new DataRow("InvalidActions")); data.Rows.Add(new DataRow("Tardiness")); data.Rows.Add(new DataRow("CapacityUtilization")); results.Add(new Result("UsedVehicles", new IntValue())); results.Add(new Result("DrivenDistance", new DoubleValue())); results.Add(new Result("InvalidActions", new DoubleValue())); results.Add(new Result("VehicleTardiness", new DoubleValue())); } DataTable vehicleStatistics = results["VehicleStatistics"].Value as DataTable; int usedVehicles = simulation.Vehicles.Where(v => v.Distance > 0).Count(); double distance = Math.Round(simulation.Vehicles.Sum(v => v.Distance) * 100.0) / 100.0; int invalidActions = simulation.Vehicles.Sum(v => v.InvalidActions); double tardiness = Math.Round(simulation.Vehicles.Sum(v => v.Tardiness) * 100.0) / 100.0; var used = simulation.Vehicles.Where(v => v.Distance > 0); double capacityUtilization = 0; if(used.Count() > 0) capacityUtilization = Math.Round(used.Average(v => 1.0 - (v.Capacity / v.TotalCapacity)) * 100.0) / 100.0; vehicleStatistics.Rows["UsedVehicles"].Values.Add(usedVehicles); vehicleStatistics.Rows["DrivenDistance"].Values.Add(distance); vehicleStatistics.Rows["InvalidActions"].Values.Add(invalidActions); vehicleStatistics.Rows["Tardiness"].Values.Add(tardiness); vehicleStatistics.Rows["CapacityUtilization"].Values.Add(capacityUtilization); (results["UsedVehicles"].Value as IntValue).Value = usedVehicles; (results["DrivenDistance"].Value as DoubleValue).Value = distance; (results["VehicleTardiness"].Value as DoubleValue).Value = tardiness; } protected virtual void UpdateConstraintViolationResults(PickupDeliverySimulation simulation, PickupDeliveryScenario scenario, ResultCollection results) { if (!results.ContainsKey("ConstraintViolations")) { DataTable data = new DataTable("ConstraintViolations"); results.Add(new Result("ConstraintViolations", data)); data.Rows.Add(new DataRow("Overload")); data.Rows.Add(new DataRow("Tardiness")); results.Add(new Result("Overload", new DoubleValue())); results.Add(new Result("Tardiness", new DoubleValue())); } DataTable violationStatistics = results["ConstraintViolations"].Value as DataTable; double overload = Math.Round(simulation.Vehicles.Sum(v => v.Overload) * 100.0) / 100.0; double tardiness = Math.Round(simulation.Orders.Sum(o => o.Tardiness) * 100.0) / 100.0; violationStatistics.Rows["Overload"].Values.Add(overload); violationStatistics.Rows["Tardiness"].Values.Add(tardiness); (results["Overload"].Value as DoubleValue).Value = overload; (results["Tardiness"].Value as DoubleValue).Value = tardiness; } protected virtual void UpdateVehicleHistoryResults(PickupDeliverySimulation simulation, PickupDeliveryScenario scenario, ResultCollection results) { if (!results.ContainsKey("VehicleHistory")) { VehicleHistoryVisualization data = new VehicleHistoryVisualization(); data.ResultCollectionInterval = simulation.TimeStepParameter.Value.Value; results.Add(new Result("VehicleHistory", data)); foreach (Vehicle vehicle in simulation.Vehicles) { string name = vehicle.Name; if (string.IsNullOrEmpty(name)) name = "Vehicle " + simulation.Vehicles.IndexOf(vehicle); data.VehicleHistory.Add(new VehicleHistory(name)); } } VehicleHistoryVisualization vehicleHistory = results["VehicleHistory"].Value as VehicleHistoryVisualization; foreach (Vehicle vehicle in simulation.Vehicles) { VehicleHistory history = vehicleHistory.VehicleHistory[simulation.Vehicles.IndexOf(vehicle)]; history.VehicleState.Add(vehicle.VehicleState); history.VehicleAvailability.Add(vehicle.Availibility); history.ActiveOrders.Add(simulation.Orders.FirstOrDefault(o => o.Id == vehicle.CurrentOrder)); history.AssignedOrders.Clear(); history.AssignedOrders.AddRange(simulation.Orders.Where(o => o.AssignedVehicle == vehicle.Id)); } vehicleHistory.Refresh(); } protected virtual void UpdateTimeHistogram(PickupDeliverySimulation simulation, PickupDeliveryScenario scenario, ResultCollection results) { if (!results.ContainsKey("TimeHistogram")) { DataTable data = new DataTable("TimeHistogram"); results.Add(new Result("TimeHistogram", data)); DataRow row = new DataRow("WaitingTime"); row.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Histogram; data.Rows.Add(row); row = new DataRow("TransferTime"); row.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Histogram; data.Rows.Add(row); row = new DataRow("Slack"); row.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Histogram; data.Rows.Add(row); row = new DataRow("LeadTime"); row.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Histogram; data.Rows.Add(row); results.Add(new Result("LeadTime", new DoubleValue())); } DataTable timeHistogram = results["TimeHistogram"].Value.Clone() as DataTable; //waiting time var values = timeHistogram.Rows["WaitingTime"].Values; values.Clear(); foreach (Order order in simulation.Orders.Where(o => o.PickupTime > 0)) { values.Add(order.PickupTime - order.PickupReadyTime); } //transfer time values = timeHistogram.Rows["TransferTime"].Values; values.Clear(); foreach (Order order in simulation.Orders.Where(o => o.OrderState == OrderState.Delivered)) { values.Add(order.DeliveryTime - order.PickupTime - order.PickupServiceTime); } //slack values = timeHistogram.Rows["Slack"].Values; values.Clear(); foreach (Order order in simulation.Orders.Where(o => o.PickupTime > 0)) { values.Add(order.PickupDueTime - order.PickupTime); } //lead time double leadTime = 0; values = timeHistogram.Rows["LeadTime"].Values; values.Clear(); foreach (Order order in simulation.Orders.Where(o => o.OrderState == OrderState.Delivered)) { double orderLeadTime = order.DeliveryTime + order.DeliveryServiceTime - order.PickupReadyTime; values.Add(orderLeadTime); leadTime += orderLeadTime; } (results["LeadTime"].Value as DoubleValue).Value = leadTime; results["TimeHistogram"].Value = timeHistogram; } public virtual void Analyze(PickupDeliverySimulation simulation, PickupDeliveryScenario scenario, ResultCollection results) { UpdateOrderResults(simulation, scenario, results); UpdateVehicleResults(simulation, scenario, results); UpdateConstraintViolationResults(simulation, scenario, results); UpdateVehicleHistoryResults(simulation, scenario, results); UpdateTimeHistogram(simulation, scenario, results); } public virtual void Tick(PickupDeliverySimulation simulation, PickupDeliveryScenario scenario, ResultCollection results) { } } }