#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.Core; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Common; using HeuristicLab.PDPSimulation.DomainModel; using System.Threading; using HeuristicLab.Problems.VehicleRouting.Interfaces; using HeuristicLab.Problems.VehicleRouting; using HeuristicLab.Problems.VehicleRouting.Variants; using HeuristicLab.Problems.VehicleRouting.ProblemInstances; using HeuristicLab.PDPSimulation.Operators; using HeuristicLab.Parameters; using HeuristicLab.Data; using System.Threading.Tasks; using HeuristicLab.PDPSimulation.DistanceMeasures; using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin; namespace HeuristicLab.PDPSimulation { [StorableClass] public abstract class DynamicPDPOptimization : PickupDeliveryOptimization { public ValueParameter OnlyOptimizedIfRequiredParameter { get { return (ValueParameter)Parameters["OnlyOptimizedIfRequired"]; } } public DynamicPDPOptimization(): base() { optimizationFinshed = true; Parameters.Add(new ValueParameter("OnlyOptimizedIfRequired", "Only optimize if new information is revealed.", new BoolValue(true))); } [StorableConstructor] protected DynamicPDPOptimization(bool deserializing) : base(deserializing) { } protected DynamicPDPOptimization(DynamicPDPOptimization original, Cloner cloner) : base(original, cloner) { instance = cloner.Clone(original.instance); lastUpdateTime = original.lastUpdateTime; optimizationFinshed = original.optimizationFinshed; } [Storable] private DynamicPDProblemInstance instance; protected DynamicPDProblemInstance Instance { get { return instance; } } [Storable] private double lastUpdateTime; [Storable] private bool optimizationFinshed; public override void SetScenario(PickupDeliveryScenario scenario) { base.SetScenario(scenario); instance = new DynamicPDProblemInstance(scenario, GetResults()); } public override void SetWaitingStrategy(WaitingStrategy waitingStrategy) { base.SetWaitingStrategy(waitingStrategy); if (instance != null) { foreach (IVRPProblemInstance staticInstance in instance.StaticInstances) (staticInstance as DynPDPProblemInstance).WaitingStrategy = waitingStrategy; } } public override void Prepare() { lastUpdateTime = 0; optimizationFinshed = true; instance = new DynamicPDProblemInstance(scenario, GetResults()); foreach (IVRPProblemInstance staticInstance in instance.StaticInstances) (staticInstance as DynPDPProblemInstance).WaitingStrategy = waitingStrategy; base.Prepare(); } protected virtual void PrepareInstance(DynamicPDProblemInstance instance, ChangeInformation changeInformation) { instance.InitializeInstance(changeInformation.CreatedVehicles, changeInformation.CreatedOrders); } protected virtual void PerformPlan(IVRPEncoding solution) { lock (actionLocker) { instance.SetCurrentPlan(PotvinEncoding.ConvertFrom(solution, instance.StaticInstance)); DynPDPEvaluation eval = instance.StaticInstance.Evaluate(solution) as DynPDPEvaluation; List vehicles = new List(); for (int i = 0; i < instance.StaticInstance.Vehicles.Value; i++) vehicles.Add(i); int tourIdx = 0; foreach (Tour tour in solution.GetTours()) { List waitingTimes = DynPDPEvaluator.GetWaitingTimes(instance.StaticInstance as DynPDPProblemInstance, tour, solution); int vehicleIdx = solution.GetVehicleAssignment( solution.GetTourIndex(tour)); vehicles.Remove(vehicleIdx); Guid vehicleId = instance.GetVehicle(vehicleIdx); Vehicle vehicle = GetVehicle(vehicleId); int stopIdx = 0; foreach (int stop in tour.Stops) { double coordX = instance.StaticInstance.GetCoordinates(stop)[0]; double coordY = instance.StaticInstance.GetCoordinates(stop)[1]; VehicleAction vehicleAction; Guid orderId = instance.GetOrder(stop); Order order = GetOrder(orderId); order.AssignedVehicle = vehicleId; if (instance.StaticInstance.GetDemand(stop) >= 0) { vehicleAction = VehicleAction.Pickup; } else { vehicleAction = VehicleAction.Deliver; } if (instance.StaticInstance.GetDemand(stop) != 0) { double waitingTime = waitingTimes[stopIdx]; PDAction action = new WaitAction(vehicleId, waitingTime); if (stopIdx == 0) { SetAction(action); } else { AppendAction(action); } action = new MoveVehicleAction( vehicleId, coordX, coordY, vehicleAction, order, scenario.AllowDiversion, scenario.DistanceMeasure); AppendAction(action); } stopIdx++; } tourIdx++; } foreach (int vehicleIdx in vehicles) { Guid vehicleId = instance.GetVehicle(vehicleIdx); Vehicle vehicle = GetVehicle(vehicleId); double posX, posY; lock (vehicle) { if (!scenario.AllowDiversion) { posX = vehicle.TargetPositionX; posY = vehicle.TargetPositionY; } else { posX = vehicle.PositionX; posY = vehicle.PositionY; } } SetAction(new WaitAction(vehicleId, 0)); } } } private void UpdateInstance(ChangeInformation changeInformation) { if (!instance.Initialized) { PrepareInstance(instance, changeInformation); } else { foreach (Vehicle vehicle in changeInformation.CreatedVehicles) { lock (vehicle) { instance.AddVehicle(vehicle); } } foreach (Order order in changeInformation.CreatedOrders) instance.AddOrder(order); foreach (Vehicle vehicle in changeInformation.ChangedVehicles) { lock (vehicle) { instance.UpdateVehicle(vehicle, scenario.AllowDiversion); } } foreach (Order order in changeInformation.ChangedOrders) instance.UpdateOrder(order, scenario.AllowDiversion); } double time = GetSimulationTime(); double delta = time - lastUpdateTime; lastUpdateTime = time; instance.UpdateTime(delta); } protected virtual void BeginInstanceUpdate(DynamicPDProblemInstance instance) { } protected virtual void EndInstanceUpdate(DynamicPDProblemInstance instance) { } protected virtual bool OptimizationRequired(ChangeInformation changeInformation) { return (!OnlyOptimizedIfRequiredParameter.Value.Value && Instance.StaticInstance != null && Instance.StaticInstance.Cities.Value > 0) || changeInformation.CreatedOrders.Count > 0 || changeInformation.InvalidActions; } protected virtual void StartOptimization() { } protected virtual void EndOptimization() { SignalWaitHandle(); running = false; } protected abstract bool PerformOptimization(DynamicPDProblemInstance instance, ChangeInformation changeInformation); protected object myLock = new object(); public override bool OptimizationRequired() { lock (myLock) { if (optimizationFinshed) { bool optimize = OptimizationRequired(GetChangeInformation(GetChanges(false))); if(optimize) optimizationFinshed = false; return optimize; } else { return true; } } } private void RelocateToDepot(Guid vehicleId, double simulationTime, bool finish) { Vehicle vehicle = GetVehicle(vehicleId); double posX, posY; lock (vehicle) { posX = vehicle.TargetPositionX; posY = vehicle.TargetPositionY; } bool moveToDepot = finish; if (!finish) { double length = scenario.DistanceMeasure.GetDistance(posX, posY, vehicle.DepotX, vehicle.DepotY); moveToDepot = (simulationTime + length >= vehicle.DueTime); } if (moveToDepot) { bool moved = false; PDAction action = GetAction(vehicle); while (action != null && action.Successor != null) { action = action.Successor; } moved = action != null && action is MoveVehicleAction && (action as MoveVehicleAction).TargetX == vehicle.DepotX && (action as MoveVehicleAction).TargetY == vehicle.DepotY; if (!moved) AppendAction(new MoveVehicleAction(vehicleId, vehicle.DepotX, vehicle.DepotY, VehicleAction.Park, null, scenario.AllowDiversion, scenario.DistanceMeasure)); } } protected virtual void RelocateVehicles(double simulationTime, bool finish) { lock (actionLocker) { for (int i = 0; i < instance.StaticInstance.Vehicles.Value; i++) { Guid vehicleId = instance.GetVehicle(i); RelocateToDepot(vehicleId, simulationTime, finish); } } } public override void RelocateVehicles() { if (scenario.RelocateBackToDepot) { double simulationTime = GetSimulationTime() + GetTimeStep(); RelocateVehicles(simulationTime, false); } } int index = 0; protected override void Optimize(CancellationToken token) { bool finish = false; bool optimize = false; bool simulationFinished = false; ChangeInformation changeInformation; StartOptimization(); while (!token.IsCancellationRequested && !finish) { WaitForSimulation(); lock (myLock) { List changes = GetChanges(true); changeInformation = GetChangeInformation(changes); BeginInstanceUpdate(instance); UpdateInstance(changeInformation); EndInstanceUpdate(instance); optimize = OptimizationRequired(changeInformation); optimizationFinshed = !optimize; } double simulationTime = GetSimulationTime(); if (changeInformation.SimulationFinished) simulationFinished = true; if (optimize) { optimizationFinshed = PerformOptimization(instance, changeInformation); /*VehicleRoutingProblem problem = new VehicleRoutingProblem(); problem.ProblemInstance = instance.StaticInstance; index++; HeuristicLab.Persistence.Default.Xml.XmlGenerator.Serialize(problem, @"C:\Users\svonolfen\Desktop\tests\i_" + index + ".hl");*/ } finish = simulationFinished && optimizationFinshed; if(scenario.RelocateBackToDepot) RelocateVehicles(simulationTime + GetTimeStep(), finish); if (!finish) SignalWaitHandle(); } EndOptimization(); } } }