#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.PDPSimulation.SimulationCore;
using HeuristicLab.Parameters;
using HeuristicLab.Data;
using System.Threading;
using HeuristicLab.Common;
using HeuristicLab.PDPSimulation.DomainModel;
using HeuristicLab.PDPSimulation.DistanceMeasures;
using HeuristicLab.Optimization;
namespace HeuristicLab.PDPSimulation {
[Item("PickupDeliveryOptimization", "A pickup and delivery optimization.")]
[StorableClass]
public abstract class PickupDeliveryOptimization: ParameterizedNamedItem {
#region constructors
public PickupDeliveryOptimization() : base() {
objectChanges = new Dictionary>();
actions = new Dictionary();
}
[StorableConstructor]
protected PickupDeliveryOptimization(bool deserializing) : base(deserializing) { }
protected PickupDeliveryOptimization(PickupDeliveryOptimization original, Cloner cloner)
: base(original, cloner) {
lock (original.objectChanges) {
lock (original.actionLocker) {
simulation = cloner.Clone(original.simulation);
if (simulation != null) {
simulation.SimulationStateChanged +=
new PickupDeliverySimulation.SimulationStateChangedHandler(simulation_SimulationStateChanged);
}
objectChanges = new Dictionary>();
foreach (BaseObject obj in original.objectChanges.Keys) {
BaseObject objClone = cloner.Clone(obj);
objectChanges.Add(objClone, new List());
foreach (PDChange change in original.objectChanges[obj])
objectChanges[objClone].Add(cloner.Clone(change));
}
actions = new Dictionary();
foreach (Guid objId in original.actions.Keys) {
actions.Add(objId, cloner.Clone(original.actions[objId]));
}
}
}
this.scenario = cloner.Clone(original.scenario);
this.waitingStrategy = cloner.Clone(original.waitingStrategy);
}
#endregion
[StorableHook(HookType.AfterDeserialization)]
private void AfterDeserialization() {
if (this.simulation != null) {
this.simulation.SimulationStateChanged +=
new PickupDeliverySimulation.SimulationStateChangedHandler(simulation_SimulationStateChanged);
}
}
[Storable]
protected PickupDeliveryScenario scenario;
[Storable]
protected WaitingStrategy waitingStrategy;
[Storable]
private PickupDeliverySimulation simulation;
protected double GetSimulationTime() {
return simulation.SimulationTime;
}
protected double GetTimeStep() {
return simulation.TimeStep;
}
protected List GetOrders() {
return simulation.Orders;
}
protected Order GetOrder(Guid orderId) {
return simulation.GetOrder(orderId);
}
protected Vehicle GetVehicle(Guid vehicleId) {
return simulation.GetVehicle(vehicleId);
}
protected List GetVehicles() {
return simulation.Vehicles;
}
protected ResultCollection GetResults() {
return simulation.Results;
}
[Storable]
private Dictionary> objectChanges;
private void RemoveObsoleteChanges(PDChange change) {
List toBeRemoved = new List();
foreach (PDChange existingChange in objectChanges[change.BaseObject]) {
if (existingChange.ChangeType == change.ChangeType) {
toBeRemoved.Add(existingChange);
}
}
foreach (PDChange removed in toBeRemoved) {
objectChanges[change.BaseObject].Remove(removed);
}
}
protected void AddChange(PDChange change) {
lock (objectChanges) {
if (!objectChanges.ContainsKey(change.BaseObject))
objectChanges.Add(change.BaseObject, new List());
RemoveObsoleteChanges(change);
objectChanges[change.BaseObject].Add(change);
}
}
protected List GetChanges(bool clear) {
lock (objectChanges) {
List result = new List();
foreach (List objChanges in objectChanges.Values)
result.AddRange(objChanges);
if(clear)
objectChanges.Clear();
return result;
}
}
protected struct ChangeInformation {
public List CreatedVehicles { get; set; }
public List CreatedOrders { get; set; }
public List ChangedVehicles { get; set; }
public List ChangedOrders { get; set; }
public bool InvalidActions { get; set; }
public bool SimulationFinished { get; set; }
}
protected ChangeInformation GetChangeInformation(List changes) {
ChangeInformation changeInformation = new ChangeInformation();
changeInformation.CreatedVehicles = new List();
changeInformation.CreatedOrders = new List();
changeInformation.ChangedVehicles = new List();
changeInformation.ChangedOrders = new List();
changeInformation.InvalidActions = false;
changeInformation.SimulationFinished = false;
foreach (PDChange change in changes) {
if (change.ChangeType == SimulationStateChange.VehicleCreated) {
Vehicle vehicle = change.BaseObject as Vehicle;
changeInformation.CreatedVehicles.Add(vehicle);
} else if (change.ChangeType == SimulationStateChange.VehicleMoved ||
change.ChangeType == SimulationStateChange.VehicleState) {
Vehicle vehicle = change.BaseObject as Vehicle;
changeInformation.ChangedVehicles.Add(vehicle);
if (change.ChangeType == SimulationStateChange.VehicleState &&
vehicle.VehicleState == VehicleState.InvalidAction)
changeInformation.InvalidActions = true;
} else if (change.ChangeType == SimulationStateChange.OrderCreated) {
Order order = change.BaseObject as Order;
changeInformation.CreatedOrders.Add(order);
} else if (change.ChangeType == SimulationStateChange.OrderState) {
Order order = change.BaseObject as Order;
changeInformation.ChangedOrders.Add(order);
} else if (change.ChangeType == SimulationStateChange.NoMoreOrders) {
changeInformation.SimulationFinished = true;
} else if (change.ChangeType == SimulationStateChange.OrderFailed) {
changeInformation.InvalidActions = true;
}
}
changeInformation.InvalidActions = changeInformation.InvalidActions ||
GetVehicles().Where(v => v.VehicleState == VehicleState.InvalidAction).Count() > 0;
return changeInformation;
}
protected object actionLocker = new object();
[Storable]
private Dictionary actions;
public PDAction GetAction(BaseObject obj) {
lock (actionLocker) {
if (actions.ContainsKey(obj.Id))
return actions[obj.Id];
else
return null;
}
}
protected void SetAction(PDAction action) {
lock (actionLocker) {
if (actions.ContainsKey(action.BaseObjectId)) {
lock (actions[action.BaseObjectId]) {
if (!actions[action.BaseObjectId].Interruptable())
actions[action.BaseObjectId].AppendAction(action, false);
else
actions[action.BaseObjectId] = action;
}
} else {
actions[action.BaseObjectId] = action;
}
}
}
protected void AppendAction(PDAction action) {
lock (actionLocker) {
if (actions.ContainsKey(action.BaseObjectId)) {
actions[action.BaseObjectId].AppendAction(action, true);
} else {
actions[action.BaseObjectId] = action;
}
}
}
public void RemoveCompletedActions() {
lock (actionLocker) {
List toBeRemoved = new List();
foreach (Guid objId in actions.Keys) {
if (actions[objId].IsCompleted)
toBeRemoved.Add(objId);
}
foreach (Guid objId in toBeRemoved)
actions.Remove(objId);
}
}
public List GetActions() {
lock (actionLocker) {
RemoveCompletedActions();
return actions.Values.ToList();
}
}
public virtual void SetScenario(PickupDeliveryScenario scenario) {
if (scenario != null) {
this.scenario = scenario;
}
}
public virtual void SetWaitingStrategy(WaitingStrategy waitingStrategy) {
this.waitingStrategy = waitingStrategy;
}
public virtual void Prepare() {
//clear state
objectChanges.Clear();
actions.Clear();
}
public virtual void SetSimulation(PickupDeliverySimulation simulation) {
if (this.simulation != simulation) {
if (this.simulation != null) {
this.simulation.SimulationStateChanged -=
new PickupDeliverySimulation.SimulationStateChangedHandler(simulation_SimulationStateChanged);
}
this.simulation = simulation;
this.simulation.SimulationStateChanged +=
new PickupDeliverySimulation.SimulationStateChangedHandler(simulation_SimulationStateChanged);
}
}
private EventWaitHandle wh;
private void InitWaitHandle(bool synchronized) {
if(wh != null)
wh.Dispose();
wh = null;
if(synchronized)
wh = new EventWaitHandle(false, EventResetMode.AutoReset);
}
protected void SignalWaitHandle() {
if(wh != null)
wh.Set();
}
public void WaitForOptimization() {
if (wh != null) {
bool signal = false;
while (!signal && Running())
signal = wh.WaitOne(100);
}
}
protected void WaitForSimulation() {
simulation.WaitForSimulation();
}
protected abstract void Optimize(CancellationToken token);
Thread optThread;
CancellationTokenSource cts;
protected bool running;
public void Start(bool synchronized) {
running = true;
InitWaitHandle(synchronized);
using (EventWaitHandle wh = new EventWaitHandle(false, EventResetMode.ManualReset)) {
cts = new CancellationTokenSource();
optThread = new Thread(delegate() {
wh.Set();
Optimize(cts.Token);
});
optThread.IsBackground = true;
optThread.Start();
wh.WaitOne();
}
}
public abstract bool OptimizationRequired();
public virtual void RelocateVehicles() {
}
public void Stop() {
if(cts != null)
cts.Cancel();
}
public bool Running() {
return optThread != null && optThread.IsAlive && running;
}
public void Exit() {
optThread = null;
}
void simulation_SimulationStateChanged(BaseObject obj, SimulationStateChange changeType) {
PDChange change = new PDChange() { BaseObject = obj.Clone() as BaseObject, ChangeType = changeType };
AddChange(change);
}
}
}