Index: /branches/DynamicVehicleRouting/Build.cmd
===================================================================
--- /branches/DynamicVehicleRouting/Build.cmd	(revision 8670)
+++ /branches/DynamicVehicleRouting/Build.cmd	(revision 8670)
@@ -0,0 +1,94 @@
+@ECHO OFF
+
+SET CLEANBEFOREBUILD=1
+
+SET SELECTED=
+SET CONFIGURATION=
+SET PLATFORM=
+
+IF "%~1"=="" GOTO :prompt_solution
+
+SET SELECTED=%1
+IF NOT EXIST %SELECTED% (
+  ECHO Solution file %SELECTED% could not be found.
+  GOTO :end
+)
+ECHO Building solution %SELECTED% ...
+GOTO :config_selection
+
+:prompt_solution
+SET /A COUNT=0
+FOR /F "tokens=*" %%A IN ('dir /B *.sln') DO (
+  CALL :forloopbody "%%A"
+)
+
+IF "%COUNT%"=="1" (
+  SET SELECTED=%SOLUTIONS.1%
+  ECHO Building %SOLUTIONS.1% as it is the only solution that was found ...
+  GOTO :config_selection
+)
+
+ECHO Found the following solutions:
+FOR /F "tokens=2* delims=.=" %%A IN ('SET SOLUTIONS.') DO ECHO %%A = %%B
+ECHO.
+SET /P SOLUTIONINDEX=Which solution to build? Type the number: 
+
+SET SELECTED=""
+FOR /F "tokens=2* delims=.=" %%A IN ('SET SOLUTIONS.') DO (
+  IF "%%A"=="%SOLUTIONINDEX%" SET SELECTED=%%B
+)
+
+IF %SELECTED%=="" GOTO :eof
+
+:config_selection
+IF "%~2"==""  GOTO :prompt_config
+
+SET CONFIGURATION=%~2
+ECHO Building configuration %CONFIGURATION% ...
+GOTO :platform_selection
+
+:prompt_config
+SET /P CONFIGURATION=Which configuration to build [Debug]: 
+IF "%CONFIGURATION%"=="" SET CONFIGURATION=Debug
+
+:platform_selection
+IF "%~3"=="" GOTO :prompt_platform
+  
+SET PLATFORM=%~3
+ECHO Building platform %PLATFORM% ...
+GOTO :main
+
+:prompt_platform
+SET /P PLATFORM=Which platform to build [Any CPU]: 
+IF "%PLATFORM%"=="" SET PLATFORM=Any CPU
+
+:main
+REM First find the path to the msbuild.exe by performing a registry query
+FOR /F "tokens=1,3 delims=	 " %%A IN ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\4.0"') DO (
+  IF "%%A"=="MSBuildToolsPath" SET MSBUILDPATH=%%B)
+
+REM Then execute msbuild to clean and build the solution
+REM Disable that msbuild creates a cache file of the solution
+SET MSBuildUseNoSolutionCache=1
+REM Run msbuild to clean and then build
+IF "%CLEANBEFOREBUILD%"=="1" (
+  ECHO Cleaning ...
+  %MSBUILDPATH%msbuild.exe %SELECTED% /target:Clean /p:Configuration="%CONFIGURATION%",Platform="%PLATFORM%" /m:2 /nologo /verbosity:q /clp:ErrorsOnly
+)
+ECHO Building ...
+%MSBUILDPATH%msbuild.exe %SELECTED% /target:Build /p:Configuration="%CONFIGURATION%",Platform="%PLATFORM%" /m:2 /nologo /verbosity:q /clp:ErrorsOnly
+
+ECHO.
+ECHO DONE.
+
+:end
+
+PAUSE
+
+GOTO :eof
+
+REM This workaround is necessary so that COUNT gets reevaluated
+:forloopbody
+SET /A COUNT+=1
+SET SOLUTIONS.%COUNT%=%1
+GOTO :eof
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/DynPDPView.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/DynPDPView.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/DynPDPView.cs	(revision 8670)
@@ -0,0 +1,228 @@
+﻿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;
+using HeuristicLab.Problems.VehicleRouting.Views;
+using HeuristicLab.Problems.VehicleRouting;
+using HeuristicLab.PDPSimulation.Operators;
+
+namespace HeuristicLab.PDPSimulation.Views {
+  [View("DynPDP View")]
+  [Content(typeof(DynPDPProblemInstance), true)]
+  public partial class DynPDPView : VRPProblemInstanceView {
+    public new DynPDPProblemInstance Content {
+      get { return (DynPDPProblemInstance)base.Content; }
+      set { base.Content = value; }
+    }
+
+    public DynPDPView() {
+      InitializeComponent();
+    }
+
+    private bool drawFlow = false;
+
+    protected override void pictureBox_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e) {
+      if (e.Button == System.Windows.Forms.MouseButtons.Right) {
+        drawFlow = !drawFlow;
+        GenerateImage();
+      }      
+    }
+
+    protected override void DrawVisualization(Bitmap bitmap) {
+      DoubleMatrix coordinates = Content.Coordinates;
+      DoubleMatrix depotCoordinates = Content.DepotCoordinates;
+      DoubleMatrix distanceMatrix = Content.DistanceMatrix;
+      BoolValue useDistanceMatrix = Content.UseDistanceMatrix;
+      DoubleArray dueTime = Content.DueTime;
+      DoubleArray serviceTime = Content.ServiceTime;
+      DoubleArray readyTime = Content.ReadyTime;
+      DoubleArray demand = Content.Demand;
+      IntArray pickupDeliveryLocation = Content.PickupDeliveryLocation;
+      IntArray vehicleAssignment = Content.VehicleDepotAssignment;
+      WaitingStrategy waitingStrategy = Content.WaitingStrategy;
+
+      int depots = Content.Depots.Value;
+      int cities = Content.Cities.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)};
+
+      Pen flowPen = new Pen(Brushes.Red, 3);
+      flowPen.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
+      flowPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
+
+      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 && !Solution.GetTours().Exists(t => t.Stops.Exists(s => s > Content.Coordinates.Rows - Content.DepotCoordinates.Rows))) {
+            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];
+              Pen[] customerPens = new Pen[tour.Stops.Count];
+              bool[] validPickupDelivery = new bool[tour.Stops.Count];
+              int lastCustomer = 0;
+
+              Dictionary<int, bool> stops = new Dictionary<int, bool>();
+              for (int i = -1; i <= tour.Stops.Count; i++) {
+                int location = 0;
+
+                if (i == -1)
+                  location = -1; //depot
+                else if (i == tour.Stops.Count)
+                  location = 0; //depot
+                else
+                  location = tour.Stops[i];
+
+                Point locationPoint;
+                if (location == -1) {
+                  locationPoint = new Point(border + ((int)((coordinates[depot, 0] - xMin) * xStep)),
+                                  bitmap.Height - (border + ((int)((coordinates[depot, 1] - yMin) * yStep))));
+                  location = 0;
+                } else if (location == 0) {
+                  locationPoint = new Point(border + ((int)((depotCoordinates[depot, 0] - xMin) * xStep)),
+                                  bitmap.Height - (border + ((int)((depotCoordinates[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) {
+                  t = readyTime[depot];
+                }
+                else if (i != tour.Stops.Count) {
+                  Brush customerBrush = Brushes.Black;
+                  Pen customerPen = Pens.Black;
+
+                  t += waitingStrategy.GetWaitingTime(t, Content, Solution, tour, i); 
+
+                  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;
+                    customerPen = Pens.Orange;
+
+                  } else if (t > dueTime[locationIndex]) {
+                    customerBrush = Brushes.Red;
+                    customerPen = Pens.Red;
+                  }
+
+                  t += serviceTime[location - 1];
+
+                  validPickupDelivery[i] =
+                    ((demand[location - 1] >= 0) ||
+                     (stops.ContainsKey(pickupDeliveryLocation[location - 1])));
+
+                  customerBrushes[i] = customerBrush;
+                  customerPens[i] = customerPen;
+
+                  stops.Add(location, true);
+                }
+                lastCustomer = location;
+              }
+
+              if (!drawFlow) {
+                Pen pen = pens[((currentTour >= pens.Length) ? (pens.Length - 1) : (currentTour))];
+                for (int i = 1; i < tourPoints.Length; i++) {
+                  Point start = tourPoints[i - 1];
+                  Point end = tourPoints[i];
+
+                  graphics.DrawLine(pen, start, end);
+                }
+              }
+
+              for (int i = 0; i < tour.Stops.Count; i++) {
+                if (validPickupDelivery[i]) {
+                  graphics.FillRectangle(customerBrushes[i], tourPoints[i + 1].X - 3, tourPoints[i + 1].Y - 3, 6, 6);
+
+                  if (demand[tour.Stops[i] - 1] < 0 && drawFlow) {
+                    int location = pickupDeliveryLocation[tour.Stops[i] - 1];
+                    int source = tour.Stops.IndexOf(location);
+
+                    graphics.DrawLine(flowPen, tourPoints[source + 1], tourPoints[i + 1]);
+                  }
+                } else
+                  graphics.DrawRectangle(customerPens[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[] locationPoints = new Point[cities];
+              //just draw customers
+              for (int i = 0; i < cities; i++) {
+                locationPoints[i] = new Point(border + ((int)((Content.GetCoordinates(i + 1)[0] - xMin) * xStep)),
+                                bitmap.Height - (border + ((int)((Content.GetCoordinates(i + 1)[1] - yMin) * yStep))));
+
+                graphics.FillRectangle(Brushes.Black, locationPoints[i].X - 3, locationPoints[i].Y - 3, 6, 6);
+              }
+
+              if (drawFlow) {
+                for (int i = 0; i < cities; i++) {
+                  if (demand[i] < 0) {
+                    graphics.DrawLine(flowPen, locationPoints[pickupDeliveryLocation[i] - 1], locationPoints[i]);
+                  }
+                }
+              }
+
+              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);
+              }
+            }
+          }
+        }
+      }
+
+      for (int i = 0; i < pens.Length; i++)
+        pens[i].Dispose();
+
+      flowPen.Dispose();
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/DynPDPView.designer.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/DynPDPView.designer.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/DynPDPView.designer.cs	(revision 8670)
@@ -0,0 +1,31 @@
+﻿namespace HeuristicLab.PDPSimulation.Views {
+  partial class DynPDPView {
+    /// <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/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/HeuristicLab.PDPSimulation.Views-3.3.csproj
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/HeuristicLab.PDPSimulation.Views-3.3.csproj	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/HeuristicLab.PDPSimulation.Views-3.3.csproj	(revision 8670)
@@ -0,0 +1,248 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{08FBD39B-C785-4199-BA39-A7AB87E364C6}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.PDPSimulation.Views</RootNamespace>
+    <AssemblyName>HeuristicLab.PDPSimulation.Views-3.3</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\..\..\..\trunk\sources\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>..\..\..\..\trunk\sources\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x64\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\HeuristicLab.PDPSimulation.Views-3.3.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+    <OutputPath>bin\x64\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Release\HeuristicLab.PDPSimulation.Views-3.3.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x86\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\HeuristicLab.PDPSimulation.Views-3.3.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+    <OutputPath>bin\x86\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Release\HeuristicLab.PDPSimulation.Views-3.3.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="HeuristicLab.Analysis-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\bin\HeuristicLab.Analysis-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Collections-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\bin\HeuristicLab.Collections-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Common-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\bin\HeuristicLab.Common-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Common.Resources-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL" />
+    <Reference Include="HeuristicLab.Core-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\bin\HeuristicLab.Core-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Core.Views-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\bin\HeuristicLab.Core.Views-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Data-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\bin\HeuristicLab.Data-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.MainForm-3.3">
+      <HintPath>..\..\bin\HeuristicLab.MainForm-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.MainForm.WindowsForms-3.3">
+      <HintPath>..\..\bin\HeuristicLab.MainForm.WindowsForms-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Optimization-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\bin\HeuristicLab.Optimization-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Optimization.Views-3.3">
+      <HintPath>..\..\bin\HeuristicLab.Optimization.Views-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Parameters-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\bin\HeuristicLab.Parameters-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Persistence-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL" />
+    <Reference Include="HeuristicLab.PluginInfrastructure-3.3">
+      <HintPath>..\..\bin\HeuristicLab.PluginInfrastructure-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Problems.VehicleRouting-3.4, Version=3.4.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\bin\HeuristicLab.Problems.VehicleRouting-3.4.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Problems.VehicleRouting.Views-3.4">
+      <HintPath>..\..\bin\HeuristicLab.Problems.VehicleRouting.Views-3.4.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Data.SQLite, Version=1.0.65.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=AMD64">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\ExternalLibs\System.Data.SQLite.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Plugin.cs" />
+    <Compile Include="VehicleHistoryView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="VehicleHistoryView.Designer.cs">
+      <DependentUpon>VehicleHistoryView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="DynPDPView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="DynPDPView.designer.cs">
+      <DependentUpon>DynPDPView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="PickupDeliveryScenarioView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="PickupDeliveryScenarioView.Designer.cs">
+      <DependentUpon>PickupDeliveryScenarioView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="PickupDeliveryVisualizationView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="PickupDeliveryVisualizationView.Designer.cs">
+      <DependentUpon>PickupDeliveryVisualizationView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Resources.Designer.cs">
+      <DependentUpon>Resources.resx</DependentUpon>
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="HeuristicLab.snk" />
+    <None Include="Plugin.cs.frame" />
+    <None Include="Properties\AssemblyInfo.frame" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.PDPSimulation\3.3\HeuristicLab.PDPSimulation-3.3.csproj">
+      <Project>{F8815280-FA2D-4B3B-B3FD-242863ADB4FF}</Project>
+      <Name>HeuristicLab.PDPSimulation-3.3</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\depot.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\source.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\target.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\truck.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="Resources\truck_idle.png" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PreBuildEvent>set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+set ProjectDir=$(ProjectDir)
+set SolutionDir=$(SolutionDir)
+set Outdir=$(Outdir)
+
+call PreBuildEvent.cmd</PreBuildEvent>
+  </PropertyGroup>
+  <PropertyGroup>
+    <PostBuildEvent>
+    </PostBuildEvent>
+  </PropertyGroup>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/PickupDeliveryScenarioView.Designer.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/PickupDeliveryScenarioView.Designer.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/PickupDeliveryScenarioView.Designer.cs	(revision 8670)
@@ -0,0 +1,69 @@
+﻿namespace HeuristicLab.PDPSimulation.Views {
+  partial class PickupDeliveryScenarioView {
+    /// <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 Component 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.importButton = new System.Windows.Forms.Button();
+      this.SuspendLayout();
+      // 
+      // importButton
+      // 
+      this.importButton.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.importButton.Location = new System.Drawing.Point(0, 26);
+      this.importButton.Name = "importButton";
+      this.importButton.Size = new System.Drawing.Size(529, 23);
+      this.importButton.TabIndex = 3;
+      this.importButton.Text = "&Import";
+      this.importButton.UseVisualStyleBackColor = true;
+      this.importButton.Click += new System.EventHandler(this.importButton_Click);
+      // 
+      // parameterCollectionView
+      // 
+      this.parameterCollectionView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                  | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.parameterCollectionView.Caption = "ParameterCollection View";
+      this.parameterCollectionView.Content = null;
+      this.parameterCollectionView.Location = new System.Drawing.Point(6, 50);
+      this.parameterCollectionView.Name = "parameterCollectionView";
+      this.parameterCollectionView.ReadOnly = false;
+      this.parameterCollectionView.Size = new System.Drawing.Size(509, 303);
+      this.parameterCollectionView.TabIndex = 0;
+      // 
+      // PickupDeliveryVisualizationView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.importButton);
+      this.Name = "PickupDeliveryScenarioView";
+      this.Size = new System.Drawing.Size(529, 422);
+      this.Controls.SetChildIndex(this.importButton, 0);
+      this.ResumeLayout(false);
+    }
+
+    #endregion
+
+    private System.Windows.Forms.Button importButton;
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/PickupDeliveryScenarioView.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/PickupDeliveryScenarioView.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/PickupDeliveryScenarioView.cs	(revision 8670)
@@ -0,0 +1,39 @@
+﻿using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using HeuristicLab.Core.Views;
+using HeuristicLab.MainForm;
+using HeuristicLab.PDPSimulation.DomainModel;
+using HeuristicLab.Optimization.Views;
+
+namespace HeuristicLab.PDPSimulation.Views {
+  [View("PickupDeliveryScenario View")]
+  [Content(typeof(PickupDeliveryScenario), true)]
+  public partial class PickupDeliveryScenarioView : ProblemView {
+    public new PickupDeliveryScenario Content {
+      get { return (PickupDeliveryScenario)base.Content; }
+      set { base.Content = value; }
+    }
+
+    public PickupDeliveryScenarioView() {
+      InitializeComponent();
+    }
+
+    private void importButton_Click(object sender, System.EventArgs e) {
+      OpenFileDialog dlg = new OpenFileDialog();
+      dlg.Filter = "dynamic PDP files (*.dpd)|*.dpd|dynamic PDP files - TSPLib (*.pdp*)|*.pdp";
+
+      if (dlg.ShowDialog() == DialogResult.OK) {
+        if (dlg.FilterIndex == 1)
+          Content.ImportFromDynPDP(dlg.FileName);
+        else
+          Content.ImportFromDynTSPLib(dlg.FileName);
+      }
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/PickupDeliveryScenarioView.resx
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/PickupDeliveryScenarioView.resx	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/PickupDeliveryScenarioView.resx	(revision 8670)
@@ -0,0 +1,129 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="errorProvider.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>107, 17</value>
+  </metadata>
+  <metadata name="errorProvider.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>107, 17</value>
+  </metadata>
+  <metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+</root>
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/PickupDeliveryVisualizationView.Designer.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/PickupDeliveryVisualizationView.Designer.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/PickupDeliveryVisualizationView.Designer.cs	(revision 8670)
@@ -0,0 +1,57 @@
+﻿namespace HeuristicLab.PDPSimulation.Views {
+  partial class PickupDeliveryVisualizationView {
+    /// <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 Component 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.pictureBox = new System.Windows.Forms.PictureBox();
+      ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // pictureBox
+      // 
+      this.pictureBox.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.pictureBox.Location = new System.Drawing.Point(0, 0);
+      this.pictureBox.Name = "pictureBox";
+      this.pictureBox.Size = new System.Drawing.Size(694, 462);
+      this.pictureBox.TabIndex = 0;
+      this.pictureBox.TabStop = false;
+      this.pictureBox.MouseClick += new System.Windows.Forms.MouseEventHandler(pictureBox_MouseClick);
+      // 
+      // PickupDeliveryVisualizationView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.pictureBox);
+      this.Name = "PickupDeliveryVisualizationView";
+      this.Size = new System.Drawing.Size(694, 462);
+      this.SizeChanged += new System.EventHandler(this.PickupDeliveryVisualizationView_SizeChanged);
+      ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).EndInit();
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.PictureBox pictureBox;
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/PickupDeliveryVisualizationView.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/PickupDeliveryVisualizationView.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/PickupDeliveryVisualizationView.cs	(revision 8670)
@@ -0,0 +1,217 @@
+﻿using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using HeuristicLab.Core.Views;
+using HeuristicLab.MainForm;
+using HeuristicLab.PDPSimulation.DomainModel;
+using HeuristicLab.MainForm.WindowsForms;
+
+namespace HeuristicLab.PDPSimulation.Views {
+  [View("PickupDeliveryVisualization View")]
+  [Content(typeof(PickupDeliveryVisualization), true)]
+  public partial class PickupDeliveryVisualizationView : ItemView {    
+    public new PickupDeliveryVisualization Content {
+      get { return (PickupDeliveryVisualization)base.Content; }
+      set { base.Content = value; }
+    }
+    
+    public PickupDeliveryVisualizationView() {
+      InitializeComponent();
+    }
+
+    protected override void DeregisterContentEvents() {
+      Content.ContentChanged -= new EventHandler(Content_ContentChanged);
+      base.DeregisterContentEvents();
+    }
+
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      Content.ContentChanged += new EventHandler(Content_ContentChanged);
+    }
+
+    void Content_ContentChanged(object sender, EventArgs e) {
+      GenerateImage();
+    }
+
+    private bool drawRoutes = false;
+
+    void pictureBox_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e) {
+      if (e.Button == System.Windows.Forms.MouseButtons.Right) {
+        drawRoutes = !drawRoutes;
+        GenerateImage();
+      }
+    }
+
+    private void GenerateImage() {
+      if ((pictureBox.Width > 0) && (pictureBox.Height > 0)) {
+        PickupDeliveryVisualization content = Content;
+
+        if (content == null) {
+          pictureBox.Image = null;
+        } else {          
+          int customerSize = Resources.source.Width;
+          int depotSize = Resources.depot.Width;
+          int truckSize = Resources.truck.Width;
+
+          int border = customerSize * 2;
+
+          Bitmap bitmap = new Bitmap(pictureBox.Width, pictureBox.Height);
+          double width = bitmap.Width - border * 2;
+          double height = bitmap.Height - border * 2;
+
+          double rangeX = content.OrderRangeX;
+          double rangeY = content.OrderRangeY;
+
+          using (Graphics graphics = Graphics.FromImage(bitmap)) {
+            if (drawRoutes) {
+              float completedWidth = 1;
+              Pen[] pastPens = {new Pen(Color.FromArgb(92,20,237), completedWidth), new Pen(Color.FromArgb(237,183,20), completedWidth), new Pen(Color.FromArgb(237,20,219), completedWidth), new Pen(Color.FromArgb(20,237,76), completedWidth),
+                    new Pen(Color.FromArgb(237,61,20), completedWidth), new Pen(Color.FromArgb(115,78,26), completedWidth), new Pen(Color.FromArgb(20,237,229), completedWidth), new Pen(Color.FromArgb(39,101,19), completedWidth),
+                    new Pen(Color.FromArgb(230,170,229), completedWidth), new Pen(Color.FromArgb(142,136,89), completedWidth), new Pen(Color.FromArgb(157,217,166), completedWidth), new Pen(Color.FromArgb(31,19,101), completedWidth),
+                    new Pen(Color.FromArgb(173,237,20), completedWidth), new Pen(Color.FromArgb(230,231,161), completedWidth), new Pen(Color.FromArgb(142,89,89), completedWidth), new Pen(Color.FromArgb(93,89,142), completedWidth),
+                    new Pen(Color.FromArgb(146,203,217), completedWidth), new Pen(Color.FromArgb(101,19,75), completedWidth), new Pen(Color.FromArgb(198,20,237), completedWidth), new Pen(Color.FromArgb(185,185,185), completedWidth),
+                    new Pen(Color.FromArgb(179,32,32), completedWidth), new Pen(Color.FromArgb(18,119,115), completedWidth), new Pen(Color.FromArgb(104,158,239), completedWidth), new Pen(Color.Black, completedWidth)};
+
+              float toBeServedWidth = 2;
+              Pen[] futurePens = {new Pen(Color.FromArgb(92,20,237), toBeServedWidth), new Pen(Color.FromArgb(237,183,20), toBeServedWidth), new Pen(Color.FromArgb(237,20,219), toBeServedWidth), new Pen(Color.FromArgb(20,237,76), toBeServedWidth),
+                    new Pen(Color.FromArgb(237,61,20), toBeServedWidth), new Pen(Color.FromArgb(115,78,26), toBeServedWidth), new Pen(Color.FromArgb(20,237,229), toBeServedWidth), new Pen(Color.FromArgb(39,101,19), toBeServedWidth),
+                    new Pen(Color.FromArgb(230,170,229), toBeServedWidth), new Pen(Color.FromArgb(142,136,89), toBeServedWidth), new Pen(Color.FromArgb(157,217,166), toBeServedWidth), new Pen(Color.FromArgb(31,19,101), toBeServedWidth),
+                    new Pen(Color.FromArgb(173,237,20), toBeServedWidth), new Pen(Color.FromArgb(230,231,161), toBeServedWidth), new Pen(Color.FromArgb(142,89,89), toBeServedWidth), new Pen(Color.FromArgb(93,89,142), toBeServedWidth),
+                    new Pen(Color.FromArgb(146,203,217), toBeServedWidth), new Pen(Color.FromArgb(101,19,75), toBeServedWidth), new Pen(Color.FromArgb(198,20,237), toBeServedWidth), new Pen(Color.FromArgb(185,185,185), toBeServedWidth),
+                    new Pen(Color.FromArgb(179,32,32), toBeServedWidth), new Pen(Color.FromArgb(18,119,115), toBeServedWidth), new Pen(Color.FromArgb(104,158,239), toBeServedWidth), new Pen(Color.Black, toBeServedWidth)};
+
+              int currentTour = 0;
+              foreach (Vehicle vehicle in content.Vehicles) {
+                PDAction action = content.GetAction(vehicle);
+                List<Point> tourPoints = new List<Point>();
+
+                while (action != null && action.ActionCompleted()) {
+                  if (action is MoveVehicleAction) {
+                    MoveVehicleAction moveAction = action as MoveVehicleAction;
+
+                    if (tourPoints.Count == 0) {
+                      tourPoints.Add(new Point((int)(border + moveAction.SourceX / rangeX * width),
+                        (int)(height + border - moveAction.SourceY / rangeY * height)));
+                    }
+
+                    Point locationPoint = new Point((int)(border + moveAction.TargetX / rangeX * width),
+                      (int)(height + border - moveAction.TargetY / rangeY * height));
+
+                    tourPoints.Add(locationPoint);
+                  }
+
+                  action = action.Successor;
+                }
+
+                if (tourPoints.Count > 1) {
+                  graphics.DrawLines(pastPens[((currentTour >= pastPens.Length) ? (pastPens.Length - 1) : (currentTour))], tourPoints.ToArray());
+
+                  Point last = tourPoints.Last();
+                  tourPoints.Clear();
+                  tourPoints.Add(last);
+                }
+
+                while (action != null) {
+                  if (action is MoveVehicleAction) {
+                    MoveVehicleAction moveAction = action as MoveVehicleAction;
+
+                    if (tourPoints.Count > 0 || (moveAction.SourceX >= 0 && moveAction.SourceY >= 0)) {
+                      if (tourPoints.Count == 0) {
+                        tourPoints.Add(new Point((int)(border + moveAction.SourceX / rangeX * width),
+                          (int)(height + border - moveAction.SourceY / rangeY * height)));
+                      }
+
+                      Point locationPoint = new Point((int)(border + moveAction.TargetX / rangeX * width),
+                        (int)(height + border - moveAction.TargetY / rangeY * height));
+
+                      tourPoints.Add(locationPoint);
+                    }
+                  }
+
+                  action = action.Successor;
+                }
+
+                if (tourPoints.Count > 1) {
+                  graphics.DrawLines(futurePens[((currentTour >= futurePens.Length) ? (futurePens.Length - 1) : (currentTour))], tourPoints.ToArray());
+                  currentTour++;
+                } 
+              }
+
+              for (int i = 0; i < pastPens.Length; i++)
+                pastPens[i].Dispose();
+              for (int i = 0; i < futurePens.Length; i++)
+                futurePens[i].Dispose();
+            } else {
+              using (Pen flowPen = new Pen(Brushes.Green)) {
+                flowPen.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
+                //flowPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
+
+                foreach (Order order in content.Orders) {
+                  if (order.OrderState != OrderState.Cancelled &&
+                    order.OrderState != OrderState.Delivered) {
+                    Point pickup = new Point(
+                      (int)(border + order.PickupXCoord / rangeX * width),
+                      (int)(height + border - order.PickupYCoord / rangeY * height));
+
+                    graphics.DrawImage(Resources.source, pickup.X - customerSize / 2, pickup.Y - customerSize / 2);
+
+                    if (!order.ServiceRequest) {
+                      Point delivery = new Point(
+                        (int)(border + order.DeliveryXCoord / rangeX * width),
+                        (int)(height + border - order.DeliveryYCoord / rangeY * height));
+
+                      graphics.DrawImage(Resources.target, delivery.X - customerSize / 2, delivery.Y - customerSize / 2);
+
+                      graphics.DrawLine(flowPen, pickup, delivery);
+                    }
+                  }
+                }
+              }
+            }
+
+            foreach (Vehicle vehicle in content.Vehicles) {
+              Point depotPoint = new Point(
+                (int)(border + vehicle.DepotX / rangeX * width),
+                (int)(height + border - vehicle.DepotY / rangeY * height));
+
+              graphics.DrawImage(Resources.depot, depotPoint.X - depotSize / 2,
+                depotPoint.Y - depotSize / 2);
+            }
+
+            foreach (Vehicle vehicle in content.Vehicles) {
+              Point vehiclePoint = new Point(
+                (int)(border + vehicle.PositionX / rangeX * width),
+                (int)(height + border - vehicle.PositionY / rangeY * height));
+
+              if (vehicle.VehicleState == VehicleState.Waiting || 
+                vehicle.VehicleState == VehicleState.Parked || 
+                vehicle.VehicleState == VehicleState.InvalidAction) {
+                graphics.DrawImage(Resources.truck_idle, vehiclePoint.X - truckSize / 2,
+                  vehiclePoint.Y - truckSize / 2);
+              } else {
+                graphics.DrawImage(Resources.truck, vehiclePoint.X - truckSize / 2,
+                  vehiclePoint.Y - truckSize / 2);
+              }
+            }
+          }
+          pictureBox.Image = bitmap;
+        }
+      }
+    }
+
+    private void PickupDeliveryVisualizationView_SizeChanged(object sender, EventArgs e) {
+      GenerateImage();
+    }
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+
+      GenerateImage();
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/Plugin.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/Plugin.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/Plugin.cs	(revision 8670)
@@ -0,0 +1,43 @@
+#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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.PDPSimulation.Views {
+  /// <summary>
+  /// Plugin class for HeuristicLab.PDPSimulationViews plugin.
+  /// </summary>
+  [Plugin("HeuristicLab.PDPSimulation.Views", "3.3.4.0")]
+  [PluginFile("HeuristicLab.PDPSimulation.Views-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.Collections", "3.3")]
+  [PluginDependency("HeuristicLab.Common", "3.3")]
+  [PluginDependency("HeuristicLab.Common.Resources", "3.3")]
+  [PluginDependency("HeuristicLab.Core", "3.3")]
+  [PluginDependency("HeuristicLab.MainForm", "3.3")]
+  [PluginDependency("HeuristicLab.MainForm.WindowsForms", "3.3")]
+  [PluginDependency("HeuristicLab.Persistence", "3.3")]
+  [PluginDependency("HeuristicLab.PDPSimulation", "3.3")]
+  public class HeuristicLabPDPSimulationViewsPlugin : PluginBase {
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/Plugin.cs.frame
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/Plugin.cs.frame	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/Plugin.cs.frame	(revision 8670)
@@ -0,0 +1,43 @@
+#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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.PDPSimulation.Views {
+  /// <summary>
+  /// Plugin class for HeuristicLab.PDPSimulationViews plugin.
+  /// </summary>
+  [Plugin("HeuristicLab.PDPSimulation.Views", "3.3.4.$WCREV$")]
+  [PluginFile("HeuristicLab.PDPSimulation.Views-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.Collections", "3.3")]
+  [PluginDependency("HeuristicLab.Common", "3.3")]
+  [PluginDependency("HeuristicLab.Common.Resources", "3.3")]
+  [PluginDependency("HeuristicLab.Core", "3.3")]
+  [PluginDependency("HeuristicLab.MainForm", "3.3")]
+  [PluginDependency("HeuristicLab.MainForm.WindowsForms", "3.3")]
+  [PluginDependency("HeuristicLab.Persistence", "3.3")]
+  [PluginDependency("HeuristicLab.PDPSimulation", "3.3")]
+  public class HeuristicLabPDPSimulationViewsPlugin : PluginBase {
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/Properties/AssemblyInfo.frame
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/Properties/AssemblyInfo.frame	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/Properties/AssemblyInfo.frame	(revision 8670)
@@ -0,0 +1,56 @@
+#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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("HeuristicLab.PDPSimulation.Views")]
+[assembly: AssemblyDescription("HeuristicLab pickup and delivery simulation")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("HeuristicLab")]
+[assembly: AssemblyCopyright("(c) 2002-2011 HEAL")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("35402752-9A80-4757-9063-149BA096B7C7")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("3.3.0.0")]
+[assembly: AssemblyFileVersion("3.3.4.$WCREV$")]
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/Resources.Designer.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/Resources.Designer.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/Resources.Designer.cs	(revision 8670)
@@ -0,0 +1,98 @@
+﻿//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.468
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace HeuristicLab.PDPSimulation.Views {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("HeuristicLab.PDPSimulation.Views.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        internal static System.Drawing.Bitmap depot {
+            get {
+                object obj = ResourceManager.GetObject("depot", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap source {
+            get {
+                object obj = ResourceManager.GetObject("source", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap target {
+            get {
+                object obj = ResourceManager.GetObject("target", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap truck {
+            get {
+                object obj = ResourceManager.GetObject("truck", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap truck_idle {
+            get {
+                object obj = ResourceManager.GetObject("truck_idle", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+    }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/Resources.resx
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/Resources.resx	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/Resources.resx	(revision 8670)
@@ -0,0 +1,136 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="depot" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>resources\depot.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="source" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>resources\source.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="target" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>resources\target.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="truck" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>resources\truck.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="truck_idle" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>resources\truck_idle.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+</root>
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/VehicleHistoryView.Designer.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/VehicleHistoryView.Designer.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/VehicleHistoryView.Designer.cs	(revision 8670)
@@ -0,0 +1,57 @@
+﻿namespace HeuristicLab.PDPSimulation.Views {
+  partial class VehicleHistoryView {
+    /// <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 Component 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.pictureBox = new System.Windows.Forms.PictureBox();
+      ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // pictureBox
+      // 
+      this.pictureBox.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.pictureBox.Location = new System.Drawing.Point(0, 0);
+      this.pictureBox.Name = "pictureBox";
+      this.pictureBox.Size = new System.Drawing.Size(694, 462);
+      this.pictureBox.TabIndex = 0;
+      this.pictureBox.TabStop = false;
+      this.pictureBox.MouseClick += new System.Windows.Forms.MouseEventHandler(pictureBox_MouseClick);
+      // 
+      // PickupDeliveryVisualizationView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.pictureBox);
+      this.Name = "PickupDeliveryVisualizationView";
+      this.Size = new System.Drawing.Size(694, 462);
+      this.SizeChanged += new System.EventHandler(this.VehicleHistoryView_SizeChanged);
+      ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).EndInit();
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.PictureBox pictureBox;
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/VehicleHistoryView.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/VehicleHistoryView.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation.Views/3.3/VehicleHistoryView.cs	(revision 8670)
@@ -0,0 +1,178 @@
+﻿using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using HeuristicLab.Core.Views;
+using HeuristicLab.MainForm;
+using HeuristicLab.PDPSimulation.DomainModel;
+using HeuristicLab.MainForm.WindowsForms;
+using HeuristicLab.Analysis;
+
+namespace HeuristicLab.PDPSimulation.Views {
+  [View("VehicleHistoryView")]
+  [Content(typeof(VehicleHistoryVisualization), true)]
+  public partial class VehicleHistoryView : ItemView {
+    public new VehicleHistoryVisualization Content {
+      get { return (VehicleHistoryVisualization)base.Content; }
+      set { base.Content = value; }
+    }
+
+    public VehicleHistoryView() {
+      InitializeComponent();
+    }
+
+    protected override void DeregisterContentEvents() {
+      Content.ContentChanged -= new EventHandler(Content_ContentChanged);
+      base.DeregisterContentEvents();
+    }
+
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      Content.ContentChanged += new EventHandler(Content_ContentChanged);
+    }
+
+    void Content_ContentChanged(object sender, EventArgs e) {
+      GenerateImage();
+    }
+
+    void pictureBox_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e) {
+      if (e.Button == System.Windows.Forms.MouseButtons.Right) {
+        GenerateImage();
+      }
+    }
+
+    private List<Order> GetServicedOrders(VehicleHistory vehicle) {
+      List<Order> result = new List<Order>();
+
+      Order current = null;
+      for (int i = 0; i < vehicle.VehicleState.Count; i++) {
+        current = vehicle.ActiveOrders[i];
+        if (vehicle.VehicleState[i] == VehicleState.Servicing && !result.Contains(current))
+          result.Add(current);
+      }
+
+      return result;
+    }
+
+    private void GenerateImage() {
+      if ((pictureBox.Width > 0) && (pictureBox.Height > 0)) {
+        VehicleHistoryVisualization content = Content;
+
+        if (content == null) {
+          pictureBox.Image = null;
+        } else {
+          Bitmap bitmap = new Bitmap(pictureBox.Width, pictureBox.Height);
+          using (Graphics graphics = Graphics.FromImage(bitmap)) {
+            IEnumerable<VehicleHistory> vehicles = content.VehicleHistory.Where(v => v.VehicleState.Any(s => s != VehicleState.Parked && s != VehicleState.Waiting));
+            int vehicleCount = vehicles.Count();
+
+            if (vehicleCount > 0) {
+              float width = pictureBox.Width - 1;
+              float height = pictureBox.Height - 1;
+
+              int orderCount = 0;
+              foreach (VehicleHistory vehicle in vehicles)
+                orderCount += GetServicedOrders(vehicle).Count;
+
+              int totalRows = vehicleCount * 3 + orderCount;
+              float rowHeight = height / (float)totalRows;
+
+              int totalColumns = vehicles.First().VehicleState.Count;
+              float columnWidth = width / (float)totalColumns;
+              float timeWidth = columnWidth / (float)content.ResultCollectionInterval;
+
+              float curY = 0;
+              foreach (VehicleHistory vehicle in vehicles) {
+                float curX = 0;
+
+                int curAvailability = 1;
+                VehicleState curState = VehicleState.Parked;
+                int counter = 0;
+                for (int i = 0; i <= vehicle.VehicleState.Count; i++) {
+                  counter++;
+
+                  int availability = 1;
+                  VehicleState state = VehicleState.Parked;
+                  if (i < vehicle.VehicleState.Count) {
+                    state = vehicle.VehicleState[i];
+                    availability = vehicle.VehicleAvailability[i];
+                  }
+
+                  if (state != curState || availability != curAvailability || (i == vehicle.VehicleState.Count && i != 0)) {
+                    float stateWidth = columnWidth * (float)counter;
+
+                    Brush brush = Brushes.White;
+                    if (curAvailability <= 0)
+                      brush = Brushes.DarkGray;
+                    if (curState == VehicleState.Moving)
+                      brush = Brushes.Green;
+                    else if (curState == VehicleState.Servicing)
+                      brush = Brushes.Red;
+                    else if (curState == VehicleState.InvalidAction)
+                      brush = Brushes.Gray;
+
+                    graphics.FillRectangle(brush, curX, curY, stateWidth, rowHeight);
+
+                    curState = state;
+                    curAvailability = availability;
+                    counter = 0;
+                    curX += stateWidth;
+                  } 
+                }
+
+                graphics.DrawRectangle(Pens.Black, 0, curY, width, rowHeight);
+                            
+                curY += rowHeight;
+                curY += rowHeight;
+
+                foreach (Order order in GetServicedOrders(vehicle)) {
+                  float begin = Math.Min(pictureBox.Width, (float)order.PickupReadyTime * timeWidth);
+                  float end = Math.Min(pictureBox.Width, (float)order.PickupDueTime * timeWidth);
+                  graphics.DrawLine(Pens.Blue, begin, curY + rowHeight / 2, end, curY + rowHeight / 2);
+                  graphics.DrawLine(Pens.Blue, begin, curY, begin, curY + rowHeight);
+                  graphics.DrawLine(Pens.Blue, end, curY, end, curY + rowHeight);
+
+                  if (order.OrderState != OrderState.Waiting) {
+                    float pickupTime = Math.Min(width, (float)order.PickupTime * timeWidth);
+                    graphics.FillEllipse(Brushes.Blue, pickupTime - rowHeight / 4, curY + rowHeight / 4, rowHeight / 2, rowHeight / 2);
+                  }
+
+                  if (!order.ServiceRequest) {
+                    begin = Math.Min(pictureBox.Width, (float)order.DeliveryReadyTime * timeWidth);
+                    end = Math.Min(pictureBox.Width, (float)order.DeliveryDueTime * timeWidth);
+                    graphics.DrawLine(Pens.Green, begin, curY + rowHeight / 2, end, curY + rowHeight / 2);
+                    graphics.DrawLine(Pens.Green, begin, curY, begin, curY + rowHeight);
+                    graphics.DrawLine(Pens.Green, end, curY, end, curY + rowHeight);
+
+                    if (order.OrderState != OrderState.Waiting && order.OrderState != OrderState.PickingUp && order.OrderState != OrderState.PickedUp) {
+                      float deliveryTime = Math.Min(width, (float)order.DeliveryTime * timeWidth);
+                      graphics.FillEllipse(Brushes.Green, deliveryTime - rowHeight / 4, curY + rowHeight / 4, rowHeight / 2, rowHeight / 2);
+                    }
+                  }
+                  
+                  curY += rowHeight;
+                }
+
+                curY += rowHeight;
+              }
+            }
+            pictureBox.Image = bitmap;
+          }
+        }
+      }
+    }
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+
+      GenerateImage();
+    }
+
+    private void VehicleHistoryView_SizeChanged(object sender, EventArgs e) {
+      GenerateImage();
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DistanceMeasures/DistanceMatrixData.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DistanceMeasures/DistanceMatrixData.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DistanceMeasures/DistanceMatrixData.cs	(revision 8670)
@@ -0,0 +1,67 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Common;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.PDPSimulation.DistanceMeasures {
+  [StorableClass]
+  public class DistanceMatrixData: ParameterizedNamedItem, IStorableContent {
+    public ValueParameter<DoubleMatrix> DistanceMatrixParameter {
+      get { return (ValueParameter<DoubleMatrix>)Parameters["DistanceMatrix"]; }
+    }
+
+    public DoubleMatrix DistanceMatrix {
+      get {
+        return DistanceMatrixParameter.Value;
+      }
+
+      set {
+        DistanceMatrixParameter.Value = value;
+      }
+    }
+
+    public ValueParameter<IntMatrix> PointMappingParameter {
+      get { return (ValueParameter<IntMatrix>)Parameters["PointMapping"]; }
+    }
+
+    public IntMatrix Mapping {
+      get {
+        return PointMappingParameter.Value;
+      }
+
+      set {
+        PointMappingParameter.Value = value;
+      }
+    }
+
+    public DistanceMatrixData()
+      : base() {
+        Parameters.Add(new ValueParameter<DoubleMatrix>("DistanceMatrix", new DoubleMatrix()));
+        Parameters.Add(new ValueParameter<IntMatrix>("PointMapping", new IntMatrix()));
+    }
+    [StorableConstructor]
+    private DistanceMatrixData(bool deserializing) : base(deserializing) {
+    }
+    private DistanceMatrixData(DistanceMatrixData original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DistanceMatrixData(this, cloner);
+    }
+    
+    #region IStorableContent Members
+
+    public string Filename {
+      get;
+      set;
+    }
+
+    #endregion
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DistanceMeasures/DistanceMatrixMeasure.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DistanceMeasures/DistanceMatrixMeasure.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DistanceMeasures/DistanceMatrixMeasure.cs	(revision 8670)
@@ -0,0 +1,151 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.PDPSimulation.DomainModel;
+
+namespace HeuristicLab.PDPSimulation.DistanceMeasures {
+  [StorableClass]
+  public class DistanceMatrixMeasure: DistanceMeasure {
+    private ValueParameter<DoubleMatrix> DistanceMatrixParameter {
+      get { return (ValueParameter<DoubleMatrix>)Parameters["DistanceMatrix"]; }
+    }
+
+    private ValueParameter<IntMatrix> PointMappingParameter {
+      get { return (ValueParameter<IntMatrix>)Parameters["PointMapping"]; }
+    }
+
+    private OptionalValueParameter<StringArray> PointNamesParameter {
+      get { return (OptionalValueParameter<StringArray>)Parameters["PointNames"]; }
+    }
+
+    public DoubleMatrix DistanceMatrix {
+      get {
+        return DistanceMatrixParameter.Value;
+      }
+      set {
+        DistanceMatrixParameter.Value = value;
+      }
+    }
+
+    public IntMatrix PointMapping {
+      get {
+        return PointMappingParameter.Value;
+      }
+      set {
+        PointMappingParameter.Value = value;
+      }
+    }
+
+    public StringArray PointNames {
+      get {
+        return PointNamesParameter.Value;
+      }
+      set {
+        PointNamesParameter.Value = value;
+      }
+    }
+
+    public DistanceMatrixMeasure()
+      : base() {
+        Parameters.Add(new ValueParameter<DoubleMatrix>("DistanceMatrix", new DoubleMatrix()));
+        Parameters.Add(new ValueParameter<IntMatrix>("PointMapping", new IntMatrix()));
+        Parameters.Add(new OptionalValueParameter<StringArray>("PointNames"));
+
+        DistanceMatrixParameter.GetsCollected = false;
+        PointMappingParameter.GetsCollected = false;
+        PointNamesParameter.GetsCollected = false;
+    }
+    [StorableConstructor]
+    protected DistanceMatrixMeasure(bool deserializing) : base(deserializing) {
+    }
+    protected DistanceMatrixMeasure(DistanceMatrixMeasure original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DistanceMatrixMeasure(this, cloner);
+    }
+
+    public override bool DiversionSupported {
+      get { return false; }
+    }
+
+    public int GetMapping(double x, double y) {
+      IntMatrix pointMapping = PointMappingParameter.Value;
+      int index = -1;
+
+      int ix = (int)Math.Round(x);
+      int iy = (int)Math.Round(y);
+
+      int i = 0;
+      while (index < 0 && i < pointMapping.Rows) {
+        if (pointMapping[i, 0] == ix && pointMapping[i, 1] == iy) {
+          index = i;
+        }         
+        i++;
+      }
+
+      return index;
+    }
+
+    protected double GetEuclideanDistance(double sourceX, double sourceY, double destX, double destY) {
+      double vx = destX - sourceX;
+      double vy = destY - sourceY;
+      double length = Math.Sqrt(vx * vx + vy * vy);
+
+      return length;
+    }
+
+    public override double GetDistance(double sourceX, double sourceY,
+      double currentX, double currentY, 
+      double destX, double destY) {
+      double total = GetEuclideanDistance(sourceX, sourceY, destX, destY);
+      double driven = GetEuclideanDistance(sourceX, sourceY, currentX, currentY);
+
+      double completed = 1.0;
+      if(total != 0)
+        completed = driven / total;
+
+      return GetDistance(sourceX, sourceY, destX, destY) * (1.0 - completed);
+    }
+
+    public override double GetDistance(double sourceX, double sourceY,
+     double destX, double destY) {
+      DoubleMatrix distanceMatrix = DistanceMatrixParameter.Value;
+
+      int i = GetMapping(sourceX, sourceY);
+      int j = GetMapping(destX, destY);
+
+      return distanceMatrix[i, j];
+    }
+
+    public override void Move(double sourceX, double sourceY,
+      double currentX, double currentY,
+      double destX, double destY, double time, Vehicle.MoveInformation moveInfo,
+      out double newPosX, out double newPosY, out double length) {
+      
+      length = GetDistance(sourceX, sourceY, currentX, currentY, destX, destY);
+      if (length < time) {
+        newPosX = destX;
+        newPosY = destY;
+      } else {
+        double step = GetEuclideanDistance(sourceX, sourceY, destX, destY) /
+          GetDistance(sourceX, sourceY, destX, destY);
+        double vx = destX - currentX;
+        double vy = destY - currentY;
+        double vl = GetEuclideanDistance(currentX, currentY, destX, destY);
+        vx = (vx / vl) * time * step;
+        vy = (vy / vl) * time * step;
+
+        newPosX = currentX + vx;
+        newPosY = currentY + vy;
+        length = time;
+      }
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DistanceMeasures/DistanceMeasure.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DistanceMeasures/DistanceMeasure.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DistanceMeasures/DistanceMeasure.cs	(revision 8670)
@@ -0,0 +1,32 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Core;
+using HeuristicLab.Common;
+using HeuristicLab.PDPSimulation.DomainModel;
+
+namespace HeuristicLab.PDPSimulation.DistanceMeasures {  
+  [StorableClass]
+  public abstract class DistanceMeasure: ParameterizedNamedItem {
+    public DistanceMeasure(): base() {
+    }
+
+    [StorableConstructor]
+    protected DistanceMeasure(bool deserializing) : base(deserializing) { }
+    protected DistanceMeasure(DistanceMeasure original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public abstract bool DiversionSupported { get; }
+    public abstract double GetDistance(double sourceX, double sourceY, double destX, double destY);
+    public abstract double GetDistance(double sourceX, double sourceY, 
+      double currentX, double currentY, 
+      double destX, double destY);
+    public abstract void Move(double sourceX, double sourceY,
+      double currentX, double currentY, 
+      double destX, double destY, double time, Vehicle.MoveInformation moveInfo,
+      out double newPosX, out double newPosY, out double length); 
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DistanceMeasures/EuclideanDistanceMeasure.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DistanceMeasures/EuclideanDistanceMeasure.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DistanceMeasures/EuclideanDistanceMeasure.cs	(revision 8670)
@@ -0,0 +1,68 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+using HeuristicLab.PDPSimulation.DomainModel;
+
+namespace HeuristicLab.PDPSimulation.DistanceMeasures {
+  [StorableClass]
+  public class EuclideanDistanceMeasure: DistanceMeasure {
+    public EuclideanDistanceMeasure()
+      : base() {
+    }
+    [StorableConstructor]
+    private EuclideanDistanceMeasure(bool deserializing) : base(deserializing) {
+    }
+    private EuclideanDistanceMeasure(EuclideanDistanceMeasure original, Cloner cloner)
+      : base(original, cloner) {
+
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new EuclideanDistanceMeasure(this, cloner);
+    }
+
+    public override bool DiversionSupported {
+      get { return true; }
+    }
+
+    public override double GetDistance(double sourceX, double sourceY,
+      double currentX, double currentY, 
+      double destX, double destY) {
+        return GetDistance(currentX, currentY, destX, destY);
+    }
+
+    public override double GetDistance(double sourceX, double sourceY,
+     double destX, double destY) {
+       double vx = destX - sourceX;
+       double vy = destY - sourceY;
+      double length = Math.Sqrt(vx * vx + vy * vy);
+
+      return length;
+    }
+
+    public override void Move(double sourceX, double sourceY,
+      double currentX, double currentY, 
+      double destX, double destY, double time, Vehicle.MoveInformation moveInfo, 
+      out double newPosX, out double newPosY, out double length) {
+      length = GetDistance(sourceX, sourceY, currentX, currentY, destX, destY);
+
+      if (length < time) {
+        newPosX = destX;
+        newPosY = destY;
+      } else {
+        double vx = destX - currentX;
+        double vy = destY - currentY;
+
+        vx = vx / length * time;
+        vy = vy / length * time;
+
+        newPosX = currentX + vx;
+        newPosY = currentY + vy;
+        length = time;
+      }
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DistanceMeasures/PathMeasure.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DistanceMeasures/PathMeasure.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DistanceMeasures/PathMeasure.cs	(revision 8670)
@@ -0,0 +1,301 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.PDPSimulation.DomainModel;
+
+namespace HeuristicLab.PDPSimulation.DistanceMeasures {
+  [StorableClass]
+  public class PathMeasure: DistanceMatrixMeasure {
+    private ValueParameter<BoolMatrix> EdgesParameter {
+      get { return (ValueParameter<BoolMatrix>)Parameters["Edges"]; }
+    }
+
+    private ValueParameter<IntMatrix> VerticesParameter {
+      get { return (ValueParameter<IntMatrix>)Parameters["Vertices"]; }
+    }
+
+    public ValueParameter<BoolValue> UseDistanceMatrix {
+      get { return (ValueParameter<BoolValue>)Parameters["UseDistanceMatrix"]; }
+    }
+
+    public ValueParameter<DoubleValue> PixelScalingFactor {
+      get { return (ValueParameter<DoubleValue>)Parameters["PixelScalingFactor"]; }
+    }
+
+    public BoolMatrix Edges {
+      get {
+        return EdgesParameter.Value;
+      }
+      set {
+        EdgesParameter.Value = value;
+      }
+    }
+
+    public IntMatrix Vertices {
+      get {
+        return VerticesParameter.Value;
+      }
+      set {
+        VerticesParameter.Value = value;
+      }
+    }
+
+    public PathMeasure()
+      : base() {
+        Parameters.Add(new ValueParameter<BoolMatrix>("Edges", new BoolMatrix()));
+        Parameters.Add(new ValueParameter<IntMatrix>("Vertices", new IntMatrix()));
+        Parameters.Add(new ValueParameter<BoolValue>("UseDistanceMatrix", new BoolValue(true)));
+        Parameters.Add(new ValueParameter<DoubleValue>("PixelScalingFactor", new DoubleValue(1.0)));
+
+        EdgesParameter.GetsCollected = false;
+        VerticesParameter.GetsCollected = false;
+
+        graph = null;
+
+        AttachEventHandlers();
+    }
+    
+    [StorableConstructor]
+    private PathMeasure(bool deserializing) : base(deserializing) {
+    }
+    private PathMeasure(PathMeasure original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PathMeasure(this, cloner);
+    }
+
+    private void AttachEventHandlers() {
+      EdgesParameter.ValueChanged += new EventHandler(EdgesParameter_ValueChanged);
+      VerticesParameter.ValueChanged += new EventHandler(VerticesParameter_ValueChanged);
+    }
+
+    void VerticesParameter_ValueChanged(object sender, EventArgs e) {
+      graph = null;
+    }
+    void EdgesParameter_ValueChanged(object sender, EventArgs e) {
+      graph = null;
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserializationHook() {
+      graph = null;
+      AttachEventHandlers();
+    }
+
+    #region Graph
+    private List<Vertex> graph;
+
+    class Vertex {
+      public int Index { get; set; }
+      public Dictionary<Vertex, double> Edges { get; set; }
+
+      public Vertex() {
+        Edges = new Dictionary<Vertex, double>();
+      }
+    }
+
+    private void BuildGraph() {
+      graph = new List<Vertex>();
+      
+      IntMatrix vertices = VerticesParameter.Value;
+      BoolMatrix edges = EdgesParameter.Value;
+      for (int i = 0; i < vertices.Rows; i++) {
+        Vertex v = new Vertex();
+        v.Index = i;
+        graph.Add(v);
+      }
+
+      for (int i = 0; i < vertices.Rows; i++) {
+        for (int j = 0; j < vertices.Rows; j++) {
+          if (edges[i, j]) {
+            double weight = GetEuclideanDistance(vertices[i, 0], vertices[i, 1], vertices[j, 0], vertices[j, 1]);
+            graph[i].Edges.Add(graph[j], weight);
+          }
+        }
+      }
+    }
+
+    private List<Vertex> FindShortestPath(Vertex source, Vertex destination) {   
+      Dictionary<Vertex, double> distance = new Dictionary<Vertex, double>();
+      Dictionary<Vertex, Vertex> previous = new Dictionary<Vertex, Vertex>();
+      foreach (Vertex v in graph) {
+        distance[v] = double.MaxValue;
+        previous[v] = null;
+      }
+
+      List<Vertex> Q = new List<Vertex>(graph);
+      distance[source] = 0;
+      Q.Remove(source);
+      Q.Insert(0, source);
+
+      bool found = false;
+      while (!found && Q.Count > 0) {
+        Vertex u = Q[0];
+        if (distance[u] == double.MaxValue)
+          break;
+        Q.Remove(u);
+        if (u == destination) {
+          found = true;
+        } else {
+          foreach (Vertex v in u.Edges.Keys) {
+            if (Q.Contains(v)) {
+              double alt = distance[u] + u.Edges[v];
+              if (alt < distance[v]) {
+                distance[v] = alt;
+                previous[v] = u;
+
+                Q.Remove(v);
+                int i = 0;
+                while (i < Q.Count && distance[Q[i]] < alt) {
+                  i++;
+                }
+                Q.Insert(i, v);
+              }
+            }
+          }
+        }
+      }
+
+      if (found) {
+        List<Vertex> shortestPath = new List<Vertex>();
+        Vertex u = destination;
+
+        while (previous[u] != null) {
+          shortestPath.Insert(0, u);
+          u = previous[u];
+        }
+
+        shortestPath.Insert(0, source);
+
+        if(shortestPath.Count == 1)
+          shortestPath.Insert(0, source);
+
+        return shortestPath;
+      } else {
+        return null;
+      }
+    }
+
+    private double GetPathLength(List<Vertex> path) {     
+      double length = 0;
+
+      if (path.Count > 2) {
+        for (int i = 0; i < path.Count - 1; i++) {
+          length += path[i].Edges[path[i + 1]];
+        }
+      }
+
+      return length;
+    }
+    #endregion
+
+    protected int GetVertexMapping(double x, double y) {
+      IntMatrix vertices = VerticesParameter.Value;
+      int index = -1;
+
+      int ix = (int)Math.Round(x);
+      int iy = (int)Math.Round(y);
+
+      int i = 0;
+      while (index < 0 && i < vertices.Rows) {
+        if (vertices[i, 0] == ix && vertices[i, 1] == iy) {
+          index = i;
+        }
+        i++;
+      }
+
+      return index;
+    }
+
+    public override double GetDistance(double sourceX, double sourceY,
+    double destX, double destY) {
+      if (UseDistanceMatrix.Value.Value)
+        return base.GetDistance(sourceX, sourceY, destX, destY);
+      else {
+        int i = GetVertexMapping(sourceX, sourceY);
+        int j = GetVertexMapping(destX, destY);
+
+        if (graph == null)
+          BuildGraph();
+
+        List<Vertex> path = FindShortestPath(graph[i], graph[j]);
+        if (path == null)
+          return int.MaxValue;
+        else
+          return GetPathLength(path) / PixelScalingFactor.Value.Value;
+      }
+    }
+
+    public override void Move(double sourceX, double sourceY, 
+      double currentX, double currentY, 
+      double destX, double destY, double time, Vehicle.MoveInformation moveInfo,
+      out double newPosX, out double newPosY, out double length) {
+      if (graph == null)
+         BuildGraph();
+      
+      int i = GetVertexMapping(sourceX, sourceY);
+      int j = GetVertexMapping(destX, destY);
+
+      if (moveInfo.Source != i || moveInfo.Dest != j) {
+        moveInfo.Source = i;
+        moveInfo.Dest = j;
+        moveInfo.Segment = 0;
+        moveInfo.Path = null;
+      }
+
+      if (moveInfo.Path == null) {
+        moveInfo.Path = FindShortestPath(graph[i], graph[j]);
+      }
+      List<Vertex> path = (List<Vertex>)(moveInfo.Path);
+      double step = 0;
+      double pathDist = GetPathLength(path);
+      double actualDist = 0;
+      if (UseDistanceMatrix.Value.Value)
+        actualDist = base.GetDistance(sourceX, sourceY, destX, destY);
+      else
+        actualDist = pathDist / PixelScalingFactor.Value.Value;
+
+      if (actualDist != 0)
+        step = pathDist / actualDist;
+
+      IntMatrix vertices = VerticesParameter.Value;
+      length = 0;
+      newPosX = currentX;
+      newPosY = currentY;
+      while (time > 0 && moveInfo.Segment < path.Count - 1) {
+        int nextIndex = path[moveInfo.Segment + 1].Index;
+        double nextX = vertices[nextIndex, 0];
+        double nextY = vertices[nextIndex, 1];
+
+        double distance = 0;
+        if(step != 0)
+          distance = GetEuclideanDistance(newPosX, newPosY, nextX, nextY) / step;
+        if (distance <= time) {
+          newPosX = nextX;
+          newPosY = nextY;
+
+          length += distance;
+          time -= distance;
+          moveInfo.Segment++;
+        } else {
+          double vx = nextX - newPosX;
+          double vy = nextY - newPosY;
+          double vl = GetEuclideanDistance(newPosX, newPosY, nextX, nextY);
+          vx = (vx / vl) * time * step;
+          vy = (vy / vl) * time * step;
+
+          length += GetEuclideanDistance(newPosX, newPosY, newPosX + vx, newPosY + vy) / step;
+          newPosX = newPosX + vx;
+          newPosY = newPosY + vy;
+          time = 0;
+        }
+      }
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DomainModel/BaseObject.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DomainModel/BaseObject.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DomainModel/BaseObject.cs	(revision 8670)
@@ -0,0 +1,38 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.PDPSimulation.DomainModel {
+  [StorableClass]
+  public abstract class BaseObject: Item {
+    [Storable]
+    public Guid Id { get; set; }
+
+    public BaseObject() {
+      Id = Guid.NewGuid();
+    }
+
+    [StorableConstructor]
+    protected BaseObject(bool deserializing) : base(deserializing) { }
+    protected BaseObject(BaseObject original, Cloner cloner)
+      : base(original, cloner) {
+        Id = original.Id;
+    }
+
+    public override bool Equals(object obj) {
+      if (obj is BaseObject) {
+        return Id == (obj as BaseObject).Id;
+      } else {
+        return base.Equals(obj);
+      }
+    }
+
+    public override int GetHashCode() {
+      return Id.GetHashCode();
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DomainModel/Order.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DomainModel/Order.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DomainModel/Order.cs	(revision 8670)
@@ -0,0 +1,111 @@
+﻿#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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.PDPSimulation.DomainModel {
+  public enum OrderState { Waiting, PickingUp, PickedUp, Delivering, Delivered, Cancelled }
+
+  [StorableClass]
+  public class Order: BaseObject {
+    //State
+    [Storable]
+    public OrderState OrderState { get; set; }
+    [Storable]
+    public double Tardiness { get; set; }
+    [Storable]
+    public double PickupTime { get; set; }
+    [Storable]
+    public double DeliveryTime { get; set; }
+    [Storable]
+    public Guid Vehicle { get; set; }
+    [Storable]
+    public Guid AssignedVehicle { get; set; }
+
+    //Data
+    [Storable]
+    public int Index { get; set; }
+    [Storable]
+    public bool ServiceRequest { get; set; }
+    [Storable]
+    public double PickupXCoord { get; set; }
+    [Storable]
+    public double PickupYCoord { get; set; }
+    [Storable]
+    public double DeliveryXCoord { get; set; }
+    [Storable]
+    public double DeliveryYCoord { get; set; }
+    [Storable]
+    public double Demand { get; set; }
+    [Storable]
+    public double PickupServiceTime { get; set; }
+    [Storable]
+    public double PickupReadyTime { get; set; }
+    [Storable]
+    public double PickupDueTime { get; set; }
+    [Storable]
+    public double DeliveryServiceTime { get; set; }
+    [Storable]
+    public double DeliveryReadyTime { get; set; }
+    [Storable]
+    public double DeliveryDueTime { get; set; }
+    [Storable]
+    public string Name { get; set; }
+
+    public Order()
+      : base() {
+    }
+    [StorableConstructor]
+    private Order(bool deserializing) : base(deserializing) {
+    }
+    private Order(Order original, Cloner cloner)
+      : base(original, cloner) {
+        Index = original.Index;
+        ServiceRequest = original.ServiceRequest;
+        OrderState = original.OrderState;
+        Tardiness = original.Tardiness;
+        PickupTime = original.PickupTime;
+        DeliveryTime = original.DeliveryTime;
+        Vehicle = original.Vehicle;
+        AssignedVehicle = original.AssignedVehicle;
+        PickupXCoord = original.PickupXCoord;
+        PickupYCoord = original.PickupYCoord;
+        DeliveryXCoord = original.DeliveryXCoord;
+        DeliveryYCoord = original.DeliveryYCoord;
+        Demand = original.Demand;
+        PickupServiceTime = original.PickupServiceTime;
+        PickupReadyTime = original.PickupReadyTime;
+        PickupDueTime = original.PickupDueTime;
+        DeliveryServiceTime = original.DeliveryServiceTime;
+        DeliveryReadyTime = original.DeliveryReadyTime;
+        DeliveryDueTime = original.DeliveryDueTime;
+        Name = original.Name;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Order(this, cloner);
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DomainModel/SimulationObject.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DomainModel/SimulationObject.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DomainModel/SimulationObject.cs	(revision 8670)
@@ -0,0 +1,45 @@
+﻿#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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.PDPSimulation.DomainModel {
+  [StorableClass]
+  public class SimulationObject: BaseObject {
+    public SimulationObject()
+      : base() {
+    }
+    [StorableConstructor]
+    private SimulationObject(bool deserializing) : base(deserializing) {
+    }
+    private SimulationObject(SimulationObject original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SimulationObject(this, cloner);
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DomainModel/Vehicle.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DomainModel/Vehicle.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/DomainModel/Vehicle.cs	(revision 8670)
@@ -0,0 +1,134 @@
+﻿#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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.PDPSimulation.DomainModel {
+  public enum VehicleState { Parked, Waiting, InvalidAction, Moving, Servicing }
+
+  [StorableClass]
+  public class Vehicle: BaseObject {
+    //State
+    [Storable]
+    public VehicleState VehicleState { get; set; }
+    [Storable]
+    public List<Guid> PickedUpOrders { get; set; }
+    [Storable]
+    public double PositionX { get; set; }
+    [Storable]
+    public double PositionY { get; set; }
+    [Storable]
+    public double Overload { get; set; }
+    [Storable]
+    public double Distance { get; set; }
+    [Storable]
+    public double Capacity { get; set; }
+    [Storable]
+    public double ReadyTime { get; set; }
+    [Storable]
+    public int InvalidActions { get; set; }
+    [Storable]
+    public double Tardiness { get; set; }
+    [Storable]
+    public double TargetPositionX { get; set; }
+    [Storable]
+    public double TargetPositionY { get; set; }
+    [Storable]
+    public Guid CurrentOrder { get; set; }
+    [Storable]
+    public VehicleAction CurrentAction { get; set; }
+    [Storable]
+    public int Availibility { get; set; }
+    
+    [StorableClass]
+    public class MoveInformation {
+      [Storable]
+      public int Segment { get; set; }
+
+      [Storable]
+      public int Source { get; set; }
+
+      [Storable]
+      public int Dest { get; set; }
+
+      public object Path { get; set; }
+    }
+    
+    [Storable]
+    public MoveInformation MoveInfo { get; set; }
+    
+    //Data
+    [Storable]
+    public string Name { get; set; }
+    [Storable]
+    public double TotalCapacity { get; set; }
+    [Storable]
+    public double DepotX { get; set; }
+    [Storable]
+    public double DepotY { get; set; }
+    [Storable]
+    public double DueTime { get; set; }
+
+    public Vehicle()
+      : base() {
+        PickedUpOrders = new List<Guid>();
+        MoveInfo = new MoveInformation();
+    }
+    [StorableConstructor]
+    private Vehicle(bool deserializing) : base(deserializing) {
+    }
+    private Vehicle(Vehicle original, Cloner cloner)
+      : base(original, cloner) {
+        VehicleState = original.VehicleState;
+        PickedUpOrders = new List<Guid>(original.PickedUpOrders);
+        PositionX = original.PositionX;
+        PositionY = original.PositionY;
+        Overload = original.Overload;
+        Distance = original.Distance;
+        DepotX = original.DepotX;
+        DepotY = original.DepotY;
+        Capacity = original.Capacity;
+        ReadyTime = original.ReadyTime;
+        DueTime = original.DueTime;
+        InvalidActions = original.InvalidActions;
+        Tardiness = original.Tardiness;
+        TargetPositionX = original.TargetPositionX;
+        TargetPositionY = original.TargetPositionY;
+        CurrentOrder = original.CurrentOrder;
+        CurrentAction = original.CurrentAction;
+        TotalCapacity = original.TotalCapacity;
+        MoveInfo = new MoveInformation();
+        MoveInfo.Source = original.MoveInfo.Source;
+        MoveInfo.Dest = original.MoveInfo.Dest;
+        MoveInfo.Segment = original.MoveInfo.Segment;
+        Availibility = original.Availibility;
+        Name = original.Name;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Vehicle(this, cloner);
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/HeuristicLab.PDPSimulation-3.3.csproj
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/HeuristicLab.PDPSimulation-3.3.csproj	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/HeuristicLab.PDPSimulation-3.3.csproj	(revision 8670)
@@ -0,0 +1,269 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{F8815280-FA2D-4B3B-B3FD-242863ADB4FF}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.PDPSimulation</RootNamespace>
+    <AssemblyName>HeuristicLab.PDPSimulation-3.3</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\..\..\..\trunk\sources\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>..\..\..\..\trunk\sources\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x64\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\HeuristicLab.PDPSimulation-3.3.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+    <OutputPath>bin\x64\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Release\HeuristicLab.PDPSimulation-3.3.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x86\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\HeuristicLab.PDPSimulation-3.3.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+    <OutputPath>bin\x86\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Release\HeuristicLab.PDPSimulation-3.3.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Accessibility">
+      <EmbedInteropTypes>True</EmbedInteropTypes>
+    </Reference>
+    <Reference Include="HeuristicLab.Analysis-3.3">
+      <HintPath>..\..\bin\HeuristicLab.Analysis-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Collections-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\bin\HeuristicLab.Collections-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Common-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\bin\HeuristicLab.Common-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Core-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\bin\HeuristicLab.Core-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Data-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\bin\HeuristicLab.Data-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Encodings.PermutationEncoding-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\bin\HeuristicLab.Encodings.PermutationEncoding-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Operators-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\bin\HeuristicLab.Operators-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Optimization-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\bin\HeuristicLab.Optimization-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Optimization.Operators-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\bin\HeuristicLab.Optimization.Operators-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Parameters-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\bin\HeuristicLab.Parameters-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Persistence-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\bin\HeuristicLab.Persistence-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.PluginInfrastructure-3.3">
+      <HintPath>..\..\bin\HeuristicLab.PluginInfrastructure-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Problems.Instances-3.3">
+      <HintPath>..\..\bin\HeuristicLab.Problems.Instances-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Problems.VehicleRouting-3.4">
+      <HintPath>..\..\bin\HeuristicLab.Problems.VehicleRouting-3.4.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Random-3.3">
+      <HintPath>..\..\bin\HeuristicLab.Random-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Data.SQLite, Version=1.0.65.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=AMD64">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\ExternalLibs\System.Data.SQLite.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Operators\Improvers\IntraRouteImprovementOperator.cs" />
+    <Compile Include="Operators\Manipulators\PotvinCustomerRelocationManipulator.cs" />
+    <Compile Include="DistanceMeasures\DistanceMatrixData.cs" />
+    <Compile Include="DistanceMeasures\DistanceMatrixMeasure.cs" />
+    <Compile Include="DistanceMeasures\DistanceMeasure.cs" />
+    <Compile Include="DistanceMeasures\EuclideanDistanceMeasure.cs" />
+    <Compile Include="DistanceMeasures\PathMeasure.cs" />
+    <Compile Include="DomainModel\SimulationObject.cs" />
+    <Compile Include="Operators\DynPDPEvaluator.cs" />
+    <Compile Include="Operators\DynPushForwardInsertionCreator.cs" />
+    <Compile Include="Operators\DynPDPProblemInstance.cs" />
+    <Compile Include="Operators\Manipulators\DynPotvinPairwiseOneLevelExchangeManipulator.cs" />
+    <Compile Include="Operators\Manipulators\DynPotvinPairwiseTwoLevelExchangeManipulator.cs" />
+    <Compile Include="Operators\Moves\Exchange\IPotvinPDExchangeMoveOperator.cs" />
+    <Compile Include="Operators\Moves\Exchange\PotvinPDExchangeExhaustiveMoveGenerator.cs" />
+    <Compile Include="Operators\Moves\Exchange\PotvinPDExchangeMove.cs" />
+    <Compile Include="Operators\Moves\Exchange\PotvinPDExchangeMoveEvaluator.cs" />
+    <Compile Include="Operators\Moves\Exchange\PotvinPDExchangeMoveGenerator.cs" />
+    <Compile Include="Operators\Moves\Exchange\PotvinPDExchangeMoveMaker.cs" />
+    <Compile Include="Operators\Moves\Exchange\PotvinPDExchangeMoveTabuCriterion.cs" />
+    <Compile Include="Operators\Moves\Exchange\PotvinPDExchangeMoveTabuMaker.cs" />
+    <Compile Include="Operators\Moves\Exchange\PotvinPDExchangeMultiMoveGenerator.cs" />
+    <Compile Include="Operators\Moves\Exchange\PotvinPDExchangeSingleMoveGenerator.cs" />
+    <Compile Include="Operators\Moves\PotvinPDRelocateMoveAttribute.cs" />
+    <Compile Include="Operators\Moves\Rearrange\IPotvinPDRearrangeMoveOperator.cs" />
+    <Compile Include="Operators\Moves\Rearrange\PotvinPDRearrangeExhaustiveMoveGenerator.cs" />
+    <Compile Include="Operators\Moves\Rearrange\PotvinPDRearrangeMove.cs" />
+    <Compile Include="Operators\Moves\Rearrange\PotvinPDRearrangeMoveEvaluator.cs" />
+    <Compile Include="Operators\Moves\Rearrange\PotvinPDRearrangeMoveGenerator.cs" />
+    <Compile Include="Operators\Moves\Rearrange\PotvinPDRearrangeMoveMaker.cs" />
+    <Compile Include="Operators\Moves\Rearrange\PotvinPDRearrangeMoveTabuCriterion.cs" />
+    <Compile Include="Operators\Moves\Rearrange\PotvinPDRearrangeMoveTabuMaker.cs" />
+    <Compile Include="Operators\Moves\Rearrange\PotvinPDRearrangeMultiMoveGenerator.cs" />
+    <Compile Include="Operators\Moves\Rearrange\PotvinPDRearrangeSingleMoveGenerator.cs" />
+    <Compile Include="Operators\Moves\Shift\IPotvinPDShiftMoveOperator.cs" />
+    <Compile Include="Operators\Moves\Shift\PotvinPDShiftExhaustiveMoveGenerator.cs" />
+    <Compile Include="Operators\Moves\Shift\PotvinPDShiftMove.cs" />
+    <Compile Include="Operators\Moves\Shift\PotvinPDShiftMoveEvaluator.cs" />
+    <Compile Include="Operators\Moves\Shift\PotvinPDShiftMoveGenerator.cs" />
+    <Compile Include="Operators\Moves\Shift\PotvinPDShiftMoveMaker.cs" />
+    <Compile Include="Operators\Moves\Shift\PotvinPDShiftMoveTabuCriterion.cs" />
+    <Compile Include="Operators\Moves\Shift\PotvinPDShiftMoveTabuMaker.cs" />
+    <Compile Include="Operators\Moves\Shift\PotvinPDShiftMultiMoveGenerator.cs" />
+    <Compile Include="Operators\Moves\Shift\PotvinPDShiftSingleMoveGenerator.cs" />
+    <Compile Include="Optimizers\DynamicPDProblemInstance.cs" />
+    <Compile Include="Optimizers\DynamicPDPOptimization.cs" />
+    <Compile Include="Optimizers\LocalUpdate\BestInsertion.cs" />
+    <Compile Include="Optimizers\Reoptimization\PFIHReoptimization.cs" />
+    <Compile Include="Parsers\DefaultDynPDPParser.cs" />
+    <Compile Include="Parsers\DynPDPParser.cs" />
+    <Compile Include="Parsers\TSPLibDynPDPParser.cs" />
+    <Compile Include="PickupDeliveryAnalyzer.cs" />
+    <Compile Include="Plugin.cs" />
+    <Compile Include="SimulationCore\IScenario.cs" />
+    <Compile Include="SimulationCore\ISimulation.cs" />
+    <Compile Include="SimulationCore\Scenario.cs" />
+    <Compile Include="SimulationCore\Simulation.cs" />
+    <Compile Include="SimulationModel\WaitAction.cs" />
+    <Compile Include="SimulationModel\PDChange.cs" />
+    <Compile Include="SimulationModel\MoveVehicleAction.cs" />
+    <Compile Include="SimulationModel\PDAction.cs" />
+    <Compile Include="DomainModel\BaseObject.cs" />
+    <Compile Include="DomainModel\Order.cs" />
+    <Compile Include="DomainModel\Vehicle.cs" />
+    <Compile Include="OrderGenerators\PickupDeliveryPredefinedOrderGenerator.cs" />
+    <Compile Include="PickupDeliveryOrderGenerator.cs" />
+    <Compile Include="PickupDeliveryOptimization.cs" />
+    <Compile Include="PickupDeliveryScenario.cs" />
+    <Compile Include="PickupDeliverySimulation.cs" />
+    <Compile Include="PickupDeliveryVisualization.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="VehicleHistoryVisualization.cs" />
+    <Compile Include="WaitingStrategies\WaitFirstWaitingStrategy.cs" />
+    <Compile Include="WaitingStrategies\DriveFirstWaitingStrategy.cs" />
+    <Compile Include="WaitingStrategies\WaitingStrategy.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="HeuristicLab.snk" />
+    <None Include="Plugin.cs.frame" />
+    <None Include="Properties\AssemblyInfo.frame" />
+  </ItemGroup>
+  <ItemGroup />
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PreBuildEvent>set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+set ProjectDir=$(ProjectDir)
+set SolutionDir=$(SolutionDir)
+set Outdir=$(Outdir)
+
+call PreBuildEvent.cmd</PreBuildEvent>
+  </PropertyGroup>
+  <PropertyGroup>
+    <PostBuildEvent>
+    </PostBuildEvent>
+  </PropertyGroup>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/DynPDPEvaluator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/DynPDPEvaluator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/DynPDPEvaluator.cs	(revision 8670)
@@ -0,0 +1,344 @@
+﻿#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 DynPDPInsertionInfo : CVRPPDTWInsertionInfo {
+    private double commitmentTime;
+
+    public double CommitmentTime {
+      get { return commitmentTime; }
+    }
+
+
+    public DynPDPInsertionInfo(int start, int end, double spareCapacity, double tourStartTime,
+      double arrivalTime, double leaveTime, double spareTime, double waitingTime, double commitmentTime, 
+      List<int> visited, double arrivalSpareCapacity)
+      : base(start, end, spareCapacity, tourStartTime, arrivalTime, leaveTime, spareTime, waitingTime, visited, arrivalSpareCapacity) {
+        this.commitmentTime = commitmentTime;
+    }
+  }
+  
+  public class DynPDPEvaluation : CVRPPDTWEvaluation {
+    //public List<List<double>> WaitingTimes { get; private set; }
+
+    public DynPDPEvaluation() {
+      //WaitingTimes = new List<List<double>>();
+    } 
+  }
+  
+  [Item("DynPDPEvaluator", "Represents a dynamic multi depot CVRPPDTW evaluator.")]
+  [StorableClass]
+  public class DynPDPEvaluator: MDCVRPTWEvaluator {
+    public ILookupParameter<IntValue> PickupViolationsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["PickupViolations"]; }
+    }
+
+    protected override VRPEvaluation CreateTourEvaluation() {
+      return new DynPDPEvaluation();
+    }
+
+    public static List<double> GetWaitingTimes(DynPDPProblemInstance instance, Tour tour, IVRPEncoding solution) {
+      DoubleArray dueTime = instance.DueTime;
+      DoubleArray readyTime = instance.ReadyTime;
+      DoubleArray serviceTimes = instance.ServiceTime;
+
+      IntArray vehicleAssignment = instance.VehicleDepotAssignment;
+      int depots = instance.Depots.Value;
+     
+      int tourIndex = solution.GetTourIndex(tour);
+      int vehicle = solution.GetVehicleAssignment(tourIndex);
+      int depot = vehicleAssignment[vehicle];
+
+      List<double> waitingTimes = new List<double>();
+      WaitingStrategy waitingStrategy = (instance as DynPDPProblemInstance).WaitingStrategy;
+
+      double time = readyTime[depot];
+      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.GetWaitingTime(time, instance as DynPDPProblemInstance, solution, tour, i);
+          waitingTimes.Add(waitAction);
+          time += waitAction;
+        }
+
+        //drive there
+        time += instance.GetDistance(start, end, solution);
+
+        int endIndex;
+        if (end == 0)
+          endIndex = depot;
+        else
+          endIndex = end + depots - 1;
+
+        //wait
+        if (time < readyTime[endIndex])
+          time = readyTime[endIndex];
+
+        if (end > 0) {
+          //service
+          time += serviceTimes[end - 1];
+        }
+      }
+
+      return waitingTimes;
+    }
+
+    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;
+
+      //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];
+          } 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;
+
+      (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;
+    }
+
+    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();
+
+      PickupViolationsParameter.ActualValue = new IntValue(0);
+    }
+
+    protected override void SetResultParameters(VRPEvaluation tourEvaluation) {
+      base.SetResultParameters(tourEvaluation);
+
+      PickupViolationsParameter.ActualValue.Value = (tourEvaluation as CVRPPDTWEvaluation).PickupViolations;
+    }
+    
+    [StorableConstructor]
+    protected DynPDPEvaluator(bool deserializing) : base(deserializing) { }
+
+    public DynPDPEvaluator() {
+      Parameters.Add(new LookupParameter<IntValue>("PickupViolations", "The number of pickup violations."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPDPEvaluator(this, cloner);
+    }
+
+    protected DynPDPEvaluator(DynPDPEvaluator 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 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/DynPDPProblemInstance.cs	(revision 8670)
@@ -0,0 +1,216 @@
+﻿#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;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+using HeuristicLab.PDPSimulation.DistanceMeasures;
+using HeuristicLab.PDPSimulation.DomainModel;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+using System.Threading;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPDPProblemInstance", "Represents a dynamic multi depot CVRPPDTW instance.")]
+  [StorableClass]
+  public class DynPDPProblemInstance: MDCVRPPDTWProblemInstance {
+    protected ValueParameter<DoubleMatrix> DepotCoordinatesParameter {
+      get { return (ValueParameter<DoubleMatrix>)Parameters["DepotCoordinates"]; }
+    }
+
+    protected ValueParameter<BoolArray> VehicleUsedParameter {
+      get { return (ValueParameter<BoolArray>)Parameters["VehicleUsed"]; }
+    }
+
+    [Storable]
+    public List<VehicleState> VehicleStates {
+      get;
+      set;
+    }
+
+    [Storable]
+    public PotvinEncoding CurrentPlan {
+      get;
+      set;
+    }
+
+    public BoolArray VehicleUsed {
+      get { return VehicleUsedParameter.Value; }
+      set { VehicleUsedParameter.Value = value; }
+    }
+
+    public DoubleMatrix DepotCoordinates {
+      get { return DepotCoordinatesParameter.Value; }
+      set { DepotCoordinatesParameter.Value = value; }
+    }
+
+    protected override IVRPCreator Creator {
+      get {
+        return new DynPushForwardInsertionCreator();
+      }
+    }
+    
+    protected override IVRPEvaluator Evaluator {
+      get {
+        return new DynPDPEvaluator();
+      }
+    }
+
+    public Barrier AlgorithmSyncObject {
+      get;
+      set;
+    }
+
+    public Barrier AnalyzerSyncObject {
+      get;
+      set;
+    }
+
+    [Storable]
+    private ResultCollection results;
+
+    public ResultCollection Results {
+      get {
+        return results;
+      }
+    }
+
+    [Storable]
+    private PickupDeliveryScenario scenario;
+
+    public bool RelocateBackToDepot {
+      get {
+        return scenario.RelocateBackToDepot;
+      }
+    }
+
+    public double Horizon {
+      get {
+        return scenario.VehicleDueTimesParameter.Value.Max();
+      }
+    }
+
+    [Storable]
+    protected WaitingStrategy waitingStrategy;
+
+    public WaitingStrategy WaitingStrategy {
+      get {
+        return waitingStrategy;
+      }
+
+      set {
+        waitingStrategy = value;
+      }
+    }
+    
+    [StorableConstructor]
+    protected DynPDPProblemInstance(bool deserializing) : base(deserializing) { }
+    
+    public DynPDPProblemInstance(PickupDeliveryScenario scenario, ResultCollection results)
+      : base() {
+      Parameters.Add(new ValueParameter<DoubleMatrix>("DepotCoordinates", "The x- and y-Coordinates of the depots.", new DoubleMatrix()));
+      Parameters.Add(new ValueParameter<BoolArray>("VehicleUsed", "Indicates, if a vehicle has been used.", new BoolArray()));
+
+      this.scenario = scenario;
+      this.results = results;
+      VehicleStates = new List<VehicleState>();
+
+      if (scenario != null) {
+        SolutionEvaluator = scenario.Evaluator;
+      }
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPDPProblemInstance(this, cloner);
+    }
+
+    protected DynPDPProblemInstance(DynPDPProblemInstance original, Cloner cloner)
+      : base(original, cloner) {
+        this.scenario = cloner.Clone<PickupDeliveryScenario>(original.scenario);
+        this.SolutionEvaluator = cloner.Clone<IVRPEvaluator>(original.SolutionEvaluator);
+        this.results = cloner.Clone<ResultCollection>(original.results);
+        this.waitingStrategy = cloner.Clone<WaitingStrategy>(original.waitingStrategy);
+        this.VehicleStates = new List<VehicleState>(original.VehicleStates);
+        this.CurrentPlan = cloner.Clone<PotvinEncoding>(CurrentPlan);
+    }
+
+    public DynPDPProblemInstance ShallowClone() {
+      Cloner cloner = new Cloner();
+      return new DynPDPProblemInstance(this, cloner, true);
+    }
+
+    protected DynPDPProblemInstance(DynPDPProblemInstance original, Cloner cloner, bool shallow)
+      : base(original, cloner) {
+      this.scenario = original.scenario;
+      this.SolutionEvaluator = cloner.Clone<IVRPEvaluator>(original.SolutionEvaluator);
+      this.results = original.results;
+      this.waitingStrategy = original.waitingStrategy;
+      this.VehicleStates = original.VehicleStates;
+      this.CurrentPlan =  cloner.Clone<PotvinEncoding>(CurrentPlan);
+    }
+
+    protected override double CalculateDistance(int start, int end) {
+      double distance = 0.0;
+
+      if (end < Depots.Value) {
+        distance =
+          scenario.DistanceMeasure.GetDistance(Coordinates[start, 0], Coordinates[start, 1], DepotCoordinates[end, 0], DepotCoordinates[end, 1]); 
+      } else {
+        distance =
+          scenario.DistanceMeasure.GetDistance(Coordinates[start, 0], Coordinates[start, 1], Coordinates[end, 0], Coordinates[end, 1]);
+      }
+
+      return distance;
+    }
+
+    public double GetDistance(int start, int end) {
+      return CalculateDistance(start, end);
+    }
+
+    public double GetDistanceToDepot(int vehicle) {
+      return CalculateDistance(vehicle, vehicle);
+    }
+
+    public void ResetDistanceMatrix() {
+      UseDistanceMatrixParameter.Value = new BoolValue(false);
+      DistanceMatrixParameter.Value = null;
+
+      UseDistanceMatrixParameter.Value = new BoolValue(true);
+    }
+
+    public void Initialize() {
+      PickupViolationPenalty.Value = scenario.PickupViolationPenaltyParameter.Value.Value;
+      OverloadPenalty.Value = scenario.OverloadPenaltyParameter.Value.Value;
+      TardinessPenalty.Value = scenario.TardinessPenaltyParameter.Value.Value;
+      FleetUsageFactor.Value = scenario.FleetUsageFactorParameter.Value.Value;
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/DynPushForwardInsertionCreator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/DynPushForwardInsertionCreator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/DynPushForwardInsertionCreator.cs	(revision 8670)
@@ -0,0 +1,627 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+using HeuristicLab.Problems.VehicleRouting;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPushForwardInsertionCreator", "Creates a randomly initialized VRP solution.")]
+  [StorableClass]
+  public sealed class DynPushForwardInsertionCreator : PotvinCreator, IStochasticOperator {
+    #region IStochasticOperator Members
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    #endregion
+
+    public IValueParameter<DoubleValue> Alpha {
+      get { return (IValueParameter<DoubleValue>)Parameters["Alpha"]; }
+    }
+    public IValueParameter<DoubleValue> AlphaVariance {
+      get { return (IValueParameter<DoubleValue>)Parameters["AlphaVariance"]; }
+    }
+    public IValueParameter<DoubleValue> Beta {
+      get { return (IValueParameter<DoubleValue>)Parameters["Beta"]; }
+    }
+    public IValueParameter<DoubleValue> BetaVariance {
+      get { return (IValueParameter<DoubleValue>)Parameters["BetaVariance"]; }
+    }
+    public IValueParameter<DoubleValue> Gamma {
+      get { return (IValueParameter<DoubleValue>)Parameters["Gamma"]; }
+    }
+    public IValueParameter<DoubleValue> GammaVariance {
+      get { return (IValueParameter<DoubleValue>)Parameters["GammaVariance"]; }
+    }
+
+    [StorableConstructor]
+    private DynPushForwardInsertionCreator(bool deserializing) : base(deserializing) { }
+
+    public DynPushForwardInsertionCreator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator."));
+      Parameters.Add(new ValueParameter<DoubleValue>("Alpha", "The alpha value.", new DoubleValue(0.7)));
+      Parameters.Add(new ValueParameter<DoubleValue>("AlphaVariance", "The alpha variance.", new DoubleValue(0.5)));
+      Parameters.Add(new ValueParameter<DoubleValue>("Beta", "The beta value.", new DoubleValue(0.1)));
+      Parameters.Add(new ValueParameter<DoubleValue>("BetaVariance", "The beta variance.", new DoubleValue(0.07)));
+      Parameters.Add(new ValueParameter<DoubleValue>("Gamma", "The gamma value.", new DoubleValue(0.2)));
+      Parameters.Add(new ValueParameter<DoubleValue>("GammaVariance", "The gamma variance.", new DoubleValue(0.14)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPushForwardInsertionCreator(this, cloner);
+    }
+
+    private DynPushForwardInsertionCreator(DynPushForwardInsertionCreator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    // use the Box-Mueller transform in the polar form to generate a N(0,1) random variable out of two uniformly distributed random variables
+    private static double Gauss(IRandom random) {
+      double u = 0.0, v = 0.0, s = 0.0;
+      do {
+        u = (random.NextDouble() * 2) - 1;
+        v = (random.NextDouble() * 2) - 1;
+        s = Math.Sqrt(u * u + v * v);
+      } while (s < Double.Epsilon || s > 1);
+      return u * Math.Sqrt((-2.0 * Math.Log(s)) / s);
+    }
+
+    private static double N(double mu, double sigma, IRandom random) {
+      return mu + (sigma * Gauss(random)); // transform the random variable sampled from N(0,1) to N(mu,sigma)
+    }
+
+    private static double GetDistance(int start, int end, IVRPProblemInstance problemInstance, PotvinEncoding solution) {
+      double distance = 0.0;
+
+      if (problemInstance is DynPDPProblemInstance) {
+        distance = (problemInstance as DynPDPProblemInstance).GetDistance(start, end);
+      }
+      else if (problemInstance.UseDistanceMatrix.Value && problemInstance.DistanceMatrix != null) {
+        distance = problemInstance.DistanceMatrix[start, end];
+      } else {
+        double startX = problemInstance.Coordinates[start, 0];
+        double startY = problemInstance.Coordinates[start, 1];
+
+        double endX = problemInstance.Coordinates[end, 0];
+        double endY = problemInstance.Coordinates[end, 1];
+
+        distance =
+            Math.Sqrt(
+              Math.Pow(startX - endX, 2) +
+              Math.Pow(startY - endY, 2));
+      }
+
+      return distance;
+    }
+
+    private static double GetCosts(int customer, int vehicle, IVRPProblemInstance problemInstance,
+      Dictionary<int, List<int>> vehicles, Dictionary<int, Tour> vehicleTours, List<bool> vehicleUsed, PotvinEncoding solution,
+      double alpha, double beta, double gamma, out bool feasible, out bool existingRoute) {
+      int depotCount = 1;
+      IMultiDepotProblemInstance mdp = problemInstance as IMultiDepotProblemInstance;
+      if (mdp != null) {
+        depotCount = mdp.Depots.Value;
+      }
+
+      feasible = true;
+
+      double distance = GetDistance(vehicle, customer + depotCount - 1, problemInstance, solution);
+      if (vehicleUsed != null) {
+        existingRoute = vehicleUsed[vehicle];
+      } else {
+        existingRoute = true;
+      }
+
+      double dueTime = 0;
+      if (problemInstance is ITimeWindowedProblemInstance) {
+        ITimeWindowedProblemInstance vrptw = problemInstance as ITimeWindowedProblemInstance;
+        dueTime = vrptw.DueTime[customer + depotCount - 1];
+      }
+
+      if (vehicleTours.ContainsKey(vehicle)) {
+        Tour tour = vehicleTours[vehicle];
+
+        IPickupAndDeliveryProblemInstance pdp = problemInstance as IPickupAndDeliveryProblemInstance;
+        if (pdp != null && pdp.GetPickupDeliveryLocation(customer) > 0) {
+          solution.InsertPair(tour, customer, pdp.GetPickupDeliveryLocation(customer), problemInstance);
+        } else {
+          tour.Stops.Insert(solution.FindBestInsertionPlace(tour, customer), customer);
+        }
+
+        feasible = problemInstance.TourFeasible(tour, solution);
+
+        tour.Stops.Remove(customer);
+        if (pdp != null && pdp.GetPickupDeliveryLocation(customer) > 0) {
+          tour.Stops.Remove(pdp.GetPickupDeliveryLocation(customer));
+        }
+      }
+      else if (problemInstance is ITimeWindowedProblemInstance) {
+        IPickupAndDeliveryProblemInstance pdp = problemInstance as IPickupAndDeliveryProblemInstance;
+        ITimeWindowedProblemInstance vrptw = problemInstance as ITimeWindowedProblemInstance;
+        double time = vrptw.ReadyTime[vehicle];
+        time += distance;
+        if (time > dueTime) {
+          feasible = false;
+        } else {
+          time += vrptw.ServiceTime[customer - 1];
+          if (pdp != null && pdp.GetPickupDeliveryLocation(customer) > 0) {
+            int targetCustomer = pdp.GetPickupDeliveryLocation(customer);
+            time += GetDistance(customer + depotCount - 1, targetCustomer + depotCount - 1, problemInstance, solution);
+            if (time > vrptw.DueTime[targetCustomer + depotCount - 1]) {
+              feasible = false;
+            } 
+
+            time += vrptw.ServiceTime[targetCustomer - 1];
+            time += GetDistance(targetCustomer + depotCount - 1, vehicle, problemInstance, solution);
+
+            if (time > vrptw.DueTime[vehicle]) {
+              feasible = false;
+            } 
+          } else {
+            time += GetDistance(customer + depotCount - 1, vehicle, problemInstance, solution);
+            if (time > vrptw.DueTime[vehicle]) {
+              feasible = false;
+            } 
+          }
+        }
+      }
+
+      if (problemInstance is IHeterogenousCapacitatedProblemInstance) {
+        IHeterogenousCapacitatedProblemInstance cvrp = problemInstance as IHeterogenousCapacitatedProblemInstance;
+        double demand = problemInstance.GetDemand(customer);
+        if (demand > cvrp.Capacity[vehicle])
+          feasible = false;
+      } else if (problemInstance is IHomogenousCapacitatedProblemInstance) {
+        IHomogenousCapacitatedProblemInstance cvrp = problemInstance as IHomogenousCapacitatedProblemInstance;
+        double demand = problemInstance.GetDemand(customer);
+        if (demand > cvrp.Capacity.Value)
+          feasible = false;
+      }
+
+      double x0 = problemInstance.Coordinates[vehicle, 0];
+      double y0 = problemInstance.Coordinates[vehicle, 1];
+      double dist;
+      if (problemInstance.Coordinates[customer + depotCount - 1, 0] < x0)
+        dist = -distance;
+      else
+        dist = distance;
+      double polarAngle = (dist != 0 ? (Math.Asin((problemInstance.Coordinates[customer + depotCount - 1, 1] - y0) / dist) / 360 * dist) : 0);
+
+      if (problemInstance is ITimeWindowedProblemInstance) {
+        ITimeWindowedProblemInstance vrptw = problemInstance as ITimeWindowedProblemInstance;
+
+        if (dueTime == double.MaxValue)
+          dueTime = 0;
+        else {
+          dueTime -= vrptw.ReadyTime[vehicle];
+        }
+      }
+
+      double cost = alpha * distance + // distance 0 <-> City[i]
+                   -beta * dueTime + // latest arrival time
+                  -gamma * polarAngle; // polar angle
+
+      if (vehicleUsed != null) {
+        if (!vehicleUsed[vehicle])
+          cost += problemInstance.FleetUsageFactor.Value;
+      }
+
+      return cost;
+    }
+
+    private static int GetNearestDepot(IVRPProblemInstance problemInstance, List<int> depots, int customer,
+      Dictionary<int, List<int>> vehicles, Dictionary<int, Tour> vehicleTours, List<bool> vehicleUsed, PotvinEncoding solution,
+      double alpha, double beta, double gamma, out double minCost, out bool bound, out bool bestExistingRoute) {
+      int nearest = -1;
+      minCost = double.MaxValue;
+      bestExistingRoute = false;
+
+      bool bestFeasible = false;
+      int feasibleCount = 0;
+      foreach (int depot in depots) {
+        int vehicle = vehicles[depot][0];
+
+        bool existingRoute;
+        bool feasible;
+        double cost = GetCosts(
+          customer, vehicle,
+          problemInstance, vehicles, vehicleTours, vehicleUsed,
+          solution, alpha, beta, gamma, out feasible, out existingRoute);
+
+        if (feasible)
+          feasibleCount++;
+
+        if ((feasible && !bestFeasible) || 
+          (feasible == bestFeasible && existingRoute && !bestExistingRoute) || 
+          (feasible == bestFeasible && existingRoute == bestExistingRoute && cost < minCost)) {
+          minCost = cost;
+          nearest = depot;
+          bestFeasible = feasible;
+          bestExistingRoute = existingRoute;
+        }
+      }
+
+      bound = (feasibleCount == 1);
+
+      return nearest;
+    }
+
+    private static List<int> SortCustomers(IVRPProblemInstance problemInstance, List<int> customers, List<int> depots,
+      Dictionary<int, int> depotAssignment, Dictionary<int, int> customerBinding, 
+      Dictionary<int, List<int>> vehicles, Dictionary<int, Tour> vehicleTours, List<bool> vehicleUsed, PotvinEncoding solution,
+      double alpha, double beta, double gamma) {
+      List<int> sortedCustomers = new List<int>();
+      depotAssignment.Clear();
+      customerBinding.Clear();
+
+      List<bool> boundList = new List<bool>();
+      List<bool> existingRouteList = new List<bool>();
+      List<double> costList = new List<double>();
+
+      for (int i = 0; i < customers.Count; i++) {
+        double cost;
+        bool bound;
+        bool existingRoute;
+        int depot = GetNearestDepot(problemInstance, depots, customers[i], vehicles, vehicleTours, vehicleUsed, solution,
+          alpha, beta, gamma,
+          out cost, out bound, out existingRoute);
+        depotAssignment[customers[i]] = depot;
+        if (bound) {
+          customerBinding.Add(customers[i], depot);
+        }
+
+        int index = 0;
+        while (index < costList.Count &&
+          ((!bound && boundList[index]) || 
+           (bound == boundList[index] && !existingRoute && existingRouteList[index]) || 
+           (bound == boundList[index] && existingRoute == existingRouteList[index] && costList[index] < cost)))
+          index++;
+
+        costList.Insert(index, cost);
+        boundList.Insert(index, bound);
+        existingRouteList.Insert(index, existingRoute);
+        sortedCustomers.Insert(index, customers[i]);
+      }
+
+      return sortedCustomers;
+    }
+
+    private static bool RemoveUnusedDepots(List<int> depots, Dictionary<int, List<int>> vehicles) {
+      List<int> toBeRemoved = new List<int>();
+
+      foreach (int depot in depots) {
+        if (vehicles[depot].Count == 0)
+          toBeRemoved.Add(depot);
+      }
+
+      foreach (int depot in toBeRemoved) {
+        depots.Remove(depot);
+        vehicles.Remove(depot);
+      }
+
+      return toBeRemoved.Count > 0;
+    }
+
+    private static Dictionary<int, Tour> CreateInitialTours(IVRPProblemInstance problemInstance, Dictionary<int, List<int>> vehicles, PotvinEncoding result) {
+      Dictionary<int, Tour> vehicleTours = new Dictionary<int, Tour>();
+      IPickupAndDeliveryProblemInstance pdp = problemInstance as IPickupAndDeliveryProblemInstance;
+
+      int currentVehicle;
+
+      for (int i = 1; i <= problemInstance.Cities.Value; i++) {
+        if (pdp != null && pdp.GetPickupDeliveryLocation(i) <= 0) {
+          currentVehicle = -pdp.GetPickupDeliveryLocation(i);
+          foreach (int depot in vehicles.Keys) {
+            if (vehicles[depot].Contains(currentVehicle)) {
+              vehicles[depot].Remove(currentVehicle);
+              vehicles[depot].Insert(0, currentVehicle);
+              break;
+            }
+          }
+
+          Tour tour;
+
+          if (!vehicleTours.ContainsKey(currentVehicle)) {
+            tour = new Tour();
+            result.Tours.Add(tour);
+            vehicleTours[currentVehicle] = tour;
+            result.VehicleAssignment[result.Tours.Count - 1] = currentVehicle;
+          } else {
+            tour = vehicleTours[currentVehicle];
+          }
+
+          tour.Stops.Add(i);
+        }
+      }
+
+      foreach (int vehicle in vehicleTours.Keys) {
+        Tour vehicleTour = vehicleTours[vehicle];
+        List<int> customers = new List<int>(vehicleTour.Stops);
+        vehicleTour.Stops.Clear();
+
+        if (problemInstance is DynPDPProblemInstance &&
+          (problemInstance as DynPDPProblemInstance).CurrentPlan != null) {
+          PotvinEncoding plan = (problemInstance as DynPDPProblemInstance).CurrentPlan;
+          Tour planTour = plan.Tours.Find(t => plan.GetVehicleAssignment(plan.Tours.IndexOf(t)) == vehicle);
+
+          customers.Sort((x, y) => planTour.Stops.IndexOf(x).CompareTo(planTour.Stops.IndexOf(y)));
+          foreach (int customer in customers)
+            vehicleTour.Stops.Add(customer);
+        } else {
+          for (int i = 0; i < customers.Count; i++) {
+            int stop = result.FindBestInsertionPlace(vehicleTour, customers[i]);
+            vehicleTour.Stops.Insert(stop, customers[i]);
+          }
+        }
+      }
+
+      return vehicleTours;
+    }
+
+    public static PotvinEncoding CreateSolution(IVRPProblemInstance problemInstance, IRandom random, List<bool> vehicleUsed, 
+      double alphaValue = 0.7, double betaValue = 0.1, double gammaValue = 0.2,
+      double alphaVariance = 0.5, double betaVariance = 0.07, double gammaVariance = 0.14) {
+      PotvinEncoding result = new PotvinEncoding(problemInstance);
+
+      IPickupAndDeliveryProblemInstance pdp = problemInstance as IPickupAndDeliveryProblemInstance;
+      IMultiDepotProblemInstance mdp = problemInstance as IMultiDepotProblemInstance;
+
+      if (mdp != null) {
+        for (int i = 0; i < result.VehicleAssignment.Length; i++) {
+          result.VehicleAssignment[i] = -1;
+        }
+      }
+
+      double alpha, beta, gamma;
+      lock (random) {
+        alpha = N(alphaValue, Math.Sqrt(alphaVariance), random);
+        beta = N(betaValue, Math.Sqrt(betaVariance), random);
+        gamma = N(gammaValue, Math.Sqrt(gammaVariance), random);
+      }
+
+      #region initialization
+      List<int> unroutedCustomers = new List<int>();
+      for (int i = 1; i <= problemInstance.Cities.Value; i++) {
+        if (pdp == null || (problemInstance.GetDemand(i) >= 0) || (pdp.GetPickupDeliveryLocation(i) == i))
+          unroutedCustomers.Add(i);
+      }
+
+      List<int> depots = new List<int>();
+      if (mdp != null) {
+        for (int i = 0; i < mdp.Depots.Value; i++) {
+          depots.Add(i);
+        }
+      } else {
+        depots.Add(0);
+      }
+
+      Dictionary<int, List<int>> vehicles = new Dictionary<int, List<int>>();
+      foreach (int depot in depots) {
+        vehicles[depot] = new List<int>();
+
+        int vehicleCount = problemInstance.Vehicles.Value;
+        if (mdp != null) {
+          for (int vehicle = 0; vehicle < mdp.VehicleDepotAssignment.Length; vehicle++) {
+            if (mdp.VehicleDepotAssignment[vehicle] == depot) {
+              vehicles[depot].Add(vehicle);
+            }
+          }
+        } else {
+          for (int vehicle = 0; vehicle < vehicleCount; vehicle++) {
+            vehicles[depot].Add(vehicle);
+          }
+        }
+
+        if (vehicleUsed != null) {
+          vehicles[depot].Sort(delegate(int x, int y) {
+            if (vehicleUsed[x] && vehicleUsed[y])
+              return 0;
+            else if (vehicleUsed[x])
+              return -1;
+            else
+              return 1;
+          });
+        }
+      }
+
+      Dictionary<int, Tour> vehicleTours = CreateInitialTours(problemInstance, vehicles, result);
+      RemoveUnusedDepots(depots, vehicles);
+      #endregion
+
+      #region route unrouted
+      if (unroutedCustomers.Count > 0) {
+        Tour tour;
+        int currentDepot;
+        int currentVehicle;
+        Dictionary<int, int> depotAssignment = new Dictionary<int, int>();
+
+        //# sort customers globally - start new tour
+        Dictionary<int, int> customerBinding = new Dictionary<int, int>();
+        unroutedCustomers = SortCustomers(
+          problemInstance, unroutedCustomers, depots, depotAssignment, customerBinding, 
+          vehicles, vehicleTours, vehicleUsed, result,
+          alpha, beta, gamma);
+
+        int currentCustomer = unroutedCustomers[0];
+        currentDepot = depotAssignment[currentCustomer];
+        currentVehicle = vehicles[currentDepot][0];
+        vehicles[currentDepot].RemoveAt(0);
+        RemoveUnusedDepots(depots, vehicles);
+
+        if (!vehicleTours.ContainsKey(currentVehicle)) {
+          tour = new Tour();
+          result.Tours.Add(tour);
+          result.VehicleAssignment[result.Tours.Count - 1] = currentVehicle;
+
+          unroutedCustomers.Remove(currentCustomer);
+          tour.Stops.Add(currentCustomer);
+          if (pdp != null && pdp.GetPickupDeliveryLocation(currentCustomer) != currentCustomer) {
+            tour.Stops.Add(pdp.GetPickupDeliveryLocation(currentCustomer));
+          }
+        } else {
+          tour = vehicleTours[currentVehicle];
+        }
+
+        while (unroutedCustomers.Count > 0) {
+          double minimumCost = double.MaxValue;
+          bool bestBoundToRoute = false;
+          int customer = -1;
+          int indexOfMinimumCost = -1;
+          int indexOfMinimumCost2 = -1;
+
+          foreach (int unrouted in unroutedCustomers) {
+            bool boundToRoute = customerBinding.ContainsKey(unrouted) && customerBinding[unrouted] == currentDepot;
+
+            VRPEvaluation eval = problemInstance.EvaluateTour(tour, result);
+            double originalCosts = eval.Quality;
+
+            for (int i = 0; i <= tour.Stops.Count; i++) {
+              tour.Stops.Insert(i, unrouted);
+              eval = problemInstance.EvaluateTour(tour, result);
+              double tourCost = eval.Quality - originalCosts;
+
+              if (pdp != null && pdp.GetPickupDeliveryLocation(unrouted) != unrouted) {
+                for (int j = i + 1; j <= tour.Stops.Count; j++) {
+                  bool feasible;
+                  double cost = tourCost +
+                    problemInstance.GetInsertionCosts(eval, result, pdp.GetPickupDeliveryLocation(unrouted), 0, j, out feasible);
+                  if ((cost < minimumCost || (!bestBoundToRoute && boundToRoute)) && (boundToRoute || !bestBoundToRoute) && feasible) {
+                    customer = unrouted;
+                    minimumCost = cost;
+                    indexOfMinimumCost = i;
+                    indexOfMinimumCost2 = j;
+                    bestBoundToRoute = boundToRoute;
+                  }
+                }
+              } else {
+                double cost = tourCost;
+                bool feasible = problemInstance.Feasible(eval);
+                if ((cost < minimumCost || (!bestBoundToRoute && boundToRoute)) && (boundToRoute || !bestBoundToRoute) && feasible) {
+                  customer = unrouted;
+                  minimumCost = cost;
+                  indexOfMinimumCost = i;
+                  bestBoundToRoute = boundToRoute;
+                }
+              }
+
+              tour.Stops.RemoveAt(i);
+            }
+          }
+
+          if (indexOfMinimumCost == -1 && vehicles.Count == 0) {
+            indexOfMinimumCost = tour.Stops.Count;
+            indexOfMinimumCost2 = tour.Stops.Count + 1;
+            customer = unroutedCustomers[0];
+          }
+
+          // insert customer if found
+          if (indexOfMinimumCost != -1) {
+            tour.Stops.Insert(indexOfMinimumCost, customer);
+            if (pdp != null && pdp.GetPickupDeliveryLocation(customer) != customer) {
+              tour.Stops.Insert(indexOfMinimumCost2, pdp.GetPickupDeliveryLocation(customer));
+            }
+            unroutedCustomers.Remove(customer);
+          } else { // no feasible customer found
+            //# sort customers globally - start new tour
+            unroutedCustomers = SortCustomers(
+              problemInstance, unroutedCustomers, depots, depotAssignment, customerBinding,
+              vehicles, vehicleTours, vehicleUsed, result,
+              alpha, beta, gamma);
+            
+            currentCustomer = unroutedCustomers[0];
+            currentDepot = depotAssignment[currentCustomer];
+            currentVehicle = vehicles[currentDepot][0];
+            vehicles[currentDepot].RemoveAt(0);
+            RemoveUnusedDepots(depots, vehicles);
+
+            if (!vehicleTours.ContainsKey(currentVehicle)) {
+              tour = new Tour();
+              result.Tours.Add(tour);
+              result.VehicleAssignment[result.Tours.Count - 1] = currentVehicle;
+
+              unroutedCustomers.Remove(currentCustomer);
+              tour.Stops.Add(currentCustomer);
+              if (pdp != null && pdp.GetPickupDeliveryLocation(currentCustomer) != currentCustomer) {
+                tour.Stops.Add(pdp.GetPickupDeliveryLocation(currentCustomer));
+              }
+            } else {
+              tour = vehicleTours[currentVehicle];
+            }
+          }
+        }
+      }
+      #endregion
+
+      #region assign vehicles
+      if (mdp != null) {
+        List<int> availableVehicles = new List<int>();
+        for (int i = 0; i < mdp.Vehicles.Value; i++)
+          availableVehicles.Add(i);
+
+        for (int i = 0; i < result.VehicleAssignment.Length; i++) {
+          if (result.VehicleAssignment[i] != -1)
+            availableVehicles.Remove(result.VehicleAssignment[i]);
+        }
+
+        for (int i = 0; i < result.VehicleAssignment.Length; i++) {
+          if (result.VehicleAssignment[i] == -1) {
+            result.VehicleAssignment[i] = availableVehicles[0];
+            availableVehicles.RemoveAt(0);
+          }
+        }
+      }
+      #endregion
+
+      return result;
+    }
+
+    public override IOperation Apply() {
+      List<bool> vehicleUsed = null;
+      
+      DynPDPProblemInstance instance = ProblemInstance as DynPDPProblemInstance;
+      if(instance != null) {
+        vehicleUsed = new List<bool>();
+        for (int i = 0; i < instance.VehicleUsed.Length; i++) {
+          vehicleUsed.Add(instance.VehicleUsed[i]);
+        }
+      }
+
+      VRPToursParameter.ActualValue = CreateSolution(ProblemInstance, RandomParameter.ActualValue, vehicleUsed,
+        Alpha.Value.Value, Beta.Value.Value, Gamma.Value.Value,
+        AlphaVariance.Value.Value, BetaVariance.Value.Value, GammaVariance.Value.Value);
+
+      return base.Apply();
+    }
+  }
+}
+
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Improvers/IntraRouteImprovementOperator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Improvers/IntraRouteImprovementOperator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Improvers/IntraRouteImprovementOperator.cs	(revision 8670)
@@ -0,0 +1,148 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Problems.VehicleRouting.Encodings;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Data;
+using HeuristicLab.Common;
+using HeuristicLab.Parameters;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+using HeuristicLab.Problems.VehicleRouting;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Optimization;
+
+namespace HeuristicLab.PDPSimulation.Operators.Improvers {
+  [Item("IntraRouteImprovementOperator", "An operator that improves vehicle routing solutions.")]
+  [StorableClass]
+  public class IntraRouteImprovementOperator : PotvinManipulator {
+    public ValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (ValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    public IValueParameter<IntValue> ExecutionIntervalParameter {
+      get { return (IValueParameter<IntValue>)Parameters["ExecutionInterval"]; }
+    }
+
+    public IValueParameter<IntValue> ImprovementAttemptsParameter {
+      get { return (IValueParameter<IntValue>)Parameters["ImprovementAttempts"]; }
+    }
+
+    public IValueParameter<IntValue> SampleSizeParameter {
+      get { return (IValueParameter<IntValue>)Parameters["SampleSize"]; }
+    }
+
+    [StorableConstructor]
+    private IntraRouteImprovementOperator(bool deserializing) : base(deserializing) { }
+    private IntraRouteImprovementOperator(IntraRouteImprovementOperator original, Cloner cloner) : base(original, cloner) { }
+    public IntraRouteImprovementOperator()
+      : base() {
+      Parameters.Add(new ValueParameter<IntValue>("ExecutionInterval", "The execution interval.", new IntValue(10)));
+      Parameters.Add(new ValueParameter<IntValue>("ImprovementAttempts", "The number of iterations that should be executed.", new IntValue(100)));
+      Parameters.Add(new ValueParameter<IntValue>("SampleSize", "The number of moves that should be sampled per iteration.", new IntValue(1000)));
+      Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", "The result collection where the best VRP solution should be stored."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new IntraRouteImprovementOperator(this, cloner);
+    }
+
+    protected override void Manipulate(IRandom random, PotvinEncoding individual) {
+      ResultCollection results = ResultsParameter.ActualValue;
+      int generations = -1;
+      if (results.ContainsKey("Iterations"))
+        generations = (results["Iterations"].Value as IntValue).Value;
+      else if (results.ContainsKey("Generations"))
+        generations = (results["Generations"].Value as IntValue).Value;
+
+      int interval = ExecutionIntervalParameter.Value.Value;
+
+      if (generations % interval == 0) {
+        int attempts = ImprovementAttemptsParameter.Value.Value;
+        int sampleSize = SampleSizeParameter.Value.Value;
+        IVRPProblemInstance instance = ProblemInstance;
+        IPickupAndDeliveryProblemInstance pdp = instance as IPickupAndDeliveryProblemInstance;
+
+        double quality = instance.Evaluate(individual).Quality;
+
+        for (int i = 0; i < attempts; i++) {
+          for (int sample = 0; sample < sampleSize; sample++) {
+            int tourIdx = random.Next(individual.Tours.Count);
+            Tour tour = individual.Tours[tourIdx];
+            ItemList<Tour> original = individual.Tours.Clone() as ItemList<Tour>;
+
+            if (tour.Stops.Count > 1) {
+              int idx1 = random.Next(tour.Stops.Count);
+              int idx2 = random.Next(tour.Stops.Count - 1);
+              if (idx2 >= idx1)
+                idx2++;
+
+              int city1 = tour.Stops[idx1];
+              int city2 = tour.Stops[idx2];
+
+              tour.Stops[idx1] = city2;
+              tour.Stops[idx2] = city1;
+
+              if (pdp != null && random.NextDouble() < 0.5) {
+                int target1 = -1;
+                int targetIdx1 = -1;
+                int target2 = -1;
+                int targetIdx2 = -1;
+
+                target1 = pdp.GetPickupDeliveryLocation(city1);
+                if (target1 == city1 || target1 <= 0)
+                  targetIdx1 = -1;
+                else {
+                  targetIdx1 = tour.Stops.IndexOf(target1);
+
+                  if (targetIdx1 == -1) {
+                    individual.Tours.First(t => t.Stops.Contains(target1)).Stops.Remove(target1);
+                    int pos = individual.FindBestInsertionPlace(tour, target1);
+                    tour.Stops.Insert(pos, target1);
+                    targetIdx1 = pos;
+                  }
+                }
+
+                target2 = pdp.GetPickupDeliveryLocation(city2);
+                if (target2 == city2 || target2 <= 0)
+                  targetIdx2 = -1;
+                else {
+                  targetIdx2 = tour.Stops.IndexOf(target2);
+
+                  if (targetIdx2 == -1) {
+                    individual.Tours.First(t => t.Stops.Contains(target2)).Stops.Remove(target2);
+                    int pos = individual.FindBestInsertionPlace(tour, target2);
+                    tour.Stops.Insert(pos, target2);
+                    targetIdx2 = pos;
+
+                    if (targetIdx1 >= pos)
+                      targetIdx1++;
+                  }
+                }
+
+                if (targetIdx1 != -1 && targetIdx2 != -1) {
+                  tour.Stops[targetIdx1] = target2;
+                  tour.Stops[targetIdx2] = target1;
+                } 
+              }
+
+              double newQuality = instance.Evaluate(individual).Quality;
+              if (newQuality < quality) {
+                quality = newQuality;
+                break;
+              } else {
+                //revert
+                individual.Tours = original;
+              }
+            }
+          }
+        }
+
+        IAtomicOperation op = this.ExecutionContext.CreateChildOperation(instance.SolutionEvaluator);
+        op.Operator.Execute((IExecutionContext)op, CancellationToken);
+      }
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Manipulators/DynPotvinPairwiseOneLevelExchangeManipulator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Manipulators/DynPotvinPairwiseOneLevelExchangeManipulator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Manipulators/DynPotvinPairwiseOneLevelExchangeManipulator.cs	(revision 8670)
@@ -0,0 +1,187 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Data;
+using System.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+using HeuristicLab.Problems.VehicleRouting;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPairwiseOneLevelExchangeMainpulator", "The 1M operator which manipulates a VRP representation.  It is implemented as described in Potvin, J.-Y. and Bengio, S. (1996). The Vehicle Routing Problem with Time Windows - Part II: Genetic Search. INFORMS Journal of Computing, 8:165–172. It was adapted to the PDP formulation.")]
+  [StorableClass]
+  public sealed class DynPotvinPairwiseOneLevelExchangeMainpulator : PotvinManipulator {
+    [StorableConstructor]
+    private DynPotvinPairwiseOneLevelExchangeMainpulator(bool deserializing) : base(deserializing) { }
+
+    public DynPotvinPairwiseOneLevelExchangeMainpulator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPairwiseOneLevelExchangeMainpulator(this, cloner);
+    }
+
+    private DynPotvinPairwiseOneLevelExchangeMainpulator(DynPotvinPairwiseOneLevelExchangeMainpulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public bool PairwiseMove(PotvinEncoding individual, int city, bool allowInfeasible) {
+      bool success;
+
+      IPickupAndDeliveryProblemInstance pdp = ProblemInstance as IPickupAndDeliveryProblemInstance;
+
+      if (pdp != null) {
+        Tour route1 = individual.Tours.Find(t => t.Stops.Contains(city));
+        int i = route1.Stops.IndexOf(city);
+
+        int dest = pdp.GetPickupDeliveryLocation(city);
+        Tour destRoute = null;
+        if(city != dest) 
+          destRoute = individual.Tours.Find(t => t.Stops.Contains(dest));
+        int j = -1;
+        
+        if(destRoute != null)
+          j = destRoute.Stops.IndexOf(dest);
+
+        route1.Stops.Remove(city);
+
+        if (destRoute != null)
+          destRoute.Stops.Remove(dest);
+
+        int routeToAvoid = -1;
+        if (route1 == destRoute || destRoute == null)
+          routeToAvoid = individual.Tours.IndexOf(route1);
+
+        int source, target;
+        if (ProblemInstance.GetDemand(city) >= 0) {
+          source = city;
+          target = dest;
+        } else {
+          source = dest;
+          target = city;
+        }
+
+        double bestQuality = double.MaxValue;
+        int bestTour = -1;
+        int bestPositionSource = -1;
+        int bestPositionTarget = -1;
+
+        for (int tourIdx = 0; tourIdx < individual.Tours.Count; tourIdx++) {
+          if (tourIdx != routeToAvoid) {
+            Tour tour = individual.Tours[tourIdx];
+
+            if (source > 0 && source != target) {
+              VRPEvaluation eval = ProblemInstance.EvaluateTour(tour, individual);
+              individual.InsertPair(tour, source, target, ProblemInstance);
+              VRPEvaluation evalNew = ProblemInstance.EvaluateTour(tour, individual);
+
+              double delta = evalNew.Quality - eval.Quality;
+
+              if (delta < bestQuality &&
+                 (ProblemInstance.Feasible(evalNew) || allowInfeasible)) {
+                bestQuality = delta;
+                bestTour = tourIdx;
+                bestPositionSource = tour.Stops.IndexOf(source);
+                bestPositionTarget = tour.Stops.IndexOf(target);
+              }
+
+              tour.Stops.Remove(source);
+              tour.Stops.Remove(target);
+            } else {
+              VRPEvaluation eval = ProblemInstance.EvaluateTour(tour, individual);
+              int place = individual.FindBestInsertionPlace(tour, target);
+              tour.Stops.Insert(place, target);
+              VRPEvaluation evalNew = ProblemInstance.EvaluateTour(tour, individual);
+
+              double delta = evalNew.Quality - eval.Quality;
+
+              if (delta < bestQuality &&
+                 (ProblemInstance.Feasible(evalNew) || allowInfeasible)) {
+                bestQuality = delta;
+                bestTour = tourIdx;
+                bestPositionTarget = tour.Stops.IndexOf(target);
+              }
+
+              tour.Stops.Remove(target);
+            }
+          }
+        }
+
+        if (bestTour >= 0) {
+          if (bestPositionTarget < bestPositionSource) {
+            individual.Tours[bestTour].Stops.Insert(bestPositionTarget, target);
+            individual.Tours[bestTour].Stops.Insert(bestPositionSource, source);
+          } else {
+            if (bestPositionSource >= 0) {
+              individual.Tours[bestTour].Stops.Insert(bestPositionSource, source);
+            }
+            individual.Tours[bestTour].Stops.Insert(bestPositionTarget, target);
+          }
+
+          success = true;
+        } else {
+          if (j < i) {
+            if (destRoute != null) {
+              destRoute.Stops.Insert(j, dest);
+            }
+            route1.Stops.Insert(i, city);
+          } else {
+            route1.Stops.Insert(i, city);
+            destRoute.Stops.Insert(j, dest);
+          }
+
+          success = false;
+        }
+      } else {
+        success = false;
+      }
+
+      return success;
+    }
+
+    protected override void Manipulate(IRandom random, PotvinEncoding individual) {
+      bool allowInfeasible = AllowInfeasibleSolutions.Value.Value;
+
+      int selectedIndex = SelectRandomTourBiasedByLength(random, individual);
+      if (selectedIndex >= 0) {
+        Tour route1 =
+          individual.Tours[selectedIndex];
+
+        int count = route1.Stops.Count;
+
+        if (count > 0) {
+          int i = random.Next(0, count);
+          int city = route1.Stops[i];
+
+          if (!PairwiseMove(individual, city, allowInfeasible))
+            i++;
+
+          count = route1.Stops.Count;
+        }
+      }
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Manipulators/DynPotvinPairwiseTwoLevelExchangeManipulator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Manipulators/DynPotvinPairwiseTwoLevelExchangeManipulator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Manipulators/DynPotvinPairwiseTwoLevelExchangeManipulator.cs	(revision 8670)
@@ -0,0 +1,230 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Data;
+using System.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+using HeuristicLab.Problems.VehicleRouting;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPairwiseTwoLevelExchangeManipulator", "The 2M operator which manipulates a VRP representation.  It is implemented as described in Potvin, J.-Y. and Bengio, S. (1996). The Vehicle Routing Problem with Time Windows - Part II: Genetic Search. INFORMS Journal of Computing, 8:165–172.  It was adapted to the PDP formulation.")]
+  [StorableClass]
+  public sealed class DynPotvinPairwiseTwoLevelExchangeManipulator : PotvinManipulator {
+    [StorableConstructor]
+    private DynPotvinPairwiseTwoLevelExchangeManipulator(bool deserializing) : base(deserializing) { }
+
+    public DynPotvinPairwiseTwoLevelExchangeManipulator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPairwiseTwoLevelExchangeManipulator(this, cloner);
+    }
+
+    private DynPotvinPairwiseTwoLevelExchangeManipulator(DynPotvinPairwiseTwoLevelExchangeManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    private PotvinEncoding ReplacePair(PotvinEncoding individual, int replaced, int replacing, bool allowInfeasible) {
+      individual = individual.Clone() as PotvinEncoding;
+      IPickupAndDeliveryProblemInstance pdp = ProblemInstance as IPickupAndDeliveryProblemInstance;
+
+      int replacedDest = pdp.GetPickupDeliveryLocation(replaced);
+      int replacedSource, replacedTarget;
+      if (pdp.GetDemand(replaced) >= 0) {
+        replacedSource = replaced;
+        replacedTarget = replacedDest;
+      } else {
+        replacedSource = replacedDest;
+        replacedTarget = replaced;
+      }
+      Tour replacedSourceTour = null; 
+      if(replacedSource != replacedTarget)
+        replacedSourceTour = individual.Tours.Find(t => t.Stops.Contains(replacedSource));
+      Tour replacedTargetTour = individual.Tours.Find(t => t.Stops.Contains(replacedTarget));
+     
+      int replacingDest = pdp.GetPickupDeliveryLocation(replacing);
+      int replacingSource, replacingTarget;
+      if (pdp.GetDemand(replacing) >= 0) {
+        replacingSource = replacing;
+        replacingTarget = replacingDest;
+      } else {
+        replacingSource = replacingDest;
+        replacingTarget = replacing;
+      }
+      Tour replacingSourceTour = null;
+      if (replacingSource != replacingTarget)
+        replacingSourceTour = individual.Tours.Find(t => t.Stops.Contains(replacingSource));
+      Tour replacingTargetTour = individual.Tours.Find(t => t.Stops.Contains(replacingTarget));
+
+      if(replacingSourceTour != null)
+        replacingSourceTour.Stops.Remove(replacingSource);
+      replacingTargetTour.Stops.Remove(replacingTarget);
+
+      if (replacedSourceTour != null) {
+        if (replacingSourceTour != null) {
+          replacedSourceTour.Stops[replacedSourceTour.Stops.IndexOf(replacedSource)] = replacingSource;
+        } else {
+          replacedSourceTour.Stops.Remove(replacedSource);
+        }
+
+        if (!allowInfeasible && !ProblemInstance.TourFeasible(replacedSourceTour, individual))
+          return null;
+      }
+      replacedTargetTour.Stops[replacedTargetTour.Stops.IndexOf(replacedTarget)] = replacingTarget;
+      if (!allowInfeasible && !ProblemInstance.TourFeasible(replacedTargetTour, individual))
+        return null;
+
+      double bestQuality = double.MaxValue;
+      int bestTour = -1;
+      int bestPositionSource = -1;
+      int bestPositionTarget = -1;
+
+      int routeToAvoid = -1;
+
+      if (replacingSourceTour != null)
+        routeToAvoid = individual.Tours.IndexOf(replacingSourceTour);
+      else
+        routeToAvoid = individual.Tours.IndexOf(replacingTargetTour);
+
+      for (int tourIdx = 0; tourIdx < individual.Tours.Count; tourIdx++) {
+        if (tourIdx != routeToAvoid) {
+          Tour tour = individual.Tours[tourIdx];
+
+          if (replacedSource > 0 && (replacedSource != replacedTarget)) {
+            VRPEvaluation eval = ProblemInstance.EvaluateTour(tour, individual);
+            individual.InsertPair(tour, replacedSource, replacedTarget, ProblemInstance);
+            VRPEvaluation evalNew = ProblemInstance.EvaluateTour(tour, individual);
+
+            double delta = evalNew.Quality - eval.Quality;
+
+            if (delta < bestQuality &&
+                (ProblemInstance.Feasible(evalNew) || allowInfeasible)) {
+              bestQuality = delta;
+              bestTour = tourIdx;
+              bestPositionSource = tour.Stops.IndexOf(replacedSource);
+              bestPositionTarget = tour.Stops.IndexOf(replacedTarget);
+            }
+
+            tour.Stops.Remove(replacedSource);
+            tour.Stops.Remove(replacedTarget);
+          } else {
+            VRPEvaluation eval = ProblemInstance.EvaluateTour(tour, individual);
+            int place = individual.FindBestInsertionPlace(tour, replacedTarget);
+            tour.Stops.Insert(place, replacedTarget);
+            VRPEvaluation evalNew = ProblemInstance.EvaluateTour(tour, individual);
+
+            double delta = evalNew.Quality - eval.Quality;
+
+            if (delta < bestQuality &&
+               (ProblemInstance.Feasible(evalNew) || allowInfeasible)) {
+              bestQuality = delta;
+              bestTour = tourIdx;
+              bestPositionTarget = tour.Stops.IndexOf(replacedTarget);
+            }
+
+            tour.Stops.Remove(replacedTarget);
+          }
+        }
+      }
+
+      if (bestTour != -1) {
+        if (bestPositionTarget < bestPositionSource) {
+          individual.Tours[bestTour].Stops.Insert(bestPositionTarget, replacedTarget);
+          individual.Tours[bestTour].Stops.Insert(bestPositionSource, replacedSource);
+        } else {
+          if (bestPositionSource >= 0) {
+            individual.Tours[bestTour].Stops.Insert(bestPositionSource, replacedSource);
+          }
+          individual.Tours[bestTour].Stops.Insert(bestPositionTarget, replacedTarget);
+        }
+
+        return individual;
+      } else {
+        return null;
+      }
+    }
+
+    protected override void Manipulate(IRandom random, PotvinEncoding individual) {     
+      bool allowInfeasible = AllowInfeasibleSolutions.Value.Value;
+      IPickupAndDeliveryProblemInstance pdp = ProblemInstance as IPickupAndDeliveryProblemInstance;
+
+      int selectedIndex = SelectRandomTourBiasedByLength(random, individual);
+      if (selectedIndex >= 0) {
+        bool performed = false;
+        Tour route1 = individual.Tours[selectedIndex];
+
+        if (route1.Stops.Count > 0) {
+          //randomize customer selection
+          Permutation perm = new Permutation(PermutationTypes.Absolute, route1.Stops.Count, random);
+          int customer1Position = 0;
+
+          int count = 1;
+          /*if(route1.Stops.Count > 1)
+            count = random.Next(1, route1.Stops.Count);*/
+
+          while (customer1Position < route1.Stops.Count && customer1Position < count) {
+            performed = false;
+
+            int customer1 = route1.Stops[perm[customer1Position]];
+            int customer2 = -1;
+
+            for (int i = 0; i < individual.Tours.Count; i++) {
+              if (i != selectedIndex) {
+                Tour tour = individual.Tours[i];
+                for (int customer2Position = 0; customer2Position < tour.Stops.Count; customer2Position++) {
+                  customer2 = tour.Stops[customer2Position];
+
+                  if (pdp.GetPickupDeliveryLocation(customer1) <= 0 || 
+                      pdp.GetPickupDeliveryLocation(customer1) != customer2) {
+                    PotvinEncoding result = ReplacePair(individual, customer2, customer1, allowInfeasible);
+                    if (result != null) {
+                      VRPToursParameter.ActualValue = result;
+                      individual = result;
+
+                      route1 = individual.Tours[selectedIndex];
+                      performed = true;
+                      break;
+                    }
+                  }
+                }
+              }
+
+              if (performed) {
+                break;
+              }
+            }
+
+            if (!performed)
+              customer1Position++;
+            else
+              break;
+          }
+        }
+      }
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Manipulators/PotvinCustomerRelocationManipulator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Manipulators/PotvinCustomerRelocationManipulator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Manipulators/PotvinCustomerRelocationManipulator.cs	(revision 8670)
@@ -0,0 +1,263 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Data;
+using System.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+using System.Linq;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinCustomerRelocationMainpulator", "A customer relocation operator")]
+  [StorableClass]
+  public sealed class PotvinCustomerRelocationMainpulator : PotvinManipulator, IPickupAndDeliveryOperator {
+    [StorableConstructor]
+    private PotvinCustomerRelocationMainpulator(bool deserializing) : base(deserializing) { }
+
+    public PotvinCustomerRelocationMainpulator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinCustomerRelocationMainpulator(this, cloner);
+    }
+
+    private PotvinCustomerRelocationMainpulator(PotvinCustomerRelocationMainpulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void Manipulate(IRandom random, PotvinEncoding individual) {
+      bool allowInfeasible = AllowInfeasibleSolutions.Value.Value;
+      bool performed = false;
+
+      int selectedIndex;
+      Tour route1;
+
+      int mode = random.Next(0,3);
+
+      //Try pickup and delivery first
+      IPickupAndDeliveryProblemInstance pdp = ProblemInstance as IPickupAndDeliveryProblemInstance;
+      if (pdp != null && mode == 0) {
+        selectedIndex = SelectRandomTourBiasedByLength(random, individual);
+        route1 =
+          individual.Tours[selectedIndex];
+
+        List<int> deliveryViolations = new List<int>();
+
+        Dictionary<int, bool> visited = new Dictionary<int, bool>();
+        for (int i = 0; i < route1.Stops.Count; i++) {
+          int stop = route1.Stops[i];
+          if (ProblemInstance.GetDemand(stop) < 0
+            && pdp.GetPickupDeliveryLocation(stop) != stop) {
+            int source = pdp.GetPickupDeliveryLocation(stop);
+            if (source > 0) {
+              if (!visited.ContainsKey(source))
+                deliveryViolations.Add(stop);
+            } else {
+              if (-source != individual.GetVehicleAssignment(selectedIndex))
+                deliveryViolations.Add(stop);
+            }
+          }
+
+          visited.Add(stop, true);
+        }
+
+        if (deliveryViolations.Count > 0) {
+          int selected =
+            deliveryViolations[random.Next(deliveryViolations.Count)];
+
+          int source = pdp.GetPickupDeliveryLocation(selected);
+          
+          //find route of source
+          Tour found = null;
+
+          if (source > 0) {
+            foreach (Tour tour in individual.Tours) {
+              if (tour.Stops.Contains(source)) {
+                found = tour;
+                break;
+              }
+            }
+          } else {
+            int vehicle = -source;
+            int tourIdx = new List<int>(individual.VehicleAssignment).IndexOf(vehicle);
+            if (tourIdx < individual.Tours.Count)
+              found = individual.Tours[tourIdx];
+            else {
+              found = new Tour();
+              int tmp = individual.VehicleAssignment[individual.Tours.Count];
+              individual.VehicleAssignment[individual.Tours.Count] = vehicle;
+              individual.VehicleAssignment[tourIdx] = tmp;
+              individual.Tours.Add(found);
+            }
+          }
+
+          if (found != null) {
+            double rand = random.NextDouble();
+            if (rand < 0.33 || source <= 0) {
+              route1.Stops.Remove(selected);
+
+              int index = individual.FindBestInsertionPlace(found, selected);
+              found.Stops.Insert(index, selected);
+              performed = true;
+
+              if (route1.Stops.Count == 0)
+                individual.Tours.Remove(route1);
+            } else if (rand < 0.66) {
+              found.Stops.Remove(source);
+
+              int index = individual.FindBestInsertionPlace(route1, source);
+              route1.Stops.Insert(index, source);
+              performed = true;
+
+              if (found.Stops.Count == 0)
+                individual.Tours.Remove(found);
+            } else {
+              found.Stops.Remove(source);
+              route1.Stops.Remove(selected);
+
+              int chosenRoute = random.Next(individual.Tours.Count);
+              Tour tour = individual.Tours[chosenRoute];
+
+              int index = individual.FindBestInsertionPlace(tour, source);
+              tour.Stops.Insert(index, source);
+              index = individual.FindBestInsertionPlace(tour, selected);
+              tour.Stops.Insert(index, selected);
+
+              if (found.Stops.Count == 0)
+                individual.Tours.Remove(found);
+              if (route1.Stops.Count == 0)
+                individual.Tours.Remove(route1);
+            }
+          }
+        }
+      }
+
+      //then try tw
+      if (!performed && mode == 1) {
+        ITimeWindowedProblemInstance vrptw = ProblemInstance as ITimeWindowedProblemInstance;
+
+        if (vrptw != null) {
+          selectedIndex = SelectRandomTourBiasedByLength(random, individual);
+          route1 =
+            individual.Tours[selectedIndex];
+
+          List<int> timeWindowViolations = new List<int>();
+
+          int depots = 1;
+          DoubleArray dueTime = vrptw.DueTime;
+          DoubleArray readyTime = vrptw.ReadyTime;
+          DoubleArray serviceTimes = vrptw.ServiceTime;
+
+          int depot = 0;
+          IMultiDepotProblemInstance mdp = ProblemInstance as IMultiDepotProblemInstance;
+          if (mdp != null) {
+            IntArray vehicleAssignment = mdp.VehicleDepotAssignment;
+            int vehicle = individual.GetVehicleAssignment(selectedIndex);
+            depot = vehicleAssignment[vehicle];
+            depots = mdp.Depots.Value;
+          }
+
+          double time = readyTime[depot];
+
+          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];
+
+            //drive there
+            double currentDistace = vrptw.GetDistance(start, end, individual);
+            time += currentDistace;
+
+            int endIndex;
+            if (end == 0)
+              endIndex = depot;
+            else
+              endIndex = end + depots - 1;
+
+            //check if it was serviced on time
+            if (time > dueTime[endIndex]) {
+              timeWindowViolations.Add(end);
+            }
+
+            //wait
+            double currentWaitingTime = 0.0;
+            if (time < readyTime[endIndex])
+              currentWaitingTime = readyTime[endIndex] - time;
+            time += currentWaitingTime;
+
+            //service
+            double currentServiceTime = serviceTimes[end-1];
+            time += currentServiceTime;
+          }
+
+          if (timeWindowViolations.Count > 0) {
+            int selected =
+              timeWindowViolations[random.Next(timeWindowViolations.Count)];
+
+            int oldIndex = route1.Stops.IndexOf(selected);
+            route1.Stops.Remove(selected);
+
+            int route, place;
+            if (FindInsertionPlace(individual, selected, -1, allowInfeasible, out route, out place)) {
+              Tour newTour = individual.Tours[route];
+              newTour.Stops.Insert(place, selected);
+              performed = true;
+            } else {
+              route1.Stops.Insert(oldIndex, selected);
+            }
+
+            if (route1.Stops.Count == 0)
+              individual.Tours.Remove(route1);
+          }
+        }
+      }
+
+      //finally relocate random customer
+      if (!performed) {
+        selectedIndex = SelectRandomTourBiasedByLength(random, individual);
+        route1 =
+          individual.Tours[selectedIndex];
+
+        int selected = route1.Stops[random.Next(route1.Stops.Count)];
+        int oldIndex = route1.Stops.IndexOf(selected);
+        route1.Stops.Remove(selected);
+
+        int route, place;
+        if (FindInsertionPlace(individual, selected, selectedIndex, allowInfeasible, out route, out place)) {
+          Tour tour = individual.Tours[route];
+          tour.Stops.Insert(place, selected);
+          performed = true;
+        } else {
+          route1.Stops.Insert(oldIndex, selected);
+        }
+
+        if (route1.Stops.Count == 0)
+          individual.Tours.Remove(route1);
+      }
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/IPotvinPDExchangeMoveOperator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/IPotvinPDExchangeMoveOperator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/IPotvinPDExchangeMoveOperator.cs	(revision 8670)
@@ -0,0 +1,31 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  public interface IDynPotvinPDExchangeMoveOperator : IVRPMoveOperator {
+    ILookupParameter<DynPotvinPDExchangeMove> PDExchangeMoveParameter { get; }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeExhaustiveMoveGenerator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeExhaustiveMoveGenerator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeExhaustiveMoveGenerator.cs	(revision 8670)
@@ -0,0 +1,91 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Parameters;
+using System.Collections.Generic;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Common;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDExchangeExhaustiveMoveGenerator", "Generates exchange moves from a given PDP encoding.")]
+  [StorableClass]
+  public sealed class DynPotvinPDExchangeExhaustiveMoveGenerator : DynPotvinPDExchangeMoveGenerator, IExhaustiveMoveGenerator {
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDExchangeExhaustiveMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private DynPotvinPDExchangeExhaustiveMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public DynPotvinPDExchangeExhaustiveMoveGenerator()
+      : base() {
+    }
+
+    private DynPotvinPDExchangeExhaustiveMoveGenerator(DynPotvinPDExchangeExhaustiveMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override DynPotvinPDExchangeMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<DynPotvinPDExchangeMove> result = new List<DynPotvinPDExchangeMove>();
+      IPickupAndDeliveryProblemInstance pdp = problemInstance as IPickupAndDeliveryProblemInstance;
+
+      int max = individual.Tours.Count;
+      if (individual.Tours.Count < problemInstance.Vehicles.Value)
+        max = max - 1;
+
+      for (int i = 0; i < individual.Tours.Count; i++) {
+        for (int j = 0; j < individual.Tours[i].Stops.Count; j++) {
+          for (int k = 0; k <= max; k++) {
+            if (k != i) {
+              int city1 = individual.Tours[i].Stops[j];
+              if (pdp == null || pdp.GetDemand(city1) >= 0 || pdp.GetPickupDeliveryLocation(city1) <= 0 || pdp.GetPickupDeliveryLocation(city1) == city1) {
+                for (int l = 0; l < individual.Tours[k].Stops.Count; l++) {
+                  int city2 = individual.Tours[k].Stops[l];
+                  if (pdp == null || pdp.GetDemand(city2) >= 0 || pdp.GetPickupDeliveryLocation(city2) <= 0) {
+                    bool valid = pdp == null || pdp.GetPickupDeliveryLocation(city1) <= 0 || pdp.GetPickupDeliveryLocation(city1) == city1 ||
+                      (pdp.GetPickupDeliveryLocation(city2) != pdp.GetPickupDeliveryLocation(city1) &&
+                       pdp.GetPickupDeliveryLocation(city2) != city1 &&
+                       pdp.GetPickupDeliveryLocation(city1) != city2);
+
+                    if (valid) {
+                      DynPotvinPDExchangeMove move = new DynPotvinPDExchangeMove(
+                        city1, i, k, city2, individual);
+
+                      result.Add(move);
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeMove.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeMove.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeMove.cs	(revision 8670)
@@ -0,0 +1,136 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Common;
+using System.Collections.Generic;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Data;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Optimization;
+using System;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDExchangeMove", "Item that describes a exchange move on a PDP representation.")]
+  [StorableClass]
+  public class DynPotvinPDExchangeMove: Item, IVRPMove {
+    [Storable]
+    public IVRPEncoding Individual { get; protected set; }
+    
+    [Storable]
+    public int City { get; protected set; }
+
+    [Storable]
+    public int OldTour { get; protected set; }
+
+    [Storable]
+    public int Tour { get; protected set; }
+
+    [Storable]
+    public int Replaced { get; protected set; }
+   
+    public DynPotvinPDExchangeMove(): base() {
+      City = -1;
+      Tour = -1;
+
+      Individual = null;
+    }
+
+    public DynPotvinPDExchangeMove(int city, int oldTour, int tour, int replaced, PotvinEncoding individual) {
+      City = city;
+      OldTour = oldTour;
+      Tour = tour;
+      Replaced = replaced;
+
+      this.Individual = individual.Clone() as PotvinEncoding;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDExchangeMove(this, cloner);
+    }
+
+    protected DynPotvinPDExchangeMove(DynPotvinPDExchangeMove original, Cloner cloner)
+      : base(original, cloner) {
+      this.City = original.City;
+      this.OldTour = original.OldTour;
+      this.Tour = original.Tour;
+      this.Replaced = original.Replaced;
+
+      this.Individual = cloner.Clone(Individual) as PotvinEncoding;
+    }
+
+    #region IVRPMove Members
+
+    [ThreadStatic]
+    private static DynPotvinPDExchangeMoveEvaluator moveEvaluator;
+    public VRPMoveEvaluator GetMoveEvaluator() {
+      if (moveEvaluator == null)
+        moveEvaluator = new DynPotvinPDExchangeMoveEvaluator();
+
+      return moveEvaluator;
+    }
+
+    [ThreadStatic]
+    private static DynPotvinPDExchangeMoveMaker moveMaker; 
+    public VRPMoveMaker GetMoveMaker() {
+      if (moveMaker == null)
+        moveMaker = new DynPotvinPDExchangeMoveMaker();
+
+      return moveMaker;
+    }
+
+    [ThreadStatic]
+    private static DynPotvinPDExchangeMoveTabuMaker tabuMaker;
+    public ITabuMaker GetTabuMaker() {
+      if (tabuMaker == null)
+        tabuMaker = new DynPotvinPDExchangeMoveTabuMaker();
+
+      return tabuMaker;
+    }
+
+    [ThreadStatic]
+    private static DynPotvinPDExchangeTabuCriterion tabuChecker;
+    public ITabuChecker GetTabuChecker() {
+      if (tabuChecker == null) {
+        tabuChecker = new DynPotvinPDExchangeTabuCriterion();
+        tabuChecker.UseAspirationCriterion.Value = false;
+      }
+
+      return tabuChecker;
+    }
+
+    [ThreadStatic]
+    private static DynPotvinPDExchangeTabuCriterion softTabuChecker;
+    public ITabuChecker GetSoftTabuChecker() {
+      if (softTabuChecker == null) {
+        softTabuChecker = new DynPotvinPDExchangeTabuCriterion();
+        softTabuChecker.UseAspirationCriterion.Value = true;
+      }
+
+      return softTabuChecker;
+    }
+
+    #endregion
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeMoveEvaluator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeMoveEvaluator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeMoveEvaluator.cs	(revision 8670)
@@ -0,0 +1,84 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Data;
+using HeuristicLab.Common;
+using HeuristicLab.Optimization;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDExchangeMoveEvaluator", "Evaluates a exchange move for a PDP representation. ")]
+  [StorableClass]
+  public sealed class DynPotvinPDExchangeMoveEvaluator : PotvinMoveEvaluator, IDynPotvinPDExchangeMoveOperator {
+    public ILookupParameter<DynPotvinPDExchangeMove> PDExchangeMoveParameter {
+      get { return (ILookupParameter<DynPotvinPDExchangeMove>)Parameters["DynPotvinPDExchangeMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return PDExchangeMoveParameter; }
+    }
+
+    public ILookupParameter<VariableCollection> MemoriesParameter {
+      get { return (ILookupParameter<VariableCollection>)Parameters["Memories"]; }
+    }
+
+    public IValueParameter<StringValue> AdditionFrequencyMemoryKeyParameter {
+      get { return (IValueParameter<StringValue>)Parameters["AdditionFrequencyMemoryKey"]; }
+    }
+
+    public IValueParameter<DoubleValue> LambdaParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["Lambda"]; }
+    }
+
+    [StorableConstructor]
+    private DynPotvinPDExchangeMoveEvaluator(bool deserializing) : base(deserializing) { }
+
+    public DynPotvinPDExchangeMoveEvaluator()
+      : base() {
+        Parameters.Add(new LookupParameter<DynPotvinPDExchangeMove>("DynPotvinPDExchangeMove", "The move that should be evaluated."));
+
+       Parameters.Add(new LookupParameter<VariableCollection>("Memories", "The TS memory collection."));
+       Parameters.Add(new ValueParameter<StringValue>("AdditionFrequencyMemoryKey", "The key that is used for the addition frequency in the TS memory.", new StringValue("AdditionFrequency")));
+       Parameters.Add(new ValueParameter<DoubleValue>("Lambda", "The lambda parameter.", new DoubleValue(0.015)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDExchangeMoveEvaluator(this, cloner);
+    }
+
+    private DynPotvinPDExchangeMoveEvaluator(DynPotvinPDExchangeMoveEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void EvaluateMove() {
+      DynPotvinPDExchangeMove move = PDExchangeMoveParameter.ActualValue;
+
+      PotvinEncoding newSolution = PDExchangeMoveParameter.ActualValue.Individual.Clone() as PotvinEncoding;
+      DynPotvinPDExchangeMoveMaker.Apply(newSolution, move, ProblemInstance);
+
+      UpdateEvaluation(newSolution);
+    } 
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeMoveGenerator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeMoveGenerator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeMoveGenerator.cs	(revision 8670)
@@ -0,0 +1,78 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Parameters;
+using System.Collections.Generic;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Common;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDExchangeMoveGenerator", "Generates exchange moves from a given PDP encoding.")]
+  [StorableClass]
+  public abstract class DynPotvinPDExchangeMoveGenerator : PotvinMoveGenerator, IDynPotvinPDExchangeMoveOperator {
+    public ILookupParameter<DynPotvinPDExchangeMove> PDExchangeMoveParameter {
+      get { return (ILookupParameter<DynPotvinPDExchangeMove>)Parameters["DynPotvinPDExchangeMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return PDExchangeMoveParameter; }
+    }
+
+    protected ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+
+    [StorableConstructor]
+    protected DynPotvinPDExchangeMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public DynPotvinPDExchangeMoveGenerator()
+      : base() {
+        Parameters.Add(new LookupParameter<DynPotvinPDExchangeMove>("DynPotvinPDExchangeMove", "The moves that should be generated in subscopes."));
+        Parameters.Add(new ScopeParameter("CurrentScope", "The current scope where the moves should be added as subscopes."));
+    }
+
+    protected DynPotvinPDExchangeMoveGenerator(DynPotvinPDExchangeMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected abstract DynPotvinPDExchangeMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance);
+
+    public override IOperation Apply() {
+      IOperation next = base.Apply();
+
+      PotvinEncoding individual = VRPToursParameter.ActualValue as PotvinEncoding;
+      DynPotvinPDExchangeMove[] moves = GenerateMoves(individual, ProblemInstance);
+      Scope[] moveScopes = new Scope[moves.Length];
+      for (int i = 0; i < moveScopes.Length; i++) {
+        moveScopes[i] = new Scope(i.ToString());
+        moveScopes[i].Variables.Add(new Variable(PDExchangeMoveParameter.ActualName, moves[i]));
+      }
+      CurrentScopeParameter.ActualValue.SubScopes.AddRange(moveScopes);
+
+      return next;
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeMoveMaker.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeMoveMaker.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeMoveMaker.cs	(revision 8670)
@@ -0,0 +1,122 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+using HeuristicLab.Problems.VehicleRouting;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDExchangeMoveMaker", "Peforms the exchange move on a given PDP encoding and updates the quality.")]
+  [StorableClass]
+  public class DynPotvinPDExchangeMoveMaker : PotvinMoveMaker, IDynPotvinPDExchangeMoveOperator, IMoveMaker {
+    public ILookupParameter<DynPotvinPDExchangeMove> PDExchangeMoveParameter {
+      get { return (ILookupParameter<DynPotvinPDExchangeMove>)Parameters["DynPotvinPDExchangeMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return PDExchangeMoveParameter; }
+    }
+
+    [StorableConstructor]
+    private DynPotvinPDExchangeMoveMaker(bool deserializing) : base(deserializing) { }
+
+    public DynPotvinPDExchangeMoveMaker()
+      : base() {
+        Parameters.Add(new LookupParameter<DynPotvinPDExchangeMove>("DynPotvinPDExchangeMove", "The moves that should be made."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDExchangeMoveMaker(this, cloner);
+    }
+
+    protected DynPotvinPDExchangeMoveMaker(DynPotvinPDExchangeMoveMaker original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static void Apply(PotvinEncoding solution, DynPotvinPDExchangeMove move, IVRPProblemInstance problemInstance) {
+      if (move.Tour >= solution.Tours.Count)
+        solution.Tours.Add(new Tour());
+      Tour tour = solution.Tours[move.Tour];
+
+      Tour oldTour = solution.Tours.Find(t => t.Stops.Contains(move.City));
+      oldTour.Stops.Remove(move.City);
+
+      if (problemInstance is IPickupAndDeliveryProblemInstance) {
+        IPickupAndDeliveryProblemInstance pdp = problemInstance as IPickupAndDeliveryProblemInstance;
+
+        Tour oldTour2;
+        int location = pdp.GetPickupDeliveryLocation(move.City);
+        if (location > 0 && location != move.City) {
+          oldTour2 = solution.Tours.Find(t => t.Stops.Contains(location));
+          oldTour2.Stops.Remove(location);
+        }
+
+        location = pdp.GetPickupDeliveryLocation(move.Replaced);
+        if (location > 0 && location != move.Replaced) {
+          oldTour2 = solution.Tours.Find(t => t.Stops.Contains(location));
+          oldTour2.Stops.Remove(location);
+        }
+
+        tour.Stops.Remove(move.Replaced);
+
+        if (move.City != pdp.GetPickupDeliveryLocation(move.City))
+          DynPotvinPDRearrangeMoveMaker.InsertPair(solution, tour, move.City, pdp.GetPickupDeliveryLocation(move.City), problemInstance);
+        else {
+          int place = solution.FindBestInsertionPlace(tour, move.City);
+          tour.Stops.Insert(place, move.City);
+        }
+
+        if (move.Replaced != pdp.GetPickupDeliveryLocation(move.Replaced))
+          DynPotvinPDRearrangeMoveMaker.InsertPair(solution, oldTour, move.Replaced, pdp.GetPickupDeliveryLocation(move.Replaced), problemInstance);
+        else {
+          int place = solution.FindBestInsertionPlace(oldTour, move.Replaced);
+          oldTour.Stops.Insert(place, move.Replaced);
+        }
+      } else {
+        tour.Stops.Remove(move.Replaced);
+
+        int place = solution.FindBestInsertionPlace(tour, move.City);
+        tour.Stops.Insert(place, move.City);
+
+        place = solution.FindBestInsertionPlace(oldTour, move.Replaced);
+        oldTour.Stops.Insert(place, move.Replaced);
+      }
+    }
+
+    protected override void PerformMove() {
+      DynPotvinPDExchangeMove move = PDExchangeMoveParameter.ActualValue;
+
+      PotvinEncoding newSolution = move.Individual.Clone() as PotvinEncoding;
+      Apply(newSolution, move, ProblemInstance);
+      newSolution.Repair();
+      VRPToursParameter.ActualValue = newSolution;
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeMoveTabuCriterion.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeMoveTabuCriterion.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeMoveTabuCriterion.cs	(revision 8670)
@@ -0,0 +1,166 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDExchangeTabuCriterion", @"Checks if a certain exchange move is tabu.")]
+  [StorableClass]
+  public class DynPotvinPDExchangeTabuCriterion : SingleSuccessorOperator, IDynPotvinPDExchangeMoveOperator, ITabuChecker, IPotvinOperator, IVRPMoveOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+
+    public ILookupParameter<DynPotvinPDExchangeMove> PDExchangeMoveParameter {
+      get { return (ILookupParameter<DynPotvinPDExchangeMove>)Parameters["DynPotvinPDExchangeMove"]; }
+    }
+    public ILookupParameter VRPMoveParameter {
+      get { return PDExchangeMoveParameter; }
+    }
+    public ILookupParameter<IVRPEncoding> VRPToursParameter {
+      get { return (ILookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (LookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }  
+
+    public ILookupParameter<ItemList<IItem>> TabuListParameter {
+      get { return (ILookupParameter<ItemList<IItem>>)Parameters["TabuList"]; }
+    }
+    public ILookupParameter<BoolValue> MoveTabuParameter {
+      get { return (ILookupParameter<BoolValue>)Parameters["MoveTabu"]; }
+    }
+    public IValueLookupParameter<BoolValue> MaximizationParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    public ILookupParameter<DoubleValue> MoveQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; }
+    }
+    public ValueParameter<BoolValue> UseAspirationCriterionParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["UseAspirationCriterion"]; }
+    }
+
+    public ILookupParameter<DoubleValue> MoveDistanceParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveDistance"]; }
+    }
+    public ILookupParameter<DoubleValue> MoveOverloadParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveOverload"]; }
+    }
+    public ILookupParameter<DoubleValue> MoveTardinessParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveTardiness"]; }
+    }
+
+    public BoolValue UseAspirationCriterion {
+      get { return UseAspirationCriterionParameter.Value; }
+      set { UseAspirationCriterionParameter.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected DynPotvinPDExchangeTabuCriterion(bool deserializing) : base(deserializing) { }
+    protected DynPotvinPDExchangeTabuCriterion(DynPotvinPDExchangeTabuCriterion original, Cloner cloner) : base(original, cloner) { }
+    public DynPotvinPDExchangeTabuCriterion()
+      : base() {
+      Parameters.Add(new LookupParameter<DynPotvinPDExchangeMove>("DynPotvinPDExchangeMove", "The moves that should be made."));
+      Parameters.Add(new LookupParameter<IVRPEncoding>("VRPTours", "The VRP tours considered in the move."));
+      Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The VRP problem instance"));
+
+      Parameters.Add(new LookupParameter<BoolValue>("MoveTabu", "The variable to store if a move was tabu."));
+      Parameters.Add(new LookupParameter<ItemList<IItem>>("TabuList", "The tabu list."));
+      Parameters.Add(new ValueParameter<BoolValue>("UseAspirationCriterion", "Whether to use the aspiration criterion or not.", new BoolValue(true)));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem, else if it is a minimization problem."));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", "The quality of the current move."));
+
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveDistance", "The distance of the move"));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveOverload", "The overload of the move"));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveTardiness", "The tardiness of the move"));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDExchangeTabuCriterion(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      ItemList<IItem> tabuList = TabuListParameter.ActualValue;
+      double moveQuality = MoveQualityParameter.ActualValue.Value;
+      bool useAspiration = UseAspirationCriterion.Value;
+      bool isTabu = false;
+      DynPotvinPDExchangeMove move = PDExchangeMoveParameter.ActualValue;
+
+      foreach (IItem tabuMove in tabuList) {
+        DynPotvinPDRelocateMoveAttribute attribute = tabuMove as DynPotvinPDRelocateMoveAttribute;
+
+        if (attribute != null) {
+          double distance = 0;
+          if (MoveDistanceParameter.ActualValue != null)
+            distance = MoveDistanceParameter.ActualValue.Value;
+
+          double overload = 0;
+          if (MoveOverloadParameter.ActualValue != null)
+            overload = MoveOverloadParameter.ActualValue.Value;
+
+          double tardiness = 0;
+          if (MoveTardinessParameter.ActualValue != null)
+            tardiness = MoveTardinessParameter.ActualValue.Value;
+
+          IVRPProblemInstance instance = ProblemInstanceParameter.ActualValue;
+          double quality = attribute.Distance * instance.DistanceFactor.Value;
+
+          IHomogenousCapacitatedProblemInstance cvrp = instance as IHomogenousCapacitatedProblemInstance;
+          if (cvrp != null)
+            quality += attribute.Overload * cvrp.OverloadPenalty.Value;
+
+          ITimeWindowedProblemInstance vrptw = instance as ITimeWindowedProblemInstance;
+          if (vrptw != null)
+            quality += attribute.Tardiness * vrptw.TardinessPenalty.Value;
+
+          IPickupAndDeliveryProblemInstance pdp = instance as IPickupAndDeliveryProblemInstance;
+          if (pdp != null)
+            quality += attribute.PickupViolations * pdp.PickupViolationPenalty.Value;
+
+          if (!useAspiration || moveQuality >= quality) {
+            if ((attribute.City == move.City && attribute.Tour == move.Tour) ||
+              (attribute.City == move.Replaced && attribute.Tour == move.OldTour)) {
+              isTabu = true;
+              break;
+            }
+
+            if (attribute.Distance == distance && attribute.Overload == overload && attribute.Tardiness == tardiness) {
+              isTabu = true;
+              break;
+            }
+          }
+        }
+      }
+      
+      MoveTabuParameter.ActualValue = new BoolValue(isTabu);
+      return base.Apply();
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeMoveTabuMaker.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeMoveTabuMaker.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeMoveTabuMaker.cs	(revision 8670)
@@ -0,0 +1,144 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Operators;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDExchangeMoveTabuMaker", "Declares a given exchange move as tabu.")]
+  [StorableClass]
+  public class DynPotvinPDExchangeMoveTabuMaker : SingleSuccessorOperator, ITabuMaker, IDynPotvinPDExchangeMoveOperator, IPotvinOperator, IVRPMoveOperator {
+    public LookupParameter<ItemList<IItem>> TabuListParameter {
+      get { return (LookupParameter<ItemList<IItem>>)Parameters["TabuList"]; }
+    }
+    public ValueLookupParameter<IntValue> TabuTenureParameter {
+      get { return (ValueLookupParameter<IntValue>)Parameters["TabuTenure"]; }
+    }
+    public ILookupParameter<DoubleValue> MoveQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; }
+    }
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public IValueLookupParameter<BoolValue> MaximizationParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+
+    
+    public ILookupParameter<DynPotvinPDExchangeMove> PDExchangeMoveParameter {
+      get { return (ILookupParameter<DynPotvinPDExchangeMove>)Parameters["DynPotvinPDExchangeMove"]; }
+    }
+    public ILookupParameter VRPMoveParameter {
+      get { return PDExchangeMoveParameter; }
+    }
+    public ILookupParameter<IVRPEncoding> VRPToursParameter {
+      get { return (ILookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (LookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+
+    public ILookupParameter<DoubleValue> DistanceParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Distance"]; }
+    }
+    public ILookupParameter<DoubleValue> OverloadParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Overload"]; }
+    }
+    public ILookupParameter<DoubleValue> TardinessParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Tardiness"]; }
+    }
+    public ILookupParameter<IntValue> PickupViolationsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["PickupViolations"]; }
+    }
+
+    [StorableConstructor]
+    protected DynPotvinPDExchangeMoveTabuMaker(bool deserializing) : base(deserializing) { }
+    protected DynPotvinPDExchangeMoveTabuMaker(DynPotvinPDExchangeMoveTabuMaker original, Cloner cloner) : base(original, cloner) { }
+    public DynPotvinPDExchangeMoveTabuMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<ItemList<IItem>>("TabuList", "The tabu list where move attributes are stored."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("TabuTenure", "The tenure of the tabu list."));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", "The quality of the move."));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality of the solution."));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem, else if it is a minimization problem."));
+
+        Parameters.Add(new LookupParameter<DynPotvinPDExchangeMove>("DynPotvinPDExchangeMove", "The moves that should be made."));
+        Parameters.Add(new LookupParameter<IVRPEncoding>("VRPTours", "The VRP tours considered in the move."));
+        Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The VRP problem instance"));
+
+        Parameters.Add(new LookupParameter<DoubleValue>("Distance", "The distance of the individual"));
+        Parameters.Add(new LookupParameter<DoubleValue>("Overload", "The overload of the individual"));
+        Parameters.Add(new LookupParameter<DoubleValue>("Tardiness", "The tardiness of the individual"));
+        Parameters.Add(new LookupParameter<IntValue>("PickupViolations", "The number of pickup violations."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDExchangeMoveTabuMaker(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      ItemList<IItem> tabuList = TabuListParameter.ActualValue;
+      int tabuTenure = TabuTenureParameter.ActualValue.Value;
+
+      int overlength = tabuList.Count - tabuTenure;
+      if (overlength >= 0) {
+        for (int i = 0; i < tabuTenure - 1; i++)
+          tabuList[i] = tabuList[i + overlength + 1];
+        while (tabuList.Count >= tabuTenure)
+          tabuList.RemoveAt(tabuList.Count - 1);
+      }
+
+      DynPotvinPDExchangeMove move = PDExchangeMoveParameter.ActualValue;
+      double moveQuality = MoveQualityParameter.ActualValue.Value;
+      double quality = QualityParameter.ActualValue.Value;
+      double baseQuality = moveQuality;
+      if (quality < moveQuality) baseQuality = quality; // we make an uphill move, the lower bound is the solution quality
+
+      double distance = 0;
+      if (DistanceParameter.ActualValue != null)
+        distance = DistanceParameter.ActualValue.Value;
+
+      double overload = 0;
+      if (OverloadParameter.ActualValue != null)
+        overload = OverloadParameter.ActualValue.Value;
+
+      double tardiness = 0;
+      if (TardinessParameter.ActualValue != null)
+        tardiness = TardinessParameter.ActualValue.Value;
+
+      int pickupViolations = 0;
+      if (PickupViolationsParameter.ActualValue != null)
+        pickupViolations = PickupViolationsParameter.ActualValue.Value;
+
+      tabuList.Add(new DynPotvinPDRelocateMoveAttribute(baseQuality, move.OldTour, move.City, distance, overload, tardiness, pickupViolations));
+      tabuList.Add(new DynPotvinPDRelocateMoveAttribute(baseQuality, move.Tour, move.Replaced, distance, overload, tardiness, pickupViolations));
+      return base.Apply();
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeMultiMoveGenerator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeMultiMoveGenerator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeMultiMoveGenerator.cs	(revision 8670)
@@ -0,0 +1,75 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Parameters;
+using System.Collections.Generic;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Common;
+using HeuristicLab.Data;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDExchangeMultiMoveGenerator", "Generates exchange moves from a given PDP encoding.")]
+  [StorableClass]
+  public sealed class DynPotvinPDExchangeMultiMoveGenerator : DynPotvinPDExchangeMoveGenerator, IMultiMoveGenerator, IMultiVRPMoveGenerator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public IValueLookupParameter<IntValue> SampleSizeParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["SampleSize"]; }
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDExchangeMultiMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private DynPotvinPDExchangeMultiMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public DynPotvinPDExchangeMultiMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("SampleSize", "The number of moves to generate."));
+    }
+
+    private DynPotvinPDExchangeMultiMoveGenerator(DynPotvinPDExchangeMultiMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override DynPotvinPDExchangeMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<DynPotvinPDExchangeMove> result = new List<DynPotvinPDExchangeMove>();
+
+      for (int i = 0; i < SampleSizeParameter.ActualValue.Value; i++) {
+        var move = DynPotvinPDExchangeSingleMoveGenerator.Apply(individual, ProblemInstance, RandomParameter.ActualValue);
+        if (move != null)
+          result.Add(move);
+      }
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeSingleMoveGenerator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeSingleMoveGenerator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Exchange/PotvinPDExchangeSingleMoveGenerator.cs	(revision 8670)
@@ -0,0 +1,118 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Parameters;
+using System.Collections.Generic;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Common;
+using HeuristicLab.Data;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+using HeuristicLab.Problems.VehicleRouting;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDExchangeSingleMoveGenerator", "Generates a single exchange move from a given PDP encoding.")]
+  [StorableClass]
+  public sealed class DynPotvinPDExchangeSingleMoveGenerator : DynPotvinPDExchangeMoveGenerator,
+    ISingleMoveGenerator {    
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDExchangeSingleMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private DynPotvinPDExchangeSingleMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public DynPotvinPDExchangeSingleMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+    }
+
+    private DynPotvinPDExchangeSingleMoveGenerator(DynPotvinPDExchangeSingleMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static DynPotvinPDExchangeMove Apply(PotvinEncoding individual, IVRPProblemInstance problemInstance, IRandom rand) {
+      List<int> cities = new List<int>();
+
+      IPickupAndDeliveryProblemInstance pdp = problemInstance as IPickupAndDeliveryProblemInstance;
+      for (int i = 1; i <= individual.Cities; i++) {
+        if (pdp == null || pdp.GetDemand(i) >= 0)
+          cities.Add(i);
+      }
+
+      if (cities.Count > 1 && individual.Tours.Count > 1) {
+        DynPotvinPDExchangeMove move = null;
+        while (cities.Count > 1 && move == null) {
+          int city = cities[rand.Next(cities.Count)];
+          Tour oldTour = individual.Tours.Find(t => t.Stops.Contains(city));
+          int oldTourIndex = individual.Tours.IndexOf(oldTour);
+
+          int max = individual.Tours.Count;
+          if (individual.Tours.Count < problemInstance.Vehicles.Value)
+            max = max - 1;
+
+          int newTourIndex = rand.Next(max);
+          if (newTourIndex >= oldTourIndex)
+            newTourIndex++;
+
+          Tour newTour = individual.Tours[newTourIndex];
+          List<int> tourCities = new List<int>();
+          foreach (int stop in newTour.Stops) {
+            if (pdp == null ||
+              ((pdp.GetDemand(stop) >= 0 || pdp.GetPickupDeliveryLocation(stop) <= 0 || pdp.GetPickupDeliveryLocation(stop) == stop) &&
+              pdp.GetPickupDeliveryLocation(stop) != pdp.GetPickupDeliveryLocation(city) &&
+              pdp.GetPickupDeliveryLocation(stop) != city &&
+              pdp.GetPickupDeliveryLocation(city) != stop))
+              tourCities.Add(stop);
+          }
+
+          if (tourCities.Count > 0) {
+            int replaced = tourCities[rand.Next(tourCities.Count)];
+            move = new DynPotvinPDExchangeMove(city, oldTourIndex, newTourIndex, replaced, individual);
+          }
+        }
+
+        return move;
+      } else {
+        return null;
+      }             
+    }
+
+    protected override DynPotvinPDExchangeMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<DynPotvinPDExchangeMove> result = new List<DynPotvinPDExchangeMove>();
+
+      DynPotvinPDExchangeMove move = Apply(individual, ProblemInstance, RandomParameter.ActualValue);
+      if (move != null)
+        result.Add(move);
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/PotvinPDRelocateMoveAttribute.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/PotvinPDRelocateMoveAttribute.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/PotvinPDRelocateMoveAttribute.cs	(revision 8670)
@@ -0,0 +1,85 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDRelocateMoveAttribute", "PD relocation move attribute")]
+  [StorableClass]
+  public class DynPotvinPDRelocateMoveAttribute : VRPMoveAttribute {
+    [Storable]
+    public int Tour { get; private set; }
+    [Storable]
+    public int City { get; set; }
+
+    [Storable]
+    public double Distance { get; private set; }
+    [Storable]
+    public double Overload { get; private set; }
+    [Storable]
+    public double Tardiness { get; private set; }
+    [Storable]
+    public int PickupViolations { get; private set; }
+
+    [StorableConstructor]
+    protected DynPotvinPDRelocateMoveAttribute(bool deserializing) : base(deserializing) { }
+    protected DynPotvinPDRelocateMoveAttribute(DynPotvinPDRelocateMoveAttribute original, Cloner cloner)
+      : base(original, cloner) {
+        this.Tour = original.Tour;
+        this.City = original.City;
+        this.Distance = original.Distance;
+        this.Overload = original.Overload;
+        this.Tardiness = original.Tardiness;
+        this.PickupViolations = original.PickupViolations;
+    }
+    public DynPotvinPDRelocateMoveAttribute(double moveQuality, int tour, int city, 
+      double distance, double overload, double tardiness, int pickupViolations)
+      : base(moveQuality) {
+      Tour = tour;
+      City = city;
+      Distance = distance;
+      Overload = overload;
+      Tardiness = tardiness;
+      PickupViolations = pickupViolations;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDRelocateMoveAttribute(this, cloner);
+    }
+
+    public override int GetHashCode() {
+      return Tour.GetHashCode() + City.GetHashCode();
+    }
+
+    public override bool Equals(object obj) {
+      if (obj is DynPotvinPDRelocateMoveAttribute) {
+        DynPotvinPDRelocateMoveAttribute other = obj as DynPotvinPDRelocateMoveAttribute;
+
+        return Tour == other.Tour && City == other.City;
+      } else {
+        return base.Equals(obj);
+      }
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/IPotvinPDRearrangeMoveOperator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/IPotvinPDRearrangeMoveOperator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/IPotvinPDRearrangeMoveOperator.cs	(revision 8670)
@@ -0,0 +1,31 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  public interface IDynPotvinPDRearrangeMoveOperator : IVRPMoveOperator {
+    ILookupParameter<DynPotvinPDRearrangeMove> PDRearrangeMoveParameter { get; }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeExhaustiveMoveGenerator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeExhaustiveMoveGenerator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeExhaustiveMoveGenerator.cs	(revision 8670)
@@ -0,0 +1,67 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Parameters;
+using System.Collections.Generic;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Common;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDRearrangeExhaustiveMoveGenerator", "Generates rearrange moves from a given PDP encoding.")]
+  [StorableClass]
+  public sealed class DynPotvinPDRearrangeExhaustiveMoveGenerator : DynPotvinPDRearrangeMoveGenerator, IExhaustiveMoveGenerator {
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDRearrangeExhaustiveMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private DynPotvinPDRearrangeExhaustiveMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public DynPotvinPDRearrangeExhaustiveMoveGenerator()
+      : base() {
+    }
+
+    private DynPotvinPDRearrangeExhaustiveMoveGenerator(DynPotvinPDRearrangeExhaustiveMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override DynPotvinPDRearrangeMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<DynPotvinPDRearrangeMove> result = new List<DynPotvinPDRearrangeMove>();
+      IPickupAndDeliveryProblemInstance pdp = problemInstance as IPickupAndDeliveryProblemInstance;
+
+      for (int i = 1; i <= problemInstance.Cities.Value; i++) {
+        if (pdp == null || pdp.GetDemand(i) >= 0 || pdp.GetPickupDeliveryLocation(i) <= 0 || pdp.GetPickupDeliveryLocation(i) == i) {
+          int tour = individual.Tours.FindIndex(t => t.Stops.Contains(i));
+
+          result.Add(new DynPotvinPDRearrangeMove(i, tour, individual));
+        }
+      }
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeMove.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeMove.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeMove.cs	(revision 8670)
@@ -0,0 +1,126 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Common;
+using System.Collections.Generic;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Data;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Optimization;
+using System;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDRearrangeMove", "Item that describes a rearrange move on a PDP representation.")]
+  [StorableClass]
+  public class DynPotvinPDRearrangeMove: Item, IVRPMove {
+    [Storable]
+    public IVRPEncoding Individual { get; protected set; }
+    
+    [Storable]
+    public int City { get; protected set; }
+
+    [Storable]
+    public int Tour { get; protected set; }
+   
+    public DynPotvinPDRearrangeMove(): base() {
+      City = -1;
+      Tour = -1;
+
+      Individual = null;
+    }
+
+    public DynPotvinPDRearrangeMove(int city, int tour, PotvinEncoding individual) {
+      City = city;
+      Tour = tour;
+
+      this.Individual = individual.Clone() as PotvinEncoding;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDRearrangeMove(this, cloner);
+    }
+
+    protected DynPotvinPDRearrangeMove(DynPotvinPDRearrangeMove original, Cloner cloner)
+      : base(original, cloner) {
+      this.City = original.City;
+      this.Tour = original.Tour;
+
+      this.Individual = cloner.Clone(Individual) as PotvinEncoding;
+    }
+
+    #region IVRPMove Members
+
+    [ThreadStatic]
+    private static DynPotvinPDRearrangeMoveEvaluator moveEvaluator;
+    public VRPMoveEvaluator GetMoveEvaluator() {
+      if(moveEvaluator == null)
+        moveEvaluator = new DynPotvinPDRearrangeMoveEvaluator();
+
+      return moveEvaluator;
+    }
+
+    [ThreadStatic]
+    private static DynPotvinPDRearrangeMoveMaker moveMaker;
+    public VRPMoveMaker GetMoveMaker() {
+      if (moveMaker == null)
+        moveMaker = new DynPotvinPDRearrangeMoveMaker();
+
+      return moveMaker;
+    }
+
+    [ThreadStatic]
+    private static DynPotvinPDRearrangeMoveTabuMaker tabuMaker;
+    public ITabuMaker GetTabuMaker() {
+      if (tabuMaker == null)
+        tabuMaker = new DynPotvinPDRearrangeMoveTabuMaker();
+
+      return tabuMaker;
+    }
+
+    [ThreadStatic]
+    private static DynPotvinPDRearrangeTabuCriterion tabuChecker;
+    public ITabuChecker GetTabuChecker() {
+      if (tabuChecker == null) {
+        tabuChecker = new DynPotvinPDRearrangeTabuCriterion();
+        tabuChecker.UseAspirationCriterion.Value = false;
+      }
+
+      return tabuChecker;
+    }
+
+    [ThreadStatic]
+    private static DynPotvinPDRearrangeTabuCriterion softTabuChecker;
+    public ITabuChecker GetSoftTabuChecker() {
+      if (softTabuChecker == null) {
+        softTabuChecker = new DynPotvinPDRearrangeTabuCriterion();
+        softTabuChecker.UseAspirationCriterion.Value = true;
+      }
+
+      return softTabuChecker;
+    }
+
+    #endregion
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeMoveEvaluator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeMoveEvaluator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeMoveEvaluator.cs	(revision 8670)
@@ -0,0 +1,84 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Data;
+using HeuristicLab.Common;
+using HeuristicLab.Optimization;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDRearrangeMoveEvaluator", "Evaluates a rearrange move for a PDP representation. ")]
+  [StorableClass]
+  public sealed class DynPotvinPDRearrangeMoveEvaluator : PotvinMoveEvaluator, IDynPotvinPDRearrangeMoveOperator {
+    public ILookupParameter<DynPotvinPDRearrangeMove> PDRearrangeMoveParameter {
+      get { return (ILookupParameter<DynPotvinPDRearrangeMove>)Parameters["DynPotvinPDRearrangeMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return PDRearrangeMoveParameter; }
+    }
+
+    public ILookupParameter<VariableCollection> MemoriesParameter {
+      get { return (ILookupParameter<VariableCollection>)Parameters["Memories"]; }
+    }
+
+    public IValueParameter<StringValue> AdditionFrequencyMemoryKeyParameter {
+      get { return (IValueParameter<StringValue>)Parameters["AdditionFrequencyMemoryKey"]; }
+    }
+
+    public IValueParameter<DoubleValue> LambdaParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["Lambda"]; }
+    }
+
+    [StorableConstructor]
+    private DynPotvinPDRearrangeMoveEvaluator(bool deserializing) : base(deserializing) { }
+
+    public DynPotvinPDRearrangeMoveEvaluator()
+      : base() {
+        Parameters.Add(new LookupParameter<DynPotvinPDRearrangeMove>("DynPotvinPDRearrangeMove", "The move that should be evaluated."));
+
+       Parameters.Add(new LookupParameter<VariableCollection>("Memories", "The TS memory collection."));
+       Parameters.Add(new ValueParameter<StringValue>("AdditionFrequencyMemoryKey", "The key that is used for the addition frequency in the TS memory.", new StringValue("AdditionFrequency")));
+       Parameters.Add(new ValueParameter<DoubleValue>("Lambda", "The lambda parameter.", new DoubleValue(0.015)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDRearrangeMoveEvaluator(this, cloner);
+    }
+
+    private DynPotvinPDRearrangeMoveEvaluator(DynPotvinPDRearrangeMoveEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void EvaluateMove() {
+      DynPotvinPDRearrangeMove move = PDRearrangeMoveParameter.ActualValue;
+
+      PotvinEncoding newSolution = PDRearrangeMoveParameter.ActualValue.Individual.Clone() as PotvinEncoding;
+      DynPotvinPDRearrangeMoveMaker.Apply(newSolution, move, ProblemInstance);
+
+      UpdateEvaluation(newSolution);
+    } 
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeMoveGenerator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeMoveGenerator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeMoveGenerator.cs	(revision 8670)
@@ -0,0 +1,78 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Parameters;
+using System.Collections.Generic;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Common;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDRearrangeMoveGenerator", "Generates rearrange moves from a given PDP encoding.")]
+  [StorableClass]
+  public abstract class DynPotvinPDRearrangeMoveGenerator : PotvinMoveGenerator, IDynPotvinPDRearrangeMoveOperator {
+    public ILookupParameter<DynPotvinPDRearrangeMove> PDRearrangeMoveParameter {
+      get { return (ILookupParameter<DynPotvinPDRearrangeMove>)Parameters["DynPotvinPDRearrangeMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return PDRearrangeMoveParameter; }
+    }
+
+    protected ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+
+    [StorableConstructor]
+    protected DynPotvinPDRearrangeMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public DynPotvinPDRearrangeMoveGenerator()
+      : base() {
+        Parameters.Add(new LookupParameter<DynPotvinPDRearrangeMove>("DynPotvinPDRearrangeMove", "The moves that should be generated in subscopes."));
+        Parameters.Add(new ScopeParameter("CurrentScope", "The current scope where the moves should be added as subscopes."));
+    }
+
+    protected DynPotvinPDRearrangeMoveGenerator(DynPotvinPDRearrangeMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected abstract DynPotvinPDRearrangeMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance);
+
+    public override IOperation Apply() {
+      IOperation next = base.Apply();
+
+      PotvinEncoding individual = VRPToursParameter.ActualValue as PotvinEncoding;
+      DynPotvinPDRearrangeMove[] moves = GenerateMoves(individual, ProblemInstance);
+      Scope[] moveScopes = new Scope[moves.Length];
+      for (int i = 0; i < moveScopes.Length; i++) {
+        moveScopes[i] = new Scope(i.ToString());
+        moveScopes[i].Variables.Add(new Variable(PDRearrangeMoveParameter.ActualName, moves[i]));
+      }
+      CurrentScopeParameter.ActualValue.SubScopes.AddRange(moveScopes);
+
+      return next;
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeMoveMaker.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeMoveMaker.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeMoveMaker.cs	(revision 8670)
@@ -0,0 +1,145 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+using HeuristicLab.Problems.VehicleRouting;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDRearrangeMoveMaker", "Peforms the rearrange move on a given PDP encoding and updates the quality.")]
+  [StorableClass]
+  public class DynPotvinPDRearrangeMoveMaker : PotvinMoveMaker, IDynPotvinPDRearrangeMoveOperator, IMoveMaker {
+    public ILookupParameter<DynPotvinPDRearrangeMove> PDRearrangeMoveParameter {
+      get { return (ILookupParameter<DynPotvinPDRearrangeMove>)Parameters["DynPotvinPDRearrangeMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return PDRearrangeMoveParameter; }
+    }
+
+    [StorableConstructor]
+    private DynPotvinPDRearrangeMoveMaker(bool deserializing) : base(deserializing) { }
+
+    public DynPotvinPDRearrangeMoveMaker()
+      : base() {
+        Parameters.Add(new LookupParameter<DynPotvinPDRearrangeMove>("DynPotvinPDRearrangeMove", "The moves that should be made."));
+     }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDRearrangeMoveMaker(this, cloner);
+    }
+
+    protected DynPotvinPDRearrangeMoveMaker(DynPotvinPDRearrangeMoveMaker original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static void InsertPair(PotvinEncoding solution, Tour tour, int source, int target, IVRPProblemInstance problemInstance, int positionToAvoid = -1, int positionToAvoid2 = -1) {
+      int stops = tour.Stops.Count;
+      VRPEvaluation eval = problemInstance.EvaluateTour(tour, solution);
+      double minCosts = double.MaxValue;
+      int sourceLocation = -1;
+      int targetLocation = -1;
+
+      for (int i = 0; i <= stops; i++) {
+        tour.Stops.Insert(i, source);
+        VRPEvaluation tourEval = problemInstance.EvaluateTour(tour, solution);
+        double sourceCosts = tourEval.Quality - eval.Quality;
+
+        if (target > 0) {
+          for (int j = i + 1; j <= stops + 1; j++) {
+            if (positionToAvoid != i || positionToAvoid2 != j || stops == 0) {
+              bool feasible;
+              double targetCosts = problemInstance.GetInsertionCosts(tourEval, solution, target, 0, j, out feasible);
+
+              double costs = sourceCosts + targetCosts;
+              if (costs < minCosts) {
+                minCosts = costs;
+                sourceLocation = i;
+                targetLocation = j;
+              }
+            }
+          }
+        } else {
+          if (positionToAvoid != i || stops == 0) {
+            double costs = sourceCosts;
+            if (costs < minCosts) {
+              minCosts = costs;
+              sourceLocation = i;
+            }
+          }
+        }
+        
+        tour.Stops.Remove(source);
+      }
+
+      tour.Stops.Insert(sourceLocation, source);
+      if(targetLocation > 0)
+        tour.Stops.Insert(targetLocation, target);
+    }
+
+    public static void Apply(PotvinEncoding solution, DynPotvinPDRearrangeMove move, IVRPProblemInstance problemInstance) {
+      Tour tour = solution.Tours[move.Tour];
+      int position = tour.Stops.IndexOf(move.City);
+
+      IPickupAndDeliveryProblemInstance pdp = problemInstance as IPickupAndDeliveryProblemInstance;
+      if (pdp != null) {
+        int location = pdp.GetPickupDeliveryLocation(move.City);
+        tour.Stops.Remove(move.City);
+
+        int position2 = -1;
+        if (location > 0 && location != move.City) {
+          Tour tour2 = solution.Tours.Find(t => t.Stops.Contains(location));
+          position2 = tour2.Stops.IndexOf(location);
+          tour2.Stops.Remove(location);
+        }
+
+        if (location != move.City)
+          DynPotvinPDRearrangeMoveMaker.InsertPair(solution, tour, move.City, location, problemInstance, position, position2);
+        else {
+          int place = solution.FindBestInsertionPlace(tour, move.City, position);
+          tour.Stops.Insert(place, move.City);
+        }
+      } else {
+        tour.Stops.Remove(move.City);
+        int place = solution.FindBestInsertionPlace(tour, move.City, position);
+        tour.Stops.Insert(place, move.City);
+      }
+    }
+
+    protected override void PerformMove() {
+      DynPotvinPDRearrangeMove move = PDRearrangeMoveParameter.ActualValue;
+
+      PotvinEncoding newSolution = move.Individual.Clone() as PotvinEncoding;
+      Apply(newSolution, move, ProblemInstance);
+      newSolution.Repair();
+      VRPToursParameter.ActualValue = newSolution;
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeMoveTabuCriterion.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeMoveTabuCriterion.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeMoveTabuCriterion.cs	(revision 8670)
@@ -0,0 +1,165 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDRearrangeTabuCriterion", @"Checks if a certain rearrange move is tabu.")]
+  [StorableClass]
+  public class DynPotvinPDRearrangeTabuCriterion : SingleSuccessorOperator, IDynPotvinPDRearrangeMoveOperator, ITabuChecker, IPotvinOperator, IVRPMoveOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+
+    public ILookupParameter<DynPotvinPDRearrangeMove> PDRearrangeMoveParameter {
+      get { return (ILookupParameter<DynPotvinPDRearrangeMove>)Parameters["DynPotvinPDRearrangeMove"]; }
+    }
+    public ILookupParameter VRPMoveParameter {
+      get { return PDRearrangeMoveParameter; }
+    }
+    public ILookupParameter<IVRPEncoding> VRPToursParameter {
+      get { return (ILookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (LookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }  
+
+    public ILookupParameter<ItemList<IItem>> TabuListParameter {
+      get { return (ILookupParameter<ItemList<IItem>>)Parameters["TabuList"]; }
+    }
+    public ILookupParameter<BoolValue> MoveTabuParameter {
+      get { return (ILookupParameter<BoolValue>)Parameters["MoveTabu"]; }
+    }
+    public IValueLookupParameter<BoolValue> MaximizationParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    public ILookupParameter<DoubleValue> MoveQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; }
+    }
+    public ValueParameter<BoolValue> UseAspirationCriterionParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["UseAspirationCriterion"]; }
+    }
+
+    public ILookupParameter<DoubleValue> MoveDistanceParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveDistance"]; }
+    }
+    public ILookupParameter<DoubleValue> MoveOverloadParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveOverload"]; }
+    }
+    public ILookupParameter<DoubleValue> MoveTardinessParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveTardiness"]; }
+    }
+
+    public BoolValue UseAspirationCriterion {
+      get { return UseAspirationCriterionParameter.Value; }
+      set { UseAspirationCriterionParameter.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected DynPotvinPDRearrangeTabuCriterion(bool deserializing) : base(deserializing) { }
+    protected DynPotvinPDRearrangeTabuCriterion(DynPotvinPDRearrangeTabuCriterion original, Cloner cloner) : base(original, cloner) { }
+    public DynPotvinPDRearrangeTabuCriterion()
+      : base() {
+      Parameters.Add(new LookupParameter<DynPotvinPDRearrangeMove>("DynPotvinPDRearrangeMove", "The moves that should be made."));
+      Parameters.Add(new LookupParameter<IVRPEncoding>("VRPTours", "The VRP tours considered in the move."));
+      Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The VRP problem instance"));
+
+      Parameters.Add(new LookupParameter<BoolValue>("MoveTabu", "The variable to store if a move was tabu."));
+      Parameters.Add(new LookupParameter<ItemList<IItem>>("TabuList", "The tabu list."));
+      Parameters.Add(new ValueParameter<BoolValue>("UseAspirationCriterion", "Whether to use the aspiration criterion or not.", new BoolValue(true)));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem, else if it is a minimization problem."));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", "The quality of the current move."));
+
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveDistance", "The distance of the move"));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveOverload", "The overload of the move"));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveTardiness", "The tardiness of the move"));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDRearrangeTabuCriterion(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      ItemList<IItem> tabuList = TabuListParameter.ActualValue;
+      double moveQuality = MoveQualityParameter.ActualValue.Value;
+      bool useAspiration = UseAspirationCriterion.Value;
+      bool isTabu = false;
+      DynPotvinPDRearrangeMove move = PDRearrangeMoveParameter.ActualValue;
+
+      foreach (IItem tabuMove in tabuList) {
+        DynPotvinPDRelocateMoveAttribute attribute = tabuMove as DynPotvinPDRelocateMoveAttribute;
+
+        if (attribute != null) {
+          double distance = 0;
+          if (MoveDistanceParameter.ActualValue != null)
+            distance = MoveDistanceParameter.ActualValue.Value;
+
+          double overload = 0;
+          if (MoveOverloadParameter.ActualValue != null)
+            overload = MoveOverloadParameter.ActualValue.Value;
+
+          double tardiness = 0;
+          if (MoveTardinessParameter.ActualValue != null)
+            tardiness = MoveTardinessParameter.ActualValue.Value;
+
+          IVRPProblemInstance instance = ProblemInstanceParameter.ActualValue;
+          double quality = attribute.Distance * instance.DistanceFactor.Value;
+
+          IHomogenousCapacitatedProblemInstance cvrp = instance as IHomogenousCapacitatedProblemInstance;
+          if (cvrp != null)
+            quality += attribute.Overload * cvrp.OverloadPenalty.Value;
+
+          ITimeWindowedProblemInstance vrptw = instance as ITimeWindowedProblemInstance;
+          if (vrptw != null)
+            quality += attribute.Tardiness * vrptw.TardinessPenalty.Value;
+
+          IPickupAndDeliveryProblemInstance pdp = instance as IPickupAndDeliveryProblemInstance;
+          if (pdp != null)
+            quality += attribute.PickupViolations * pdp.PickupViolationPenalty.Value;
+
+          if (!useAspiration || moveQuality >= quality) {
+            if (attribute.City == move.City && attribute.Tour == move.Tour) {
+              isTabu = true;
+              break;
+            }
+
+            if (attribute.Distance == distance && attribute.Overload == overload && attribute.Tardiness == tardiness) {
+              isTabu = true;
+              break;
+            }
+          }
+        }
+      }
+      
+      MoveTabuParameter.ActualValue = new BoolValue(isTabu);
+      return base.Apply();
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeMoveTabuMaker.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeMoveTabuMaker.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeMoveTabuMaker.cs	(revision 8670)
@@ -0,0 +1,105 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using System.Collections.Generic;
+using HeuristicLab.Data;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDRearrangeMoveTabuMaker", "Declares a given rearrange move as tabu.")]
+  [StorableClass]
+  public class DynPotvinPDRearrangeMoveTabuMaker : TabuMaker, IDynPotvinPDRearrangeMoveOperator, IPotvinOperator, IVRPMoveOperator {
+    public ILookupParameter<DynPotvinPDRearrangeMove> PDRearrangeMoveParameter {
+      get { return (ILookupParameter<DynPotvinPDRearrangeMove>)Parameters["DynPotvinPDRearrangeMove"]; }
+    }
+    public ILookupParameter VRPMoveParameter {
+      get { return PDRearrangeMoveParameter; }
+    }
+    public ILookupParameter<IVRPEncoding> VRPToursParameter {
+      get { return (ILookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (LookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+
+    public ILookupParameter<DoubleValue> DistanceParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Distance"]; }
+    }
+    public ILookupParameter<DoubleValue> OverloadParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Overload"]; }
+    }
+    public ILookupParameter<DoubleValue> TardinessParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Tardiness"]; }
+    }
+    public ILookupParameter<IntValue> PickupViolationsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["PickupViolations"]; }
+    }
+
+    [StorableConstructor]
+    protected DynPotvinPDRearrangeMoveTabuMaker(bool deserializing) : base(deserializing) { }
+    protected DynPotvinPDRearrangeMoveTabuMaker(DynPotvinPDRearrangeMoveTabuMaker original, Cloner cloner) : base(original, cloner) { }
+    public DynPotvinPDRearrangeMoveTabuMaker()
+      : base() {
+        Parameters.Add(new LookupParameter<DynPotvinPDRearrangeMove>("DynPotvinPDRearrangeMove", "The moves that should be made."));
+        Parameters.Add(new LookupParameter<IVRPEncoding>("VRPTours", "The VRP tours considered in the move."));
+        Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The VRP problem instance"));
+
+        Parameters.Add(new LookupParameter<DoubleValue>("Distance", "The distance of the individual"));
+        Parameters.Add(new LookupParameter<DoubleValue>("Overload", "The overload of the individual"));
+        Parameters.Add(new LookupParameter<DoubleValue>("Tardiness", "The tardiness of the individual"));
+        Parameters.Add(new LookupParameter<IntValue>("PickupViolations", "The number of pickup violations."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDRearrangeMoveTabuMaker(this, cloner);
+    }
+
+    protected override IItem GetTabuAttribute(bool maximization, double quality, double moveQuality) {
+      DynPotvinPDRearrangeMove move = PDRearrangeMoveParameter.ActualValue;
+      double baseQuality = moveQuality;
+      if (quality < moveQuality) baseQuality = quality; // we make an uphill move, the lower bound is the solution quality
+
+      double distance = 0;
+      if (DistanceParameter.ActualValue != null)
+        distance = DistanceParameter.ActualValue.Value;
+
+      double overload = 0;
+      if (OverloadParameter.ActualValue != null)
+        overload = OverloadParameter.ActualValue.Value;
+
+      double tardiness = 0;
+      if (TardinessParameter.ActualValue != null)
+        tardiness = TardinessParameter.ActualValue.Value;
+
+      int pickupViolations = 0;
+      if (PickupViolationsParameter.ActualValue != null)
+        pickupViolations = PickupViolationsParameter.ActualValue.Value;
+
+      return new DynPotvinPDRelocateMoveAttribute(baseQuality, move.Tour, move.City, distance, overload, tardiness, pickupViolations);
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeMultiMoveGenerator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeMultiMoveGenerator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeMultiMoveGenerator.cs	(revision 8670)
@@ -0,0 +1,75 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Parameters;
+using System.Collections.Generic;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Common;
+using HeuristicLab.Data;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDRearrangeMultiMoveGenerator", "Generates rearrange moves from a given PDP encoding.")]
+  [StorableClass]
+  public sealed class DynPotvinPDRearrangeMultiMoveGenerator : DynPotvinPDRearrangeMoveGenerator, IMultiMoveGenerator, IMultiVRPMoveGenerator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public IValueLookupParameter<IntValue> SampleSizeParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["SampleSize"]; }
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDRearrangeMultiMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private DynPotvinPDRearrangeMultiMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public DynPotvinPDRearrangeMultiMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("SampleSize", "The number of moves to generate."));
+    }
+
+    private DynPotvinPDRearrangeMultiMoveGenerator(DynPotvinPDRearrangeMultiMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override DynPotvinPDRearrangeMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<DynPotvinPDRearrangeMove> result = new List<DynPotvinPDRearrangeMove>();
+
+      for (int i = 0; i < SampleSizeParameter.ActualValue.Value; i++) {
+        var move = DynPotvinPDRearrangeSingleMoveGenerator.Apply(individual, ProblemInstance, RandomParameter.ActualValue);
+        if (move != null)
+          result.Add(move);
+      }
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeSingleMoveGenerator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeSingleMoveGenerator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Rearrange/PotvinPDRearrangeSingleMoveGenerator.cs	(revision 8670)
@@ -0,0 +1,88 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Parameters;
+using System.Collections.Generic;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Common;
+using HeuristicLab.Data;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDRearrangeSingleMoveGenerator", "Generates a single rearrange move from a given PDP encoding.")]
+  [StorableClass]
+  public sealed class DynPotvinPDRearrangeSingleMoveGenerator : DynPotvinPDRearrangeMoveGenerator,
+    ISingleMoveGenerator {    
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDRearrangeSingleMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private DynPotvinPDRearrangeSingleMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public DynPotvinPDRearrangeSingleMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+    }
+
+    private DynPotvinPDRearrangeSingleMoveGenerator(DynPotvinPDRearrangeSingleMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static DynPotvinPDRearrangeMove Apply(PotvinEncoding individual, IVRPProblemInstance problemInstance, IRandom rand) {
+      List<int> cities = new List<int>();
+
+      IPickupAndDeliveryProblemInstance pdp = problemInstance as IPickupAndDeliveryProblemInstance;
+      for (int i = 1; i <= individual.Cities; i++) {
+        if (pdp == null || pdp.GetDemand(i) >= 0 || pdp.GetPickupDeliveryLocation(i) <= 0 || pdp.GetPickupDeliveryLocation(i) == i)
+          cities.Add(i);
+      }
+
+      if (cities.Count > 0) {
+        int city = cities[rand.Next(cities.Count)];
+        int tour = individual.Tours.FindIndex(t => t.Stops.Contains(city));
+        return new DynPotvinPDRearrangeMove(city, tour, individual);
+      } else {
+        return null;
+      }
+    }
+
+    protected override DynPotvinPDRearrangeMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<DynPotvinPDRearrangeMove> result = new List<DynPotvinPDRearrangeMove>();
+
+      DynPotvinPDRearrangeMove move = Apply(individual, ProblemInstance, RandomParameter.ActualValue);
+      if (move != null)
+        result.Add(move);
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/IPotvinPDShiftMoveOperator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/IPotvinPDShiftMoveOperator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/IPotvinPDShiftMoveOperator.cs	(revision 8670)
@@ -0,0 +1,31 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  public interface IDynPotvinPDShiftMoveOperator : IVRPMoveOperator {
+    ILookupParameter<DynPotvinPDShiftMove> PDShiftMoveParameter { get; }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftExhaustiveMoveGenerator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftExhaustiveMoveGenerator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftExhaustiveMoveGenerator.cs	(revision 8670)
@@ -0,0 +1,79 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Parameters;
+using System.Collections.Generic;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Common;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDShiftExhaustiveMoveGenerator", "Generates shift moves from a given PDP encoding.")]
+  [StorableClass]
+  public sealed class DynPotvinPDShiftExhaustiveMoveGenerator : DynPotvinPDShiftMoveGenerator, IExhaustiveMoveGenerator {
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDShiftExhaustiveMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private DynPotvinPDShiftExhaustiveMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public DynPotvinPDShiftExhaustiveMoveGenerator()
+      : base() {
+    }
+
+    private DynPotvinPDShiftExhaustiveMoveGenerator(DynPotvinPDShiftExhaustiveMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override DynPotvinPDShiftMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<DynPotvinPDShiftMove> result = new List<DynPotvinPDShiftMove>();
+      IPickupAndDeliveryProblemInstance pdp = problemInstance as IPickupAndDeliveryProblemInstance;
+
+      int max = individual.Tours.Count;
+      if (individual.Tours.Count >= problemInstance.Vehicles.Value)
+        max = max - 1;
+
+      for (int i = 0; i < individual.Tours.Count; i++) {
+        for (int j = 0; j < individual.Tours[i].Stops.Count; j++) {
+          for (int k = 0; k <= max; k++) {
+            if (k != i) {
+              int city = individual.Tours[i].Stops[j];
+              if (pdp == null || pdp.GetDemand(city) >= 0 || pdp.GetPickupDeliveryLocation(city) <= 0 || pdp.GetPickupDeliveryLocation(city) == city) {
+                DynPotvinPDShiftMove move = new DynPotvinPDShiftMove(
+                  city, i, k, individual);
+
+                result.Add(move);
+              }
+            }
+          }
+        }
+      }
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftMove.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftMove.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftMove.cs	(revision 8670)
@@ -0,0 +1,130 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Common;
+using System.Collections.Generic;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Data;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Optimization;
+using System;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDShiftMove", "Item that describes a shift move on a PDP representation.")]
+  [StorableClass]
+  public class DynPotvinPDShiftMove: Item, IVRPMove {
+    [Storable]
+    public IVRPEncoding Individual { get; protected set; }
+    
+    [Storable]
+    public int City { get; protected set; }
+
+    [Storable]
+    public int OldTour { get; protected set; }
+
+    [Storable]
+    public int Tour { get; protected set; }
+   
+    public DynPotvinPDShiftMove(): base() {
+      City = -1;
+      Tour = -1;
+
+      Individual = null;
+    }
+
+    public DynPotvinPDShiftMove(int city, int oldTour, int tour, PotvinEncoding individual) {
+      City = city;
+      OldTour = oldTour;
+      Tour = tour;
+
+      this.Individual = individual.Clone() as PotvinEncoding;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDShiftMove(this, cloner);
+    }
+
+    protected DynPotvinPDShiftMove(DynPotvinPDShiftMove original, Cloner cloner)
+      : base(original, cloner) {
+      this.City = original.City;
+      this.OldTour = original.OldTour;
+      this.Tour = original.Tour;
+
+      this.Individual = cloner.Clone(Individual) as PotvinEncoding;
+    }
+
+    #region IVRPMove Members
+
+    [ThreadStatic]
+    private static DynPotvinPDShiftMoveEvaluator moveEvaluator;
+    public VRPMoveEvaluator GetMoveEvaluator() {
+      if (moveEvaluator == null)
+        moveEvaluator = new DynPotvinPDShiftMoveEvaluator();
+
+      return moveEvaluator;
+    }
+
+    [ThreadStatic]
+    private static DynPotvinPDShiftMoveMaker moveMaker;
+    public VRPMoveMaker GetMoveMaker() {
+      if (moveMaker == null)
+        moveMaker = new DynPotvinPDShiftMoveMaker();
+
+      return moveMaker;
+    }
+
+    [ThreadStatic]
+    private static DynPotvinPDShiftMoveTabuMaker tabuMaker;
+    public ITabuMaker GetTabuMaker() {
+      if (tabuMaker == null)
+        tabuMaker = new DynPotvinPDShiftMoveTabuMaker();
+
+      return tabuMaker;
+    }
+
+    [ThreadStatic]
+    private static DynPotvinPDShiftTabuCriterion tabuChecker;
+    public ITabuChecker GetTabuChecker() {
+      if (tabuChecker == null) {
+        tabuChecker = new DynPotvinPDShiftTabuCriterion();
+        tabuChecker.UseAspirationCriterion.Value = false;
+      }
+
+      return tabuChecker;
+    }
+
+    [ThreadStatic]
+    private static DynPotvinPDShiftTabuCriterion softTabuChecker;
+    public ITabuChecker GetSoftTabuChecker() {
+      if (softTabuChecker == null) {
+        softTabuChecker = new DynPotvinPDShiftTabuCriterion();
+        softTabuChecker.UseAspirationCriterion.Value = true;
+      }
+
+      return softTabuChecker;
+    }
+    #endregion
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftMoveEvaluator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftMoveEvaluator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftMoveEvaluator.cs	(revision 8670)
@@ -0,0 +1,103 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Data;
+using HeuristicLab.Common;
+using HeuristicLab.Optimization;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDShiftMoveEvaluator", "Evaluates a shift move for a PDP representation. ")]
+  [StorableClass]
+  public sealed class DynPotvinPDShiftMoveEvaluator : PotvinMoveEvaluator, IDynPotvinPDShiftMoveOperator {
+    public ILookupParameter<DynPotvinPDShiftMove> PDShiftMoveParameter {
+      get { return (ILookupParameter<DynPotvinPDShiftMove>)Parameters["DynPotvinPDShiftMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return PDShiftMoveParameter; }
+    }
+
+    public ILookupParameter<VariableCollection> MemoriesParameter {
+      get { return (ILookupParameter<VariableCollection>)Parameters["Memories"]; }
+    }
+
+    public IValueParameter<StringValue> AdditionFrequencyMemoryKeyParameter {
+      get { return (IValueParameter<StringValue>)Parameters["AdditionFrequencyMemoryKey"]; }
+    }
+
+    public IValueParameter<DoubleValue> LambdaParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["Lambda"]; }
+    }
+
+    [StorableConstructor]
+    private DynPotvinPDShiftMoveEvaluator(bool deserializing) : base(deserializing) { }
+
+    public DynPotvinPDShiftMoveEvaluator()
+      : base() {
+        Parameters.Add(new LookupParameter<DynPotvinPDShiftMove>("DynPotvinPDShiftMove", "The move that should be evaluated."));
+
+       Parameters.Add(new LookupParameter<VariableCollection>("Memories", "The TS memory collection."));
+       Parameters.Add(new ValueParameter<StringValue>("AdditionFrequencyMemoryKey", "The key that is used for the addition frequency in the TS memory.", new StringValue("AdditionFrequency")));
+       Parameters.Add(new ValueParameter<DoubleValue>("Lambda", "The lambda parameter.", new DoubleValue(0.015)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDShiftMoveEvaluator(this, cloner);
+    }
+
+    private DynPotvinPDShiftMoveEvaluator(DynPotvinPDShiftMoveEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void EvaluateMove() {
+      DynPotvinPDShiftMove move = PDShiftMoveParameter.ActualValue;
+
+      PotvinEncoding newSolution = PDShiftMoveParameter.ActualValue.Individual.Clone() as PotvinEncoding;
+      DynPotvinPDShiftMoveMaker.Apply(newSolution, move, ProblemInstance);
+      newSolution.Repair();
+      UpdateEvaluation(newSolution);
+
+      //Apply memory, only if move is worse
+      /*if (MoveQualityParameter.ActualValue.Value >= QualityParameter.ActualValue.Value) {
+        VariableCollection memory = MemoriesParameter.ActualValue;
+        string key = AdditionFrequencyMemoryKeyParameter.Value.Value;
+
+        if (memory != null && memory.ContainsKey(key)) {
+          ItemDictionary<PotvinCustomerRelocationMoveAttribute, IntValue> additionFrequency =
+               memory[key].Value as ItemDictionary<PotvinCustomerRelocationMoveAttribute, IntValue>;
+          PotvinCustomerRelocationMoveAttribute attr = new PotvinCustomerRelocationMoveAttribute(0, move.Tour, move.City);
+          if (additionFrequency.ContainsKey(attr)) {
+            int frequency = additionFrequency[attr].Value;
+            double quality = MoveQualityParameter.ActualValue.Value;
+
+            MoveQualityParameter.ActualValue.Value +=
+              LambdaParameter.Value.Value * quality * frequency;
+          }
+        }
+      }*/
+    } 
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftMoveGenerator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftMoveGenerator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftMoveGenerator.cs	(revision 8670)
@@ -0,0 +1,78 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Parameters;
+using System.Collections.Generic;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Common;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDShiftMoveGenerator", "Generates shift moves from a given PDP encoding.")]
+  [StorableClass]
+  public abstract class DynPotvinPDShiftMoveGenerator : PotvinMoveGenerator, IDynPotvinPDShiftMoveOperator {
+    public ILookupParameter<DynPotvinPDShiftMove> PDShiftMoveParameter {
+      get { return (ILookupParameter<DynPotvinPDShiftMove>)Parameters["DynPotvinPDShiftMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return PDShiftMoveParameter; }
+    }
+
+    protected ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+
+    [StorableConstructor]
+    protected DynPotvinPDShiftMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public DynPotvinPDShiftMoveGenerator()
+      : base() {
+        Parameters.Add(new LookupParameter<DynPotvinPDShiftMove>("DynPotvinPDShiftMove", "The moves that should be generated in subscopes."));
+        Parameters.Add(new ScopeParameter("CurrentScope", "The current scope where the moves should be added as subscopes."));
+    }
+
+    protected DynPotvinPDShiftMoveGenerator(DynPotvinPDShiftMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected abstract DynPotvinPDShiftMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance);
+
+    public override IOperation Apply() {
+      IOperation next = base.Apply();
+
+      PotvinEncoding individual = VRPToursParameter.ActualValue as PotvinEncoding;
+      DynPotvinPDShiftMove[] moves = GenerateMoves(individual, ProblemInstance);
+      Scope[] moveScopes = new Scope[moves.Length];
+      for (int i = 0; i < moveScopes.Length; i++) {
+        moveScopes[i] = new Scope(i.ToString());
+        moveScopes[i].Variables.Add(new Variable(PDShiftMoveParameter.ActualName, moves[i]));
+      }
+      CurrentScopeParameter.ActualValue.SubScopes.AddRange(moveScopes);
+
+      return next;
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftMoveMaker.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftMoveMaker.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftMoveMaker.cs	(revision 8670)
@@ -0,0 +1,173 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+using HeuristicLab.Problems.VehicleRouting;
+using System.Collections.Generic;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDShiftMoveMaker", "Peforms the shift move on a given PDP encoding and updates the quality.")]
+  [StorableClass]
+  public class DynPotvinPDShiftMoveMaker : PotvinMoveMaker, IDynPotvinPDShiftMoveOperator, IMoveMaker {
+    public ILookupParameter<DynPotvinPDShiftMove> PDShiftMoveParameter {
+      get { return (ILookupParameter<DynPotvinPDShiftMove>)Parameters["DynPotvinPDShiftMove"]; }
+    }
+
+    public ILookupParameter<VariableCollection> MemoriesParameter {
+      get { return (ILookupParameter<VariableCollection>)Parameters["Memories"]; }
+    }
+
+    public IValueParameter<StringValue> AdditionFrequencyMemoryKeyParameter {
+      get { return (IValueParameter<StringValue>)Parameters["AdditionFrequencyMemoryKey"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return PDShiftMoveParameter; }
+    }
+
+    [StorableConstructor]
+    private DynPotvinPDShiftMoveMaker(bool deserializing) : base(deserializing) { }
+
+    public DynPotvinPDShiftMoveMaker()
+      : base() {
+        Parameters.Add(new LookupParameter<DynPotvinPDShiftMove>("DynPotvinPDShiftMove", "The moves that should be made."));
+
+        Parameters.Add(new LookupParameter<VariableCollection>("Memories", "The TS memory collection."));
+        Parameters.Add(new ValueParameter<StringValue>("AdditionFrequencyMemoryKey", "The key that is used for the addition frequency in the TS memory.", new StringValue("AdditionFrequency")));
+     }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDShiftMoveMaker(this, cloner);
+    }
+
+    protected DynPotvinPDShiftMoveMaker(DynPotvinPDShiftMoveMaker original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static void Apply(PotvinEncoding solution, DynPotvinPDShiftMove move, IVRPProblemInstance problemInstance) {
+      bool newTour = false;
+
+      if (move.Tour >= solution.Tours.Count) {
+        solution.Tours.Add(new Tour());
+        newTour = true;
+      }
+      Tour tour = solution.Tours[move.Tour];
+
+      Tour oldTour = solution.Tours.Find(t => t.Stops.Contains(move.City));
+      oldTour.Stops.Remove(move.City);
+
+      if (problemInstance is IPickupAndDeliveryProblemInstance) {
+        IPickupAndDeliveryProblemInstance pdp = problemInstance as IPickupAndDeliveryProblemInstance;
+        
+        int location = pdp.GetPickupDeliveryLocation(move.City);
+        if (location > 0 && location != move.City) {
+          Tour oldTour2 = solution.Tours.Find(t => t.Stops.Contains(location));
+          oldTour2.Stops.Remove(location);
+          DynPotvinPDRearrangeMoveMaker.InsertPair(solution, tour, move.City, location, problemInstance);
+        } else {
+          int place = solution.FindBestInsertionPlace(tour, move.City);
+          tour.Stops.Insert(place, move.City);
+        } 
+      } else {
+        int place = solution.FindBestInsertionPlace(tour, move.City);
+        tour.Stops.Insert(place, move.City);
+      }
+
+      if (newTour) {
+        DynPDPProblemInstance dynPDP = problemInstance as DynPDPProblemInstance;
+
+        List<int> vehicles = new List<int>();
+        for (int i = move.Tour; i < problemInstance.Vehicles.Value; i++) {
+          int vehicle = solution.GetVehicleAssignment(i);
+          vehicles.Add(vehicle);
+        }
+
+        double bestQuality = double.MaxValue;
+        int bestVehicle = -1;
+
+        int originalVehicle = solution.GetVehicleAssignment(move.Tour);
+        foreach (int vehicle in vehicles) {
+          solution.VehicleAssignment[move.Tour] = vehicle;
+
+          double quality = problemInstance.EvaluateTour(tour, solution).Quality;
+          if (quality < bestQuality) {
+            bestQuality = quality;
+            bestVehicle = vehicle;
+          }
+        }
+
+        solution.VehicleAssignment[move.Tour] = originalVehicle;
+
+        int index = -1;
+        for (int i = move.Tour; i < solution.VehicleAssignment.Length; i++) {
+          if (solution.VehicleAssignment[i] == bestVehicle) {
+            index = i;
+            break;
+          }
+        }
+        solution.VehicleAssignment[index] = originalVehicle;
+        solution.VehicleAssignment[move.Tour] = bestVehicle;
+      }
+    }
+
+    protected override void PerformMove() {
+      DynPotvinPDShiftMove move = PDShiftMoveParameter.ActualValue;
+
+      PotvinEncoding newSolution = move.Individual.Clone() as PotvinEncoding;
+      Apply(newSolution, move, ProblemInstance);
+      newSolution.Repair();
+      VRPToursParameter.ActualValue = newSolution;
+
+      //reset move quality
+      VRPEvaluation eval = ProblemInstance.Evaluate(newSolution);
+      MoveQualityParameter.ActualValue.Value = eval.Quality;
+
+      //update memory
+      VariableCollection memory = MemoriesParameter.ActualValue;
+      string key = AdditionFrequencyMemoryKeyParameter.Value.Value;
+
+      if (memory != null) {
+        if (!memory.ContainsKey(key)) {
+          memory.Add(new Variable(key,
+              new ItemDictionary<PotvinCustomerRelocationMoveAttribute, IntValue>()));
+        }
+        ItemDictionary<PotvinCustomerRelocationMoveAttribute, IntValue> additionFrequency =
+          memory[key].Value as ItemDictionary<PotvinCustomerRelocationMoveAttribute, IntValue>;
+
+        PotvinCustomerRelocationMoveAttribute attr = new PotvinCustomerRelocationMoveAttribute(0, move.Tour, move.City);
+        if (!additionFrequency.ContainsKey(attr))
+          additionFrequency[attr] = new IntValue(0);
+
+        additionFrequency[attr].Value++;
+      }
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftMoveTabuCriterion.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftMoveTabuCriterion.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftMoveTabuCriterion.cs	(revision 8670)
@@ -0,0 +1,165 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDShiftTabuCriterion", @"Checks if a certain shift move is tabu.")]
+  [StorableClass]
+  public class DynPotvinPDShiftTabuCriterion : SingleSuccessorOperator, IDynPotvinPDShiftMoveOperator, ITabuChecker, IPotvinOperator, IVRPMoveOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+
+    public ILookupParameter<DynPotvinPDShiftMove> PDShiftMoveParameter {
+      get { return (ILookupParameter<DynPotvinPDShiftMove>)Parameters["DynPotvinPDShiftMove"]; }
+    }
+    public ILookupParameter VRPMoveParameter {
+      get { return PDShiftMoveParameter; }
+    }
+    public ILookupParameter<IVRPEncoding> VRPToursParameter {
+      get { return (ILookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (LookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }  
+
+    public ILookupParameter<ItemList<IItem>> TabuListParameter {
+      get { return (ILookupParameter<ItemList<IItem>>)Parameters["TabuList"]; }
+    }
+    public ILookupParameter<BoolValue> MoveTabuParameter {
+      get { return (ILookupParameter<BoolValue>)Parameters["MoveTabu"]; }
+    }
+    public IValueLookupParameter<BoolValue> MaximizationParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    public ILookupParameter<DoubleValue> MoveQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; }
+    }
+    public ValueParameter<BoolValue> UseAspirationCriterionParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["UseAspirationCriterion"]; }
+    }
+
+    public ILookupParameter<DoubleValue> MoveDistanceParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveDistance"]; }
+    }
+    public ILookupParameter<DoubleValue> MoveOverloadParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveOverload"]; }
+    }
+    public ILookupParameter<DoubleValue> MoveTardinessParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveTardiness"]; }
+    }
+
+    public BoolValue UseAspirationCriterion {
+      get { return UseAspirationCriterionParameter.Value; }
+      set { UseAspirationCriterionParameter.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected DynPotvinPDShiftTabuCriterion(bool deserializing) : base(deserializing) { }
+    protected DynPotvinPDShiftTabuCriterion(DynPotvinPDShiftTabuCriterion original, Cloner cloner) : base(original, cloner) { }
+    public DynPotvinPDShiftTabuCriterion()
+      : base() {
+      Parameters.Add(new LookupParameter<DynPotvinPDShiftMove>("DynPotvinPDShiftMove", "The moves that should be made."));
+      Parameters.Add(new LookupParameter<IVRPEncoding>("VRPTours", "The VRP tours considered in the move."));
+      Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The VRP problem instance"));
+
+      Parameters.Add(new LookupParameter<BoolValue>("MoveTabu", "The variable to store if a move was tabu."));
+      Parameters.Add(new LookupParameter<ItemList<IItem>>("TabuList", "The tabu list."));
+      Parameters.Add(new ValueParameter<BoolValue>("UseAspirationCriterion", "Whether to use the aspiration criterion or not.", new BoolValue(true)));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem, else if it is a minimization problem."));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", "The quality of the current move."));
+
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveDistance", "The distance of the move"));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveOverload", "The overload of the move"));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveTardiness", "The tardiness of the move"));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDShiftTabuCriterion(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      ItemList<IItem> tabuList = TabuListParameter.ActualValue;
+      double moveQuality = MoveQualityParameter.ActualValue.Value;
+      bool useAspiration = UseAspirationCriterion.Value;
+      bool isTabu = false;
+      DynPotvinPDShiftMove move = PDShiftMoveParameter.ActualValue;
+
+      foreach (IItem tabuMove in tabuList) {
+        DynPotvinPDRelocateMoveAttribute attribute = tabuMove as DynPotvinPDRelocateMoveAttribute;
+
+        if (attribute != null) {
+          double distance = 0;
+          if (MoveDistanceParameter.ActualValue != null)
+            distance = MoveDistanceParameter.ActualValue.Value;
+
+          double overload = 0;
+          if (MoveOverloadParameter.ActualValue != null)
+            overload = MoveOverloadParameter.ActualValue.Value;
+
+          double tardiness = 0;
+          if (MoveTardinessParameter.ActualValue != null)
+            tardiness = MoveTardinessParameter.ActualValue.Value;
+
+          IVRPProblemInstance instance = ProblemInstanceParameter.ActualValue;
+          double quality = attribute.Distance * instance.DistanceFactor.Value;
+
+          IHomogenousCapacitatedProblemInstance cvrp = instance as IHomogenousCapacitatedProblemInstance;
+          if (cvrp != null)
+            quality += attribute.Overload * cvrp.OverloadPenalty.Value;
+
+          ITimeWindowedProblemInstance vrptw = instance as ITimeWindowedProblemInstance;
+          if (vrptw != null)
+            quality += attribute.Tardiness * vrptw.TardinessPenalty.Value;
+
+          IPickupAndDeliveryProblemInstance pdp = instance as IPickupAndDeliveryProblemInstance;
+          if (pdp != null)
+            quality += attribute.PickupViolations * pdp.PickupViolationPenalty.Value;
+
+          if (!useAspiration || moveQuality >= quality) {
+            if (attribute.City == move.City && attribute.Tour == move.Tour) {
+              isTabu = true;
+              break;
+            }
+
+            if (attribute.Distance == distance && attribute.Overload == overload && attribute.Tardiness == tardiness) {
+              isTabu = true;
+              break;
+            }
+          }
+        }
+      }
+      
+      MoveTabuParameter.ActualValue = new BoolValue(isTabu);
+      return base.Apply();
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftMoveTabuMaker.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftMoveTabuMaker.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftMoveTabuMaker.cs	(revision 8670)
@@ -0,0 +1,104 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Data;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDShiftMoveTabuMaker", "Declares a given shift move as tabu.")]
+  [StorableClass]
+  public class DynPotvinPDShiftMoveTabuMaker : TabuMaker, IDynPotvinPDShiftMoveOperator, IPotvinOperator, IVRPMoveOperator {
+    public ILookupParameter<DynPotvinPDShiftMove> PDShiftMoveParameter {
+      get { return (ILookupParameter<DynPotvinPDShiftMove>)Parameters["DynPotvinPDShiftMove"]; }
+    }
+    public ILookupParameter VRPMoveParameter {
+      get { return PDShiftMoveParameter; }
+    }
+    public ILookupParameter<IVRPEncoding> VRPToursParameter {
+      get { return (ILookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (LookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+
+    public ILookupParameter<DoubleValue> DistanceParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Distance"]; }
+    }
+    public ILookupParameter<DoubleValue> OverloadParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Overload"]; }
+    }
+    public ILookupParameter<DoubleValue> TardinessParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Tardiness"]; }
+    }
+    public ILookupParameter<IntValue> PickupViolationsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["PickupViolations"]; }
+    }
+
+    [StorableConstructor]
+    protected DynPotvinPDShiftMoveTabuMaker(bool deserializing) : base(deserializing) { }
+    protected DynPotvinPDShiftMoveTabuMaker(DynPotvinPDShiftMoveTabuMaker original, Cloner cloner) : base(original, cloner) { }
+    public DynPotvinPDShiftMoveTabuMaker()
+      : base() {
+        Parameters.Add(new LookupParameter<DynPotvinPDShiftMove>("DynPotvinPDShiftMove", "The moves that should be made."));
+        Parameters.Add(new LookupParameter<IVRPEncoding>("VRPTours", "The VRP tours considered in the move."));
+        Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The VRP problem instance"));
+
+        Parameters.Add(new LookupParameter<DoubleValue>("Distance", "The distance of the individual"));
+        Parameters.Add(new LookupParameter<DoubleValue>("Overload", "The overload of the individual"));
+        Parameters.Add(new LookupParameter<DoubleValue>("Tardiness", "The tardiness of the individual"));
+        Parameters.Add(new LookupParameter<IntValue>("PickupViolations", "The number of pickup violations."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDShiftMoveTabuMaker(this, cloner);
+    }
+
+    protected override IItem GetTabuAttribute(bool maximization, double quality, double moveQuality) {
+      DynPotvinPDShiftMove move = PDShiftMoveParameter.ActualValue;
+      double baseQuality = moveQuality;
+      if (quality < moveQuality) baseQuality = quality; // we make an uphill move, the lower bound is the solution quality
+
+      double distance = 0;
+      if (DistanceParameter.ActualValue != null)
+        distance = DistanceParameter.ActualValue.Value;
+
+      double overload = 0;
+      if (OverloadParameter.ActualValue != null)
+        overload = OverloadParameter.ActualValue.Value;
+
+      double tardiness = 0;
+      if (TardinessParameter.ActualValue != null)
+        tardiness = TardinessParameter.ActualValue.Value;
+
+      int pickupViolations = 0;
+      if (PickupViolationsParameter.ActualValue != null)
+        pickupViolations = PickupViolationsParameter.ActualValue.Value;
+
+      return new DynPotvinPDRelocateMoveAttribute(baseQuality, move.OldTour, move.City, distance, overload, tardiness, pickupViolations);
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftMultiMoveGenerator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftMultiMoveGenerator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftMultiMoveGenerator.cs	(revision 8670)
@@ -0,0 +1,114 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Parameters;
+using System.Collections.Generic;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Common;
+using HeuristicLab.Data;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+using HeuristicLab.Problems.VehicleRouting;
+using HeuristicLab.Encodings.PermutationEncoding;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDShiftMultiMoveGenerator", "Generates shift moves from a given PDP encoding.")]
+  [StorableClass]
+  public sealed class DynPotvinPDShiftMultiMoveGenerator : DynPotvinPDShiftMoveGenerator, IMultiMoveGenerator, IMultiVRPMoveGenerator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public IValueLookupParameter<IntValue> SampleSizeParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["SampleSize"]; }
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDShiftMultiMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private DynPotvinPDShiftMultiMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public DynPotvinPDShiftMultiMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("SampleSize", "The number of moves to generate."));
+    }
+
+    private DynPotvinPDShiftMultiMoveGenerator(DynPotvinPDShiftMultiMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override DynPotvinPDShiftMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<DynPotvinPDShiftMove> result = new List<DynPotvinPDShiftMove>();
+      IRandom rand = RandomParameter.ActualValue;
+      double samples = Math.Min(100, SampleSizeParameter.ActualValue.Value);
+
+      List<int> cities = new List<int>();
+      IPickupAndDeliveryProblemInstance pdp = problemInstance as IPickupAndDeliveryProblemInstance;
+      for (int i = 1; i <= individual.Cities; i++) {
+        if (pdp == null || pdp.GetDemand(i) >= 0 || pdp.GetPickupDeliveryLocation(i) <= 0 || pdp.GetPickupDeliveryLocation(i) == i)
+          cities.Add(i);
+      }
+
+      if (cities.Count >= 1) {
+        int max = individual.Tours.Count;
+        if (individual.Tours.Count >= problemInstance.Vehicles.Value)
+          max = max - 1;
+
+        if (max > 0) {
+          Dictionary<int, int> tours = new Dictionary<int, int>();
+          for (int tourIdx = 0; tourIdx < individual.Tours.Count; tourIdx++) {
+            for (int stop = 0; stop < individual.Tours[tourIdx].Stops.Count; stop++) {
+              int city = individual.Tours[tourIdx].Stops[stop];
+              tours[city] = tourIdx;
+            }
+          }
+
+          Permutation perm = new Permutation(PermutationTypes.Absolute, cities.Count * max);
+          perm.Randomize(rand);
+
+          samples = Math.Max(1, (int)(perm.Length * (samples / 100.0)));
+
+          for (int i = 0; i < Math.Min(perm.Length, samples); i++) {
+            int city = cities[perm[i] / max];
+            int oldTourIndex = tours[city];
+
+            int newTourIndex = perm[i] % max;
+            if (newTourIndex >= oldTourIndex)
+              newTourIndex++;
+
+            var move = new DynPotvinPDShiftMove(city, oldTourIndex, newTourIndex, individual);
+            result.Add(move);
+          }
+        }
+      }
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftSingleMoveGenerator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftSingleMoveGenerator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Operators/Moves/Shift/PotvinPDShiftSingleMoveGenerator.cs	(revision 8670)
@@ -0,0 +1,99 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Parameters;
+using System.Collections.Generic;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Common;
+using HeuristicLab.Data;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+using HeuristicLab.Problems.VehicleRouting;
+
+namespace HeuristicLab.PDPSimulation.Operators {
+  [Item("DynPotvinPDShiftSingleMoveGenerator", "Generates a single shift move from a given PDP encoding.")]
+  [StorableClass]
+  public sealed class DynPotvinPDShiftSingleMoveGenerator : DynPotvinPDShiftMoveGenerator,
+    ISingleMoveGenerator {    
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynPotvinPDShiftSingleMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private DynPotvinPDShiftSingleMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public DynPotvinPDShiftSingleMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+    }
+
+    private DynPotvinPDShiftSingleMoveGenerator(DynPotvinPDShiftSingleMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static DynPotvinPDShiftMove Apply(PotvinEncoding individual, IVRPProblemInstance problemInstance, IRandom rand) {
+      List<int> cities = new List<int>();
+
+      IPickupAndDeliveryProblemInstance pdp = problemInstance as IPickupAndDeliveryProblemInstance;
+      for (int i = 1; i <= individual.Cities; i++) {
+        if (pdp == null || pdp.GetDemand(i) >= 0 || pdp.GetPickupDeliveryLocation(i) <= 0 || pdp.GetPickupDeliveryLocation(i) == i)
+          cities.Add(i);
+      }
+
+      if (cities.Count >= 1) {
+        int city = cities[rand.Next(cities.Count)];
+        Tour oldTour = individual.Tours.Find(t => t.Stops.Contains(city));
+        int oldTourIndex = individual.Tours.IndexOf(oldTour);
+
+        int max = individual.Tours.Count;
+        if (individual.Tours.Count >= problemInstance.Vehicles.Value)
+          max = max - 1;
+
+        int newTourIndex = rand.Next(max);
+        if (newTourIndex >= oldTourIndex)
+          newTourIndex++;
+
+        return new DynPotvinPDShiftMove(city, oldTourIndex, newTourIndex, individual);
+      } else {
+        return null;
+      }             
+    }
+
+    protected override DynPotvinPDShiftMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<DynPotvinPDShiftMove> result = new List<DynPotvinPDShiftMove>();
+
+      DynPotvinPDShiftMove move = Apply(individual, ProblemInstance, RandomParameter.ActualValue);
+      if (move != null)
+        result.Add(move);
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Optimizers/DynamicPDPOptimization.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Optimizers/DynamicPDPOptimization.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Optimizers/DynamicPDPOptimization.cs	(revision 8670)
@@ -0,0 +1,351 @@
+﻿#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 <http://www.gnu.org/licenses/>.
+ */
+#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<BoolValue> OnlyOptimizedIfRequiredParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["OnlyOptimizedIfRequired"]; }
+    }
+
+    public DynamicPDPOptimization(): base() {
+      optimizationFinshed = true;
+      Parameters.Add(new ValueParameter<BoolValue>("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<DynamicPDProblemInstance>(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<int> vehicles = new List<int>();
+        for (int i = 0; i < instance.StaticInstance.Vehicles.Value; i++)
+          vehicles.Add(i);
+
+        int tourIdx = 0;
+        foreach (Tour tour in solution.GetTours()) {
+          List<double> 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();
+    }
+
+    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<PDChange> 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)
+          running = false;
+        else
+          SignalWaitHandle();
+      }
+
+      EndOptimization();
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Optimizers/DynamicPDProblemInstance.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Optimizers/DynamicPDProblemInstance.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Optimizers/DynamicPDProblemInstance.cs	(revision 8670)
@@ -0,0 +1,524 @@
+﻿#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 <http://www.gnu.org/licenses/>.
+ */
+#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.Problems.VehicleRouting.ProblemInstances;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.PDPSimulation.DomainModel;
+using HeuristicLab.Data;
+using HeuristicLab.PDPSimulation.Operators;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+using HeuristicLab.Problems.VehicleRouting;
+using HeuristicLab.PDPSimulation.DistanceMeasures;
+using HeuristicLab.Optimization;
+
+namespace HeuristicLab.PDPSimulation {
+  [Item("DynamicPDProblemInstance", "A dynamic PD instance.")]
+  [StorableClass]
+  public class DynamicPDProblemInstance: Item {
+    [Storable]
+    private List<DynPDPProblemInstance> instances;
+
+    [Storable]
+    private HashSet<PotvinEncoding> solutions;
+
+    [Storable]
+    private List<Item> tabuAttributes;
+
+    [Storable]
+    private Dictionary<int, Guid> vehicleAssignment;
+
+    [Storable]
+    private Dictionary<int, Guid> orderAssignment;
+
+    [Storable]
+    private double timeDelta;
+
+    [Storable]
+    private bool initialized;
+
+    public bool Initialized {
+      get { return initialized; }
+    }
+
+    public List<IVRPProblemInstance> StaticInstances {
+      get {
+        List<IVRPProblemInstance> result = new List<IVRPProblemInstance>();
+
+        foreach (DynPDPProblemInstance instance in instances)
+          result.Add(instance);
+
+        return result;
+      }
+    }
+
+    public IVRPProblemInstance StaticInstance {
+      get {
+        return instances[0];
+      }
+    }
+
+    public HashSet<PotvinEncoding> Solutions {
+      get { return solutions;  }
+    }
+
+    public List<Item> TabuAttributes {
+      get { return tabuAttributes; }
+    }
+
+    public void SetInstanceCount(int count) {
+      if (count > 0) {
+        if (instances.Count > count)
+          instances.RemoveRange(0, instances.Count - count);
+        else
+          while(instances.Count < count)
+            instances.Add(instances[0].ShallowClone());
+      }
+    }
+
+    public DynamicPDProblemInstance(PickupDeliveryScenario scenario, ResultCollection results): base() {
+      vehicleAssignment = new Dictionary<int, Guid>();
+      orderAssignment = new Dictionary<int, Guid>();
+      solutions = new HashSet<PotvinEncoding>();
+      tabuAttributes = new List<Item>();
+      timeDelta = 0;
+      initialized = false;
+
+      instances = new List<DynPDPProblemInstance>();
+      instances.Add(new DynPDPProblemInstance(scenario, results));
+    }
+
+    [StorableConstructor]
+    private DynamicPDProblemInstance(bool deserializing) : base(deserializing) {
+    }
+    private DynamicPDProblemInstance(DynamicPDProblemInstance original, Cloner cloner)
+      : base(original, cloner) {
+      instances = new List<DynPDPProblemInstance>();
+      foreach (DynPDPProblemInstance instance in original.instances)
+        instances.Add(cloner.Clone<DynPDPProblemInstance>(instance));
+
+      vehicleAssignment = new Dictionary<int, Guid>();
+      foreach (int key in original.vehicleAssignment.Keys)
+        vehicleAssignment.Add(key, original.vehicleAssignment[key]);
+
+      orderAssignment = new Dictionary<int, Guid>();
+      foreach (int key in original.orderAssignment.Keys)
+        orderAssignment.Add(key, original.orderAssignment[key]);
+
+      solutions = new HashSet<PotvinEncoding>();
+      foreach (PotvinEncoding solution in original.solutions)
+        solutions.Add(cloner.Clone<PotvinEncoding>(solution));
+      
+      tabuAttributes = new List<Item>();
+      foreach (Item tabuAttribute in original.tabuAttributes)
+        tabuAttributes.Add(cloner.Clone<Item>(tabuAttribute));
+
+      timeDelta = original.timeDelta;
+      initialized = original.initialized;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DynamicPDProblemInstance(this, cloner);
+    }
+
+    public void SetCurrentPlan(PotvinEncoding plan) {
+      foreach (DynPDPProblemInstance instance in instances) {
+        if (instance.CurrentPlan != null)
+          solutions.Remove(instance.CurrentPlan);
+
+        instance.CurrentPlan = PotvinEncoding.ConvertFrom(plan, instance);
+        solutions.Add(instance.CurrentPlan);
+      }
+    }
+
+    public Guid GetOrder(int stop) {
+      return orderAssignment[stop - 1];
+    }
+
+    public List<int> GetStops(Guid order) {
+      return (from a in orderAssignment where a.Value == order select a.Key).OrderBy(s => s).ToList();
+    }
+
+    public Guid GetVehicle(int index) {
+      return vehicleAssignment[index];
+    }
+
+    public void UpdateTime(double delta) {
+      foreach (DynPDPProblemInstance instance in instances) {
+        for (int i = 0; i < instance.DueTime.Length; i++) {
+          instance.DueTime[i] = Math.Max(0, instance.DueTime[i] - delta);
+          instance.ReadyTime[i] = Math.Max(0, instance.ReadyTime[i] - delta);
+        }
+      }
+
+      timeDelta += delta;
+    }
+
+    public void AddVehicle(Vehicle vehicle) {
+      throw new NotImplementedException();
+    }
+
+    private void AddOrder(DynPDPProblemInstance instance, Order order, ref int customerIdx, ref int depotIdx) {
+      orderAssignment[customerIdx] = order.Id;
+
+      instance.Demand[customerIdx] = order.Demand;
+      instance.PickupDeliveryLocation[customerIdx] = customerIdx + (order.ServiceRequest ? 1 : 2);
+      instance.ServiceTime[customerIdx] = order.PickupServiceTime;
+      instance.ReadyTime[customerIdx + depotIdx] = Math.Max(0, order.PickupReadyTime - timeDelta);
+      instance.DueTime[customerIdx + depotIdx] = Math.Max(0, order.PickupDueTime - timeDelta);
+      instance.Coordinates[customerIdx + depotIdx, 0] = order.PickupXCoord;
+      instance.Coordinates[customerIdx + depotIdx, 1] = order.PickupYCoord;
+      customerIdx++;
+
+      if (!order.ServiceRequest) {
+        orderAssignment[customerIdx] = order.Id;
+
+        instance.Demand[customerIdx] = -order.Demand;
+        instance.PickupDeliveryLocation[customerIdx] = customerIdx;
+        instance.ServiceTime[customerIdx] = order.DeliveryServiceTime;
+        instance.ReadyTime[customerIdx + depotIdx] = Math.Max(0, order.DeliveryReadyTime - timeDelta);
+        instance.DueTime[customerIdx + depotIdx] = Math.Max(0, order.DeliveryDueTime - timeDelta);
+        instance.Coordinates[customerIdx + depotIdx, 0] = order.DeliveryXCoord;
+        instance.Coordinates[customerIdx + depotIdx, 1] = order.DeliveryYCoord;
+        customerIdx++;
+      }
+
+      foreach (PotvinEncoding solution in solutions) {
+        if (!order.ServiceRequest && !solution.Unrouted.Contains(customerIdx - 1))
+          solution.Unrouted.Add(customerIdx - 1);
+
+        if (!solution.Unrouted.Contains(customerIdx))
+          solution.Unrouted.Add(customerIdx);
+      }
+    }
+
+    public void AddOrder(Order order) {
+      foreach (DynPDPProblemInstance instance in instances) {
+        int customerIdx = instance.Demand.Length;
+        int depotIdx = instance.Vehicles.Value;
+
+        int added = order.ServiceRequest ? 1 : 2;
+        (instance.Coordinates as IStringConvertibleMatrix).Rows += added;
+        (instance.ReadyTime as IStringConvertibleArray).Length += added;
+        (instance.DueTime as IStringConvertibleArray).Length += added;
+        (instance.Demand as IStringConvertibleArray).Length += added;
+        (instance.ServiceTime as IStringConvertibleArray).Length += added;
+        (instance.PickupDeliveryLocation as IStringConvertibleArray).Length += added;
+
+        AddOrder(instance, order, ref customerIdx, ref depotIdx);
+
+        instance.ResetDistanceMatrix();
+      }
+    }
+
+    public void UpdateVehicle(Vehicle vehicle, bool diversionAllowed) {
+      bool last = false;
+      for (int i = 0; i < instances.Count; i++) {
+        DynPDPProblemInstance instance = instances[i];
+        last = (i == instances.Count - 1);
+        int vehicleIdx = vehicleAssignment.First(kvp => kvp.Value == vehicle.Id).Key;
+
+        if (!diversionAllowed && vehicle.VehicleState == VehicleState.Moving)
+          instance.VehicleStates[vehicleIdx] = VehicleState.Waiting;
+        else
+          instance.VehicleStates[vehicleIdx] = vehicle.VehicleState;
+
+        if (diversionAllowed) {
+          instance.Coordinates[vehicleIdx, 0] = vehicle.PositionX;
+          instance.Coordinates[vehicleIdx, 1] = vehicle.PositionY;
+
+          instance.Capacity[vehicleIdx] = vehicle.Capacity;
+
+          instance.ResetDistanceMatrix();
+          if (vehicle.Distance > 0)
+            instance.VehicleUsed[vehicleIdx] = true;
+        } else {
+          var found = orderAssignment.Where(kvp => kvp.Value == vehicle.CurrentOrder).ToList();
+          if (found.Count() > 0) {
+            instance.Coordinates[vehicleIdx, 0] = vehicle.TargetPositionX;
+            instance.Coordinates[vehicleIdx, 1] = vehicle.TargetPositionY;
+
+            int target = -1, source = -1;
+            if (found.Count == 2 &&
+               (vehicle.CurrentAction == VehicleAction.Pickup || vehicle.CurrentAction == VehicleAction.Deliver)) {
+              if (instance.Demand[found[0].Key] >= 0) {
+                source = found[0].Key;
+                target = found[1].Key;
+              } else {
+                target = found[0].Key;
+                source = found[1].Key;
+              }
+
+              int vehicleId = vehicleAssignment.First(
+               kvp => kvp.Value == vehicle.Id).Key;
+              instance.PickupDeliveryLocation[target] = -vehicleId;
+            } else if (found.Count == 1 &&
+              (vehicle.CurrentAction == VehicleAction.Deliver)) {
+              source = found[0].Key;
+            }
+
+            if (source >= 0) {
+              if(last)
+                RemoveCustomer(source, vehicleIdx, diversionAllowed);
+              instance.ResetDistanceMatrix();
+            }
+
+            instance.VehicleUsed[vehicleIdx] = true;
+          }
+        }
+
+        instance.ReadyTime[vehicleIdx] = Math.Max(0, vehicle.ReadyTime - timeDelta);
+        vehicleAssignment[vehicleIdx] = vehicle.Id;
+      }
+    }
+
+    private void RemoveCustomer(int customer, int vehicle, bool diversionAllowed) {
+      foreach (DynPDPProblemInstance instance in instances) {
+        if (!diversionAllowed) {
+          instance.Capacity[vehicle] -= instance.Demand[customer];
+        }
+
+        int customers = instance.Cities.Value;
+        int depots = instance.Vehicles.Value;
+
+        for (int i = customer; i < customers - 1; i++) {
+          instance.Demand[i] = instance.Demand[i + 1];
+          instance.ServiceTime[i] = instance.ServiceTime[i + 1];
+          instance.PickupDeliveryLocation[i] = instance.PickupDeliveryLocation[i + 1];
+
+          int index = i + depots;
+          instance.ReadyTime[index] = instance.ReadyTime[index + 1];
+          instance.DueTime[index] = instance.DueTime[index + 1];
+          instance.Coordinates[index, 0] = instance.Coordinates[index + 1, 0];
+          instance.Coordinates[index, 1] = instance.Coordinates[index + 1, 1];
+        }
+
+        for (int i = 0; i < customers; i++) {
+          if (instance.PickupDeliveryLocation[i] > customer)
+            instance.PickupDeliveryLocation[i] -= 1;
+        }
+
+        (instance.Coordinates as IStringConvertibleMatrix).Rows -= 1;
+        (instance.ReadyTime as IStringConvertibleArray).Length -= 1;
+        (instance.DueTime as IStringConvertibleArray).Length -= 1;
+        (instance.Demand as IStringConvertibleArray).Length -= 1;
+        (instance.ServiceTime as IStringConvertibleArray).Length -= 1;
+        (instance.PickupDeliveryLocation as IStringConvertibleArray).Length -= 1;
+      }
+
+      foreach (PotvinEncoding solution in solutions) {
+        int i;
+        foreach (Tour tour in solution.Tours) {
+          i = 0;
+          while (i < tour.Stops.Count) {
+            if (tour.Stops[i] > (customer + 1)) {
+              tour.Stops[i] = tour.Stops[i] - 1;
+              i++;
+            } else if (tour.Stops[i] < (customer + 1)) {
+              i++;
+            } else {
+              tour.Stops.RemoveAt(i);
+            }
+          }
+        }
+
+        solution.Repair();
+
+        i = 0;
+        while (i < solution.Unrouted.Count) {
+          if (solution.Unrouted[i] > (customer + 1)) {
+            solution.Unrouted[i] = solution.Unrouted[i] - 1;
+            i++;
+          } else if (solution.Unrouted[i] < (customer + 1)) {
+            i++;
+          } else {
+            solution.Unrouted.RemoveAt(i);
+          }
+        }
+      }
+
+      int j = 0;
+      while (j < tabuAttributes.Count) {
+        if (tabuAttributes[j] is DynPotvinPDRelocateMoveAttribute) {
+          DynPotvinPDRelocateMoveAttribute attr =
+            tabuAttributes[j] as DynPotvinPDRelocateMoveAttribute;
+
+          if (attr.City > (customer + 1)) {
+            attr.City = attr.City - 1;
+            j++;
+          } else if (attr.City < (customer + 1)) {
+            j++;
+          } else {
+            attr.City = -1;
+            j++;
+          }
+        } else {
+          j++;
+        }
+      }
+
+      Dictionary<int, Guid> newOrderAssignment = new Dictionary<int, Guid>();
+      foreach (int assigned in orderAssignment.Keys) {
+        if (assigned > customer)
+          newOrderAssignment[assigned - 1] = orderAssignment[assigned];
+        else if (assigned != customer)
+          newOrderAssignment[assigned] = orderAssignment[assigned];
+      }
+      orderAssignment = newOrderAssignment;
+    }
+
+    public void UpdateOrder(Order order, bool diversionAllowed) {
+      bool last = false;
+      for(int i = 0; i < instances.Count; i++) {
+        DynPDPProblemInstance instance = instances[i];
+        last = (i == instances.Count - 1);
+        var customers = orderAssignment.Where(
+          kvp => kvp.Value == order.Id).ToList();
+        int depots = instance.Vehicles.Value;
+        int vehicle = vehicleAssignment.First(
+              kvp => kvp.Value == order.Vehicle).Key;
+
+        int source = -1;
+        int target = -1;
+
+        if (order.OrderState == OrderState.PickingUp || order.OrderState == OrderState.PickedUp) {
+          if (!order.ServiceRequest && customers.Count == 2) {
+            if (instance.Demand[customers[0].Key] >= 0) {
+              source = customers[0].Key;
+              target = customers[1].Key;
+            } else {
+              source = customers[1].Key;
+              target = customers[0].Key;
+            }
+
+            instance.PickupDeliveryLocation[target] = -vehicle;
+            if (last)
+              RemoveCustomer(source, vehicle, diversionAllowed);
+            instance.ResetDistanceMatrix();
+          } else if (order.ServiceRequest && customers.Count == 1) {
+            target = customers[0].Key;
+
+            if (last)
+              RemoveCustomer(target, vehicle, diversionAllowed);
+            instance.ResetDistanceMatrix();
+          }
+        } else if (order.OrderState == OrderState.Delivering || order.OrderState == OrderState.Delivered) {
+          if (customers.Count == 1) {
+            target = customers[0].Key;
+
+            if (last)
+              RemoveCustomer(target, vehicle, diversionAllowed);
+            instance.ResetDistanceMatrix();
+          } else if (customers.Count == 2) {
+            if (instance.Demand[customers[0].Key] >= 0) {
+              source = customers[0].Key;
+              target = customers[1].Key;
+            } else {
+              source = customers[1].Key;
+              target = customers[0].Key;
+            }
+
+            if (last)
+              RemoveCustomer(source, vehicle, diversionAllowed);
+            if (last)
+              RemoveCustomer(target - 1, vehicle, diversionAllowed);
+            instance.ResetDistanceMatrix();
+          }
+        }
+      }
+    }
+
+    public void InitializeInstance(List<Vehicle> vehicles, List<Order> orders) {
+      if (vehicles.Count > 0) {
+        foreach (DynPDPProblemInstance instance in instances) {
+          timeDelta = 0;
+
+          instance.Coordinates = new DoubleMatrix(vehicles.Count + orders.Count * 2, 2);
+          instance.DepotCoordinates = new DoubleMatrix(vehicles.Count, 2);
+          instance.ReadyTime = new DoubleArray(vehicles.Count + orders.Count * 2);
+          instance.DueTime = new DoubleArray(vehicles.Count + orders.Count * 2);
+
+          instance.Capacity = new DoubleArray(vehicles.Count);
+          instance.VehicleDepotAssignment = new IntArray(vehicles.Count);
+          instance.VehicleUsed = new BoolArray(vehicles.Count);
+          instance.VehicleStates.Clear();
+          for (int i = 0; i < vehicles.Count; i++) {
+            instance.VehicleStates.Add(VehicleState.Parked);
+          }
+
+          int depotIdx = 0;
+          int vehicleIdx = 0;
+          foreach (Vehicle vehicle in vehicles) {
+            vehicleAssignment[vehicleIdx] = vehicle.Id;
+
+            instance.Coordinates[depotIdx, 0] = vehicle.DepotX;
+            instance.Coordinates[depotIdx, 1] = vehicle.DepotY;
+            instance.DepotCoordinates[depotIdx, 0] = vehicle.DepotX;
+            instance.DepotCoordinates[depotIdx, 1] = vehicle.DepotY;
+
+            instance.ReadyTime[vehicleIdx] = 0;
+            instance.DueTime[vehicleIdx] = vehicle.DueTime;
+
+            instance.Capacity[vehicleIdx] = vehicle.Capacity;
+            instance.VehicleDepotAssignment[vehicleIdx] = depotIdx;
+
+            depotIdx++;
+            vehicleIdx++;
+          }
+
+          instance.Depots.Value = depotIdx;
+          instance.Vehicles.Value = vehicleIdx;
+
+          foreach (PotvinEncoding solution in solutions) {
+            (solution.VehicleAssignment as IStringConvertibleArray).Length = instance.Vehicles.Value;
+          }
+
+          instance.Demand = new DoubleArray(orders.Count * 2);
+          instance.ServiceTime = new DoubleArray(orders.Count * 2);
+          instance.PickupDeliveryLocation = new IntArray(orders.Count * 2);
+
+          int customerIdx = 0;
+          foreach (Order order in orders) {
+            AddOrder(instance, order, ref customerIdx, ref depotIdx);
+          }
+
+          if (customerIdx != orders.Count * 2) {
+            (instance.Coordinates as IStringConvertibleMatrix).Rows = vehicles.Count + customerIdx;
+            (instance.ReadyTime as IStringConvertibleArray).Length = vehicles.Count + customerIdx;
+            (instance.DueTime as IStringConvertibleArray).Length = vehicles.Count + customerIdx;
+            (instance.Demand as IStringConvertibleArray).Length = customerIdx;
+            (instance.ServiceTime as IStringConvertibleArray).Length = customerIdx;
+            (instance.PickupDeliveryLocation as IStringConvertibleArray).Length = customerIdx;
+          }
+
+          instance.ResetDistanceMatrix();
+          instance.Initialize();
+        }
+        initialized = true;
+      }
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Optimizers/LocalUpdate/BestInsertion.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Optimizers/LocalUpdate/BestInsertion.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Optimizers/LocalUpdate/BestInsertion.cs	(revision 8670)
@@ -0,0 +1,158 @@
+﻿#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 <http://www.gnu.org/licenses/>.
+ */
+#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.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation {
+  [Item("BestInsertion", "A best insertion local update optimization.")]
+  [StorableClass]
+  public class BestInsertion : DynamicPDPOptimization {    
+    public BestInsertion(): base() {
+    }
+    [StorableConstructor]
+    private BestInsertion(bool deserializing) : base(deserializing) {
+    }
+    private BestInsertion(BestInsertion original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BestInsertion(this, cloner);
+    }
+
+    public static void RouteUnrouted(IVRPProblemInstance instance, PotvinEncoding solution) {
+      DynPDPProblemInstance pdp = instance as DynPDPProblemInstance;
+      
+      while (solution.Unrouted.Count > 0) {
+        int city = solution.Unrouted[0];
+        int dest = pdp.GetPickupDeliveryLocation(city);
+
+        int source, target;
+        if (instance.GetDemand(city) >= 0) {
+          source = city;
+          target = dest;
+        } else {
+          source = dest;
+          target = city;
+        }
+
+        //consider creating new tours
+        int tours = solution.Tours.Count;
+        
+        /*for (int i = tours; i < solution.VehicleAssignment.Length; i++)*/ 
+        if(tours < solution.VehicleAssignment.Length) {
+          Tour newTour = new Tour();
+          solution.Tours.Add(newTour);
+        }
+
+        double minCosts = double.MaxValue;
+        Tour insertTour = null;
+        int sourceLocation = -1;
+        int targetLocation = -1;  
+
+        foreach (Tour tour in solution.Tours) {
+          VRPEvaluation eval = instance.Evaluate(solution);
+
+          for (int i = 0; i <= tour.Stops.Count; i++) {
+            tour.Stops.Insert(i, source);
+            VRPEvaluation tourEval = instance.Evaluate(solution);
+            double sourceCosts = tourEval.Quality - eval.Quality;
+
+            if (tour.Stops.Count == 1) {
+              int vehicle = solution.VehicleAssignment[solution.Tours.IndexOf(tour)];
+              if (!pdp.VehicleUsed[vehicle])
+                sourceCosts += instance.FleetUsageFactor.Value;
+            }
+
+
+            if (source != target) {
+              for (int j = i + 1; j <= tour.Stops.Count; j++) {
+                bool feasible;
+                double targetCosts = instance.GetInsertionCosts(tourEval, solution, target, solution.Tours.IndexOf(tour), j, out feasible);
+
+                double costs = sourceCosts + targetCosts;
+                if (costs < minCosts) {
+                  minCosts = costs;
+                  insertTour = tour;
+                  sourceLocation = i;
+                  targetLocation = j;
+                }
+              }
+            } else {
+              double costs = sourceCosts;
+              if (costs < minCosts) {
+                minCosts = costs;
+                insertTour = tour;
+                sourceLocation = i;
+                targetLocation = -1;
+              }
+            }
+            tour.Stops.Remove(source);
+          }
+        }
+
+        insertTour.Stops.Insert(sourceLocation, source);
+        if (source != target) {
+          insertTour.Stops.Insert(targetLocation, target);
+        }
+
+        solution.Unrouted.Remove(source);
+        if (source != target) {
+          solution.Unrouted.Remove(target);
+        }
+
+        solution.Repair();
+      }
+    }
+
+    protected override void PrepareInstance(DynamicPDProblemInstance instance, ChangeInformation changeInformation) {
+      instance.StaticInstance.Vehicles.Value = changeInformation.CreatedVehicles.Count;
+      instance.SetCurrentPlan(new PotvinEncoding(instance.StaticInstance));
+      instance.InitializeInstance(changeInformation.CreatedVehicles, changeInformation.CreatedOrders);
+    }
+
+    protected override bool PerformOptimization(DynamicPDProblemInstance instance, ChangeInformation changeInformation) {
+     PotvinEncoding solution = instance.Solutions.First();
+
+     RouteUnrouted(instance.StaticInstance, solution);
+
+     PerformPlan(solution);
+
+     return true;
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Optimizers/Reoptimization/PFIHReoptimization.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Optimizers/Reoptimization/PFIHReoptimization.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Optimizers/Reoptimization/PFIHReoptimization.cs	(revision 8670)
@@ -0,0 +1,172 @@
+﻿#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 <http://www.gnu.org/licenses/>.
+ */
+#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.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.PDPSimulation {
+  [Item("PFIHReoptimization", "A pickup and delivery PFIH optimization.")]
+  [StorableClass]
+  public class PFIHReoptimization : DynamicPDPOptimization {
+    public IValueParameter<DoubleValue> Alpha {
+      get { return (IValueParameter<DoubleValue>)Parameters["Alpha"]; }
+    }
+    public IValueParameter<DoubleValue> AlphaVariance {
+      get { return (IValueParameter<DoubleValue>)Parameters["AlphaVariance"]; }
+    }
+    public IValueParameter<DoubleValue> Beta {
+      get { return (IValueParameter<DoubleValue>)Parameters["Beta"]; }
+    }
+    public IValueParameter<DoubleValue> BetaVariance {
+      get { return (IValueParameter<DoubleValue>)Parameters["BetaVariance"]; }
+    }
+    public IValueParameter<DoubleValue> Gamma {
+      get { return (IValueParameter<DoubleValue>)Parameters["Gamma"]; }
+    }
+    public IValueParameter<DoubleValue> GammaVariance {
+      get { return (IValueParameter<DoubleValue>)Parameters["GammaVariance"]; }
+    }
+
+    public ValueParameter<IntValue> SampleSizeParameter {
+      get { return (ValueParameter<IntValue>)Parameters["SampleSize"]; }
+    }
+
+    public ValueParameter<BoolValue> ComputeInParallelParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["ComputeInParallel"]; }
+    }
+    
+    public PFIHReoptimization(): base() {
+      Parameters.Add(new ValueParameter<DoubleValue>("Alpha", "The alpha value.", new DoubleValue(0.7)));
+      Parameters.Add(new ValueParameter<DoubleValue>("AlphaVariance", "The alpha variance.", new DoubleValue(0.5)));
+      Parameters.Add(new ValueParameter<DoubleValue>("Beta", "The beta value.", new DoubleValue(0.1)));
+      Parameters.Add(new ValueParameter<DoubleValue>("BetaVariance", "The beta variance.", new DoubleValue(0.07)));
+      Parameters.Add(new ValueParameter<DoubleValue>("Gamma", "The gamma value.", new DoubleValue(0.2)));
+      Parameters.Add(new ValueParameter<DoubleValue>("GammaVariance", "The gamma variance.", new DoubleValue(0.14)));
+
+      Parameters.Add(new ValueParameter<IntValue>("SampleSize", "The sample size.", new IntValue(10)));
+      Parameters.Add(new ValueParameter<BoolValue>("ComputeInParallel", "Indicates if the samples should be computed in parallel.", new BoolValue(true)));
+    }
+    [StorableConstructor]
+    private PFIHReoptimization(bool deserializing) : base(deserializing) {
+    }
+    private PFIHReoptimization(PFIHReoptimization original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PFIHReoptimization(this, cloner);
+    }
+
+    class PFIHResult {
+      public PFIHResult() {
+        bestFeasible = false;
+        bestQuality = double.MaxValue;
+        bestSolution = null;
+      }
+
+      public bool bestFeasible;
+      public double bestQuality;
+      public IVRPEncoding bestSolution;
+    }
+
+    private IVRPEncoding Optimize(DynamicPDProblemInstance instance) {
+      List<bool> vehicleUsed = new List<bool>();
+      for (int i = 0; i < instance.StaticInstance.Vehicles.Value; i++) {
+        Vehicle vehicle = GetVehicle(instance.GetVehicle(i));
+        vehicleUsed.Add(vehicle.Distance > 0);
+      }
+
+      int sampleSize = SampleSizeParameter.Value.Value;
+      PFIHResult bestResult = new PFIHResult();
+
+      var options = new ParallelOptions();
+      if (ComputeInParallelParameter.Value.Value)
+        options.MaxDegreeOfParallelism = Math.Max(Environment.ProcessorCount - 1, 1);
+      else
+        options.MaxDegreeOfParallelism = 1;
+
+      IRandom random = new HeuristicLab.Random.MersenneTwister(1234);
+
+      Parallel.For<PFIHResult>(0, sampleSize, options,
+        () => new PFIHResult(),
+        (i, loop, result) => {
+          IVRPEncoding current = DynPushForwardInsertionCreator.CreateSolution(instance.StaticInstance,
+                  random, vehicleUsed,
+                  Alpha.Value.Value, Beta.Value.Value, Gamma.Value.Value,
+                  AlphaVariance.Value.Value, BetaVariance.Value.Value, GammaVariance.Value.Value);
+
+          VRPEvaluation eval = instance.StaticInstance.Evaluate(current);
+          double quality = eval.Quality;
+          bool feasible = instance.StaticInstance.Feasible(eval);
+
+          if ((feasible && !result.bestFeasible) || (feasible == result.bestFeasible && quality < result.bestQuality)) {
+            result.bestQuality = quality;
+            result.bestSolution = current;
+            result.bestFeasible = feasible;
+          }
+
+          return result;
+        },
+        (result) => {
+          lock (bestResult) {
+            if ((result.bestFeasible && !bestResult.bestFeasible) || (result.bestFeasible == bestResult.bestFeasible && result.bestQuality < bestResult.bestQuality)) {
+              bestResult.bestQuality = result.bestQuality;
+              bestResult.bestSolution = result.bestSolution;
+              bestResult.bestFeasible = result.bestFeasible;
+            }
+          }
+        }
+        );
+
+      //Recourse
+      if (!bestResult.bestFeasible) {
+        PotvinEncoding currentPlan = (instance.StaticInstance as DynPDPProblemInstance).CurrentPlan;
+        BestInsertion.RouteUnrouted(instance.StaticInstance, currentPlan);
+        bestResult.bestSolution = currentPlan;
+      }
+
+      return bestResult.bestSolution;
+    }
+
+    protected override bool PerformOptimization(DynamicPDProblemInstance instance, ChangeInformation changeInformation) {
+
+      IVRPEncoding solution = Optimize(instance);
+      PerformPlan(solution);
+
+      return true;
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/OrderGenerators/Parsers/DefaultDynPDPParser.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/OrderGenerators/Parsers/DefaultDynPDPParser.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/OrderGenerators/Parsers/DefaultDynPDPParser.cs	(revision 8670)
@@ -0,0 +1,84 @@
+﻿#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.IO;
+using System.Text.RegularExpressions;
+
+namespace HeuristicLab.PDPSimulation {
+  class DefaultDynPDPParser: DynPDPParser {
+    public DefaultDynPDPParser(string file): base(file) {
+    }
+
+    public override void Parse() {
+      string line;
+      Regex reg = new Regex(@"-?\d+");
+      MatchCollection m;
+
+      StreamReader reader = new StreamReader(file);
+
+      line = reader.ReadLine();
+      problemName = line;
+
+      line = reader.ReadLine();
+      int vehicleCount = int.Parse(line);
+
+      for (int i = 0; i < vehicleCount; i++) {
+        line = reader.ReadLine();
+        m = reg.Matches(line);
+        Vehicle v = new Vehicle();
+
+        v.xCoord = double.Parse(m[0].Value);
+        v.yCoord = double.Parse(m[1].Value);
+        v.capacity = double.Parse(m[2].Value);
+        v.readyTime = double.Parse(m[3].Value);
+        v.dueTime = double.Parse(m[4].Value);
+
+        vehicles.Add(v);
+      }
+
+      line = reader.ReadLine();
+      int orderCount = int.Parse(line);
+      m = reg.Matches(line);
+      for (int i = 0; i < orderCount; i++) {
+        line = reader.ReadLine();
+        m = reg.Matches(line);
+        Order o = new Order();
+
+        o.revealedTime = double.Parse(m[0].Value);
+        o.pickupXCoord = double.Parse(m[1].Value);
+        o.pickupYCoord = double.Parse(m[2].Value);
+        o.deliveryXCoord = double.Parse(m[3].Value);
+        o.deliveryYCoord = double.Parse(m[4].Value);
+        o.demand = double.Parse(m[5].Value);
+        o.pickupServiceTime = double.Parse(m[6].Value);
+        o.pickupReadyTime = double.Parse(m[7].Value);
+        o.pickupDueTime = double.Parse(m[8].Value);
+        o.deliveryServiceTime = double.Parse(m[9].Value);
+        o.deliveryReadyTime = double.Parse(m[10].Value);
+        o.deliveryDueTime = double.Parse(m[11].Value);
+
+        orders.Add(o);
+      }
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/OrderGenerators/Parsers/DynPDPParser.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/OrderGenerators/Parsers/DynPDPParser.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/OrderGenerators/Parsers/DynPDPParser.cs	(revision 8670)
@@ -0,0 +1,83 @@
+﻿#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.IO;
+using System.Text.RegularExpressions;
+
+namespace HeuristicLab.PDPSimulation {
+  abstract class DynPDPParser {
+    public struct Vehicle {
+      public double xCoord;
+      public double yCoord;
+      public double capacity;
+      public double readyTime;
+      public double dueTime;
+    }
+
+    public struct Order {
+      public double revealedTime;
+      public double pickupXCoord;
+      public double pickupYCoord;
+      public double deliveryXCoord;
+      public double deliveryYCoord;
+      public double demand;
+      public double pickupServiceTime;
+      public double pickupReadyTime;
+      public double pickupDueTime;
+      public double deliveryServiceTime;
+      public double deliveryReadyTime;
+      public double deliveryDueTime;
+    }
+
+    protected string file;
+    protected string problemName;
+    protected List<Vehicle> vehicles;
+    protected List<Order> orders;
+
+    public string ProblemName {
+      get {
+        return new string(problemName.ToCharArray());
+      }
+    }
+
+    public Vehicle[] Vehicles {
+      get {
+        return vehicles.ToArray();
+      }
+    }
+
+    public Order[] Orders {
+      get {
+        return orders.ToArray();
+      }
+    }
+
+    public DynPDPParser(string file) {
+      this.file = file;
+      vehicles = new List<Vehicle>();
+      orders = new List<Order>();
+    }
+
+    public abstract void Parse();
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/OrderGenerators/Parsers/TSPLibDynPDPParser.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/OrderGenerators/Parsers/TSPLibDynPDPParser.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/OrderGenerators/Parsers/TSPLibDynPDPParser.cs	(revision 8670)
@@ -0,0 +1,117 @@
+﻿#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.IO;
+using System.Text.RegularExpressions;
+
+namespace HeuristicLab.PDPSimulation {
+  class TSPLibDynPDPParser: DynPDPParser {
+    public TSPLibDynPDPParser(string file): base(file) {
+    }
+
+    public override void Parse() {
+      string line;
+      Regex reg = new Regex(@"-?\d+");
+      MatchCollection m;
+
+      StreamReader reader = new StreamReader(file);
+
+      line = reader.ReadLine();
+      problemName = line.Split(':')[1].Remove(0, 1);
+
+      line = reader.ReadLine();
+      string vehicleLine = problemName = line.Split(':')[1].Remove(0, 1);
+      int vehicleCount = int.Parse(vehicleLine);
+
+      line = reader.ReadLine();
+      string capacityLine = problemName = line.Split(':')[1].Remove(0, 1);
+      int capacity = int.Parse(capacityLine);
+
+      line = reader.ReadLine();
+      string dueTimeLine = problemName = line.Split(':')[1].Remove(0, 1);
+      int dueTime = int.Parse(dueTimeLine);
+
+      List<double> xCoord = new List<double>();
+      List<double> yCoord = new List<double>();
+
+      line = reader.ReadLine();
+      line = reader.ReadLine();
+      m = reg.Matches(line);
+      while (m.Count == 3) {
+        xCoord.Add(double.Parse(m[1].Value));
+        yCoord.Add(double.Parse(m[2].Value));
+
+        line = reader.ReadLine();
+        m = reg.Matches(line);
+      }
+
+      for (int i = 0; i < vehicleCount; i++) {
+        Vehicle v = new Vehicle();
+
+        v.xCoord = xCoord[0];
+        v.yCoord = yCoord[0];
+        v.capacity = capacity;
+        v.readyTime = 0;
+        v.dueTime = dueTime;
+
+        vehicles.Add(v);
+      }
+
+      line = reader.ReadLine();
+      m = reg.Matches(line);
+
+      while (m.Count == 11) {
+        Order o = new Order();
+
+        int pickupId = int.Parse(m[1].Value);
+        int deliveryId = int.Parse(m[2].Value);
+        double pickupTWOpen = double.Parse(m[3].Value);
+        double pickupTWClose = double.Parse(m[4].Value);
+        double pickupServiceTime = double.Parse(m[5].Value);
+        double deliveryTWOpen = double.Parse(m[6].Value);
+        double deliveryTWClose = double.Parse(m[7].Value);
+        double deliveryServiceTime = double.Parse(m[8].Value);
+        double demand = double.Parse(m[9].Value);
+        double revealed = double.Parse(m[10].Value);
+
+        o.revealedTime = revealed;
+        o.pickupXCoord = xCoord[pickupId];
+        o.pickupYCoord = yCoord[pickupId];
+        o.deliveryXCoord = xCoord[deliveryId];
+        o.deliveryYCoord = yCoord[deliveryId];
+        o.demand = demand;
+        o.pickupServiceTime = pickupServiceTime;
+        o.pickupReadyTime = pickupTWOpen;
+        o.pickupDueTime = pickupTWClose;
+        o.deliveryServiceTime = deliveryServiceTime;
+        o.deliveryReadyTime = deliveryTWOpen;
+        o.deliveryDueTime = deliveryTWClose;
+
+        orders.Add(o);
+
+        line = reader.ReadLine();
+        m = reg.Matches(line);
+      }
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/OrderGenerators/PickupDeliveryPredefinedOrderGenerator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/OrderGenerators/PickupDeliveryPredefinedOrderGenerator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/OrderGenerators/PickupDeliveryPredefinedOrderGenerator.cs	(revision 8670)
@@ -0,0 +1,163 @@
+﻿#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 <http://www.gnu.org/licenses/>.
+ */
+#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.Parameters;
+using HeuristicLab.Data;
+using HeuristicLab.PDPSimulation.DomainModel;
+
+namespace HeuristicLab.PDPSimulation {
+  [Item("PickupDeliveryPredefinedOrderGenerator", "A pickup and delivery order generator.")]
+  [StorableClass]
+  public sealed class PickupDeliveryPredefinedOrderGenerator: PickupDeliveryOrderGenerator {
+    public ValueParameter<IntValue> OrderRangeXParameter {
+      get { return (ValueParameter<IntValue>)Parameters["OrderRangeX"]; }
+    }
+
+    public ValueParameter<IntValue> OrderRangeYParameter {
+      get { return (ValueParameter<IntValue>)Parameters["OrderRangeY"]; }
+    }
+    
+    public ValueParameter<DoubleMatrix> OrdersParameter {
+      get { return (ValueParameter<DoubleMatrix>)Parameters["Orders"]; }
+    }
+
+    public OptionalValueParameter<StringArray> OrderNamesParameter {
+      get { return (OptionalValueParameter<StringArray>)Parameters["OrderNames"]; }
+    }
+    
+    public PickupDeliveryPredefinedOrderGenerator() : base() {
+      Parameters.Add(new ValueParameter<DoubleMatrix>("Orders", new DoubleMatrix()));
+      Parameters.Add(new OptionalValueParameter<StringArray>("OrderNames"));
+      Parameters.Add(new ValueParameter<IntValue>("OrderRangeX", new IntValue(0)));
+      Parameters.Add(new ValueParameter<IntValue>("OrderRangeY", new IntValue(0)));
+
+      OrdersParameter.GetsCollected = false;
+    }
+    [StorableConstructor]
+    private PickupDeliveryPredefinedOrderGenerator(bool deserializing) : base(deserializing) { }
+    private PickupDeliveryPredefinedOrderGenerator(PickupDeliveryPredefinedOrderGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PickupDeliveryPredefinedOrderGenerator(this, cloner);
+    }
+
+    public override double RangeX() {
+      double maxX = OrderRangeXParameter.Value.Value;
+
+      if (maxX == 0) {
+        DoubleMatrix orderMatrix = OrdersParameter.Value;
+
+        for (int i = 0; i < orderMatrix.Rows; i++) {
+          double pickupXCoord = orderMatrix[i, 1];
+          if (pickupXCoord > maxX)
+            maxX = pickupXCoord;
+
+          double deliveryXCoord = orderMatrix[i, 3];
+          if (deliveryXCoord > maxX)
+            maxX = deliveryXCoord;
+        }
+      } 
+
+      return maxX;
+    }
+
+    public override double RangeY() {
+      double maxY = OrderRangeYParameter.Value.Value;
+
+      if (maxY == 0) {
+        DoubleMatrix orderMatrix = OrdersParameter.Value;
+
+        for (int i = 0; i < orderMatrix.Rows; i++) {
+          double pickupYCoord = orderMatrix[i, 2];
+          if (pickupYCoord > maxY)
+            maxY = pickupYCoord;
+
+          double deliveryYCoord = orderMatrix[i, 4];
+          if (deliveryYCoord > maxY)
+            maxY = deliveryYCoord;
+        }
+      }
+
+      return maxY;
+    }
+
+    public override bool MoreOrders(double time) {
+      bool moreOrders = false; 
+      
+      DoubleMatrix orderMatrix = OrdersParameter.Value;
+       for (int i = 0; i < orderMatrix.Rows; i++) {
+         double revealedTime = orderMatrix[i, 0];
+
+         if (revealedTime >= time) {
+           moreOrders = true;
+           break;
+         }
+       }
+
+       return moreOrders;
+    }
+
+    public override IEnumerable<Order> GetOrders(double timeStart, double timeEnd) {
+      List<Order> orders = new List<Order>();
+
+      DoubleMatrix orderMatrix = OrdersParameter.Value;
+      for (int i = 0; i < orderMatrix.Rows; i++) {
+        double revealedTime = orderMatrix[i, 0];
+        if (revealedTime >= timeStart && revealedTime < timeEnd) {
+          Order order = new Order();
+          order.OrderState = OrderState.Waiting;
+
+          order.Index = i;
+          order.PickupXCoord = orderMatrix[i, 1];
+          order.PickupYCoord = orderMatrix[i, 2];
+          order.DeliveryXCoord = orderMatrix[i, 3];
+          order.DeliveryYCoord = orderMatrix[i, 4];
+          order.Demand = orderMatrix[i, 5];
+          order.PickupServiceTime = orderMatrix[i, 6];
+          order.PickupReadyTime = orderMatrix[i, 7];
+          order.PickupDueTime = orderMatrix[i, 8];
+          order.DeliveryServiceTime = orderMatrix[i, 9];
+          order.DeliveryReadyTime = orderMatrix[i, 10];
+          order.DeliveryDueTime = orderMatrix[i, 11];
+
+          order.ServiceRequest = order.DeliveryDueTime < 0;
+
+          if (OrderNamesParameter.Value != null && i < OrderNamesParameter.Value.Length)
+            order.Name = OrderNamesParameter.Value[i];
+          else
+            order.Name = "Order" + i;
+
+          orders.Add(order);
+        }
+      }
+
+      return orders;
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Parsers/DefaultDynPDPParser.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Parsers/DefaultDynPDPParser.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Parsers/DefaultDynPDPParser.cs	(revision 8670)
@@ -0,0 +1,84 @@
+﻿#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.IO;
+using System.Text.RegularExpressions;
+
+namespace HeuristicLab.PDPSimulation {
+  class DefaultDynPDPParser: DynPDPParser {
+    public DefaultDynPDPParser(string file): base(file) {
+    }
+
+    public override void Parse() {
+      string line;
+      Regex reg = new Regex(@"-?\d+");
+      MatchCollection m;
+
+      StreamReader reader = new StreamReader(file);
+
+      line = reader.ReadLine();
+      problemName = line;
+
+      line = reader.ReadLine();
+      int vehicleCount = int.Parse(line);
+
+      for (int i = 0; i < vehicleCount; i++) {
+        line = reader.ReadLine();
+        m = reg.Matches(line);
+        Vehicle v = new Vehicle();
+
+        v.xCoord = double.Parse(m[0].Value);
+        v.yCoord = double.Parse(m[1].Value);
+        v.capacity = double.Parse(m[2].Value);
+        v.readyTime = double.Parse(m[3].Value);
+        v.dueTime = double.Parse(m[4].Value);
+
+        vehicles.Add(v);
+      }
+
+      line = reader.ReadLine();
+      int orderCount = int.Parse(line);
+      m = reg.Matches(line);
+      for (int i = 0; i < orderCount; i++) {
+        line = reader.ReadLine();
+        m = reg.Matches(line);
+        Order o = new Order();
+
+        o.revealedTime = double.Parse(m[0].Value);
+        o.pickupXCoord = double.Parse(m[1].Value);
+        o.pickupYCoord = double.Parse(m[2].Value);
+        o.deliveryXCoord = double.Parse(m[3].Value);
+        o.deliveryYCoord = double.Parse(m[4].Value);
+        o.demand = double.Parse(m[5].Value);
+        o.pickupServiceTime = double.Parse(m[6].Value);
+        o.pickupReadyTime = double.Parse(m[7].Value);
+        o.pickupDueTime = double.Parse(m[8].Value);
+        o.deliveryServiceTime = double.Parse(m[9].Value);
+        o.deliveryReadyTime = double.Parse(m[10].Value);
+        o.deliveryDueTime = double.Parse(m[11].Value);
+
+        orders.Add(o);
+      }
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Parsers/DynPDPParser.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Parsers/DynPDPParser.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Parsers/DynPDPParser.cs	(revision 8670)
@@ -0,0 +1,83 @@
+﻿#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.IO;
+using System.Text.RegularExpressions;
+
+namespace HeuristicLab.PDPSimulation {
+  abstract class DynPDPParser {
+    public struct Vehicle {
+      public double xCoord;
+      public double yCoord;
+      public double capacity;
+      public double readyTime;
+      public double dueTime;
+    }
+
+    public struct Order {
+      public double revealedTime;
+      public double pickupXCoord;
+      public double pickupYCoord;
+      public double deliveryXCoord;
+      public double deliveryYCoord;
+      public double demand;
+      public double pickupServiceTime;
+      public double pickupReadyTime;
+      public double pickupDueTime;
+      public double deliveryServiceTime;
+      public double deliveryReadyTime;
+      public double deliveryDueTime;
+    }
+
+    protected string file;
+    protected string problemName;
+    protected List<Vehicle> vehicles;
+    protected List<Order> orders;
+
+    public string ProblemName {
+      get {
+        return new string(problemName.ToCharArray());
+      }
+    }
+
+    public Vehicle[] Vehicles {
+      get {
+        return vehicles.ToArray();
+      }
+    }
+
+    public Order[] Orders {
+      get {
+        return orders.ToArray();
+      }
+    }
+
+    public DynPDPParser(string file) {
+      this.file = file;
+      vehicles = new List<Vehicle>();
+      orders = new List<Order>();
+    }
+
+    public abstract void Parse();
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Parsers/TSPLibDynPDPParser.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Parsers/TSPLibDynPDPParser.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Parsers/TSPLibDynPDPParser.cs	(revision 8670)
@@ -0,0 +1,117 @@
+﻿#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.IO;
+using System.Text.RegularExpressions;
+
+namespace HeuristicLab.PDPSimulation {
+  class TSPLibDynPDPParser: DynPDPParser {
+    public TSPLibDynPDPParser(string file): base(file) {
+    }
+
+    public override void Parse() {
+      string line;
+      Regex reg = new Regex(@"-?\d+");
+      MatchCollection m;
+
+      StreamReader reader = new StreamReader(file);
+
+      line = reader.ReadLine();
+      problemName = line.Split(':')[1].Remove(0, 1);
+
+      line = reader.ReadLine();
+      string vehicleLine = problemName = line.Split(':')[1].Remove(0, 1);
+      int vehicleCount = int.Parse(vehicleLine);
+
+      line = reader.ReadLine();
+      string capacityLine = problemName = line.Split(':')[1].Remove(0, 1);
+      int capacity = int.Parse(capacityLine);
+
+      line = reader.ReadLine();
+      string dueTimeLine = problemName = line.Split(':')[1].Remove(0, 1);
+      int dueTime = int.Parse(dueTimeLine);
+
+      List<double> xCoord = new List<double>();
+      List<double> yCoord = new List<double>();
+
+      line = reader.ReadLine();
+      line = reader.ReadLine();
+      m = reg.Matches(line);
+      while (m.Count == 3) {
+        xCoord.Add(double.Parse(m[1].Value));
+        yCoord.Add(double.Parse(m[2].Value));
+
+        line = reader.ReadLine();
+        m = reg.Matches(line);
+      }
+
+      for (int i = 0; i < vehicleCount; i++) {
+        Vehicle v = new Vehicle();
+
+        v.xCoord = xCoord[0];
+        v.yCoord = yCoord[0];
+        v.capacity = capacity;
+        v.readyTime = 0;
+        v.dueTime = dueTime;
+
+        vehicles.Add(v);
+      }
+
+      line = reader.ReadLine();
+      m = reg.Matches(line);
+
+      while (m.Count == 11) {
+        Order o = new Order();
+
+        int pickupId = int.Parse(m[1].Value);
+        int deliveryId = int.Parse(m[2].Value);
+        double pickupTWOpen = double.Parse(m[3].Value);
+        double pickupTWClose = double.Parse(m[4].Value);
+        double pickupServiceTime = double.Parse(m[5].Value);
+        double deliveryTWOpen = double.Parse(m[6].Value);
+        double deliveryTWClose = double.Parse(m[7].Value);
+        double deliveryServiceTime = double.Parse(m[8].Value);
+        double demand = double.Parse(m[9].Value);
+        double revealed = double.Parse(m[10].Value);
+
+        o.revealedTime = revealed;
+        o.pickupXCoord = xCoord[pickupId];
+        o.pickupYCoord = yCoord[pickupId];
+        o.deliveryXCoord = xCoord[deliveryId];
+        o.deliveryYCoord = yCoord[deliveryId];
+        o.demand = demand;
+        o.pickupServiceTime = pickupServiceTime;
+        o.pickupReadyTime = pickupTWOpen;
+        o.pickupDueTime = pickupTWClose;
+        o.deliveryServiceTime = deliveryServiceTime;
+        o.deliveryReadyTime = deliveryTWOpen;
+        o.deliveryDueTime = deliveryTWClose;
+
+        orders.Add(o);
+
+        line = reader.ReadLine();
+        m = reg.Matches(line);
+      }
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliveryAnalyzer.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliveryAnalyzer.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliveryAnalyzer.cs	(revision 8670)
@@ -0,0 +1,195 @@
+﻿#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 <http://www.gnu.org/licenses/>.
+ */
+#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"));
+
+        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;
+
+      vehicleStatistics.Rows["UsedVehicles"].Values.Add(usedVehicles);
+      vehicleStatistics.Rows["DrivenDistance"].Values.Add(distance);
+      vehicleStatistics.Rows["InvalidActions"].Values.Add(invalidActions);
+      vehicleStatistics.Rows["Tardiness"].Values.Add(tardiness);
+
+      (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();
+    }
+
+    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);
+    }
+
+    public virtual void Tick(PickupDeliverySimulation simulation, PickupDeliveryScenario scenario, ResultCollection results) {
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliveryOptimization.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliveryOptimization.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliveryOptimization.cs	(revision 8670)
@@ -0,0 +1,391 @@
+﻿#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 <http://www.gnu.org/licenses/>.
+ */
+#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<BaseObject, List<PDChange>>();
+      actions = new Dictionary<Guid, PDAction>();
+    }
+    [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<PickupDeliverySimulation>(original.simulation);
+          if (simulation != null) {
+            simulation.SimulationStateChanged +=
+              new PickupDeliverySimulation.SimulationStateChangedHandler(simulation_SimulationStateChanged);
+          }
+
+          objectChanges = new Dictionary<BaseObject, List<PDChange>>();
+          foreach (BaseObject obj in original.objectChanges.Keys) {
+            BaseObject objClone = cloner.Clone<BaseObject>(obj);
+
+            objectChanges.Add(objClone, new List<PDChange>());
+            foreach (PDChange change in original.objectChanges[obj])
+              objectChanges[objClone].Add(cloner.Clone<PDChange>(change));
+          }
+
+          actions = new Dictionary<Guid, PDAction>();
+          foreach (Guid objId in original.actions.Keys) {
+            actions.Add(objId, cloner.Clone<PDAction>(original.actions[objId]));
+          }
+        }
+      }
+
+      this.scenario = cloner.Clone<PickupDeliveryScenario>(original.scenario);
+      this.waitingStrategy = cloner.Clone<WaitingStrategy>(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<Order> GetOrders() {
+      return simulation.Orders;
+    }
+
+    protected Order GetOrder(Guid orderId) {
+      return simulation.GetOrder(orderId);
+    }
+
+    protected Vehicle GetVehicle(Guid vehicleId) {
+      return simulation.GetVehicle(vehicleId);
+    }
+
+    protected List<Vehicle> GetVehicles() {
+      return simulation.Vehicles;
+    }
+
+    protected ResultCollection GetResults() {
+      return simulation.Results;
+    }
+
+    [Storable]
+    private Dictionary<BaseObject, List<PDChange>> objectChanges;
+
+    private void RemoveObsoleteChanges(PDChange change) {
+      List<PDChange> toBeRemoved = new List<PDChange>();
+
+      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<PDChange>());
+
+        RemoveObsoleteChanges(change);
+
+        objectChanges[change.BaseObject].Add(change);
+      }
+    }
+
+    protected List<PDChange> GetChanges(bool clear) {
+      lock (objectChanges) {
+        List<PDChange> result = new List<PDChange>();
+        foreach (List<PDChange> objChanges in objectChanges.Values)
+          result.AddRange(objChanges);
+
+        if(clear)
+          objectChanges.Clear();
+
+        return result;
+      }
+    }
+
+    protected struct ChangeInformation {
+      public List<Vehicle> CreatedVehicles { get; set; }
+      public List<Order> CreatedOrders { get; set; }
+      public List<Vehicle> ChangedVehicles { get; set; }
+      public List<Order> ChangedOrders { get; set; }
+      public bool InvalidActions { get; set; }
+      public bool SimulationFinished { get; set; }
+    }
+
+    protected ChangeInformation GetChangeInformation(List<PDChange> changes) {
+      ChangeInformation changeInformation = new ChangeInformation();
+
+      changeInformation.CreatedVehicles = new List<Vehicle>();
+      changeInformation.CreatedOrders = new List<Order>();
+      changeInformation.ChangedVehicles = new List<Vehicle>();
+      changeInformation.ChangedOrders = new List<Order>();
+      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<Guid, PDAction> 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<Guid> toBeRemoved = new List<Guid>();
+        foreach (Guid objId in actions.Keys) {
+          if (actions[objId].IsCompleted)
+            toBeRemoved.Add(objId);
+        }
+        foreach (Guid objId in toBeRemoved)
+          actions.Remove(objId);
+      }
+    }
+
+    public List<PDAction> 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;
+      started = false;
+      InitWaitHandle(synchronized);
+
+      cts = new CancellationTokenSource();
+      optThread = new Thread(delegate() {
+        lock (this) {
+          started = true;
+        }
+        Optimize(cts.Token);
+      });
+      optThread.IsBackground = true;
+      optThread.Start();
+
+      while (!Started())
+        Thread.Sleep(100);
+    }
+
+    public abstract bool OptimizationRequired();
+
+    public virtual void RelocateVehicles() {
+
+    }
+
+    public void Stop() {
+      if(cts != null)
+       cts.Cancel();
+    }
+
+    private bool started;
+    private bool Started() {
+      bool result;
+      lock (this) {
+        result = started;
+        started = false;
+      }
+      return result;
+    }
+
+    public bool Running() {
+      return optThread != null && optThread.IsAlive && running;
+    }
+
+    public void WaitForExit() {
+      while (Running()) {
+        Thread.Sleep(100);
+      }
+      optThread = null;
+    }
+
+    void simulation_SimulationStateChanged(BaseObject obj, SimulationStateChange changeType) {
+      PDChange change = new PDChange() { BaseObject = obj.Clone() as BaseObject, ChangeType = changeType };
+      AddChange(change);
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliveryOrderGenerator.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliveryOrderGenerator.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliveryOrderGenerator.cs	(revision 8670)
@@ -0,0 +1,52 @@
+﻿#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 <http://www.gnu.org/licenses/>.
+ */
+#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;
+
+namespace HeuristicLab.PDPSimulation {
+  [Item("PickupDeliveryOrderGenerator", "A pickup and delivery order generator.")]
+  [StorableClass]
+  public abstract class PickupDeliveryOrderGenerator: ParameterizedNamedItem {
+    public PickupDeliveryOrderGenerator() : base() {
+    }
+    [StorableConstructor]
+    protected PickupDeliveryOrderGenerator(bool deserializing) : base(deserializing) { }
+    protected PickupDeliveryOrderGenerator(PickupDeliveryOrderGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public abstract IEnumerable<Order> GetOrders(double timeStart, double timeEnd);
+    public abstract bool MoreOrders(double time);
+    public abstract double RangeX();
+    public abstract double RangeY();
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliveryScenario.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliveryScenario.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliveryScenario.cs	(revision 8670)
@@ -0,0 +1,256 @@
+﻿#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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.PDPSimulation.SimulationCore;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+using HeuristicLab.Parameters;
+using HeuristicLab.Data;
+using HeuristicLab.PDPSimulation.DomainModel;
+using HeuristicLab.PDPSimulation.DistanceMeasures;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+using HeuristicLab.PDPSimulation.Operators;
+
+namespace HeuristicLab.PDPSimulation {
+  [Item("PickupDeliveryScenario", "A pickup and delivery scenario.")]
+  [StorableClass]
+  public sealed class PickupDeliveryScenario: Scenario {
+    public event EventHandler ScenarioChanged;
+
+    public ValueParameter<DistanceMeasure> DistanceMeasureParameter {
+      get { return (ValueParameter<DistanceMeasure>)Parameters["DistanceMeasure"]; }
+    }
+
+    public ValueParameter<BoolValue> AllowDiversionParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["AllowDiversion"]; }
+    }
+    
+    public ValueParameter<DoubleMatrix> DepotCoordinatesParameter {
+      get { return (ValueParameter<DoubleMatrix>)Parameters["DepotCoordinates"]; }
+    }
+
+    public ValueParameter<DoubleArray> VehicleCapacitiesParameter {
+      get { return (ValueParameter<DoubleArray>)Parameters["VehicleCapacities"]; }
+    }
+
+    public ValueParameter<DoubleArray> VehicleReadyTimesParameter {
+      get { return (ValueParameter<DoubleArray>)Parameters["VehicleReadyTimes"]; }
+    }
+
+    public ValueParameter<DoubleArray> VehicleDueTimesParameter {
+      get { return (ValueParameter<DoubleArray>)Parameters["VehicleDueTimes"]; }
+    }
+    
+    public OptionalValueParameter<PickupDeliveryOrderGenerator> OrderGeneratorParameter {
+      get { return (OptionalValueParameter<PickupDeliveryOrderGenerator>)Parameters["PickupDeliveryOrderGenerator"]; }
+    }
+
+    public ValueParameter<MDCVRPTWEvaluator> EvaluatorParameter {
+      get { return (ValueParameter<MDCVRPTWEvaluator>)Parameters["Evaluator"]; }
+    }
+
+    public IValueParameter<DoubleValue> FleetUsageFactorParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["FleetUsageFactor"]; }
+    }
+
+    public IValueParameter<DoubleValue> OverloadPenaltyParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["OverloadPenalty"]; }
+    }
+
+    public IValueParameter<DoubleValue> TardinessPenaltyParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["TardinessPenalty"]; }
+    }
+
+    public IValueParameter<DoubleValue> PickupViolationPenaltyParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["PickupViolationPenalty"]; }
+    }
+
+    public IValueParameter<BoolValue> RelocateBackToDepotParameter {
+      get { return (IValueParameter<BoolValue>)Parameters["RelocateBackToDepot"]; }
+    }
+
+    public DistanceMeasure DistanceMeasure {
+      get {
+        return DistanceMeasureParameter.Value;
+      }
+      set {
+        DistanceMeasureParameter.Value = value;
+      }
+    }
+
+    public PickupDeliveryOrderGenerator OrderGenerator {
+      get {
+        return OrderGeneratorParameter.Value;
+      }
+      set {
+        OrderGeneratorParameter.Value = value;
+      }
+    }
+
+    public MDCVRPTWEvaluator Evaluator {
+      get {
+        return EvaluatorParameter.Value;
+      }
+
+      set {
+        EvaluatorParameter.Value = value;
+      }
+    }
+
+    public bool AllowDiversion {
+      get {
+        return AllowDiversionParameter.Value.Value &&
+          DistanceMeasure.DiversionSupported;
+      }
+    }
+
+    public bool RelocateBackToDepot {
+      get {
+        return RelocateBackToDepotParameter.Value.Value;
+      }
+    }
+
+    public PickupDeliveryScenario() : base() {
+      Parameters.Add(new ValueParameter<DistanceMeasure>("DistanceMeasure", new EuclideanDistanceMeasure()));
+      Parameters.Add(new ValueParameter<BoolValue>("AllowDiversion", new BoolValue(false)));
+      Parameters.Add(new ValueParameter<DoubleMatrix>("DepotCoordinates", new DoubleMatrix()));
+      Parameters.Add(new ValueParameter<BoolValue>("RelocateBackToDepot", new BoolValue(true)));
+      Parameters.Add(new ValueParameter<DoubleArray>("VehicleCapacities", new DoubleArray()));
+      Parameters.Add(new ValueParameter<DoubleArray>("VehicleReadyTimes", new DoubleArray()));
+      Parameters.Add(new ValueParameter<DoubleArray>("VehicleDueTimes", new DoubleArray()));
+      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)));
+      Parameters.Add(new ValueParameter<DoubleValue>("TardinessPenalty", "The tardiness penalty considered in the evaluation.", new DoubleValue(10000)));
+      Parameters.Add(new ValueParameter<DoubleValue>("PickupViolationPenalty", "The pickup violation penalty considered in the evaluation.", new DoubleValue(1000000)));
+      Parameters.Add(new OptionalValueParameter<PickupDeliveryOrderGenerator>("PickupDeliveryOrderGenerator"));
+      Parameters.Add(new ValueParameter<MDCVRPTWEvaluator>("Evaluator", new DynPDPEvaluator()));
+
+      DepotCoordinatesParameter.GetsCollected = false;
+      VehicleCapacitiesParameter.GetsCollected = false;
+      VehicleReadyTimesParameter.GetsCollected = false;
+      VehicleDueTimesParameter.GetsCollected = false;
+      OrderGeneratorParameter.GetsCollected = false;
+      DistanceMeasureParameter.GetsCollected = false;
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (!Parameters.ContainsKey("Evaluator")) {
+        Parameters.Add(new ValueParameter<MDCVRPTWEvaluator>("Evaluator", new DynPDPEvaluator()));
+      }
+    }
+
+    public IEnumerable<Order> GetOrders(double timeStart, double timeEnd) {
+      return OrderGeneratorParameter.Value.GetOrders(timeStart, timeEnd);
+    }
+
+    public bool MoreOrders(double time) {
+      return OrderGeneratorParameter.Value.MoreOrders(time);
+    }
+
+    public double OrderRangeX() {
+      return OrderGeneratorParameter.Value.RangeX();
+    }
+
+    public double OrderRangeY() {
+      return OrderGeneratorParameter.Value.RangeY();
+    }
+
+    private void OnScenarioChanged() {
+      if (ScenarioChanged != null)
+        ScenarioChanged(this, null);
+    }
+
+    private void ImportFromDynPDP(DynPDPParser parser) {
+      parser.Parse();
+
+      int vehicles = parser.Vehicles.Length;
+      DoubleMatrix depotCoordinates = new DoubleMatrix(vehicles, 2);
+      DoubleArray vehicleCapacities = new DoubleArray(vehicles);
+      DoubleArray vehicleReadyTimes = new DoubleArray(vehicles);
+      DoubleArray vehicleDueTimes = new DoubleArray(vehicles);
+
+      for (int i = 0; i < vehicles; i++) {
+        DynPDPParser.Vehicle vehicle = parser.Vehicles[i];
+        depotCoordinates[i, 0] = vehicle.xCoord;
+        depotCoordinates[i, 1] = vehicle.yCoord;
+        vehicleCapacities[i] = vehicle.capacity;
+        vehicleReadyTimes[i] = vehicle.readyTime;
+        vehicleDueTimes[i] = vehicle.dueTime;
+      }
+      DepotCoordinatesParameter.Value = depotCoordinates;
+      VehicleCapacitiesParameter.Value = vehicleCapacities;
+      VehicleReadyTimesParameter.Value = vehicleReadyTimes;
+      VehicleDueTimesParameter.Value = vehicleDueTimes;
+
+      PickupDeliveryPredefinedOrderGenerator orderGen = new PickupDeliveryPredefinedOrderGenerator();
+      int orders = parser.Orders.Length;
+
+      DoubleMatrix orderMatrix = new DoubleMatrix(orders, 12,
+        new string[] { "Time revealed", "P X coordinate", "P Y coordinate", "D X coordinate", "D Y coordinate",
+        "Demand", "P service time", "P ready time", "P due time", "D service time", "D ready time", "D due time"});
+      for (int i = 0; i < orders; i++) {
+        DynPDPParser.Order order = parser.Orders[i];
+
+        orderMatrix[i, 0] = order.revealedTime;
+        orderMatrix[i, 1] = order.pickupXCoord;
+        orderMatrix[i, 2] = order.pickupYCoord;
+        orderMatrix[i, 3] = order.deliveryXCoord;
+        orderMatrix[i, 4] = order.deliveryYCoord;
+        orderMatrix[i, 5] = order.demand;
+        orderMatrix[i, 6] = order.pickupServiceTime;
+        orderMatrix[i, 7] = order.pickupReadyTime;
+        orderMatrix[i, 8] = order.pickupDueTime;
+        orderMatrix[i, 9] = order.deliveryServiceTime;
+        orderMatrix[i, 10] = order.deliveryReadyTime;
+        orderMatrix[i, 11] = order.deliveryDueTime;
+      }
+      orderGen.OrdersParameter.Value = orderMatrix;
+      OrderGeneratorParameter.Value = orderGen;
+
+      OnScenarioChanged();
+    }
+
+    public void ImportFromDynPDP(string fileName) {
+      DefaultDynPDPParser parser = new DefaultDynPDPParser(fileName);
+      ImportFromDynPDP(parser);
+    }
+
+    public void ImportFromDynTSPLib(string fileName) {
+      TSPLibDynPDPParser parser = new TSPLibDynPDPParser(fileName);
+      ImportFromDynPDP(parser);
+    }
+
+    [StorableConstructor]
+    private PickupDeliveryScenario(bool deserializing) : base(deserializing) { }
+    private PickupDeliveryScenario(PickupDeliveryScenario original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PickupDeliveryScenario(this, cloner);
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliverySimulation.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliverySimulation.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliverySimulation.cs	(revision 8670)
@@ -0,0 +1,608 @@
+﻿#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 <http://www.gnu.org/licenses/>.
+ */
+#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.Optimization;
+using HeuristicLab.Analysis;
+
+namespace HeuristicLab.PDPSimulation {
+  [Item("PickupDeliverySimulation", "A pickup and delivery simulation.")]
+  [Creatable("Simulations")]
+  [StorableClass]
+  public sealed class PickupDeliverySimulation: Simulation {
+    #region parameters
+    public OptionalValueParameter<PickupDeliveryOptimization> OptimizationParameter {
+      get { return (OptionalValueParameter<PickupDeliveryOptimization>)Parameters["PickupDeliveryOptimization"]; }
+    }
+
+    public OptionalValueParameter<WaitingStrategy> WaitingStrategyParameter {
+      get { return (OptionalValueParameter<WaitingStrategy>)Parameters["WaitingStrategy"]; }
+    }
+
+    public OptionalValueParameter<PickupDeliveryAnalyzer> AnalyzerParameter {
+      get { return (OptionalValueParameter<PickupDeliveryAnalyzer>)Parameters["Analyzer"]; }
+    }
+
+    public ValueParameter<DoubleValue> TimeStepParameter {
+      get { return (ValueParameter<DoubleValue>)Parameters["TimeStep"]; }
+    }
+
+    public ValueParameter<DoubleValue> ResultCollectionIntervalParameter {
+      get { return (ValueParameter<DoubleValue>)Parameters["ResultCollectionInterval"]; }
+    }
+
+
+    public ValueParameter<BoolValue> SynchronizedParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["Synchronized"]; }
+    }
+    public ValueParameter<IntValue> DelayParameter {
+      get { return (ValueParameter<IntValue>)Parameters["Delay"]; }
+    }
+    public ValueParameter<IntValue> InitialDelayParameter {
+      get { return (ValueParameter<IntValue>)Parameters["InitialDelay"]; }
+    }
+
+    private ValueParameter<IntValue> SeedParameter {
+      get { return (ValueParameter<IntValue>)Parameters["Seed"]; }
+    }
+    private ValueParameter<BoolValue> SetSeedRandomlyParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["SetSeedRandomly"]; }
+    }
+    #endregion
+
+    #region properties
+    public double SimulationTime {
+      get {
+        if (!Results.ContainsKey("SimulationTime")) {
+          return 0;
+        } else {
+          DoubleValue simulationTime =
+            (Results["SimulationTime"].Value as DoubleValue);
+          return simulationTime.Value;
+        }
+      }
+
+      private set {
+        if (!Results.ContainsKey("SimulationTime")) {
+          Results.Add(new Result("SimulationTime", new DoubleValue(0)));
+        }
+
+        Results["SimulationTime"].Value = new DoubleValue(value);
+      }
+    }
+
+    public double TimeStep {
+      get {
+        return TimeStepParameter.Value.Value;
+      }
+    }
+
+    private double ResultCollectionInterval {
+      get {
+        return ResultCollectionIntervalParameter.Value.Value;
+      }
+    }
+
+    private bool Synchronized {
+      get {
+        return SynchronizedParameter.Value.Value;
+      }
+    }
+
+    private int Delay {
+      get {
+        return DelayParameter.Value.Value;
+      }
+    }
+
+    public override Type ProblemType {
+      get { return typeof(PickupDeliveryScenario); }
+    }
+
+    private PickupDeliveryScenario Scenario {
+      get {
+        return Problem as PickupDeliveryScenario;
+      }
+    }
+
+    private PickupDeliveryOptimization Optimization {
+      get { return OptimizationParameter.Value;  }
+    }
+
+    private WaitingStrategy WaitingStrategy {
+      get { return WaitingStrategyParameter.Value; }
+    }
+
+    private PickupDeliveryAnalyzer Analyzer {
+      get { return AnalyzerParameter.Value; }
+    }
+    #endregion
+
+    #region constructors
+    public PickupDeliverySimulation()
+      : base() {
+      Parameters.Add(new OptionalValueParameter<PickupDeliveryOptimization>("PickupDeliveryOptimization", new BestInsertion()));
+      Parameters.Add(new OptionalValueParameter<WaitingStrategy>("WaitingStrategy", new DriveFirstWaitingStrategy()));
+      Parameters.Add(new OptionalValueParameter<PickupDeliveryAnalyzer>("Analyzer", new PickupDeliveryAnalyzer()));
+      Parameters.Add(new ValueParameter<DoubleValue>("TimeStep", "The time progress after every tick", new DoubleValue(1)));
+      Parameters.Add(new ValueParameter<DoubleValue>("ResultCollectionInterval", "The result collection interval", new DoubleValue(1)));
+      Parameters.Add(new ValueParameter<BoolValue>("Synchronized", "Indicates if the simulation and optimization should be synchronized", new BoolValue(true)));
+      Parameters.Add(new ValueParameter<IntValue>("Delay", "The delay after each tick", new IntValue(0)));
+      Parameters.Add(new ValueParameter<IntValue>("InitialDelay", "The initial delay", new IntValue(0)));
+      Parameters.Add(new ValueParameter<IntValue>("Seed", "The random seed used to initialize the new pseudo random number generator.", new IntValue(0)));
+      Parameters.Add(new ValueParameter<BoolValue>("SetSeedRandomly", "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true)));
+
+      OptimizationParameter.GetsCollected = false;
+
+      orders = new List<Order>();
+      vehicles = new List<Vehicle>();
+
+      AttachEventHandlers();
+      SetOptimizationSimulation();
+      SetOptimizationScenario();
+      SetWaitingStrategy();
+      SetWaitingStrategyScenario();
+    }
+    [StorableConstructor]
+    private PickupDeliverySimulation(bool deserializing) : base(deserializing) {
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      AttachEventHandlers();
+    }
+
+    private PickupDeliverySimulation(PickupDeliverySimulation original, Cloner cloner)
+      : base(original, cloner) {
+      orders = new List<Order>();
+      foreach (Order order in original.orders) {
+        orders.Add(cloner.Clone<Order>(order));
+      }
+
+      vehicles = new List<Vehicle>();
+      foreach (Vehicle vehicle in original.vehicles) {
+        vehicles.Add(cloner.Clone<Vehicle>(vehicle));
+      }
+
+      newSimulationTime = original.newSimulationTime;
+      lastResultCollection = original.lastResultCollection;
+      simulationObject = cloner.Clone<SimulationObject>(original.simulationObject);
+
+      AttachEventHandlers();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PickupDeliverySimulation(this, cloner);
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AttachEventHandlers() {
+      OptimizationParameter.ValueChanged += new EventHandler(OptimizationParameter_ValueChanged);
+      WaitingStrategyParameter.ValueChanged += new EventHandler(WaitingStrategyParameter_ValueChanged);
+
+      if(Scenario != null)
+        Scenario.ScenarioChanged += new EventHandler(Scenario_ScenarioChanged);
+    }
+
+    void Scenario_ScenarioChanged(object sender, EventArgs e) {
+      SetOptimizationScenario();
+      SetWaitingStrategy();
+      SetWaitingStrategyScenario();
+
+      Prepare();
+    }
+
+    void WaitingStrategyParameter_ValueChanged(object sender, EventArgs e) {
+      SetWaitingStrategy();
+      SetWaitingStrategyScenario();
+    }
+
+    void OptimizationParameter_ValueChanged(object sender, EventArgs e) {
+      SetOptimizationSimulation();
+      SetOptimizationScenario();
+      SetWaitingStrategy();
+    }
+
+    protected override void OnProblemChanged() {
+      base.OnProblemChanged();
+
+      SetOptimizationScenario();
+      SetWaitingStrategy();
+      SetWaitingStrategyScenario();
+
+      if (Scenario != null)
+        Scenario.ScenarioChanged += new EventHandler(Scenario_ScenarioChanged);
+    }
+    #endregion
+
+    #region state
+    [Storable]
+    private List<Order> orders;
+
+    public List<Order> Orders {
+      get {
+        lock (orders) {
+          return new List<Order>(orders);
+        }
+      }
+    }
+
+    public Order GetOrder(Guid orderId) {
+      lock (orders) {
+        return orders.FirstOrDefault(o => o.Id == orderId);
+      }
+    }
+
+    public double OrderRangeX {
+      get { return Scenario.OrderRangeX(); }
+    }
+
+    public double OrderRangeY {
+      get { return Scenario.OrderRangeY(); }
+    }
+
+    private bool AllOrdersDelivered() {
+      bool delivered = true;
+
+      foreach(Order order in orders) {
+        if (order.OrderState != OrderState.Delivered) {
+          delivered = false;
+          break;
+        }
+      }
+
+      return delivered;
+    }
+
+    [Storable]
+    private List<Vehicle> vehicles;
+
+    public List<Vehicle> Vehicles {
+      get {
+        return new List<Vehicle>(vehicles);
+      }
+    }
+
+    public Vehicle GetVehicle(Guid vehicleId) {
+      return vehicles.FirstOrDefault(v => v.Id == vehicleId);
+    }
+
+    private bool AllVehiclesAtDepot() {
+      bool atDepot = true;
+
+      foreach (Vehicle vehicle in vehicles) {
+        if ((vehicle.VehicleState != VehicleState.Parked && vehicle.VehicleState != VehicleState.Waiting) ||
+          vehicle.PositionX != vehicle.DepotX ||
+          vehicle.PositionY != vehicle.DepotY) {
+          atDepot = false;
+          break;
+        }
+      }
+
+      return atDepot;
+    }
+
+    public PDAction GetAction(Vehicle vehicle) {
+      if (Optimization != null)
+        return Optimization.GetAction(vehicle);
+      else
+        return null;
+    }
+
+    [Storable]
+    private double newSimulationTime;
+
+    [Storable]
+    private double lastResultCollection;
+
+    [Storable]
+    private SimulationObject simulationObject;
+    #endregion
+
+    #region events
+
+    public delegate void SimulationStateChangedHandler(BaseObject obj, SimulationStateChange change);
+    public event SimulationStateChangedHandler SimulationStateChanged;
+
+    private void OnSimulationStateChanged(BaseObject obj, SimulationStateChange change) {
+      SimulationStateChangedHandler handler = SimulationStateChanged;
+      if (handler != null)
+        handler(obj, change);
+    }
+    #endregion
+
+    #region synchronization
+    private EventWaitHandle wh;
+    private void InitWaitHandle() {
+      if(wh != null)
+        wh.Dispose();
+
+      wh = null;
+      if (Synchronized)
+        wh = new EventWaitHandle(false, EventResetMode.AutoReset);
+    }
+    private void SignalWaitHandle() {
+      if (wh != null)
+        wh.Set();
+    }
+    public void WaitForSimulation() {
+      if (wh != null)
+        wh.WaitOne();
+    }
+    private void WaitForOptimization() {
+      if (Optimization != null)
+        Optimization.WaitForOptimization();
+    }
+    #endregion
+
+    #region simulation logic
+    private void UpdateVisualization() {
+      if (Analyzer != null)
+        Analyzer.UpdateVisualization(this, Scenario, Results);
+    }
+
+    private void UpdateSimulationState() {
+      bool update = false;
+      if (Optimization != null) {
+        foreach (PDAction action in Optimization.GetActions()) {
+          BaseObject obj = vehicles.FirstOrDefault(v => v.Id == action.BaseObjectId);
+          if(obj == null)
+            obj = orders.FirstOrDefault(o => o.Id == action.BaseObjectId);
+
+          List<PDChange> changes = action.Perform(obj, SimulationTime, TimeStep);
+
+          foreach (PDChange change in changes)
+            OnSimulationStateChanged(change.BaseObject, change.ChangeType);
+
+          if (changes.Count > 0)
+            update = true;
+        }
+      }
+
+      if (update)
+        UpdateVisualization();
+    }
+
+    private void UpdateResults(bool stopped) {
+      if (stopped || SimulationTime == 0 ||
+         (SimulationTime - lastResultCollection) >= ResultCollectionInterval) {
+        //UpdateVisualization();   
+        if (Analyzer != null) {
+          Analyzer.Analyze(this, Scenario, Results);
+        }
+
+        lastResultCollection = SimulationTime;
+      }
+      if (Analyzer != null) {
+        Analyzer.Tick(this, Scenario, Results);
+      }
+    }
+
+    private void UpdateOrders() {
+      lock (orders) {
+        IEnumerable<Order> newOrders = Scenario.GetOrders(SimulationTime, newSimulationTime);
+        foreach (Order order in newOrders) {
+          orders.Add(order);
+          OnSimulationStateChanged(order, SimulationStateChange.OrderCreated);
+        }
+
+        if (!Scenario.MoreOrders(newSimulationTime))
+          OnSimulationStateChanged(simulationObject, SimulationStateChange.NoMoreOrders);
+      }
+    }
+
+    private void CreateSimulation() {
+      vehicles.Clear();
+      orders.Clear();
+
+      simulationObject = new SimulationObject();
+      lastResultCollection = 0;
+      newSimulationTime = TimeStep;
+
+      //create vehicles
+      for (int i = 0; i < Scenario.VehicleCapacitiesParameter.Value.Length; i++) {
+        Vehicle v = new Vehicle();
+        v.VehicleState = VehicleState.Parked;
+        v.Availibility = 1;
+        v.DepotX = v.PositionX = v.TargetPositionX = Scenario.DepotCoordinatesParameter.Value[i, 0];
+        v.DepotY = v.PositionY = v.TargetPositionY = Scenario.DepotCoordinatesParameter.Value[i, 1];
+        v.Capacity = v.TotalCapacity = Scenario.VehicleCapacitiesParameter.Value[i];
+        v.ReadyTime = Scenario.VehicleReadyTimesParameter.Value[i];
+        v.DueTime = Scenario.VehicleDueTimesParameter.Value[i];
+
+        vehicles.Add(v);
+        OnSimulationStateChanged(v, SimulationStateChange.VehicleCreated);
+      }
+
+      //create initial orders
+      UpdateOrders();
+      UpdateResults(false);
+
+      UpdateVisualization();
+    }
+
+    protected override void OnPrepared() {
+      base.OnPrepared();
+      PrepareOptimization();
+      newSimulationTime = 0;
+    }
+
+    private void InitSimulation() {
+      pausePending = false;
+      stopPending = false;
+      InitWaitHandle();
+
+      if (!Results.ContainsKey("SimulationTime")) {
+        PrepareOptimization();
+        CreateSimulation();
+
+        SignalWaitHandle();
+        if (OptimizationRequired()) {
+          StartOptimization();
+          Thread.Sleep(InitialDelayParameter.Value.Value);
+          WaitForOptimization();
+        } else {
+          Thread.Sleep(InitialDelayParameter.Value.Value);
+        }
+      }
+    }
+
+    private void StartOptimization() {
+      if (Optimization != null) {
+        Optimization.Start(Synchronized);
+      }
+    }
+
+    private void StopOptimization() {
+      if (Optimization != null)
+        Optimization.Stop();
+    }
+
+    private void PrepareOptimization() {
+      if (Optimization != null)
+        Optimization.Prepare();
+    }
+
+    private void SetOptimizationScenario() {
+      if (Optimization != null)
+        Optimization.SetScenario(Scenario);
+    }
+
+    private void SetOptimizationSimulation() {
+      if (Optimization != null)
+        Optimization.SetSimulation(this);
+    }
+
+    private void SetWaitingStrategyScenario() {
+      if (WaitingStrategy != null)
+        WaitingStrategy.SetScenario(Scenario);
+    }
+
+    private void SetWaitingStrategy() {
+      if (Optimization != null)
+        Optimization.SetWaitingStrategy(WaitingStrategyParameter.Value);
+    }
+
+    private bool OptimizationRunning() {
+      bool running = false;
+
+      if (Optimization != null)
+        running = Optimization.Running();
+
+      return running;
+    }
+
+    private void RelocateVehicles() {
+      if (Optimization != null)
+        Optimization.RelocateVehicles();
+    }
+
+    private bool OptimizationRequired() {
+      bool required = false;
+
+      if (Optimization != null)
+        required = Optimization.OptimizationRequired();
+
+      return required;
+    }
+
+    private void WaitForOptimizationExit() {
+      if (Optimization != null)
+        Optimization.WaitForExit();
+    }
+
+    private void StopSimulation() {
+      SignalWaitHandle();
+      StopOptimization();
+    }
+
+    private bool pausePending;
+    public override void Pause() {
+      base.Pause();
+      pausePending = true;
+    }
+
+    private bool stopPending;
+    public override void Stop() {
+      base.Stop();
+      stopPending = true;
+    }
+
+    protected override void Run(CancellationToken cancellationToken) {
+      InitSimulation();
+
+      while (!AllOrdersDelivered() || Scenario.MoreOrders(newSimulationTime) || (Scenario.RelocateBackToDepot && !AllVehiclesAtDepot())) {
+        //perform actions
+        UpdateSimulationState();
+
+        //next step
+        SimulationTime = newSimulationTime;
+        newSimulationTime = SimulationTime + TimeStep;
+
+        UpdateOrders();
+        UpdateResults(false);
+
+        if (OptimizationRequired()) {
+          SignalWaitHandle();
+
+          if (!OptimizationRunning() && !(pausePending || stopPending)) {
+            SignalWaitHandle();
+            StartOptimization();
+          }
+
+          WaitForOptimization();
+        } else {
+          RelocateVehicles();
+        }
+
+        if (pausePending || stopPending) {
+          if (!OptimizationRunning()) {
+            cancellationToken.ThrowIfCancellationRequested();
+          } else
+            StopOptimization();
+        }
+
+        Thread.Sleep(Delay);
+      }
+
+      if (Optimization != null)
+        Optimization.RemoveCompletedActions();
+      UpdateResults(true);
+
+      Results.Add(new Result("Finished", new BoolValue(true)));
+
+      Thread.Sleep(500);
+      StopSimulation();
+      WaitForOptimizationExit();
+    }
+  }
+  #endregion
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliveryVisualization.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliveryVisualization.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/PickupDeliveryVisualization.cs	(revision 8670)
@@ -0,0 +1,132 @@
+﻿#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 <http://www.gnu.org/licenses/>.
+ */
+#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.Data;
+using HeuristicLab.PDPSimulation.DomainModel;
+
+namespace HeuristicLab.PDPSimulation {
+  [Item("PickupDeliveryVisualization", "Represents an PDP scenario visualization.")]
+  [StorableClass]
+  public class PickupDeliveryVisualization : Item {
+    [Storable]
+    private List<Order> orders;
+    public IEnumerable<Order> Orders {
+      get { return orders; }
+    }
+
+    [Storable]
+    private double orderRangeX;
+    public double OrderRangeX {
+      get { return orderRangeX; }
+    }
+
+    [Storable]
+    private double orderRangeY;
+    public double OrderRangeY {
+      get { return orderRangeY; }
+    }
+
+    [Storable]
+    private List<Vehicle> vehicles;
+    public IEnumerable<Vehicle> Vehicles {
+      get { return vehicles; }
+    }
+
+    [Storable]
+    private Dictionary<Vehicle, PDAction> actions;
+    public PDAction GetAction(Vehicle vehicle) {
+      if (actions.ContainsKey(vehicle))
+        return actions[vehicle];
+      else
+        return null;
+    }
+
+    public void SetState(PickupDeliverySimulation simulation) {
+      orders = new List<Order>();
+      foreach (Order order in simulation.Orders) {
+        orders.Add(order.Clone() as Order);
+      }
+
+      orderRangeX = simulation.OrderRangeX;
+      orderRangeY = simulation.OrderRangeY;
+
+      vehicles = new List<Vehicle>();
+      actions = new Dictionary<Vehicle, PDAction>();
+      foreach (Vehicle vehicle in simulation.Vehicles) {
+        Vehicle clone = vehicle.Clone() as Vehicle;
+        vehicles.Add(clone);
+        PDAction action = simulation.GetAction(vehicle);
+        if (action != null)
+          actions[clone] = action.Clone() as PDAction;
+      }
+    }
+
+    public PickupDeliveryVisualization(PickupDeliverySimulation simulation)
+      : base() {
+      SetState(simulation);      
+    }
+
+    [StorableConstructor]
+    protected PickupDeliveryVisualization(bool deserializing) : base(deserializing) { }
+    protected PickupDeliveryVisualization(PickupDeliveryVisualization original, Cloner cloner)
+      : base(original, cloner) {
+      orders = new List<Order>();
+      foreach (Order order in original.orders) {
+        orders.Add(order.Clone() as Order);
+      }
+
+      orderRangeX = original.orderRangeX;
+      orderRangeY = original.orderRangeY;
+
+      vehicles = new List<Vehicle>();
+      actions = new Dictionary<Vehicle, PDAction>();
+      foreach (Vehicle vehicle in original.vehicles) {
+        Vehicle clone = vehicle.Clone() as Vehicle;
+        vehicles.Add(clone);
+        PDAction action = original.GetAction(vehicle);
+        if (action != null)
+          actions[clone] = action.Clone() as PDAction;
+      }   
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PickupDeliveryVisualization(this, cloner);
+    }
+
+    public event EventHandler ContentChanged;
+    private void OnContentChanged() {
+      var changed = ContentChanged;
+      if (changed != null)
+        changed(this, EventArgs.Empty);
+    }
+
+    public void Refresh() {
+      OnContentChanged();
+    }
+  }
+}
+
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Plugin.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Plugin.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Plugin.cs	(revision 8670)
@@ -0,0 +1,49 @@
+#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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.PDPSimulation {
+  /// <summary>
+  /// Plugin class for HeuristicLab.PDPSimulation plugin.
+  /// </summary>
+  [Plugin("HeuristicLab.PDPSimulation", "3.3.4.0")]
+  [PluginFile("HeuristicLab.PDPSimulation-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.Analysis", "3.3")]
+  [PluginDependency("HeuristicLab.Collections", "3.3")]
+  [PluginDependency("HeuristicLab.Common", "3.3")]
+  [PluginDependency("HeuristicLab.Common.Resources", "3.3")]
+  [PluginDependency("HeuristicLab.Core", "3.3")]
+  [PluginDependency("HeuristicLab.Data", "3.3")]
+  [PluginDependency("HeuristicLab.Encodings.PermutationEncoding", "3.3")]
+  [PluginDependency("HeuristicLab.Operators", "3.3")]
+  [PluginDependency("HeuristicLab.Optimization", "3.3")]
+  [PluginDependency("HeuristicLab.Optimization.Operators", "3.3")]
+  [PluginDependency("HeuristicLab.Parameters", "3.3")]
+  [PluginDependency("HeuristicLab.Persistence", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.VehicleRouting", "3.4")]
+  [PluginDependency("HeuristicLab.Random", "3.3")]
+  public class HeuristicLabPDPSimulationPlugin : PluginBase {
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Plugin.cs.frame
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Plugin.cs.frame	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Plugin.cs.frame	(revision 8670)
@@ -0,0 +1,49 @@
+#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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.PDPSimulation {
+  /// <summary>
+  /// Plugin class for HeuristicLab.PDPSimulation plugin.
+  /// </summary>
+  [Plugin("HeuristicLab.PDPSimulation", "3.3.4.$WCREV$")]
+  [PluginFile("HeuristicLab.PDPSimulation-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.Analysis", "3.3")]
+  [PluginDependency("HeuristicLab.Collections", "3.3")]
+  [PluginDependency("HeuristicLab.Common", "3.3")]
+  [PluginDependency("HeuristicLab.Common.Resources", "3.3")]
+  [PluginDependency("HeuristicLab.Core", "3.3")]
+  [PluginDependency("HeuristicLab.Data", "3.3")]
+  [PluginDependency("HeuristicLab.Encodings.PermutationEncoding", "3.3")]
+  [PluginDependency("HeuristicLab.Operators", "3.3")]
+  [PluginDependency("HeuristicLab.Optimization", "3.3")]
+  [PluginDependency("HeuristicLab.Optimization.Operators", "3.3")]
+  [PluginDependency("HeuristicLab.Parameters", "3.3")]
+  [PluginDependency("HeuristicLab.Persistence", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.VehicleRouting", "3.4")]
+  [PluginDependency("HeuristicLab.Random", "3.3")]
+  public class HeuristicLabPDPSimulationPlugin : PluginBase {
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Properties/AssemblyInfo.frame
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Properties/AssemblyInfo.frame	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/Properties/AssemblyInfo.frame	(revision 8670)
@@ -0,0 +1,56 @@
+#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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("HeuristicLab.PDPSimulation")]
+[assembly: AssemblyDescription("HeuristicLab pickup and delivery simulation")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("HeuristicLab")]
+[assembly: AssemblyCopyright("(c) 2002-2011 HEAL")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("1A1B1495-36DD-4EE5-ACAA-0490EE333D13")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("3.3.0.0")]
+[assembly: AssemblyFileVersion("3.3.4.$WCREV$")]
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationCore/IScenario.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationCore/IScenario.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationCore/IScenario.cs	(revision 8670)
@@ -0,0 +1,32 @@
+﻿#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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+
+namespace HeuristicLab.PDPSimulation.SimulationCore {
+  public interface IScenario : IProblem {
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationCore/ISimulation.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationCore/ISimulation.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationCore/ISimulation.cs	(revision 8670)
@@ -0,0 +1,32 @@
+﻿#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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+
+namespace HeuristicLab.PDPSimulation.SimulationCore {
+  public interface ISimulation: IAlgorithm {
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationCore/Scenario.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationCore/Scenario.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationCore/Scenario.cs	(revision 8670)
@@ -0,0 +1,51 @@
+﻿#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 <http://www.gnu.org/licenses/>.
+ */
+#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;
+
+namespace HeuristicLab.PDPSimulation.SimulationCore {
+  [Item("Scenario", "Represents the base class for a simulation scenario.")]
+  [StorableClass]
+  public abstract class Scenario : ParameterizedNamedItem, IScenario  {
+    [StorableConstructor]
+    protected Scenario(bool deserializing) : base(deserializing) { }
+    protected Scenario(Scenario original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected Scenario() : base() {}
+
+    #region IProblem Members
+    public IEnumerable<IItem> Operators {
+      get { return null; }
+    }
+    
+    public event EventHandler OperatorsChanged;
+    public event EventHandler Reset;
+    #endregion
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationCore/Simulation.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationCore/Simulation.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationCore/Simulation.cs	(revision 8670)
@@ -0,0 +1,185 @@
+﻿#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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using System.Drawing;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+using HeuristicLab.Collections;
+using HeuristicLab.Optimization;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace HeuristicLab.PDPSimulation.SimulationCore {
+  [Item("Simulation", "A base class for simulations.")]
+  [StorableClass]
+  public abstract class Simulation: Algorithm, ISimulation, IStorableContent {
+    public string Filename { get; set; }
+        
+    public override Type ProblemType {
+      get { return typeof(IScenario); }
+    }
+
+    [Storable]
+    private ResultCollection results;
+    public override ResultCollection Results {
+      get {
+        return results;
+      }
+    }
+
+    #region Variables for communication between threads
+    private CancellationTokenSource cancellationTokenSource;
+    private bool stopPending;
+    private DateTime lastUpdateTime;
+    #endregion
+
+    [StorableConstructor]
+    protected Simulation(bool deserializing) : base(deserializing) { }
+    protected Simulation()
+      : base() {
+        results = new ResultCollection();
+    }
+    protected Simulation(Simulation original, Cloner cloner)
+      : base(original, cloner) {
+        results = cloner.Clone(original.results) as ResultCollection;
+    }
+
+    public sealed override void Prepare() {
+      base.Prepare();
+      results.Clear();
+      OnPrepared();
+    }
+    protected override void OnPrepared() {
+      base.OnPrepared();
+    }
+
+    private class RunInformation {
+      public CancellationTokenSource CancellationToken { get; set; }
+      public IExecutionContext ExecutionContext { get; set; }
+    }
+
+    public virtual void Start(IExecutionContext executionContext) {
+      base.Start();
+
+      RunInformation runInfo = new RunInformation();
+      cancellationTokenSource = new CancellationTokenSource();
+      runInfo.CancellationToken = cancellationTokenSource;
+      runInfo.ExecutionContext = executionContext;
+      stopPending = false;
+      Task task = Task.Factory.StartNew(Run, runInfo, runInfo.CancellationToken.Token);
+      task.ContinueWith(t => {
+        try {
+          t.Wait();
+        }
+        catch (AggregateException ex) {
+          try {
+            ex.Flatten().Handle(x => x is OperationCanceledException);
+          }
+          catch (AggregateException remaining) {
+            if (remaining.InnerExceptions.Count == 1) OnExceptionOccurred(remaining.InnerExceptions[0]);
+            else OnExceptionOccurred(remaining);
+          }
+        }
+        cancellationTokenSource.Dispose();
+        cancellationTokenSource = null;
+        if (stopPending) OnStopped();
+        else OnPaused();
+      });
+    }
+
+    public override void Start() {
+      Start(null);      
+    }
+    protected override void OnStarted() {
+      base.OnStarted();
+    }
+
+    public override void Pause() {
+      base.Pause();
+      cancellationTokenSource.Cancel();
+    }
+    protected override void OnPaused() {
+      base.OnPaused();
+    }
+
+    public override void Stop() {
+      base.Stop();
+      if (ExecutionState == ExecutionState.Paused) {
+        OnStopped();
+      } else {
+        stopPending = true;
+        cancellationTokenSource.Cancel();
+      }
+    }
+    protected override void OnStopped() {
+      base.OnStopped();
+    }
+
+    protected override void OnExceptionOccurred(Exception exception) {
+      base.OnExceptionOccurred(exception);
+    }
+
+    private void Run(object state) {
+      RunInformation runInfo = (RunInformation)state;
+
+      OnStarted();
+      lastUpdateTime = DateTime.Now;
+      System.Timers.Timer timer = new System.Timers.Timer(250);
+      timer.AutoReset = true;
+      timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
+      timer.Start();
+      try {
+        foreach (IParameter parameter in Parameters) {
+          parameter.ExecutionContext = runInfo.ExecutionContext;
+        }
+
+        Run(runInfo.CancellationToken.Token);
+      }
+      finally {
+        timer.Elapsed -= new System.Timers.ElapsedEventHandler(timer_Elapsed);
+        timer.Stop();
+        ExecutionTime += DateTime.Now - lastUpdateTime;
+
+        foreach (IParameter parameter in Parameters) {
+          parameter.ExecutionContext = null;
+        }
+      }
+      Stop();
+
+      runInfo.CancellationToken.Token.ThrowIfCancellationRequested();
+    }
+    protected abstract void Run(CancellationToken cancellationToken);
+
+    private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
+      System.Timers.Timer timer = (System.Timers.Timer)sender;
+      timer.Enabled = false;
+      DateTime now = DateTime.Now;
+      ExecutionTime += now - lastUpdateTime;
+      lastUpdateTime = now;
+      timer.Enabled = true;
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationModel/MoveVehicleAction.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationModel/MoveVehicleAction.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationModel/MoveVehicleAction.cs	(revision 8670)
@@ -0,0 +1,373 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+using HeuristicLab.PDPSimulation.DomainModel;
+using HeuristicLab.PDPSimulation.DistanceMeasures;
+
+namespace HeuristicLab.PDPSimulation {
+  public enum VehicleAction { Wait, Pickup, Deliver, Park, Invalid }  
+  
+  [StorableClass]
+  public class MoveVehicleAction: PDAction {    
+    [Storable]
+    double sourceX;
+
+    public double SourceX {
+      get { return sourceX; }
+    }
+
+    [Storable]
+    double sourceY;
+
+    public double SourceY {
+      get { return sourceY; }
+    }
+    
+    [Storable]
+    double targetX;
+
+    public double TargetX {
+      get { return targetX; }
+    }
+
+    [Storable]
+    double targetY;
+
+    public double TargetY {
+      get { return targetY; }
+    }
+
+    [Storable]
+    VehicleAction action;
+
+    [Storable]
+    Order order;
+
+    [Storable]
+    double serviceTime;
+
+    [Storable]
+    bool interruptable;
+
+    [Storable]
+    bool completed;
+
+    [Storable]
+    DistanceMeasure distMeasure;
+
+    [Storable]
+    bool diversionAllowed;
+
+    public MoveVehicleAction(
+      Guid vehicleId, 
+      double targetX, double targetY, VehicleAction action, Order order, bool diversionAllowed, DistanceMeasure distMeasure)
+      : base(vehicleId) {
+        this.targetX = targetX;
+        this.targetY = targetY;
+        this.action = action;
+        this.order = order;
+        this.serviceTime = 0;
+        this.completed = false;
+        this.diversionAllowed = diversionAllowed;
+        this.interruptable = diversionAllowed;
+        this.distMeasure = distMeasure;
+
+        this.sourceX = -1;
+        this.sourceY = -1;
+    }
+    [StorableConstructor]
+    protected MoveVehicleAction(bool deserializing) : base(deserializing) {
+    }
+    protected MoveVehicleAction(MoveVehicleAction original, Cloner cloner)
+      : base(original, cloner) {
+      this.targetX = original.targetX;
+      this.sourceX = original.sourceX;
+      this.targetY = original.targetY;
+      this.sourceY = original.sourceY;
+      this.action = original.action;
+      this.order = cloner.Clone<Order>(original.order);
+      this.serviceTime = original.serviceTime;
+      this.completed = original.completed;
+      this.interruptable = original.interruptable;
+      this.distMeasure = cloner.Clone<DistanceMeasure>(original.distMeasure);
+      this.diversionAllowed = original.diversionAllowed;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MoveVehicleAction(this, cloner);
+    }
+
+    protected override bool ActionInterruptable() {
+      return interruptable;
+    }
+
+    public override bool ActionCompleted() {
+      return completed;
+    }
+
+    protected override double Perform(BaseObject baseObject, double simulationTime, double tickTime, List<PDChange> changes) {
+      Vehicle vehicle = baseObject as Vehicle;
+      lock (vehicle) {
+        if ((action == VehicleAction.Pickup && (order.OrderState != OrderState.Waiting && order.OrderState != OrderState.PickingUp)) ||
+            (action == VehicleAction.Deliver && ((order.ServiceRequest && order.OrderState != OrderState.Waiting && order.OrderState != OrderState.PickingUp) ||
+                                                 (!order.ServiceRequest && ((order.OrderState != OrderState.PickedUp && order.OrderState != OrderState.Delivering) || !vehicle.PickedUpOrders.Contains(order.Id))))) ||
+           (order != null && (order.Vehicle != Guid.Empty && order.Vehicle != vehicle.Id))) {
+          if (vehicle.VehicleState != VehicleState.InvalidAction) {
+            vehicle.InvalidActions++;
+
+            vehicle.VehicleState = VehicleState.InvalidAction;
+            changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+          }
+
+          if (diversionAllowed)
+            vehicle.ReadyTime = simulationTime;
+          interruptable = diversionAllowed;
+          completed = diversionAllowed;
+
+          if (diversionAllowed)
+            return simulationTime;
+          else {
+            if (order != null) {
+              changes.Add(new PDChange() { ChangeType = SimulationStateChange.OrderFailed, BaseObject = order });
+              order = null;
+              action = VehicleAction.Invalid;
+            }
+          }
+        }
+
+        if (sourceX == -1) {
+          sourceX = vehicle.PositionX;
+          sourceY = vehicle.PositionY;
+        }
+
+        vehicle.TargetPositionX = targetX;
+        vehicle.TargetPositionY = targetY;
+        vehicle.CurrentAction = action;
+        if (order == null)
+          vehicle.CurrentOrder = Guid.Empty;
+        else {
+          if (!diversionAllowed)
+            order.Vehicle = vehicle.Id;
+          vehicle.CurrentOrder = order.Id;
+          changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+        }
+
+        if (action == VehicleAction.Wait || action == VehicleAction.Park)
+          if (diversionAllowed)
+            vehicle.ReadyTime = simulationTime;
+
+        double tx, ty, length;
+        distMeasure.Move(sourceX, sourceY, vehicle.PositionX, vehicle.PositionY, targetX, targetY, tickTime, vehicle.MoveInfo,
+          out tx, out ty, out length);
+
+        if (!diversionAllowed) {
+          double time = simulationTime;
+          time += distMeasure.GetDistance(sourceX, sourceY, vehicle.PositionX, vehicle.PositionY, targetX, targetY);
+          if (action == VehicleAction.Pickup) {
+            if (time < order.PickupReadyTime)
+              time = order.PickupReadyTime;
+
+            time += order.PickupServiceTime - serviceTime;
+          } else if (action == VehicleAction.Deliver) {
+            if (time < order.DeliveryReadyTime)
+              time = order.DeliveryReadyTime;
+
+            time += order.DeliveryServiceTime - serviceTime;
+          }
+
+          vehicle.ReadyTime = time;
+        }
+
+        vehicle.PositionX = tx;
+        vehicle.PositionY = ty;
+
+        if (length > 0) {
+          vehicle.Distance += length;
+          tickTime -= length;
+          simulationTime += length;
+
+          if (vehicle.VehicleState != VehicleState.Moving) {
+            vehicle.VehicleState = VehicleState.Moving;
+            changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+          }
+          changes.Add(
+            new PDChange() { ChangeType = SimulationStateChange.VehicleMoved, BaseObject = baseObject });
+        }
+
+        if (vehicle.PositionX == targetX && vehicle.PositionY == targetY) {
+          if (action == VehicleAction.Pickup || (action == VehicleAction.Deliver && order.ServiceRequest)) {
+            if (order.Vehicle != Guid.Empty && order.Vehicle != vehicle.Id)
+              throw new Exception("Order already assigned");
+
+            if (simulationTime < order.PickupReadyTime) {
+              if (vehicle.VehicleState != VehicleState.Waiting) {
+                if (diversionAllowed)
+                  vehicle.ReadyTime = simulationTime;
+
+                vehicle.VehicleState = VehicleState.Waiting;
+                interruptable = diversionAllowed;
+                changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+              }
+
+              double waitTime = Math.Min(tickTime,
+                order.PickupReadyTime - simulationTime);
+
+              simulationTime += waitTime;
+              tickTime -= waitTime;
+            }
+
+            //pickup
+            if (simulationTime >= order.PickupReadyTime &&
+              tickTime > 0) {
+              if (vehicle.VehicleState != VehicleState.Servicing) {
+                if (diversionAllowed) {
+                  vehicle.ReadyTime = simulationTime;
+                  vehicle.ReadyTime += order.PickupServiceTime;
+                }
+
+                vehicle.VehicleState = VehicleState.Servicing;
+                interruptable = false;
+                changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+              }
+
+              if (order.OrderState != OrderState.PickingUp) {
+                order.PickupTime = simulationTime;
+                order.Vehicle = vehicle.Id;
+                order.OrderState = OrderState.PickingUp;
+                changes.Add(new PDChange() { ChangeType = SimulationStateChange.OrderState, BaseObject = order });
+
+                if (simulationTime > order.PickupDueTime) {
+                  order.Tardiness += simulationTime - order.PickupDueTime;
+                }
+              }
+
+              double service = Math.Min(tickTime,
+                order.PickupServiceTime - serviceTime);
+
+              serviceTime += service;
+              simulationTime += service;
+              tickTime -= service;
+
+              //load
+              if (serviceTime == order.PickupServiceTime) {
+                vehicle.Capacity -= order.Demand;
+
+                if (vehicle.Capacity < 0) {
+                  vehicle.Overload += -vehicle.Capacity;
+                  vehicle.Capacity = 0;
+                }
+
+                vehicle.PickedUpOrders.Add(order.Id);
+                order.Vehicle = vehicle.Id;
+                if (order.ServiceRequest)
+                  order.OrderState = OrderState.Delivered;
+                else
+                  order.OrderState = OrderState.PickedUp;
+                changes.Add(new PDChange() { ChangeType = SimulationStateChange.OrderState, BaseObject = order });
+
+                vehicle.VehicleState = VehicleState.Waiting;
+                changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+                completed = true;
+              }
+            }
+          } else if (action == VehicleAction.Deliver) {
+            if (order.Vehicle != Guid.Empty && order.Vehicle != vehicle.Id)
+              throw new Exception("Order already assigned");
+
+            if (simulationTime < order.DeliveryReadyTime) {
+              if (vehicle.VehicleState != VehicleState.Waiting) {
+                if (diversionAllowed)
+                  vehicle.ReadyTime = simulationTime;
+
+                vehicle.VehicleState = VehicleState.Waiting;
+                interruptable = diversionAllowed;
+                changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+              }
+
+              double waitTime = Math.Min(tickTime,
+                order.DeliveryReadyTime - simulationTime);
+
+              simulationTime += waitTime;
+              tickTime -= waitTime;
+            }
+
+            //deliver
+            if (simulationTime >= order.DeliveryReadyTime &&
+              tickTime > 0) {
+              if (vehicle.VehicleState != VehicleState.Servicing) {
+                if (diversionAllowed) {
+                  vehicle.ReadyTime = simulationTime;
+                  vehicle.ReadyTime += order.DeliveryServiceTime;
+                }
+
+                vehicle.VehicleState = VehicleState.Servicing;
+                interruptable = false;
+                changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+              }
+
+              if (order.OrderState != OrderState.Delivering) {
+                order.DeliveryTime = simulationTime;
+                order.OrderState = OrderState.Delivering;
+                changes.Add(new PDChange() { ChangeType = SimulationStateChange.OrderState, BaseObject = order });
+
+                if (simulationTime > order.DeliveryDueTime) {
+                  order.Tardiness += simulationTime - order.DeliveryDueTime;
+                }
+              }
+
+              double service = Math.Min(tickTime,
+                order.DeliveryServiceTime - serviceTime);
+
+              serviceTime += service;
+              simulationTime += service;
+              tickTime -= service;
+
+              //load
+              if (serviceTime == order.DeliveryServiceTime) {
+                vehicle.Capacity += order.Demand;
+                vehicle.PickedUpOrders.Remove(order.Id);
+                order.OrderState = OrderState.Delivered;
+                changes.Add(new PDChange() { ChangeType = SimulationStateChange.OrderState, BaseObject = order });
+
+                vehicle.VehicleState = VehicleState.Waiting;
+                changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+                completed = true;
+              }
+            }
+          } else if (action == VehicleAction.Park) {
+            completed = true;
+
+            if (vehicle.VehicleState != VehicleState.Parked) {
+              vehicle.VehicleState = VehicleState.Parked;
+              changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+
+              if (vehicle.PositionX == vehicle.DepotX && vehicle.PositionY == vehicle.DepotY) {
+                if (simulationTime > vehicle.DueTime) {
+                  vehicle.Tardiness = simulationTime - vehicle.DueTime;
+                }
+              }
+            }
+          } else if (action == VehicleAction.Wait) {
+            completed = true;
+
+            if (vehicle.VehicleState != VehicleState.Waiting) {
+              vehicle.VehicleState = VehicleState.Waiting;
+              changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+            }
+          } else if (action == VehicleAction.Invalid) {
+            completed = true;
+
+            if (vehicle.VehicleState != VehicleState.InvalidAction) {
+              vehicle.VehicleState = VehicleState.InvalidAction;
+              changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+            }
+          }
+        }
+
+        return simulationTime;
+      }
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationModel/PDAction.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationModel/PDAction.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationModel/PDAction.cs	(revision 8670)
@@ -0,0 +1,134 @@
+﻿#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 <http://www.gnu.org/licenses/>.
+ */
+#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;
+
+namespace HeuristicLab.PDPSimulation {
+  [StorableClass]
+  public abstract class PDAction: Item {
+    [Storable]
+    private Guid baseObjectId;
+
+    public Guid BaseObjectId {
+      get { return baseObjectId; }
+    }
+
+    [Storable]
+    protected PDAction successor;
+
+    public PDAction Successor {
+      get { return successor; }
+    }
+
+    [Storable]
+    protected bool started;
+
+    public void AppendAction(PDAction action, bool recursive) {
+      if (!action.BaseObjectId.Equals(this.BaseObjectId))
+        throw new Exception("Can only append actions of the same object");
+      
+      PDAction predecessor = this;
+      while (predecessor.successor != null && 
+            (recursive || predecessor.ActionCompleted()))
+        predecessor = predecessor.successor;
+
+      predecessor.successor = action;
+    }
+
+    public bool IsCompleted {
+      get {
+        return ActionCompleted() &&
+          (successor == null || successor.IsCompleted);
+      }
+    }
+
+    protected abstract bool ActionInterruptable();
+
+    public bool Interruptable() {
+      PDAction action = this;
+
+      while (action != null && action.ActionCompleted())
+        action = action.successor;
+
+      return action == null || !action.started || action.ActionInterruptable();
+    }
+
+    public abstract bool ActionCompleted();
+
+    protected abstract double Perform(BaseObject baseObject, double simulationTime, double tickTime, List<PDChange> changes);
+
+    public List<PDChange> Perform(BaseObject baseObject, double simulationTime, double timeStep) {
+      List<PDChange> changes = new List<PDChange>();
+
+      lock (this) {
+        double startTime = simulationTime;
+
+        double tickTime = timeStep;
+        bool complete = ActionCompleted();
+        if (!complete && tickTime > 0) {
+          started = true;
+          simulationTime = Perform(baseObject, simulationTime, tickTime, changes);
+          complete = ActionCompleted();
+        }
+
+        PDAction next = successor;
+        while (complete && next != null) {
+          tickTime = timeStep - (simulationTime - startTime);
+
+          complete = next.ActionCompleted();
+          if (!complete && tickTime > 0) {
+            next.started = true;
+            simulationTime = next.Perform(baseObject, simulationTime, tickTime, changes);
+            complete = next.ActionCompleted();
+          }
+
+          next = next.successor;
+        }
+      }
+
+      return changes;
+    }
+
+    public virtual bool Obsoletes(PDAction action) {
+      return this.BaseObjectId.Equals(action.BaseObjectId);
+    }
+
+    protected PDAction(Guid baseObjectId) {
+      this.baseObjectId = baseObjectId;
+    }
+
+    [StorableConstructor]
+    protected PDAction(bool deserializing) : base(deserializing) { }
+    protected PDAction(PDAction original, Cloner cloner)
+      : base(original, cloner) {
+        baseObjectId = original.baseObjectId;
+        successor = cloner.Clone<PDAction>(original.successor);
+        started = original.started;
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationModel/PDChange.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationModel/PDChange.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationModel/PDChange.cs	(revision 8670)
@@ -0,0 +1,35 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PDPSimulation.DomainModel;
+using HeuristicLab.Core;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.PDPSimulation {
+  public enum SimulationStateChange { OrderCreated, OrderState, OrderFailed, VehicleCreated, VehicleMoved, VehicleState, VehicleAvailability, NoMoreOrders }
+  
+  [StorableClass]
+  public class PDChange : Item {
+    [Storable]
+    public BaseObject BaseObject { get; set; }
+
+    [Storable]
+    public SimulationStateChange ChangeType { get; set; }
+
+    public PDChange() {
+    }
+
+    [StorableConstructor]
+    protected PDChange(bool deserializing) : base(deserializing) { }
+    protected PDChange(PDChange original, Cloner cloner)
+      : base(original, cloner) {
+        BaseObject = cloner.Clone<BaseObject>(original.BaseObject);
+        ChangeType = original.ChangeType;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PDChange(this, cloner);
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationModel/WaitAction.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationModel/WaitAction.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/SimulationModel/WaitAction.cs	(revision 8670)
@@ -0,0 +1,57 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+using HeuristicLab.PDPSimulation.DomainModel;
+using HeuristicLab.PDPSimulation.DistanceMeasures;
+
+namespace HeuristicLab.PDPSimulation {  
+  [StorableClass]
+  public class WaitAction: PDAction {    
+    [Storable]
+    double waitingTime;
+
+    public WaitAction(Guid vehicleId, double waitingTime)
+      : base(vehicleId) {
+        this.waitingTime = waitingTime;
+    }
+    [StorableConstructor]
+    protected WaitAction(bool deserializing) : base(deserializing) {
+    }
+    protected WaitAction(WaitAction original, Cloner cloner)
+      : base(original, cloner) {
+        this.waitingTime = original.waitingTime;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new WaitAction(this, cloner);
+    }
+
+    protected override bool ActionInterruptable() {
+      return true;
+    }
+
+    public override bool ActionCompleted() {
+      return waitingTime <= double.Epsilon;
+    }
+
+    protected override double Perform(BaseObject baseObject, double simulationTime, double tickTime, List<PDChange> changes) {
+      double time = Math.Min(tickTime, waitingTime);
+      waitingTime -= time;
+
+      simulationTime += time;
+
+      Vehicle vehicle = baseObject as Vehicle;
+      lock (vehicle) {
+        if ((time > 0) && (vehicle.VehicleState != VehicleState.Waiting) && (vehicle.VehicleState != VehicleState.Parked)) {
+          vehicle.ReadyTime = 0;
+          vehicle.VehicleState = VehicleState.Waiting;
+          changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+        }
+      }
+
+      return simulationTime;
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/VehicleHistoryVisualization.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/VehicleHistoryVisualization.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/VehicleHistoryVisualization.cs	(revision 8670)
@@ -0,0 +1,92 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.PDPSimulation.DomainModel;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.PDPSimulation {
+  [StorableClass]
+  public class VehicleHistory: Item {
+    [Storable]
+    public string VehicleName { get; private set; }
+    [Storable]
+    public List<VehicleState> VehicleState { get; private set; }
+    [Storable]
+    public List<int> VehicleAvailability { get; private set; }
+    [Storable]
+    public List<string> AvailabilityInformation { get; private set; }
+    [Storable]
+    public List<Order> ActiveOrders { get; private set; }
+    [Storable]
+    public List<Order> AssignedOrders { get; private set; }
+
+    public VehicleHistory(string vehicleName) {
+      VehicleName = vehicleName;
+      VehicleState = new List<VehicleState>();
+      VehicleAvailability = new List<int>();
+      AvailabilityInformation = new List<string>();
+      ActiveOrders = new List<Order>();
+      AssignedOrders = new List<Order>();
+    }
+     [StorableConstructor]
+    private VehicleHistory(bool deserializing) : base(deserializing) {
+    }
+     private VehicleHistory(VehicleHistory original, Cloner cloner)
+      : base(original, cloner) {
+        VehicleName = original.VehicleName;
+        VehicleState = new List<VehicleState>(original.VehicleState);
+        AvailabilityInformation = new List<string>(original.AvailabilityInformation);
+        ActiveOrders = new List<Order>();
+        foreach (Order order in original.ActiveOrders)
+          ActiveOrders.Add(cloner.Clone<Order>(order));
+        AssignedOrders = new List<Order>();
+        foreach (Order order in original.AssignedOrders)
+          AssignedOrders.Add(cloner.Clone<Order>(order));
+        VehicleAvailability = new List<int>();
+        VehicleAvailability.AddRange(original.VehicleAvailability);
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new VehicleHistory(this, cloner);
+    }
+  }
+
+  [StorableClass]
+  public class VehicleHistoryVisualization: Item {
+    [Storable]
+    public double ResultCollectionInterval { get; set; }
+    
+    [Storable]
+    public List<VehicleHistory> VehicleHistory { get; private set; }
+
+    public VehicleHistoryVisualization() {
+      VehicleHistory = new List<VehicleHistory>();
+      ResultCollectionInterval = 1.0;
+    }
+    [StorableConstructor]
+    protected VehicleHistoryVisualization(bool deserializing) : base(deserializing) {
+    }
+    protected VehicleHistoryVisualization(VehicleHistoryVisualization original, Cloner cloner)
+      : base(original, cloner) {
+        VehicleHistory = new List<VehicleHistory>();
+        foreach (VehicleHistory history in original.VehicleHistory) {
+          VehicleHistory.Add(cloner.Clone<VehicleHistory>(history));
+        } 
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new VehicleHistoryVisualization(this, cloner);
+    }
+    public event EventHandler ContentChanged;
+    private void OnContentChanged() {
+      var changed = ContentChanged;
+      if (changed != null)
+        changed(this, EventArgs.Empty);
+    }
+
+    public void Refresh() {
+      OnContentChanged();
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/WaitingStrategies/DriveFirstWaitingStrategy.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/WaitingStrategies/DriveFirstWaitingStrategy.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/WaitingStrategies/DriveFirstWaitingStrategy.cs	(revision 8670)
@@ -0,0 +1,66 @@
+﻿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.Operators;
+using HeuristicLab.Problems.VehicleRouting;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Parameters;
+using HeuristicLab.Data;
+
+namespace HeuristicLab.PDPSimulation {
+  [Item("DriveFirstWaitingStrategy", "A pickup and delivery waiting strategy.")]
+  [StorableClass]
+  public class DriveFirstWaitingStrategy : WaitingStrategy {
+    public ValueParameter<BoolValue> WaitAtSourceParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["WaitAtSource"]; }
+    }
+
+    public DriveFirstWaitingStrategy()
+      : base() {
+        Parameters.Add(new ValueParameter<BoolValue>("WaitAtSource", "Indicates, if waiting should only occur at the source and not the target.", new BoolValue(true)));
+    }
+    [StorableConstructor]
+    protected DriveFirstWaitingStrategy(bool deserializing) : base(deserializing) { }
+    protected DriveFirstWaitingStrategy(DriveFirstWaitingStrategy original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DriveFirstWaitingStrategy(this, cloner);
+    }
+
+    public override double GetWaitingTime(double time, DynPDPProblemInstance instance, IVRPEncoding solution, Tour tour, int stop) {
+      bool waitAtSource = WaitAtSourceParameter.Value.Value;
+
+      if (waitAtSource) {
+        double waitTime = 0;
+
+        int vehicle = solution.GetVehicleAssignment(solution.GetTourIndex(tour));
+        bool moving = instance.VehicleStates[vehicle] == DomainModel.VehicleState.Moving;
+        if (!moving || stop != 0) {
+          int customer = 0;
+          if (stop < tour.Stops.Count)
+            customer = tour.Stops[stop];
+          int prev = 0;
+          if (stop > 0)
+            prev = tour.Stops[stop - 1];
+
+          if (customer > 0) {
+            time += instance.GetDistance(prev, customer, solution);
+            double readyTime = instance.ReadyTime[customer + instance.Depots.Value - 1];
+            if (time < readyTime) {
+              waitTime = readyTime - time;
+            }
+          }
+        }
+
+        return waitTime;
+      } else {
+        return 0;
+      }
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/WaitingStrategies/SimulationModel/MoveVehicleAction.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/WaitingStrategies/SimulationModel/MoveVehicleAction.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/WaitingStrategies/SimulationModel/MoveVehicleAction.cs	(revision 8670)
@@ -0,0 +1,368 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+using HeuristicLab.PDPSimulation.DomainModel;
+using HeuristicLab.PDPSimulation.DistanceMeasures;
+
+namespace HeuristicLab.PDPSimulation {
+  public enum VehicleAction { Wait, Pickup, Deliver, Park, Invalid }  
+  
+  [StorableClass]
+  public class MoveVehicleAction: PDAction {    
+    [Storable]
+    double sourceX;
+
+    public double SourceX {
+      get { return sourceX; }
+    }
+
+    [Storable]
+    double sourceY;
+
+    public double SourceY {
+      get { return sourceY; }
+    }
+    
+    [Storable]
+    double targetX;
+
+    public double TargetX {
+      get { return targetX; }
+    }
+
+    [Storable]
+    double targetY;
+
+    public double TargetY {
+      get { return targetY; }
+    }
+
+    [Storable]
+    VehicleAction action;
+
+    [Storable]
+    Order order;
+
+    [Storable]
+    double serviceTime;
+
+    [Storable]
+    bool interruptable;
+
+    [Storable]
+    bool completed;
+
+    [Storable]
+    DistanceMeasure distMeasure;
+
+    [Storable]
+    bool diversionAllowed;
+
+    public MoveVehicleAction(
+      Guid vehicleId, 
+      double targetX, double targetY, VehicleAction action, Order order, bool diversionAllowed, DistanceMeasure distMeasure)
+      : base(vehicleId) {
+        this.targetX = targetX;
+        this.targetY = targetY;
+        this.action = action;
+        this.order = order;
+        this.serviceTime = 0;
+        this.completed = false;
+        this.diversionAllowed = diversionAllowed;
+        this.interruptable = diversionAllowed;
+        this.distMeasure = distMeasure;
+
+        this.sourceX = -1;
+        this.sourceY = -1;
+    }
+    [StorableConstructor]
+    protected MoveVehicleAction(bool deserializing) : base(deserializing) {
+    }
+    protected MoveVehicleAction(MoveVehicleAction original, Cloner cloner)
+      : base(original, cloner) {
+      this.targetX = original.targetX;
+      this.sourceX = original.sourceX;
+      this.targetY = original.targetY;
+      this.sourceY = original.sourceY;
+      this.action = original.action;
+      this.order = cloner.Clone<Order>(original.order);
+      this.serviceTime = original.serviceTime;
+      this.completed = original.completed;
+      this.interruptable = original.interruptable;
+      this.distMeasure = cloner.Clone<DistanceMeasure>(original.distMeasure);
+      this.diversionAllowed = original.diversionAllowed;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MoveVehicleAction(this, cloner);
+    }
+
+    protected override bool ActionInterruptable() {
+      return interruptable;
+    }
+
+    public override bool ActionCompleted() {
+      return completed;
+    }
+
+    protected override double Perform(BaseObject baseObject, double simulationTime, double tickTime, List<PDChange> changes) {
+      Vehicle vehicle = baseObject as Vehicle;
+      lock (vehicle) {
+        if ((action == VehicleAction.Pickup && (order.OrderState != OrderState.Waiting && order.OrderState != OrderState.PickingUp)) ||
+           (action == VehicleAction.Deliver && ((order.OrderState != OrderState.PickedUp && order.OrderState != OrderState.Delivering)
+              || !vehicle.PickedUpOrders.Contains(order.Id))) ||
+           (order != null && (order.Vehicle != Guid.Empty && order.Vehicle != vehicle.Id))) {
+          if (vehicle.VehicleState != VehicleState.InvalidAction) {
+            vehicle.InvalidActions++;
+
+            vehicle.VehicleState = VehicleState.InvalidAction;
+            changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+          }
+
+          if (diversionAllowed)
+            vehicle.ReadyTime = simulationTime;
+          interruptable = diversionAllowed;
+          completed = diversionAllowed;
+
+          if (diversionAllowed)
+            return simulationTime;
+          else {
+            if (order != null) {
+              changes.Add(new PDChange() { ChangeType = SimulationStateChange.OrderFailed, BaseObject = order });
+              order = null;
+              action = VehicleAction.Invalid;
+            }
+          }
+        }
+
+        if (sourceX == -1) {
+          sourceX = vehicle.PositionX;
+          sourceY = vehicle.PositionY;
+        }
+
+        vehicle.TargetPositionX = targetX;
+        vehicle.TargetPositionY = targetY;
+        vehicle.CurrentAction = action;
+        if (order == null)
+          vehicle.CurrentOrder = Guid.Empty;
+        else {
+          if (!diversionAllowed)
+            order.Vehicle = vehicle.Id;
+          vehicle.CurrentOrder = order.Id;
+          changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+        }
+
+        if (action == VehicleAction.Wait || action == VehicleAction.Park)
+          if (diversionAllowed)
+            vehicle.ReadyTime = simulationTime;
+
+        double tx, ty, length;
+        distMeasure.Move(sourceX, sourceY, vehicle.PositionX, vehicle.PositionY, targetX, targetY, tickTime, vehicle.MoveInfo,
+          out tx, out ty, out length);
+
+        if (!diversionAllowed) {
+          double time = simulationTime;
+          time += distMeasure.GetDistance(sourceX, sourceY, vehicle.PositionX, vehicle.PositionY, targetX, targetY);
+          if (action == VehicleAction.Pickup) {
+            if (time < order.PickupReadyTime)
+              time = order.PickupReadyTime;
+
+            time += order.PickupServiceTime - serviceTime;
+          } else if (action == VehicleAction.Deliver) {
+            if (time < order.DeliveryReadyTime)
+              time = order.DeliveryReadyTime;
+
+            time += order.DeliveryServiceTime - serviceTime;
+          }
+
+          vehicle.ReadyTime = time;
+        }
+
+        vehicle.PositionX = tx;
+        vehicle.PositionY = ty;
+
+        if (length > 0) {
+          vehicle.Distance += length;
+          tickTime -= length;
+          simulationTime += length;
+
+          if (vehicle.VehicleState != VehicleState.Moving) {
+            vehicle.VehicleState = VehicleState.Moving;
+            changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+          }
+          changes.Add(
+            new PDChange() { ChangeType = SimulationStateChange.VehicleMoved, BaseObject = baseObject });
+        }
+
+        if (vehicle.PositionX == targetX && vehicle.PositionY == targetY) {
+          if (action == VehicleAction.Pickup) {
+            if (order.Vehicle != Guid.Empty && order.Vehicle != vehicle.Id)
+              throw new Exception("Order already assigned");
+
+            if (simulationTime < order.PickupReadyTime) {
+              if (vehicle.VehicleState != VehicleState.Waiting) {
+                if (diversionAllowed)
+                  vehicle.ReadyTime = simulationTime;
+
+                vehicle.VehicleState = VehicleState.Waiting;
+                interruptable = diversionAllowed;
+                changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+              }
+
+              double waitTime = Math.Min(tickTime,
+                order.PickupReadyTime - simulationTime);
+
+              simulationTime += waitTime;
+              tickTime -= waitTime;
+            }
+
+            //pickup
+            if (simulationTime >= order.PickupReadyTime &&
+              tickTime > 0) {
+              if (vehicle.VehicleState != VehicleState.Servicing) {
+                if (diversionAllowed) {
+                  vehicle.ReadyTime = simulationTime;
+                  vehicle.ReadyTime += order.PickupServiceTime;
+                }
+
+                vehicle.VehicleState = VehicleState.Servicing;
+                interruptable = false;
+                changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+              }
+
+              if (order.OrderState != OrderState.PickingUp) {
+                order.Vehicle = vehicle.Id;
+                order.OrderState = OrderState.PickingUp;
+                changes.Add(new PDChange() { ChangeType = SimulationStateChange.OrderState, BaseObject = order });
+              }
+
+              if (serviceTime == 0 && simulationTime > order.PickupDueTime) {
+                order.Tardiness += simulationTime - order.PickupDueTime;
+              }
+
+              double service = Math.Min(tickTime,
+                order.PickupServiceTime - serviceTime);
+
+              serviceTime += service;
+              simulationTime += service;
+              tickTime -= service;
+
+              //load
+              if (serviceTime == order.PickupServiceTime) {
+                vehicle.Capacity -= order.Demand;
+
+                if (vehicle.Capacity < 0) {
+                  vehicle.Overload = -vehicle.Capacity;
+                  vehicle.Capacity = 0;
+                }
+
+                vehicle.PickedUpOrders.Add(order.Id);
+                order.Vehicle = vehicle.Id;
+                order.OrderState = OrderState.PickedUp;
+                changes.Add(new PDChange() { ChangeType = SimulationStateChange.OrderState, BaseObject = order });
+
+                vehicle.VehicleState = VehicleState.Waiting;
+                changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+                completed = true;
+              }
+            }
+          } else if (action == VehicleAction.Deliver) {
+            if (order.Vehicle != Guid.Empty && order.Vehicle != vehicle.Id)
+              throw new Exception("Order already assigned");
+
+            if (simulationTime < order.DeliveryReadyTime) {
+              if (vehicle.VehicleState != VehicleState.Waiting) {
+                if (diversionAllowed)
+                  vehicle.ReadyTime = simulationTime;
+
+                vehicle.VehicleState = VehicleState.Waiting;
+                interruptable = diversionAllowed;
+                changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+              }
+
+              double waitTime = Math.Min(tickTime,
+                order.DeliveryReadyTime - simulationTime);
+
+              simulationTime += waitTime;
+              tickTime -= waitTime;
+            }
+
+            //deliver
+            if (simulationTime >= order.DeliveryReadyTime &&
+              tickTime > 0) {
+              if (vehicle.VehicleState != VehicleState.Servicing) {
+                if (diversionAllowed) {
+                  vehicle.ReadyTime = simulationTime;
+                  vehicle.ReadyTime += order.DeliveryServiceTime;
+                }
+
+                vehicle.VehicleState = VehicleState.Servicing;
+                interruptable = false;
+                changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+              }
+
+              if (order.OrderState != OrderState.Delivering) {
+                order.OrderState = OrderState.Delivering;
+                changes.Add(new PDChange() { ChangeType = SimulationStateChange.OrderState, BaseObject = order });
+              }
+
+              if (serviceTime == 0 && simulationTime > order.DeliveryDueTime) {
+                order.Tardiness += simulationTime - order.DeliveryDueTime;
+              }
+
+              double service = Math.Min(tickTime,
+                order.DeliveryServiceTime - serviceTime);
+
+              serviceTime += service;
+              simulationTime += service;
+              tickTime -= service;
+
+              //load
+              if (serviceTime == order.DeliveryServiceTime) {
+                vehicle.Capacity += order.Demand;
+                vehicle.PickedUpOrders.Remove(order.Id);
+                order.OrderState = OrderState.Delivered;
+                changes.Add(new PDChange() { ChangeType = SimulationStateChange.OrderState, BaseObject = order });
+
+                vehicle.VehicleState = VehicleState.Waiting;
+                changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+                completed = true;
+              }
+            }
+          } else if (action == VehicleAction.Park) {
+            completed = true;
+
+            if (vehicle.VehicleState != VehicleState.Parked) {
+              vehicle.VehicleState = VehicleState.Parked;
+              changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+
+              if (vehicle.PositionX == vehicle.DepotX && vehicle.PositionY == vehicle.DepotY) {
+                if (simulationTime > vehicle.DueTime) {
+                  vehicle.Tardiness = simulationTime - vehicle.DueTime;
+                }
+              }
+            }
+          } else if (action == VehicleAction.Wait) {
+            completed = true;
+
+            if (vehicle.VehicleState != VehicleState.Waiting) {
+              vehicle.VehicleState = VehicleState.Waiting;
+              changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+            }
+          } else if (action == VehicleAction.Invalid) {
+            completed = true;
+
+            if (vehicle.VehicleState != VehicleState.InvalidAction) {
+              vehicle.VehicleState = VehicleState.InvalidAction;
+              changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+            }
+          }
+        }
+
+        return simulationTime;
+      }
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/WaitingStrategies/SimulationModel/PDAction.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/WaitingStrategies/SimulationModel/PDAction.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/WaitingStrategies/SimulationModel/PDAction.cs	(revision 8670)
@@ -0,0 +1,128 @@
+﻿#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 <http://www.gnu.org/licenses/>.
+ */
+#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;
+
+namespace HeuristicLab.PDPSimulation {
+  [StorableClass]
+  public abstract class PDAction: Item {
+    [Storable]
+    private Guid baseObjectId;
+
+    public Guid BaseObjectId {
+      get { return baseObjectId; }
+    }
+
+    [Storable]
+    protected PDAction successor;
+
+    public PDAction Successor {
+      get { return successor; }
+    }
+
+    public void AppendAction(PDAction action, bool recursive) {
+      if (!action.BaseObjectId.Equals(this.BaseObjectId))
+        throw new Exception("Can only append actions of the same object");
+      
+      PDAction predecessor = this;
+      while (predecessor.successor != null && 
+            (recursive || predecessor.ActionCompleted()))
+        predecessor = predecessor.successor;
+
+      predecessor.successor = action;
+    }
+
+    public bool IsCompleted {
+      get {
+        return ActionCompleted() &&
+          (successor == null || successor.IsCompleted);
+      }
+    }
+
+    protected abstract bool ActionInterruptable();
+
+    public bool Interruptable() {
+      PDAction action = this;
+
+      while (action != null && action.ActionCompleted())
+        action = action.successor;
+
+      return action == null || action.ActionInterruptable();
+    }
+
+    public abstract bool ActionCompleted();
+
+    protected abstract double Perform(BaseObject baseObject, double simulationTime, double tickTime, List<PDChange> changes);
+
+    public List<PDChange> Perform(BaseObject baseObject, double simulationTime, double timeStep) {
+      List<PDChange> changes = new List<PDChange>();
+
+      lock (this) {
+        double startTime = simulationTime;
+
+        double tickTime = timeStep;
+        bool complete = ActionCompleted();
+        if (!complete && tickTime > 0) {
+          simulationTime = Perform(baseObject, simulationTime, tickTime, changes);
+          complete = ActionCompleted();
+        }
+
+        PDAction next = successor;
+        while (complete && next != null) {
+          tickTime = timeStep - (simulationTime - startTime);
+
+          complete = next.ActionCompleted();
+          if (!complete && tickTime > 0) {
+            simulationTime = next.Perform(baseObject, simulationTime, tickTime, changes);
+            complete = next.ActionCompleted();
+          }
+
+          next = next.successor;
+        }
+      }
+
+      return changes;
+    }
+
+    public virtual bool Obsoletes(PDAction action) {
+      return this.BaseObjectId.Equals(action.BaseObjectId);
+    }
+
+    protected PDAction(Guid baseObjectId) {
+      this.baseObjectId = baseObjectId;
+    }
+
+    [StorableConstructor]
+    protected PDAction(bool deserializing) : base(deserializing) { }
+    protected PDAction(PDAction original, Cloner cloner)
+      : base(original, cloner) {
+        baseObjectId = original.baseObjectId;
+        successor = cloner.Clone<PDAction>(original.successor);
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/WaitingStrategies/SimulationModel/PDChange.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/WaitingStrategies/SimulationModel/PDChange.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/WaitingStrategies/SimulationModel/PDChange.cs	(revision 8670)
@@ -0,0 +1,35 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PDPSimulation.DomainModel;
+using HeuristicLab.Core;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.PDPSimulation {
+  public enum SimulationStateChange { OrderCreated, OrderState, OrderFailed, VehicleCreated, VehicleMoved, VehicleState, NoMoreOrders }
+  
+  [StorableClass]
+  public class PDChange : Item {
+    [Storable]
+    public BaseObject BaseObject { get; set; }
+
+    [Storable]
+    public SimulationStateChange ChangeType { get; set; }
+
+    public PDChange() {
+    }
+
+    [StorableConstructor]
+    protected PDChange(bool deserializing) : base(deserializing) { }
+    protected PDChange(PDChange original, Cloner cloner)
+      : base(original, cloner) {
+        BaseObject = cloner.Clone<BaseObject>(original.BaseObject);
+        ChangeType = original.ChangeType;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PDChange(this, cloner);
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/WaitingStrategies/SimulationModel/WaitAction.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/WaitingStrategies/SimulationModel/WaitAction.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/WaitingStrategies/SimulationModel/WaitAction.cs	(revision 8670)
@@ -0,0 +1,57 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+using HeuristicLab.PDPSimulation.DomainModel;
+using HeuristicLab.PDPSimulation.DistanceMeasures;
+
+namespace HeuristicLab.PDPSimulation {  
+  [StorableClass]
+  public class WaitAction: PDAction {    
+    [Storable]
+    double waitingTime;
+
+    public WaitAction(Guid vehicleId, double waitingTime)
+      : base(vehicleId) {
+        this.waitingTime = waitingTime;
+    }
+    [StorableConstructor]
+    protected WaitAction(bool deserializing) : base(deserializing) {
+    }
+    protected WaitAction(WaitAction original, Cloner cloner)
+      : base(original, cloner) {
+        this.waitingTime = original.waitingTime;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new WaitAction(this, cloner);
+    }
+
+    protected override bool ActionInterruptable() {
+      return true;
+    }
+
+    public override bool ActionCompleted() {
+      return waitingTime <= double.Epsilon;
+    }
+
+    protected override double Perform(BaseObject baseObject, double simulationTime, double tickTime, List<PDChange> changes) {
+      double time = Math.Min(tickTime, waitingTime);
+      waitingTime -= time;
+
+      simulationTime += time;
+
+      Vehicle vehicle = baseObject as Vehicle;
+      lock (vehicle) {
+        if ((time > 0) && (vehicle.VehicleState != VehicleState.Waiting)) {
+          vehicle.ReadyTime = 0;
+          vehicle.VehicleState = VehicleState.Waiting;
+          changes.Add(new PDChange() { ChangeType = SimulationStateChange.VehicleState, BaseObject = baseObject });
+        }
+      }
+
+      return simulationTime;
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/WaitingStrategies/WaitFirstWaitingStrategy.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/WaitingStrategies/WaitFirstWaitingStrategy.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/WaitingStrategies/WaitFirstWaitingStrategy.cs	(revision 8670)
@@ -0,0 +1,97 @@
+﻿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.Operators;
+using HeuristicLab.Problems.VehicleRouting;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Parameters;
+using HeuristicLab.Data;
+
+namespace HeuristicLab.PDPSimulation {
+  [Item("WaitFirstWaitingStrategy", "A pickup and delivery waiting strategy.")]
+  [StorableClass]
+  public class WaitFirstWaitingStrategy : WaitingStrategy {
+    protected ValueParameter<BoolValue> OnlyFirstStopParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["OnlyFirstStop"]; }
+    }
+
+    public WaitFirstWaitingStrategy()
+      : base() {
+        Parameters.Add(new ValueParameter<BoolValue>("OnlyFirstStop", "Indicates, if waiting should only occur at the first stop.", new BoolValue(false)));
+    }
+    [StorableConstructor]
+    protected WaitFirstWaitingStrategy(bool deserializing) : base(deserializing) { }
+    protected WaitFirstWaitingStrategy(WaitFirstWaitingStrategy original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new WaitFirstWaitingStrategy(this, cloner);
+    }
+
+    public static double GetSlack(double time, DynPDPProblemInstance instance, IVRPEncoding solution, Tour tour, int stop) {
+      double slack = 0;
+      double minBuffer = double.MaxValue;
+      int count = tour.Stops.Count;
+      if (!(instance as DynPDPProblemInstance).RelocateBackToDepot)
+        count -= 1;
+      for (int i = stop; i <= count; i++) {
+        int customer = 0;
+        if (i < tour.Stops.Count)
+          customer = tour.Stops[i];
+        int prev = 0;
+        if (i > 0)
+          prev = tour.Stops[i - 1];
+
+        int depots = instance.Depots.Value;
+        double distance = instance.GetDistance(prev, customer, solution);
+        time += distance;
+
+        double arrivalTime = time;
+        double deadline = 0;
+        if (customer > 0) {
+          double readyTime = instance.ReadyTime[customer + depots - 1];
+          if (time < readyTime) {
+            slack += readyTime - time;
+            time = readyTime;
+            arrivalTime = time;
+          }
+
+          double serviceTime = instance.ServiceTime[customer - 1];
+          time += serviceTime;
+
+          deadline = instance.DueTime[customer + depots - 1];
+        } else {
+          int depot = instance.GetDepot(prev, solution);
+          deadline = instance.DueTime[depot];
+        }
+
+        double buffer = Math.Max(0, Math.Max(slack, deadline - arrivalTime + slack));
+        if (buffer < minBuffer)
+          minBuffer = buffer;
+      }
+
+      return Math.Floor(minBuffer * 100) / 100;
+    }
+
+    public override double GetWaitingTime(double time, DynPDPProblemInstance instance, IVRPEncoding solution, Tour tour, int stop) {
+      bool onlyFirstStop = OnlyFirstStopParameter.Value.Value;
+      
+      int vehicle = solution.GetVehicleAssignment(solution.GetTourIndex(tour));
+      bool moving = instance.VehicleStates[vehicle] == DomainModel.VehicleState.Moving;
+
+      if (onlyFirstStop) {
+        if ((!moving && stop != 0) || (moving && stop != 1))
+          return 0;
+      } else {
+        if (moving && stop == 0)
+          return 0;
+      }
+
+      return GetSlack(time, instance, solution, tour, stop);
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/WaitingStrategies/WaitingStrategy.cs
===================================================================
--- /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/WaitingStrategies/WaitingStrategy.cs	(revision 8670)
+++ /branches/DynamicVehicleRouting/HeuristicLab.PDPSimulation/3.3/WaitingStrategies/WaitingStrategy.cs	(revision 8670)
@@ -0,0 +1,41 @@
+﻿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.Operators;
+using HeuristicLab.Problems.VehicleRouting;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.PDPSimulation {
+  [Item("Waiting strategy", "A pickup and delivery waiting strategy.")]
+  [StorableClass]
+  public abstract class WaitingStrategy : ParameterizedNamedItem {
+    [Storable]
+    protected PickupDeliveryScenario scenario;
+    
+    public WaitingStrategy()
+      : base() {
+    }
+    [StorableConstructor]
+    protected WaitingStrategy(bool deserializing) : base(deserializing) { }
+    protected WaitingStrategy(WaitingStrategy original, Cloner cloner)
+      : base(original, cloner) {
+        this.scenario = cloner.Clone<PickupDeliveryScenario>(original.scenario);
+    }
+
+    public virtual void SetScenario(PickupDeliveryScenario scenario) {
+      if (scenario != null) {
+        this.scenario = scenario;
+      }
+    }
+
+    public abstract double GetWaitingTime(double time, DynPDPProblemInstance instance, IVRPEncoding solution, Tour tour, int stop);
+
+    public virtual double GetBufferTime(double time, DynPDPProblemInstance instance, IVRPEncoding solution, Tour tour, int stop) {
+      return 0;
+    }
+  }
+}
Index: /branches/DynamicVehicleRouting/PDPSimulation.sln
===================================================================
--- /branches/DynamicVehicleRouting/PDPSimulation.sln	(revision 8670)
+++ /branches/DynamicVehicleRouting/PDPSimulation.sln	(revision 8670)
@@ -0,0 +1,52 @@
+﻿
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{89C26307-57A6-4A44-BB5F-27B39D093EE5}"
+	ProjectSection(SolutionItems) = preProject
+		Build.cmd = Build.cmd
+		PreBuildEvent.cmd = PreBuildEvent.cmd
+	EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.PDPSimulation-3.3", "HeuristicLab.PDPSimulation\3.3\HeuristicLab.PDPSimulation-3.3.csproj", "{F8815280-FA2D-4B3B-B3FD-242863ADB4FF}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.PDPSimulation.Views-3.3", "HeuristicLab.PDPSimulation.Views\3.3\HeuristicLab.PDPSimulation.Views-3.3.csproj", "{08FBD39B-C785-4199-BA39-A7AB87E364C6}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Debug|x64 = Debug|x64
+		Debug|x86 = Debug|x86
+		Release|Any CPU = Release|Any CPU
+		Release|x64 = Release|x64
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{F8815280-FA2D-4B3B-B3FD-242863ADB4FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{F8815280-FA2D-4B3B-B3FD-242863ADB4FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{F8815280-FA2D-4B3B-B3FD-242863ADB4FF}.Debug|x64.ActiveCfg = Debug|x64
+		{F8815280-FA2D-4B3B-B3FD-242863ADB4FF}.Debug|x64.Build.0 = Debug|x64
+		{F8815280-FA2D-4B3B-B3FD-242863ADB4FF}.Debug|x86.ActiveCfg = Debug|x86
+		{F8815280-FA2D-4B3B-B3FD-242863ADB4FF}.Debug|x86.Build.0 = Debug|x86
+		{F8815280-FA2D-4B3B-B3FD-242863ADB4FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{F8815280-FA2D-4B3B-B3FD-242863ADB4FF}.Release|Any CPU.Build.0 = Release|Any CPU
+		{F8815280-FA2D-4B3B-B3FD-242863ADB4FF}.Release|x64.ActiveCfg = Release|x64
+		{F8815280-FA2D-4B3B-B3FD-242863ADB4FF}.Release|x64.Build.0 = Release|x64
+		{F8815280-FA2D-4B3B-B3FD-242863ADB4FF}.Release|x86.ActiveCfg = Release|x86
+		{F8815280-FA2D-4B3B-B3FD-242863ADB4FF}.Release|x86.Build.0 = Release|x86
+		{08FBD39B-C785-4199-BA39-A7AB87E364C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{08FBD39B-C785-4199-BA39-A7AB87E364C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{08FBD39B-C785-4199-BA39-A7AB87E364C6}.Debug|x64.ActiveCfg = Debug|x64
+		{08FBD39B-C785-4199-BA39-A7AB87E364C6}.Debug|x64.Build.0 = Debug|x64
+		{08FBD39B-C785-4199-BA39-A7AB87E364C6}.Debug|x86.ActiveCfg = Debug|x86
+		{08FBD39B-C785-4199-BA39-A7AB87E364C6}.Debug|x86.Build.0 = Debug|x86
+		{08FBD39B-C785-4199-BA39-A7AB87E364C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{08FBD39B-C785-4199-BA39-A7AB87E364C6}.Release|Any CPU.Build.0 = Release|Any CPU
+		{08FBD39B-C785-4199-BA39-A7AB87E364C6}.Release|x64.ActiveCfg = Release|x64
+		{08FBD39B-C785-4199-BA39-A7AB87E364C6}.Release|x64.Build.0 = Release|x64
+		{08FBD39B-C785-4199-BA39-A7AB87E364C6}.Release|x86.ActiveCfg = Release|x86
+		{08FBD39B-C785-4199-BA39-A7AB87E364C6}.Release|x86.Build.0 = Release|x86
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
Index: /branches/DynamicVehicleRouting/PreBuildEvent.cmd
===================================================================
--- /branches/DynamicVehicleRouting/PreBuildEvent.cmd	(revision 8670)
+++ /branches/DynamicVehicleRouting/PreBuildEvent.cmd	(revision 8670)
@@ -0,0 +1,2 @@
+IF EXIST "%ProjectDir%\Properties\AssemblyInfo.cs.frame" SubWCRev "%ProjectDir%\" "%ProjectDir%\Properties\AssemblyInfo.cs.frame" "%ProjectDir%\Properties\AssemblyInfo.cs"
+IF EXIST "%ProjectDir%\Plugin.cs.frame" SubWCRev "%ProjectDir%\" "%ProjectDir%\Plugin.cs.frame" "%ProjectDir%\Plugin.cs"
