Index: branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/HeuristicLab.PDPSimulation-3.3.csproj
===================================================================
--- branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/HeuristicLab.PDPSimulation-3.3.csproj	(revision 8713)
+++ branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/HeuristicLab.PDPSimulation-3.3.csproj	(revision 8714)
@@ -181,4 +181,5 @@
     <Compile Include="DistanceMeasures\EuclideanDistanceMeasure.cs" />
     <Compile Include="DomainModel\SimulationObject.cs" />
+    <Compile Include="Operators\DialARideEvaluator.cs" />
     <Compile Include="Operators\DynPDPEvaluator.cs" />
     <Compile Include="Operators\DynPushForwardInsertionCreator.cs" />
Index: branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/DialARideEvaluator.cs
===================================================================
--- branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/DialARideEvaluator.cs	(revision 8714)
+++ branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/DialARideEvaluator.cs	(revision 8714)
@@ -0,0 +1,296 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Core;
+using HeuristicLab.Parameters;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.PluginInfrastructure;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+using HeuristicLab.Problems.VehicleRouting.Encodings;
+using HeuristicLab.Common;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+using HeuristicLab.Problems.VehicleRouting;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  public class DialARideEvaluation : DynPDPEvaluation {
+    public List<double> LeadTimes { get; private set; }
+
+    public DialARideEvaluation() {
+      LeadTimes = new List<double>();
+    } 
+  }
+
+  [Item("DialARideEvaluator", "Represents a dynamic multi depot CVRPPDTW evaluator.")]
+  [StorableClass]
+  public class DialARideEvaluator: DynPDPEvaluator {
+    public ILookupParameter<DoubleValue> LeadTimeParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["LeadTime"]; }
+    }
+
+    public IValueParameter<DoubleValue> LeadTimeFactorParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["LeadTimeFactor"]; }
+    }
+
+    protected override VRPEvaluation CreateTourEvaluation() {
+      return new DialARideEvaluation();
+    }
+
+    protected override void EvaluateTour(VRPEvaluation eval, IVRPProblemInstance instance, Tour tour, IVRPEncoding solution) {
+      TourInsertionInfo tourInfo = new TourInsertionInfo(solution.GetVehicleAssignment(solution.GetTourIndex(tour)));
+      eval.InsertionInfo.AddTourInsertionInfo(tourInfo);
+      double originalQuality = eval.Quality;
+
+      IHeterogenousCapacitatedProblemInstance cvrpInstance = instance as IHeterogenousCapacitatedProblemInstance;
+      DoubleArray demand = instance.Demand;
+
+      ITimeWindowedProblemInstance vrptw = instance as ITimeWindowedProblemInstance;
+      DoubleArray dueTime = vrptw.DueTime;
+      DoubleArray readyTime = vrptw.ReadyTime;
+      DoubleArray serviceTimes = vrptw.ServiceTime;
+
+      IPickupAndDeliveryProblemInstance pdp = instance as IPickupAndDeliveryProblemInstance;
+      IntArray pickupDeliveryLocation = pdp.PickupDeliveryLocation;
+
+      IMultiDepotProblemInstance mdp = instance as IMultiDepotProblemInstance;
+      IntArray vehicleAssignment = mdp.VehicleDepotAssignment;
+      int depots = mdp.Depots.Value;
+
+      double time = 0.0;
+      double waitingTime = 0.0;
+      double serviceTime = 0.0;
+      double tardiness = 0.0;
+      double overweight = 0.0;
+      double distance = 0.0;
+
+      int tourIndex = solution.GetTourIndex(tour);
+      int vehicle = solution.GetVehicleAssignment(tourIndex);
+      int depot = vehicleAssignment[vehicle];
+
+      double capacity = cvrpInstance.Capacity[vehicle];
+
+      double currentLoad = 0.0;
+      Dictionary<int, bool> stops = new Dictionary<int, bool>();
+      int pickupViolations = 0;
+
+      double tourStartTime = readyTime[depot];
+      time = tourStartTime;
+
+      WaitingStrategy waitingStrategy = (instance as DynPDPProblemInstance).WaitingStrategy;
+
+      List<double> leadTimes = new List<double>();
+
+      //simulate a tour
+      int count = tour.Stops.Count;
+      if (!(instance as DynPDPProblemInstance).RelocateBackToDepot)
+        count -= 1;
+      for (int i = 0; i <= count; i++) {
+        int start = 0;
+        if (i > 0)
+          start = tour.Stops[i - 1];
+        int end = 0;
+        if (i < tour.Stops.Count)
+          end = tour.Stops[i];
+
+        //Waiting strategy...
+        if (end != 0) {
+          double waitAction = waitingStrategy.GetBufferTime(time, instance as DynPDPProblemInstance, solution, tour, i);
+          time += waitAction;
+        }
+
+        double commitmentTime = time;
+        
+        //drive there
+        double currentDistace = vrptw.GetDistance(start, end, solution);
+
+        time += currentDistace;
+        distance += currentDistace;
+
+        double arrivalTime = time;
+
+        int endIndex;
+        if (end == 0)
+          endIndex = depot;
+        else
+          endIndex = end + depots - 1;
+
+        //check if it was serviced on time
+        if (time > dueTime[endIndex])
+          tardiness += time - dueTime[endIndex];
+
+        //wait
+        double currentWaitingTime = 0.0;
+        if (time < readyTime[endIndex])
+          currentWaitingTime = readyTime[endIndex] - time;
+
+        double waitTime = readyTime[endIndex] - time;
+
+        waitingTime += currentWaitingTime;
+        time += currentWaitingTime;
+
+        double spareTime = dueTime[endIndex] - time;
+        double arrivalSpareCapacity = capacity - currentLoad;
+
+        if (end > 0) {
+          //service
+          double currentServiceTime = serviceTimes[end - 1];
+          serviceTime += currentServiceTime;
+          time += currentServiceTime;
+
+          //Pickup / deliver
+          int location = pickupDeliveryLocation[end - 1];
+          bool validPickupDelivery =
+            validPickupDelivery =
+            ((demand[end - 1] >= 0) ||
+             (end == location) ||
+             (location <= 0 && vehicle == -location) ||
+             (stops.ContainsKey(location)));
+
+          if (validPickupDelivery) {
+            currentLoad += demand[end - 1];
+
+            if (demand[end - 1] < 0) {
+              double pickupReady = 0;
+              if (location > 0) {
+                pickupReady = readyTime[location + depots - 1];
+              }
+              leadTimes.Add(time - pickupReady);
+            }
+          } else {
+            pickupViolations++;
+          }
+
+          if (currentLoad > capacity)
+            overweight += currentLoad - capacity;
+        }
+
+        double spareCapacity = capacity - currentLoad;
+        CVRPPDTWInsertionInfo stopInfo = new DynPDPInsertionInfo(start, end, spareCapacity, tourStartTime,
+          arrivalTime, time, spareTime, waitTime, commitmentTime, new List<int>(stops.Keys), arrivalSpareCapacity);
+        tourInfo.AddStopInsertionInfo(stopInfo);
+
+        stops.Add(end, true);
+      }
+
+      if(!(instance as DynPDPProblemInstance).VehicleUsed[vehicle])
+        eval.Quality += instance.FleetUsageFactor.Value;
+
+      eval.Quality += instance.DistanceFactor.Value * distance;
+      eval.Distance += distance;
+      eval.VehicleUtilization += 1;
+      double leadTime = 0;
+      if (leadTimes.Count > 0)
+        leadTime = leadTimes.Average();
+      eval.Quality += leadTime * LeadTimeFactorParameter.Value.Value;
+
+      (eval as CVRPEvaluation).Overload += overweight;
+      double tourPenalty = 0;
+      double penalty = overweight * cvrpInstance.OverloadPenalty.Value;
+      eval.Penalty += penalty;
+      eval.Quality += penalty;
+      tourPenalty += penalty;
+
+      (eval as CVRPTWEvaluation).Tardiness += tardiness;
+      (eval as CVRPTWEvaluation).TravelTime += time;
+
+      penalty = tardiness * vrptw.TardinessPenalty.Value;
+      eval.Penalty += penalty;
+      eval.Quality += penalty;
+      tourPenalty += penalty;
+
+      (eval as CVRPPDTWEvaluation).PickupViolations += pickupViolations;
+      penalty = pickupViolations * pdp.PickupViolationPenalty.Value;
+      eval.Penalty += penalty;
+      tourPenalty += penalty;
+
+      eval.Quality += penalty;
+      eval.Quality += time * vrptw.TimeFactor.Value;
+      tourInfo.Penalty = tourPenalty;
+      tourInfo.Quality = eval.Quality - originalQuality;
+
+      (eval as DialARideEvaluation).LeadTimes.AddRange(leadTimes);
+    }
+
+    protected override double GetTourInsertionCosts(IVRPProblemInstance instance, IVRPEncoding solution, TourInsertionInfo tourInsertionInfo, int index, int customer, 
+      out bool feasible) {
+        TourEncoding individual = null;
+        if (solution is TourEncoding)
+          individual = solution as TourEncoding;
+        else {
+          individual = new PotvinEncoding(instance);
+          individual.Tours.AddRange(solution.GetTours());
+        }
+
+        int tourIdx = -1;
+        for (int i = 0; i < individual.Tours.Count; i++) {
+          if (solution.GetVehicleAssignment(i) == tourInsertionInfo.Vehicle)
+            tourIdx = i;
+        }
+        Tour tour = individual.Tours[tourIdx];
+
+        tour.Stops.Insert(index, customer);
+        VRPEvaluation newEval = instance.EvaluateTour(tour, individual);
+        tour.Stops.RemoveAt(index);
+
+        feasible = instance.Feasible(newEval);
+        return newEval.Quality - tourInsertionInfo.Quality;
+    }
+
+    protected override void InitResultParameters() {
+      base.InitResultParameters();
+
+      LeadTimeParameter.ActualValue = new DoubleValue(0);
+    }
+
+    protected override void SetResultParameters(VRPEvaluation tourEvaluation) {
+      base.SetResultParameters(tourEvaluation);
+
+      double leadTime = 0;
+      if((tourEvaluation as DialARideEvaluation).LeadTimes.Count > 0)
+        leadTime = (tourEvaluation as DialARideEvaluation).LeadTimes.Average();
+      LeadTimeParameter.ActualValue.Value = leadTime;
+    }
+    
+    [StorableConstructor]
+    protected DialARideEvaluator(bool deserializing) : base(deserializing) { }
+
+    public DialARideEvaluator() {
+      Parameters.Add(new LookupParameter<DoubleValue>("LeadTime", "The total lead time."));
+      Parameters.Add(new ValueParameter<DoubleValue>("LeadTimeFactor", "The lead time factor considered in the evaluation.", new DoubleValue(0)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DialARideEvaluator(this, cloner);
+    }
+
+    protected DialARideEvaluator(DialARideEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/DynPDPProblemInstance.cs
===================================================================
--- branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/DynPDPProblemInstance.cs	(revision 8713)
+++ branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/DynPDPProblemInstance.cs	(revision 8714)
@@ -212,4 +212,5 @@
       TardinessPenalty.Value = scenario.TardinessPenaltyParameter.Value.Value;
       FleetUsageFactor.Value = scenario.FleetUsageFactorParameter.Value.Value;
+      DistanceFactor.Value = scenario.DistanceFactorParameter.Value.Value;
     }
   }
Index: branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliveryAnalyzer.cs
===================================================================
--- branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliveryAnalyzer.cs	(revision 8713)
+++ branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliveryAnalyzer.cs	(revision 8714)
@@ -108,4 +108,5 @@
         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()));
@@ -120,5 +121,9 @@
       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;
+      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);
@@ -126,4 +131,5 @@
       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;
@@ -183,4 +189,59 @@
     }
 
+    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);
+      }
+
+      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
+      values = timeHistogram.Rows["LeadTime"].Values;
+      values.Clear();
+      foreach (Order order in simulation.Orders.Where(o => o.OrderState == OrderState.Delivered)) {
+        values.Add(order.DeliveryTime + order.DeliveryServiceTime - order.PickupReadyTime);
+      }
+
+      results["TimeHistogram"].Value = timeHistogram;
+    }
+
     public virtual void Analyze(PickupDeliverySimulation simulation, PickupDeliveryScenario scenario, ResultCollection results) {
       UpdateOrderResults(simulation, scenario, results);
@@ -188,4 +249,5 @@
       UpdateConstraintViolationResults(simulation, scenario, results);
       UpdateVehicleHistoryResults(simulation, scenario, results);
+      UpdateTimeHistogram(simulation, scenario, results);
     }
 
Index: branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliveryScenario.cs
===================================================================
--- branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliveryScenario.cs	(revision 8713)
+++ branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliveryScenario.cs	(revision 8714)
@@ -73,4 +73,8 @@
     }
 
+    public IValueParameter<DoubleValue> DistanceFactorParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["DistanceFactor"]; }
+    }
+
     public IValueParameter<DoubleValue> FleetUsageFactorParameter {
       get { return (IValueParameter<DoubleValue>)Parameters["FleetUsageFactor"]; }
@@ -142,4 +146,5 @@
       Parameters.Add(new ValueParameter<DoubleArray>("VehicleReadyTimes", new DoubleArray()));
       Parameters.Add(new ValueParameter<DoubleArray>("VehicleDueTimes", new DoubleArray()));
+      Parameters.Add(new ValueParameter<DoubleValue>("DistanceFactor", "The distance factor considered in the evaluation.", new DoubleValue(1)));
       Parameters.Add(new ValueParameter<DoubleValue>("FleetUsageFactor", "The fleet usage factor considered in the evaluation.", new DoubleValue(3000)));
       Parameters.Add(new ValueParameter<DoubleValue>("OverloadPenalty", "The overload penalty considered in the evaluation.", new DoubleValue(10000)));
