Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/HeuristicLab.Problems.VehicleRouting.Views-3.4.csproj
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/HeuristicLab.Problems.VehicleRouting.Views-3.4.csproj	(revision 6853)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/HeuristicLab.Problems.VehicleRouting.Views-3.4.csproj	(revision 6854)
@@ -112,4 +112,10 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="MDCVRPTWView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="MDCVRPTWView.Designer.cs">
+      <DependentUpon>MDCVRPTWView.cs</DependentUpon>
+    </Compile>
     <Compile Include="MultiDepotVRPView.cs">
       <SubType>UserControl</SubType>
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/MDCVRPTWView.Designer.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/MDCVRPTWView.Designer.cs	(revision 6854)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/MDCVRPTWView.Designer.cs	(revision 6854)
@@ -0,0 +1,31 @@
+﻿namespace HeuristicLab.Problems.VehicleRouting.Views {
+  partial class MDCVRPTWView {
+    /// <summary>
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary>
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Windows Form Designer generated code
+
+    /// <summary>
+    /// Required method for Designer support - do not modify
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      this.components = new System.ComponentModel.Container();
+    }
+
+    #endregion
+  }
+}
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/MDCVRPTWView.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/MDCVRPTWView.cs	(revision 6854)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/MDCVRPTWView.cs	(revision 6854)
@@ -0,0 +1,151 @@
+﻿using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using HeuristicLab.MainForm;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+using HeuristicLab.Data;
+
+namespace HeuristicLab.Problems.VehicleRouting.Views {
+  [View("MDCVRPTWProblemInstance View")]
+  [Content(typeof(MDCVRPTWProblemInstance), true)]
+  public partial class MDCVRPTWView : VRPProblemInstanceView {
+    public new MDCVRPTWProblemInstance Content {
+      get { return (MDCVRPTWProblemInstance)base.Content; }
+      set { base.Content = value; }
+    }
+
+    public MDCVRPTWView() {
+      InitializeComponent();
+    }
+
+    protected override void DrawVisualization(Bitmap bitmap) {
+      DoubleMatrix coordinates = Content.Coordinates;
+      DoubleMatrix distanceMatrix = Content.DistanceMatrix;
+      BoolValue useDistanceMatrix = Content.UseDistanceMatrix;
+      DoubleArray dueTime = Content.DueTime;
+      DoubleArray serviceTime = Content.ServiceTime;
+      DoubleArray readyTime = Content.ReadyTime;
+      IntArray vehicleAssignment = Content.VehicleDepotAssignment;
+
+      int depots = Content.Depots.Value;
+
+      Pen[] pens = {new Pen(Color.FromArgb(92,20,237)), new Pen(Color.FromArgb(237,183,20)), new Pen(Color.FromArgb(237,20,219)), new Pen(Color.FromArgb(20,237,76)),
+                    new Pen(Color.FromArgb(237,61,20)), new Pen(Color.FromArgb(115,78,26)), new Pen(Color.FromArgb(20,237,229)), new Pen(Color.FromArgb(39,101,19)),
+                    new Pen(Color.FromArgb(230,170,229)), new Pen(Color.FromArgb(142,136,89)), new Pen(Color.FromArgb(157,217,166)), new Pen(Color.FromArgb(31,19,101)),
+                    new Pen(Color.FromArgb(173,237,20)), new Pen(Color.FromArgb(230,231,161)), new Pen(Color.FromArgb(142,89,89)), new Pen(Color.FromArgb(93,89,142)),
+                    new Pen(Color.FromArgb(146,203,217)), new Pen(Color.FromArgb(101,19,75)), new Pen(Color.FromArgb(198,20,237)), new Pen(Color.FromArgb(185,185,185)),
+                    new Pen(Color.FromArgb(179,32,32)), new Pen(Color.FromArgb(18,119,115)), new Pen(Color.FromArgb(104,158,239)), new Pen(Color.Black)};
+
+      if ((coordinates != null) && (coordinates.Rows > 0) && (coordinates.Columns == 2)) {
+        double xMin = double.MaxValue, yMin = double.MaxValue, xMax = double.MinValue, yMax = double.MinValue;
+        for (int i = 0; i < coordinates.Rows; i++) {
+          if (xMin > coordinates[i, 0]) xMin = coordinates[i, 0];
+          if (yMin > coordinates[i, 1]) yMin = coordinates[i, 1];
+          if (xMax < coordinates[i, 0]) xMax = coordinates[i, 0];
+          if (yMax < coordinates[i, 1]) yMax = coordinates[i, 1];
+        }
+
+        int border = 20;
+        double xStep = xMax != xMin ? (bitmap.Width - 2 * border) / (xMax - xMin) : 1;
+        double yStep = yMax != yMin ? (bitmap.Height - 2 * border) / (yMax - yMin) : 1;
+
+        using (Graphics graphics = Graphics.FromImage(bitmap)) {
+          if (Solution != null) {
+            for (int i = 0; i < Content.Depots.Value; i++) {
+              Point locationPoint = new Point(border + ((int)((coordinates[i, 0] - xMin) * xStep)),
+                                bitmap.Height - (border + ((int)((coordinates[i, 1] - yMin) * yStep))));
+              graphics.FillEllipse(Brushes.Blue, locationPoint.X - 5, locationPoint.Y - 5, 10, 10);
+            }
+
+            int currentTour = 0;
+            foreach (Tour tour in Solution.GetTours()) {
+              int tourIndex = Solution.GetTourIndex(tour);
+              int vehicle = Solution.GetVehicleAssignment(tourIndex);
+              int depot = vehicleAssignment[vehicle];
+
+              double t = 0.0;
+              Point[] tourPoints = new Point[tour.Stops.Count + 2];
+              Brush[] customerBrushes = new Brush[tour.Stops.Count];
+              int lastCustomer = 0;
+
+              for (int i = -1; i <= tour.Stops.Count; i++) {
+                int location = 0;
+
+                if (i == -1 || i == tour.Stops.Count)
+                  location = 0; //depot
+                else
+                  location = tour.Stops[i];
+
+                Point locationPoint;
+                if (location == 0) {
+                  locationPoint = new Point(border + ((int)((Content.Coordinates[depot, 0] - xMin) * xStep)),
+                                  bitmap.Height - (border + ((int)((Content.Coordinates[depot, 1] - yMin) * yStep))));
+                } else {
+                  locationPoint = new Point(border + ((int)((Content.GetCoordinates(location)[0] - xMin) * xStep)),
+                                  bitmap.Height - (border + ((int)((Content.GetCoordinates(location)[1] - yMin) * yStep))));
+                }
+                tourPoints[i + 1] = locationPoint;
+
+                if (i != -1 && i != tour.Stops.Count) {
+                  Brush customerBrush = Brushes.Black;
+
+                  t += Content.GetDistance(
+                    lastCustomer, location, Solution);
+
+                  int locationIndex;
+                  if (location == 0)
+                    locationIndex = depot;
+                  else
+                    locationIndex = location + depots - 1;
+
+                  if (t < readyTime[locationIndex]) {
+                    t = readyTime[locationIndex];
+                    customerBrush = Brushes.Orange;
+                  } else if (t > dueTime[locationIndex]) {
+                    customerBrush = Brushes.Red;
+                  }
+
+                  t += serviceTime[location - 1];
+                  customerBrushes[i] = customerBrush;
+                }
+                lastCustomer = location;
+              }
+
+              graphics.DrawPolygon(pens[((currentTour >= pens.Length) ? (pens.Length - 1) : (currentTour))], tourPoints);
+
+              for (int i = 0; i < tour.Stops.Count; i++) {
+                graphics.FillRectangle(customerBrushes[i], tourPoints[i + 1].X - 3, tourPoints[i + 1].Y - 3, 6, 6);
+              }
+
+              graphics.FillEllipse(Brushes.DarkBlue, tourPoints[0].X - 5, tourPoints[0].Y - 5, 10, 10);
+
+              currentTour++;
+            }
+          } else {
+            Point locationPoint;
+            //just draw customers
+            for (int i = 1; i < coordinates.Rows; i++) {
+              locationPoint = new Point(border + ((int)((coordinates[i, 0] - xMin) * xStep)),
+                              bitmap.Height - (border + ((int)((coordinates[i, 1] - yMin) * yStep))));
+
+              graphics.FillRectangle(Brushes.Black, locationPoint.X - 3, locationPoint.Y - 3, 6, 6);
+            }
+
+            for (int i = 0; i < Content.Depots.Value; i++) {
+              locationPoint = new Point(border + ((int)((coordinates[i, 0] - xMin) * xStep)),
+                                bitmap.Height - (border + ((int)((coordinates[i, 1] - yMin) * yStep))));
+              graphics.FillEllipse(Brushes.Blue, locationPoint.X - 5, locationPoint.Y - 5, 10, 10);
+            }
+          }
+        }
+      }
+
+      for (int i = 0; i < pens.Length; i++)
+        pens[i].Dispose();
+    }
+  }
+}
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/ExtendedPotvin/Creators/PushForwardInsertionCreator.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/ExtendedPotvin/Creators/PushForwardInsertionCreator.cs	(revision 6853)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/ExtendedPotvin/Creators/PushForwardInsertionCreator.cs	(revision 6854)
@@ -182,5 +182,5 @@
             double dueTime = 0;
             if (problemInstance is ITimeWindowedProblemInstance)
-              dueTime = (problemInstance as ITimeWindowedProblemInstance).DueTime[i];
+              dueTime = (problemInstance as ITimeWindowedProblemInstance).DueTime[i + depots - 1];
 
             cost = -alpha * distance + // distance 0 <-> City[i]
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinCustomerRelocationManipulator.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinCustomerRelocationManipulator.cs	(revision 6853)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinCustomerRelocationManipulator.cs	(revision 6854)
@@ -146,14 +146,21 @@
           DoubleArray serviceTimes = vrptw.ServiceTime;
 
+          int depot = 0;
+          int depots = 1;
+
+          int tourIndex = individual.GetTourIndex(route1);
+          int vehicle = individual.GetVehicleAssignment(tourIndex);
+
+          if (ProblemInstance is IMultiDepotProblemInstance) {
+            depots = (ProblemInstance as IMultiDepotProblemInstance).Depots.Value;
+            depot = (ProblemInstance as IMultiDepotProblemInstance).VehicleDepotAssignment[vehicle];
+          }
+
           List<int> timeWindowViolations = new List<int>();
           double time = 0;
 
           for (int i = 0; i < route1.Stops.Count; i++) {
-            int start = 0;
-            if (i > 0)
-              start = route1.Stops[i - 1];
-            int end = 0;
-            if (i < route1.Stops.Count)
-              end = route1.Stops[i];
+            int start = route1.Stops[i - 1];
+            int end = route1.Stops[i];
 
             //drive there
@@ -161,6 +168,8 @@
             time += currentDistace;
 
+            int endIndex = end + depots - 1;
+
             //check if it was serviced on time
-            if (time > dueTime[end]) {
+            if (time > dueTime[endIndex]) {
               timeWindowViolations.Add(end);
             }
@@ -168,10 +177,10 @@
             //wait
             double currentWaitingTime = 0.0;
-            if (time < readyTime[end])
-              currentWaitingTime = readyTime[end] - time;
+            if (time < readyTime[endIndex])
+              currentWaitingTime = readyTime[endIndex] - time;
             time += currentWaitingTime;
 
             //service
-            double currentServiceTime = serviceTimes[end];
+            double currentServiceTime = serviceTimes[end - 1];
             time += currentServiceTime;
           }
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/HeuristicLab.Problems.VehicleRouting-3.4.csproj
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/HeuristicLab.Problems.VehicleRouting-3.4.csproj	(revision 6853)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/HeuristicLab.Problems.VehicleRouting-3.4.csproj	(revision 6854)
@@ -301,4 +301,6 @@
     <Compile Include="ProblemInstances\MultiDepotVRP\MDCVRP\MDCVRPEvaluator.cs" />
     <Compile Include="ProblemInstances\MultiDepotVRP\MDCVRP\MDCVRPProblemInstance.cs" />
+    <Compile Include="ProblemInstances\MultiDepotVRP\MDCVRP\MDCVRPTW\MDCVRPTWEvaluator.cs" />
+    <Compile Include="ProblemInstances\MultiDepotVRP\MDCVRP\MDCVRPTW\MDCVRPTWProblemInstance.cs" />
     <Compile Include="ProblemInstances\MultiDepotVRP\MultiDepotVRPProblemInstance.cs" />
     <Compile Include="ProblemInstances\MultiDepotVRP\MultiDepotVRPEvaluator.cs" />
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPProblemInstance.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPProblemInstance.cs	(revision 6853)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPProblemInstance.cs	(revision 6854)
@@ -51,5 +51,5 @@
     double GetDemand(int city);
     double GetDistance(int start, int end, IVRPEncoding solution);
-    double GetInsertionDistance(int start, int customer, int end, IVRPEncoding solution);
+    double GetInsertionDistance(int start, int customer, int end, IVRPEncoding solution, out double startDistance, out double endDistance);
     bool Feasible(IVRPEncoding solution);
     bool TourFeasible(Tour tour, IVRPEncoding solution);
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/Parsers/CordeauParser.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/Parsers/CordeauParser.cs	(revision 6853)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/Parsers/CordeauParser.cs	(revision 6854)
@@ -132,4 +132,5 @@
         throw new InvalidDataException("File has wrong format!");
 
+      bool timeWindows = int.Parse(m[0].Value) == 6;
       vehicles = int.Parse(m[3].Value);
       line = reader.ReadLine();
@@ -146,14 +147,35 @@
       List<double> depotXcoord = new List<double>();
       List<double> depotYcoord = new List<double>();
+      List<double> depotReadyTime = new List<double>();
+      List<double> depotDueTime = new List<double>();
+
       while ((line != null)) {
         m = reg.Matches(line);
 
-        if (m.Count == 11) {
+        if (m.Count >= 11) {
           xCoord.Add(double.Parse(m[1].Value, System.Globalization.CultureInfo.InvariantCulture));
           yCoord.Add(double.Parse(m[2].Value, System.Globalization.CultureInfo.InvariantCulture));
           demand.Add((double)int.Parse(m[4].Value, System.Globalization.CultureInfo.InvariantCulture));
-        } else if (m.Count == 7) {
+
+          if (timeWindows) {
+            serviceTime.Add(int.Parse(m[3].Value));
+            readyTime.Add(int.Parse(m[m.Count - 2].Value));
+            dueTime.Add(int.Parse(m[m.Count - 1].Value));
+          } else {
+            serviceTime.Add(0);
+            readyTime.Add(0);
+            dueTime.Add(double.MaxValue);
+          }
+        } else if (m.Count >= 7) {
           depotXcoord.Add(double.Parse(m[1].Value, System.Globalization.CultureInfo.InvariantCulture));
           depotYcoord.Add(double.Parse(m[2].Value, System.Globalization.CultureInfo.InvariantCulture));
+
+          if (timeWindows) {
+            depotReadyTime.Add(int.Parse(m[m.Count - 2].Value));
+            depotDueTime.Add(int.Parse(m[m.Count - 1].Value));
+          } else {
+            depotReadyTime.Add(0);
+            depotDueTime.Add(double.MaxValue);
+          }
         }
                
@@ -163,4 +185,6 @@
       xCoord.InsertRange(0, depotXcoord);
       yCoord.InsertRange(0, depotYcoord);
+      readyTime.InsertRange(0, depotReadyTime);
+      dueTime.InsertRange(0, depotDueTime);
 
       cities = demand.Count;
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPEvaluator.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPEvaluator.cs	(revision 6853)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPEvaluator.cs	(revision 6854)
@@ -111,5 +111,6 @@
       double overloadPenalty = cvrp.OverloadPenalty.Value;
 
-      costs += instance.GetInsertionDistance(insertionInfo.Start, customer, insertionInfo.End, solution);
+      double startDistance, endDistance;
+      costs += instance.GetInsertionDistance(insertionInfo.Start, customer, insertionInfo.End, solution, out startDistance, out endDistance);
 
       double demand = instance.GetDemand(customer);
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPTW/MDCVRPTWEvaluator.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPTW/MDCVRPTWEvaluator.cs	(revision 6854)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPTW/MDCVRPTWEvaluator.cs	(revision 6854)
@@ -0,0 +1,290 @@
+﻿#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;
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  [Item("MDCVRPTWEvaluator", "Represents a multi depot CVRPTW evaluator.")]
+  [StorableClass]
+  public class MDCVRPTWEvaluator: MDCVRPEvaluator {
+    public ILookupParameter<DoubleValue> TardinessParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Tardiness"]; }
+    }
+
+    public ILookupParameter<DoubleValue> TravelTimeParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["TravelTime"]; }
+    }
+
+    protected override VRPEvaluation CreateTourEvaluation() {
+      return new CVRPTWEvaluation();
+    }
+
+    protected override void EvaluateTour(VRPEvaluation eval, IVRPProblemInstance instance, Tour tour, IVRPEncoding solution) {
+      TourInsertionInfo tourInfo = new TourInsertionInfo();
+      eval.InsertionInfo.AddTourInsertionInfo(tourInfo);
+
+      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;
+
+      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 delivered = 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];
+      for (int i = 0; i < tour.Stops.Count; i++) {
+        delivered += instance.GetDemand(tour.Stops[i]);
+      }
+
+      double spareCapacity = capacity - delivered;
+
+      //simulate a tour, start and end at depot
+      for (int i = 0; i <= tour.Stops.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];
+
+        //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;
+
+        //service
+        double currentServiceTime = 0;
+        if(end > 0)
+          currentServiceTime = serviceTimes[end - 1];
+        serviceTime += currentServiceTime;
+        time += currentServiceTime;
+
+        CVRPTWInsertionInfo stopInfo = new CVRPTWInsertionInfo(start, end, spareCapacity, arrivalTime, time, spareTime, waitTime);
+        tourInfo.AddStopInsertionInfo(stopInfo);
+      }
+
+      eval.Quality += instance.FleetUsageFactor.Value;
+      eval.Quality += instance.DistanceFactor.Value * distance;
+      eval.Distance += distance;
+      eval.VehicleUtilization += 1;
+
+      if (delivered > capacity) {
+        overweight = delivered - capacity;
+      }
+
+      (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.Quality += time * vrptw.TimeFactor.Value;
+      tourInfo.Penalty = tourPenalty;
+    }
+
+    protected override double GetTourInsertionCosts(IVRPProblemInstance instance, IVRPEncoding solution, TourInsertionInfo tourInsertionInfo, int index, int customer,
+      out bool feasible) {
+      CVRPTWInsertionInfo insertionInfo = tourInsertionInfo.GetStopInsertionInfo(index) as CVRPTWInsertionInfo;
+
+      double costs = 0;
+      feasible = tourInsertionInfo.Penalty < double.Epsilon;
+
+      ICapacitatedProblemInstance cvrp = instance as ICapacitatedProblemInstance;
+      double overloadPenalty = cvrp.OverloadPenalty.Value;
+
+      ITimeWindowedProblemInstance vrptw = instance as ITimeWindowedProblemInstance;
+      DoubleArray dueTime = vrptw.DueTime;
+      DoubleArray readyTime = vrptw.ReadyTime;
+      DoubleArray serviceTimes = vrptw.ServiceTime;
+      double tardinessPenalty = vrptw.TardinessPenalty.Value;
+
+      IMultiDepotProblemInstance mdp = instance as IMultiDepotProblemInstance;
+      int depots = mdp.Depots.Value;
+
+      double startDistance, endDistance;
+      costs += instance.GetInsertionDistance(insertionInfo.Start, customer, insertionInfo.End, solution, out startDistance, out endDistance);
+
+      double demand = instance.GetDemand(customer);
+      if (demand > insertionInfo.SpareCapacity) {
+        feasible = false;
+
+        if(insertionInfo.SpareCapacity >= 0)
+          costs += (demand - insertionInfo.SpareCapacity) * overloadPenalty;
+        else
+          costs += demand * overloadPenalty;
+      }
+
+      double time = 0;
+      double tardiness = 0;
+
+      if (index > 0)
+        time = (tourInsertionInfo.GetStopInsertionInfo(index - 1) as CVRPTWInsertionInfo).LeaveTime;
+      time += startDistance;
+
+      int customerIndex = customer + depots - 1;
+
+      if (time > dueTime[customerIndex]) {
+        tardiness += time - dueTime[customerIndex];
+      }
+      if (time < readyTime[customerIndex])
+        time += readyTime[customerIndex] - time;
+      time += serviceTimes[customer - 1];
+      time += endDistance;
+
+      double additionalTime = time - (tourInsertionInfo.GetStopInsertionInfo(index) as CVRPTWInsertionInfo).ArrivalTime;
+      for (int i = index; i < tourInsertionInfo.GetStopCount(); i++) {
+        CVRPTWInsertionInfo nextStop = tourInsertionInfo.GetStopInsertionInfo(i) as CVRPTWInsertionInfo;
+
+        if (additionalTime < 0) {
+          //arrive earlier than before
+          //wait probably
+          if (nextStop.WaitingTime < 0) {
+            double wait = nextStop.WaitingTime - additionalTime;
+            if (wait > 0)
+              additionalTime += wait;
+          } else {
+            additionalTime = 0;
+          }
+
+          //check due date, decrease tardiness
+          if (nextStop.SpareTime < 0) {
+            costs += Math.Max(nextStop.SpareTime, additionalTime) * tardinessPenalty;
+          }
+        } else {
+          //arrive later than before, probably don't have to wait
+          if (nextStop.WaitingTime > 0) {
+            additionalTime -= Math.Min(additionalTime, nextStop.WaitingTime);            
+          }
+
+          //check due date
+          if (nextStop.SpareTime > 0) {
+            double spare = nextStop.SpareTime - additionalTime;
+            if (spare < 0)
+              tardiness += -spare; 
+          } else {
+            tardiness += additionalTime;
+          }
+        }
+      }
+
+      costs += additionalTime * vrptw.TimeFactor.Value;
+
+      if (tardiness > 0) {
+        feasible = false;
+      }
+
+      costs += tardiness * tardinessPenalty;
+
+      return costs;
+    }
+
+    protected override void InitResultParameters() {
+      base.InitResultParameters();
+
+      TardinessParameter.ActualValue = new DoubleValue(0);
+      TravelTimeParameter.ActualValue = new DoubleValue(0);
+    }
+
+    protected override void SetResultParameters(VRPEvaluation tourEvaluation) {
+      base.SetResultParameters(tourEvaluation);
+
+      TardinessParameter.ActualValue.Value = (tourEvaluation as CVRPTWEvaluation).Tardiness;
+      TravelTimeParameter.ActualValue.Value = (tourEvaluation as CVRPTWEvaluation).TravelTime;
+    }
+    
+    [StorableConstructor]
+    protected MDCVRPTWEvaluator(bool deserializing) : base(deserializing) { }
+
+    public MDCVRPTWEvaluator() {
+      Parameters.Add(new LookupParameter<DoubleValue>("Tardiness", "The tardiness."));
+      Parameters.Add(new LookupParameter<DoubleValue>("TravelTime", "The travel time."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MDCVRPTWEvaluator(this, cloner);
+    }
+
+    protected MDCVRPTWEvaluator(MDCVRPTWEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPTW/MDCVRPTWProblemInstance.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPTW/MDCVRPTWProblemInstance.cs	(revision 6854)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPTW/MDCVRPTWProblemInstance.cs	(revision 6854)
@@ -0,0 +1,164 @@
+﻿#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.Common;
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  [Item("MDCVRPTWProblemInstance", "Represents a multi depot CVRPTW instance.")]
+  [StorableClass]
+  public class MDCVRPTWProblemInstance: MDCVRPProblemInstance, ITimeWindowedProblemInstance {
+    protected IValueParameter<DoubleArray> ReadyTimeParameter {
+      get { return (IValueParameter<DoubleArray>)Parameters["ReadyTime"]; }
+    }
+    protected IValueParameter<DoubleArray> DueTimeParameter {
+      get { return (IValueParameter<DoubleArray>)Parameters["DueTime"]; }
+    }
+    protected IValueParameter<DoubleArray> ServiceTimeParameter {
+      get { return (IValueParameter<DoubleArray>)Parameters["ServiceTime"]; }
+    }
+
+    protected IValueParameter<DoubleValue> TimeFactorParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["EvalTimeFactor"]; }
+    }
+    protected IValueParameter<DoubleValue> TardinessPenaltyParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["EvalTardinessPenalty"]; }
+    }
+
+    public DoubleArray ReadyTime {
+      get { return ReadyTimeParameter.Value; }
+      set { ReadyTimeParameter.Value = value; }
+    }
+    public DoubleArray DueTime {
+      get { return DueTimeParameter.Value; }
+      set { DueTimeParameter.Value = value; }
+    }
+    public DoubleArray ServiceTime {
+      get { return ServiceTimeParameter.Value; }
+      set { ServiceTimeParameter.Value = value; }
+    }
+    public DoubleValue TimeFactor {
+      get { return TimeFactorParameter.Value; }
+      set { TimeFactorParameter.Value = value; }
+    }
+
+    [Storable]
+    private DoubleValue currentTardinessPenalty;
+
+    public DoubleValue TardinessPenalty {
+      get {
+        if (currentTardinessPenalty != null)
+          return currentTardinessPenalty;
+        else
+          return TardinessPenaltyParameter.Value;
+      }
+      set { currentTardinessPenalty = value; }
+    }
+
+    protected override IEnumerable<IOperator> GetOperators() {
+      return base.GetOperators()
+        .Where(o => o is ITimeWindowedOperator).Cast<IOperator>();
+    }
+
+    protected override IEnumerable<IOperator> GetAnalyzers() {
+      return ApplicationManager.Manager.GetInstances<ITimeWindowedOperator>()
+        .Where(o => o is IAnalyzer)
+        .Cast<IOperator>().Union(base.GetAnalyzers());
+    }
+    
+    protected override IVRPEvaluator Evaluator {
+      get {
+        return new MDCVRPTWEvaluator();
+      }
+    }
+    
+    [StorableConstructor]
+    protected MDCVRPTWProblemInstance(bool deserializing) : base(deserializing) { }
+
+    public MDCVRPTWProblemInstance() {
+      Parameters.Add(new ValueParameter<DoubleArray>("ReadyTime", "The ready time of each customer.", new DoubleArray()));
+      Parameters.Add(new ValueParameter<DoubleArray>("DueTime", "The due time of each customer.", new DoubleArray()));
+      Parameters.Add(new ValueParameter<DoubleArray>("ServiceTime", "The service time of each customer.", new DoubleArray()));
+
+      Parameters.Add(new ValueParameter<DoubleValue>("EvalTimeFactor", "The time factor considered in the evaluation.", new DoubleValue(0)));
+      Parameters.Add(new ValueParameter<DoubleValue>("EvalTardinessPenalty", "The tardiness penalty considered in the evaluation.", new DoubleValue(100)));
+
+      AttachEventHandlers();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MDCVRPTWProblemInstance(this, cloner);
+    }
+
+    protected MDCVRPTWProblemInstance(MDCVRPTWProblemInstance original, Cloner cloner)
+      : base(original, cloner) {
+        currentTardinessPenalty = cloner.Clone(original.currentTardinessPenalty) as DoubleValue;
+
+        AttachEventHandlers();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserializationHook() {
+      AttachEventHandlers();
+    }
+
+    private void AttachEventHandlers() {
+      TardinessPenaltyParameter.ValueChanged += new EventHandler(TardinessPenaltyParameter_ValueChanged);
+      TardinessPenaltyParameter.Value.ValueChanged += new EventHandler(TardinessPenalty_ValueChanged);
+      TimeFactorParameter.ValueChanged += new EventHandler(TimeFactorParameter_ValueChanged);
+      TimeFactorParameter.Value.ValueChanged += new EventHandler(TimeFactor_ValueChanged);
+    }
+
+    public override void InitializeState() {
+      base.InitializeState();
+
+      currentTardinessPenalty = null;
+    }
+
+    #region Event handlers
+    void TardinessPenaltyParameter_ValueChanged(object sender, EventArgs e) {
+      TardinessPenaltyParameter.Value.ValueChanged += new EventHandler(TardinessPenalty_ValueChanged);
+      EvalBestKnownSolution();
+    }
+    void TardinessPenalty_ValueChanged(object sender, EventArgs e) {
+      EvalBestKnownSolution();
+    }
+    void TimeFactorParameter_ValueChanged(object sender, EventArgs e) {
+      TimeFactorParameter.Value.ValueChanged += new EventHandler(TimeFactor_ValueChanged);
+      EvalBestKnownSolution();
+    }
+    void TimeFactor_ValueChanged(object sender, EventArgs e) {
+      EvalBestKnownSolution();
+    }
+    #endregion
+  }
+}
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MultiDepotVRPEvaluator.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MultiDepotVRPEvaluator.cs	(revision 6853)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MultiDepotVRPEvaluator.cs	(revision 6854)
@@ -81,6 +81,7 @@
       double costs = 0;
       feasible = true;
+      double startDistance, endDistance;
 
-      costs += instance.GetInsertionDistance(insertionInfo.Start, customer, insertionInfo.End, solution);
+      costs += instance.GetInsertionDistance(insertionInfo.Start, customer, insertionInfo.End, solution, out startDistance, out endDistance);
 
       return costs;
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MultiDepotVRPProblemInstance.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MultiDepotVRPProblemInstance.cs	(revision 6853)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MultiDepotVRPProblemInstance.cs	(revision 6854)
@@ -150,5 +150,6 @@
     }
 
-    public override double GetInsertionDistance(int start, int customer, int end, IVRPEncoding solution) {
+    public override double GetInsertionDistance(int start, int customer, int end, IVRPEncoding solution, 
+      out double startDistance, out double endDistance) {
       if (start == 0) {
         start = GetDepot(end, solution);
@@ -164,7 +165,9 @@
       
       double distance = base.GetDistance(start, end, solution);
-      double newDistance =
-        base.GetDistance(start, customer, solution) +
-        base.GetDistance(customer, end, solution);
+
+      startDistance = base.GetDistance(start, customer, solution);
+      endDistance = base.GetDistance(customer, end, solution);
+
+      double newDistance = startDistance + endDistance;
 
       return newDistance - distance;
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/VRPProblemInstance.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/VRPProblemInstance.cs	(revision 6853)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/VRPProblemInstance.cs	(revision 6854)
@@ -220,9 +220,12 @@
     }
 
-    public virtual double GetInsertionDistance(int start, int customer, int end, IVRPEncoding solution) {
+    public virtual double GetInsertionDistance(int start, int customer, int end, IVRPEncoding solution,
+      out double startDistance, out double endDistance) {
       double distance = GetDistance(start, end, solution);
-      double newDistance =
-        GetDistance(start, customer, solution) +
-        GetDistance(customer, end, solution);
+
+      startDistance = GetDistance(start, customer, solution);
+      endDistance = GetDistance(customer, end, solution);
+      
+      double newDistance = startDistance + endDistance;
 
       return newDistance - distance;
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/VehicleRoutingProblem.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/VehicleRoutingProblem.cs	(revision 6853)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/VehicleRoutingProblem.cs	(revision 6854)
@@ -247,5 +247,5 @@
       parser.Parse();
 
-      MDCVRPProblemInstance problem = new MDCVRPProblemInstance();
+      MDCVRPTWProblemInstance problem = new MDCVRPTWProblemInstance();
 
       problem.Coordinates = new DoubleMatrix(parser.Coordinates);
@@ -255,4 +255,8 @@
       problem.Depots.Value = parser.Depots;
       problem.VehicleDepotAssignment = new IntArray(parser.Vehicles);
+      problem.ReadyTime = new DoubleArray(parser.Readytimes);
+      problem.ServiceTime = new DoubleArray(parser.Servicetimes);
+      problem.DueTime = new DoubleArray(parser.Duetimes);
+
       int depot = 0;
       int i = 0;
