Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/BestAverageWorstVRPToursAnalyzer.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/BestAverageWorstVRPToursAnalyzer.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/BestAverageWorstVRPToursAnalyzer.cs	(revision 14416)
@@ -0,0 +1,208 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  /// <summary>
+  /// An operator which analyzes the best, average and worst quality of solutions in the scope tree.
+  /// </summary>
+  [Item("BestAverageWorstVRPToursAnalyzer", "An operator which analyzes the best, average and worst properties of the VRP tours in the scope tree.")]
+  [StorableClass]
+  public sealed class BestAverageWorstVRPToursAnalyzer : AlgorithmOperator, IAnalyzer, IGeneralVRPOperator {
+    #region Parameter properties
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (ILookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> DistanceParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Distance"]; }
+    }
+    public ValueLookupParameter<DoubleValue> BestDistanceParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestDistance"]; }
+    }
+    public ValueLookupParameter<DoubleValue> CurrentBestDistanceParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["CurrentBestDistance"]; }
+    }
+    public ValueLookupParameter<DoubleValue> CurrentAverageDistanceParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["CurrentAverageDistance"]; }
+    }
+    public ValueLookupParameter<DoubleValue> CurrentWorstDistanceParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["CurrentWorstDistance"]; }
+    }
+    public ValueLookupParameter<DataTable> DistancesParameter {
+      get { return (ValueLookupParameter<DataTable>)Parameters["Distances"]; }
+    }
+
+    public ScopeTreeLookupParameter<DoubleValue> VehiclesUtilizedParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["VehiclesUtilized"]; }
+    }
+    public ValueLookupParameter<DoubleValue> BestVehiclesUtilizedParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestVehiclesUtilized"]; }
+    }
+    public ValueLookupParameter<DoubleValue> CurrentBestVehiclesUtilizedParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["CurrentBestVehiclesUtilized"]; }
+    }
+    public ValueLookupParameter<DoubleValue> CurrentAverageVehiclesUtilizedParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["CurrentAverageVehiclesUtilized"]; }
+    }
+    public ValueLookupParameter<DoubleValue> CurrentWorstVehiclesUtilizedParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["CurrentWorstVehiclesUtilized"]; }
+    }
+    public ValueLookupParameter<DataTable> VehiclesUtilizedValuesParameter {
+      get { return (ValueLookupParameter<DataTable>)Parameters["VehiclesUtilizedValues"]; }
+    }
+
+    public ValueLookupParameter<VariableCollection> ResultsParameter {
+      get { return (ValueLookupParameter<VariableCollection>)Parameters["Results"]; }
+    }
+    #endregion
+
+    #region Properties
+    public bool EnabledByDefault {
+      get { return true; }
+    }
+    private BestVRPToursMemorizer BestMemorizer {
+      get { return (BestVRPToursMemorizer)OperatorGraph.InitialOperator; }
+    }
+    private BestAverageWorstVRPToursCalculator BestAverageWorstCalculator {
+      get { return (BestAverageWorstVRPToursCalculator)BestMemorizer.Successor; }
+    }
+    #endregion
+
+    public BestAverageWorstVRPToursAnalyzer()
+      : base() {
+      #region Create parameters
+      Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The problem instance."));
+
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Distance", "The distance of the VRP solutions which should be analyzed."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestDistance", "The best distance value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentBestDistance", "The current best distance value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentAverageDistance", "The current average distance value of all solutions."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentWorstDistance", "The current worst distance value of all solutions."));
+      Parameters.Add(new ValueLookupParameter<DataTable>("Distances", "The data table to store the current best, current average, current worst, best and best known distance value."));
+
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("VehiclesUtilized", "The vehicles utilized of the VRP solutions which should be analyzed."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestVehiclesUtilized", "The best  vehicles utilized value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentBestVehiclesUtilized", "The current best  vehicles utilized value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentAverageVehiclesUtilized", "The current average  vehicles utilized value of all solutions."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentWorstVehiclesUtilized", "The current worst  vehicles utilized value of all solutions."));
+      Parameters.Add(new ValueLookupParameter<DataTable>("VehiclesUtilizedValues", "The data table to store the current best, current average, current worst, best and best known vehicles utilized value."));
+
+      Parameters.Add(new ValueLookupParameter<VariableCollection>("Results", "The results collection where the analysis values should be stored."));
+      #endregion
+
+      #region Create operators
+      BestVRPToursMemorizer bestMemorizer = new BestVRPToursMemorizer();
+      BestAverageWorstVRPToursCalculator calculator = new BestAverageWorstVRPToursCalculator();
+      ResultsCollector resultsCollector = new ResultsCollector();
+
+      //Distance
+      bestMemorizer.BestDistanceParameter.ActualName = BestDistanceParameter.Name;
+      bestMemorizer.DistanceParameter.ActualName = DistanceParameter.Name;
+      bestMemorizer.DistanceParameter.Depth = DistanceParameter.Depth;
+
+      calculator.DistanceParameter.ActualName = DistanceParameter.Name;
+      calculator.DistanceParameter.Depth = DistanceParameter.Depth;
+      calculator.BestDistanceParameter.ActualName = CurrentBestDistanceParameter.Name;
+      calculator.AverageDistanceParameter.ActualName = CurrentAverageDistanceParameter.Name;
+      calculator.WorstDistanceParameter.ActualName = CurrentWorstDistanceParameter.Name;
+
+      DataTableValuesCollector distanceDataTablesCollector = new DataTableValuesCollector();
+      distanceDataTablesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("BestDistance", null, BestDistanceParameter.Name));
+      distanceDataTablesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("CurrentBestDistance", null, CurrentBestDistanceParameter.Name));
+      distanceDataTablesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("CurrentAverageDistance", null, CurrentAverageDistanceParameter.Name));
+      distanceDataTablesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("CurrentWorstDistance", null, CurrentWorstDistanceParameter.Name));
+      distanceDataTablesCollector.DataTableParameter.ActualName = DistancesParameter.Name;
+
+      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>(DistancesParameter.Name));
+
+      //Vehicles Utlized
+      bestMemorizer.BestVehiclesUtilizedParameter.ActualName = BestVehiclesUtilizedParameter.Name;
+      bestMemorizer.VehiclesUtilizedParameter.ActualName = VehiclesUtilizedParameter.Name;
+      bestMemorizer.VehiclesUtilizedParameter.Depth = VehiclesUtilizedParameter.Depth;
+
+      calculator.VehiclesUtilizedParameter.ActualName = VehiclesUtilizedParameter.Name;
+      calculator.VehiclesUtilizedParameter.Depth = VehiclesUtilizedParameter.Depth;
+      calculator.BestVehiclesUtilizedParameter.ActualName = CurrentBestVehiclesUtilizedParameter.Name;
+      calculator.AverageVehiclesUtilizedParameter.ActualName = CurrentAverageVehiclesUtilizedParameter.Name;
+      calculator.WorstVehiclesUtilizedParameter.ActualName = CurrentWorstVehiclesUtilizedParameter.Name;
+
+      DataTableValuesCollector vehiclesUtilizedDataTablesCollector = new DataTableValuesCollector();
+      vehiclesUtilizedDataTablesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("BestVehiclesUtilized", null, BestVehiclesUtilizedParameter.Name));
+      vehiclesUtilizedDataTablesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("CurrentBestVehiclesUtilized", null, CurrentBestVehiclesUtilizedParameter.Name));
+      vehiclesUtilizedDataTablesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("CurrentAverageVehiclesUtilized", null, CurrentAverageVehiclesUtilizedParameter.Name));
+      vehiclesUtilizedDataTablesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("CurrentWorstVehiclesUtilized", null, CurrentWorstVehiclesUtilizedParameter.Name));
+      vehiclesUtilizedDataTablesCollector.DataTableParameter.ActualName = VehiclesUtilizedValuesParameter.Name;
+
+      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>(VehiclesUtilizedValuesParameter.Name));
+      #endregion
+
+      #region Create operator graph
+      OperatorGraph.InitialOperator = bestMemorizer;
+      bestMemorizer.Successor = calculator;
+      calculator.Successor = distanceDataTablesCollector;
+      distanceDataTablesCollector.Successor = vehiclesUtilizedDataTablesCollector;
+      vehiclesUtilizedDataTablesCollector.Successor = resultsCollector;
+      resultsCollector.Successor = null;
+      #endregion
+
+      Initialize();
+    }
+    [StorableConstructor]
+    private BestAverageWorstVRPToursAnalyzer(bool deserializing) : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BestAverageWorstVRPToursAnalyzer(this, cloner);
+    }
+
+    private BestAverageWorstVRPToursAnalyzer(BestAverageWorstVRPToursAnalyzer original, Cloner cloner)
+      : base(original, cloner) {
+      this.Initialize();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void Initialize() {
+      DistanceParameter.DepthChanged += new EventHandler(DistanceParameter_DepthChanged);
+      VehiclesUtilizedParameter.DepthChanged += new EventHandler(VehiclesUtilizedParameter_DepthChanged);
+    }
+
+    void DistanceParameter_DepthChanged(object sender, EventArgs e) {
+      BestAverageWorstCalculator.DistanceParameter.Depth = DistanceParameter.Depth;
+      BestMemorizer.DistanceParameter.Depth = DistanceParameter.Depth;
+    }
+
+    void VehiclesUtilizedParameter_DepthChanged(object sender, EventArgs e) {
+      BestAverageWorstCalculator.VehiclesUtilizedParameter.Depth = VehiclesUtilizedParameter.Depth;
+      BestMemorizer.VehiclesUtilizedParameter.Depth = DistanceParameter.Depth;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/BestAverageWorstVRPToursCalculator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/BestAverageWorstVRPToursCalculator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/BestAverageWorstVRPToursCalculator.cs	(revision 14416)
@@ -0,0 +1,135 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  [Item("BestAverageWorstVRPToursCalculator", "An operator which calculates the current best, average and worst properties of VRP tours in the scope tree.")]
+  [StorableClass]
+  public sealed class BestAverageWorstVRPToursCalculator : SingleSuccessorOperator {
+    public ScopeTreeLookupParameter<DoubleValue> DistanceParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Distance"]; }
+    }
+    public ValueLookupParameter<DoubleValue> BestDistanceParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestDistance"]; }
+    }
+    public ValueLookupParameter<DoubleValue> AverageDistanceParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["AverageDistance"]; }
+    }
+    public ValueLookupParameter<DoubleValue> WorstDistanceParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["WorstDistance"]; }
+    }
+
+    public ScopeTreeLookupParameter<DoubleValue> VehiclesUtilizedParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["VehiclesUtilized"]; }
+    }
+    public ValueLookupParameter<DoubleValue> BestVehiclesUtilizedParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestVehiclesUtilized"]; }
+    }
+    public ValueLookupParameter<DoubleValue> AverageVehiclesUtilizedParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["AverageVehiclesUtilized"]; }
+    }
+    public ValueLookupParameter<DoubleValue> WorstVehiclesUtilizedParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["WorstVehiclesUtilized"]; }
+    }
+
+    public BestAverageWorstVRPToursCalculator()
+      : base() {
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Distance", "The distances of the VRP solutions which should be analyzed."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestDistance", "The best distance value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("AverageDistance", "The average distance value of all solutions."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("WorstDistance", "The worst distance value of all solutions."));
+
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("VehiclesUtilized", "The utilized vehicles of the VRP solutions which should be analyzed."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestVehiclesUtilized", "The best utilized vehicles value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("AverageVehiclesUtilized", "The average utilized vehicles value of all solutions."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("WorstVehiclesUtilized", "The worst utilized vehicles value of all solutions."));
+    }
+
+    [StorableConstructor]
+    private BestAverageWorstVRPToursCalculator(bool deserializing) : base(deserializing) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BestAverageWorstVRPToursCalculator(this, cloner);
+    }
+
+    private BestAverageWorstVRPToursCalculator(BestAverageWorstVRPToursCalculator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    private void UpdateDistances() {
+      ItemArray<DoubleValue> distances = DistanceParameter.ActualValue;
+      if (distances.Length > 0) {
+        double min = double.MaxValue, max = double.MinValue, sum = 0.0;
+        for (int i = 0; i < distances.Length; i++) {
+          if (distances[i].Value < min) min = distances[i].Value;
+          if (distances[i].Value > max) max = distances[i].Value;
+          sum += distances[i].Value;
+        }
+
+        DoubleValue best = BestDistanceParameter.ActualValue;
+        if (best == null) BestDistanceParameter.ActualValue = new DoubleValue(min);
+        else best.Value = min;
+        DoubleValue average = AverageDistanceParameter.ActualValue;
+        if (average == null) AverageDistanceParameter.ActualValue = new DoubleValue(sum / distances.Length);
+        else average.Value = sum / distances.Length;
+        DoubleValue worst = WorstDistanceParameter.ActualValue;
+        if (worst == null) WorstDistanceParameter.ActualValue = new DoubleValue(max);
+        else worst.Value = max;
+      }
+    }
+
+
+    private void UpdateVehiclesUtilized() {
+      ItemArray<DoubleValue> vehiclesUtilized = VehiclesUtilizedParameter.ActualValue;
+      if (vehiclesUtilized.Length > 0) {
+        double min = double.MaxValue, max = double.MinValue, sum = 0.0;
+        for (int i = 0; i < vehiclesUtilized.Length; i++) {
+          if (vehiclesUtilized[i].Value < min) min = vehiclesUtilized[i].Value;
+          if (vehiclesUtilized[i].Value > max) max = vehiclesUtilized[i].Value;
+          sum += vehiclesUtilized[i].Value;
+        }
+
+        DoubleValue best = BestVehiclesUtilizedParameter.ActualValue;
+        if (best == null) BestVehiclesUtilizedParameter.ActualValue = new DoubleValue(min);
+        else best.Value = min;
+        DoubleValue average = AverageVehiclesUtilizedParameter.ActualValue;
+        if (average == null) AverageVehiclesUtilizedParameter.ActualValue = new DoubleValue(sum / vehiclesUtilized.Length);
+        else average.Value = sum / vehiclesUtilized.Length;
+        DoubleValue worst = WorstVehiclesUtilizedParameter.ActualValue;
+        if (worst == null) WorstVehiclesUtilizedParameter.ActualValue = new DoubleValue(max);
+        else worst.Value = max;
+      }
+    }
+
+    public override IOperation Apply() {
+      UpdateDistances();
+      UpdateVehiclesUtilized();
+
+      return base.Apply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/BestVRPToursMemorizer.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/BestVRPToursMemorizer.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/BestVRPToursMemorizer.cs	(revision 14416)
@@ -0,0 +1,85 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  [Item("BestVRPToursMemorizer", "An operator that updates the best VRP tour found so far in the scope three.")]
+  [StorableClass]
+  public class BestVRPToursMemorizer : SingleSuccessorOperator {
+    public ScopeTreeLookupParameter<DoubleValue> DistanceParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Distance"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> VehiclesUtilizedParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["VehiclesUtilized"]; }
+    }
+
+    public ValueLookupParameter<DoubleValue> BestDistanceParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestDistance"]; }
+    }
+    public ValueLookupParameter<DoubleValue> BestVehiclesUtilizedParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestVehiclesUtilized"]; }
+    }
+
+    public BestVRPToursMemorizer()
+      : base() {
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Distance", "The distances of the VRP solutions which should be analyzed."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("VehiclesUtilized", "The utilized vehicles of the VRP solutions which should be analyzed."));
+
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestDistance", "The best distance found so far."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestVehiclesUtilized", "The best vehicles utilized found so far."));
+
+    }
+
+    [StorableConstructor]
+    protected BestVRPToursMemorizer(bool deserializing) : base(deserializing) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BestVRPToursMemorizer(this, cloner);
+    }
+
+    protected BestVRPToursMemorizer(BestVRPToursMemorizer original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IOperation Apply() {
+      int i = DistanceParameter.ActualValue.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index;
+      if (BestDistanceParameter.ActualValue == null)
+        BestDistanceParameter.ActualValue = new DoubleValue(DistanceParameter.ActualValue[i].Value);
+      else if (DistanceParameter.ActualValue[i].Value <= BestDistanceParameter.ActualValue.Value)
+        BestDistanceParameter.ActualValue.Value = DistanceParameter.ActualValue[i].Value;
+
+      i = VehiclesUtilizedParameter.ActualValue.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index;
+      if (BestVehiclesUtilizedParameter.ActualValue == null)
+        BestVehiclesUtilizedParameter.ActualValue = new DoubleValue(VehiclesUtilizedParameter.ActualValue[i].Value);
+      else if (VehiclesUtilizedParameter.ActualValue[i].Value <= BestVehiclesUtilizedParameter.ActualValue.Value)
+        BestVehiclesUtilizedParameter.ActualValue.Value = VehiclesUtilizedParameter.ActualValue[i].Value;
+
+      return base.Apply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/Capacitated/BestAverageWorstCapacitatedVRPToursAnalyzer.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/Capacitated/BestAverageWorstCapacitatedVRPToursAnalyzer.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/Capacitated/BestAverageWorstCapacitatedVRPToursAnalyzer.cs	(revision 14416)
@@ -0,0 +1,155 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  /// <summary>
+  /// An operator which analyzes the best, average and worst quality of solutions in the scope tree.
+  /// </summary>
+  [Item("BestAverageWorstCapaciatatedVRPToursAnalyzer", "An operator which analyzes the best, average and worst properties of the VRP tours in the scope tree.")]
+  [StorableClass]
+  public sealed class BestAverageWorstCapaciatatedVRPToursAnalyzer : AlgorithmOperator, IAnalyzer, IHomogenousCapacitatedOperator {
+    #region Parameter properties
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (ILookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> OverloadParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Overload"]; }
+    }
+    public ValueLookupParameter<DoubleValue> BestOverloadParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestOverload"]; }
+    }
+    public ValueLookupParameter<DoubleValue> CurrentBestOverloadParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["CurrentBestOverload"]; }
+    }
+    public ValueLookupParameter<DoubleValue> CurrentAverageOverloadParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["CurrentAverageOverload"]; }
+    }
+    public ValueLookupParameter<DoubleValue> CurrentWorstOverloadParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["CurrentWorstOverload"]; }
+    }
+    public ValueLookupParameter<DataTable> OverloadsParameter {
+      get { return (ValueLookupParameter<DataTable>)Parameters["Overloads"]; }
+    }
+
+    public ValueLookupParameter<VariableCollection> ResultsParameter {
+      get { return (ValueLookupParameter<VariableCollection>)Parameters["Results"]; }
+    }
+    #endregion
+
+    #region Properties
+    public bool EnabledByDefault {
+      get { return true; }
+    }
+    private BestCapacitatedVRPToursMemorizer BestMemorizer {
+      get { return (BestCapacitatedVRPToursMemorizer)OperatorGraph.InitialOperator; }
+    }
+    private BestAverageWorstCapacitatedVRPToursCalculator BestAverageWorstCalculator {
+      get { return (BestAverageWorstCapacitatedVRPToursCalculator)BestMemorizer.Successor; }
+    }
+    #endregion
+
+    public BestAverageWorstCapaciatatedVRPToursAnalyzer()
+      : base() {
+      #region Create parameters
+      Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The problem instance."));
+
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Overload", "The overloads of the VRP solutions which should be analyzed."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestOverload", "The best overload value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentBestOverload", "The current best overload value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentAverageOverload", "The current average overload value of all solutions."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentWorstOverload", "The current worst overload value of all solutions."));
+      Parameters.Add(new ValueLookupParameter<DataTable>("Overloads", "The data table to store the current best, current average, current worst, best and best known overload value."));
+
+      Parameters.Add(new ValueLookupParameter<VariableCollection>("Results", "The results collection where the analysis values should be stored."));
+      #endregion
+
+      #region Create operators
+      BestCapacitatedVRPToursMemorizer bestMemorizer = new BestCapacitatedVRPToursMemorizer();
+      BestAverageWorstCapacitatedVRPToursCalculator calculator = new BestAverageWorstCapacitatedVRPToursCalculator();
+      ResultsCollector resultsCollector = new ResultsCollector();
+
+      //overload
+      bestMemorizer.BestOverloadParameter.ActualName = BestOverloadParameter.Name;
+      bestMemorizer.OverloadParameter.ActualName = OverloadParameter.Name;
+      bestMemorizer.OverloadParameter.Depth = OverloadParameter.Depth;
+
+      calculator.OverloadParameter.ActualName = OverloadParameter.Name;
+      calculator.OverloadParameter.Depth = OverloadParameter.Depth;
+      calculator.BestOverloadParameter.ActualName = CurrentBestOverloadParameter.Name;
+      calculator.AverageOverloadParameter.ActualName = CurrentAverageOverloadParameter.Name;
+      calculator.WorstOverloadParameter.ActualName = CurrentWorstOverloadParameter.Name;
+
+      DataTableValuesCollector overloadDataTablesCollector = new DataTableValuesCollector();
+      overloadDataTablesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("BestOverload", null, BestOverloadParameter.Name));
+      overloadDataTablesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("CurrentBestOverload", null, CurrentBestOverloadParameter.Name));
+      overloadDataTablesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("CurrentAverageOverload", null, CurrentAverageOverloadParameter.Name));
+      overloadDataTablesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("CurrentWorstOverload", null, CurrentWorstOverloadParameter.Name));
+      overloadDataTablesCollector.DataTableParameter.ActualName = OverloadsParameter.Name;
+
+      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>(OverloadsParameter.Name));
+      #endregion
+
+      #region Create operator graph
+      OperatorGraph.InitialOperator = bestMemorizer;
+      bestMemorizer.Successor = calculator;
+      calculator.Successor = overloadDataTablesCollector;
+      overloadDataTablesCollector.Successor = resultsCollector;
+      resultsCollector.Successor = null;
+      #endregion
+
+      Initialize();
+    }
+    [StorableConstructor]
+    private BestAverageWorstCapaciatatedVRPToursAnalyzer(bool deserializing) : base() { }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void Initialize() {
+      OverloadParameter.DepthChanged += new EventHandler(OverloadParameter_DepthChanged);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BestAverageWorstCapaciatatedVRPToursAnalyzer(this, cloner);
+    }
+
+    private BestAverageWorstCapaciatatedVRPToursAnalyzer(BestAverageWorstCapaciatatedVRPToursAnalyzer original, Cloner cloner)
+      : base(original, cloner) {
+      this.Initialize();
+    }
+
+    void OverloadParameter_DepthChanged(object sender, EventArgs e) {
+      BestAverageWorstCalculator.OverloadParameter.Depth = OverloadParameter.Depth;
+      BestMemorizer.OverloadParameter.Depth = OverloadParameter.Depth;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/Capacitated/BestAverageWorstCapacitatedVRPToursCalculator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/Capacitated/BestAverageWorstCapacitatedVRPToursCalculator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/Capacitated/BestAverageWorstCapacitatedVRPToursCalculator.cs	(revision 14416)
@@ -0,0 +1,93 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  [Item("BestAverageWorstCapacitatedVRPToursCalculator", "An operator which calculates the current best, average and worst properties of VRP tours in the scope tree.")]
+  [StorableClass]
+  public sealed class BestAverageWorstCapacitatedVRPToursCalculator : SingleSuccessorOperator {
+    public ScopeTreeLookupParameter<DoubleValue> OverloadParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Overload"]; }
+    }
+    public ValueLookupParameter<DoubleValue> BestOverloadParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestOverload"]; }
+    }
+    public ValueLookupParameter<DoubleValue> AverageOverloadParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["AverageOverload"]; }
+    }
+    public ValueLookupParameter<DoubleValue> WorstOverloadParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["WorstOverload"]; }
+    }
+
+    public BestAverageWorstCapacitatedVRPToursCalculator()
+      : base() {
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Overload", "The overloads of the VRP solutions which should be analyzed."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestOverload", "The best overload value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("AverageOverload", "The average overload value of all solutions."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("WorstOverload", "The worst overload value of all solutions."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BestAverageWorstCapacitatedVRPToursCalculator(this, cloner);
+    }
+
+    private BestAverageWorstCapacitatedVRPToursCalculator(BestAverageWorstCapacitatedVRPToursCalculator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    [StorableConstructor]
+    private BestAverageWorstCapacitatedVRPToursCalculator(bool deserializing) : base(deserializing) { }
+
+    private void UpdateOverloads() {
+      ItemArray<DoubleValue> overloads = OverloadParameter.ActualValue;
+      if (overloads.Length > 0) {
+        double min = double.MaxValue, max = double.MinValue, sum = 0.0;
+        for (int i = 0; i < overloads.Length; i++) {
+          if (overloads[i].Value < min) min = overloads[i].Value;
+          if (overloads[i].Value > max) max = overloads[i].Value;
+          sum += overloads[i].Value;
+        }
+
+        DoubleValue best = BestOverloadParameter.ActualValue;
+        if (best == null) BestOverloadParameter.ActualValue = new DoubleValue(min);
+        else best.Value = min;
+        DoubleValue average = AverageOverloadParameter.ActualValue;
+        if (average == null) AverageOverloadParameter.ActualValue = new DoubleValue(sum / overloads.Length);
+        else average.Value = sum / overloads.Length;
+        DoubleValue worst = WorstOverloadParameter.ActualValue;
+        if (worst == null) WorstOverloadParameter.ActualValue = new DoubleValue(max);
+        else worst.Value = max;
+      }
+    }
+
+    public override IOperation Apply() {
+      UpdateOverloads();
+
+      return base.Apply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/Capacitated/BestCapacitatedVRPToursMemorizer.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/Capacitated/BestCapacitatedVRPToursMemorizer.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/Capacitated/BestCapacitatedVRPToursMemorizer.cs	(revision 14416)
@@ -0,0 +1,70 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  [Item("BestCapacitatedVRPToursMemorizer", "An operator that updates the best VRP tour found so far in the scope three.")]
+  [StorableClass]
+  public class BestCapacitatedVRPToursMemorizer : SingleSuccessorOperator {
+    public ScopeTreeLookupParameter<DoubleValue> OverloadParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Overload"]; }
+    }
+
+    public ValueLookupParameter<DoubleValue> BestOverloadParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestOverload"]; }
+    }
+
+    public BestCapacitatedVRPToursMemorizer()
+      : base() {
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Overload", "The overloads of the VRP solutions which should be analyzed."));
+
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestOverload", "The best overload found so far."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BestCapacitatedVRPToursMemorizer(this, cloner);
+    }
+
+    protected BestCapacitatedVRPToursMemorizer(BestCapacitatedVRPToursMemorizer original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    [StorableConstructor]
+    protected BestCapacitatedVRPToursMemorizer(bool deserializing) : base(deserializing) { }
+
+    public override IOperation Apply() {
+      int i = OverloadParameter.ActualValue.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index;
+      if (BestOverloadParameter.ActualValue == null)
+        BestOverloadParameter.ActualValue = new DoubleValue(OverloadParameter.ActualValue[i].Value);
+      else if (OverloadParameter.ActualValue[i].Value <= BestOverloadParameter.ActualValue.Value)
+        BestOverloadParameter.ActualValue.Value = OverloadParameter.ActualValue[i].Value;
+
+      return base.Apply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/PickupAndDelivery/BestAverageWorstPickupAndDeliveryVRPToursAnalyzer.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/PickupAndDelivery/BestAverageWorstPickupAndDeliveryVRPToursAnalyzer.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/PickupAndDelivery/BestAverageWorstPickupAndDeliveryVRPToursAnalyzer.cs	(revision 14416)
@@ -0,0 +1,155 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  /// <summary>
+  /// An operator which analyzes the best, average and worst quality of solutions in the scope tree.
+  /// </summary>
+  [Item("BestAverageWorstPickupAndDeliveryVRPToursAnalyzer", "An operator which analyzes the best, average and worst properties of the VRP tours in the scope tree.")]
+  [StorableClass]
+  public sealed class BestAverageWorstPickupAndDeliveryVRPToursAnalyzer : AlgorithmOperator, IAnalyzer, IPickupAndDeliveryOperator {
+    #region Parameter properties
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (ILookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+    public ScopeTreeLookupParameter<IntValue> PickupViolationsParameter {
+      get { return (ScopeTreeLookupParameter<IntValue>)Parameters["PickupViolations"]; }
+    }
+    public ValueLookupParameter<IntValue> BestPickupViolationsParameter {
+      get { return (ValueLookupParameter<IntValue>)Parameters["BestPickupViolations"]; }
+    }
+    public ValueLookupParameter<IntValue> CurrentBestPickupViolationsParameter {
+      get { return (ValueLookupParameter<IntValue>)Parameters["CurrentBestPickupViolations"]; }
+    }
+    public ValueLookupParameter<DoubleValue> CurrentAveragePickupViolationsParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["CurrentAveragePickupViolations"]; }
+    }
+    public ValueLookupParameter<IntValue> CurrentWorstPickupViolationsParameter {
+      get { return (ValueLookupParameter<IntValue>)Parameters["CurrentWorstPickupViolations"]; }
+    }
+    public ValueLookupParameter<DataTable> PickupViolationsValuesParameter {
+      get { return (ValueLookupParameter<DataTable>)Parameters["PickupViolationsValues"]; }
+    }
+
+    public ValueLookupParameter<VariableCollection> ResultsParameter {
+      get { return (ValueLookupParameter<VariableCollection>)Parameters["Results"]; }
+    }
+    #endregion
+
+    #region Properties
+    public bool EnabledByDefault {
+      get { return true; }
+    }
+    private BestPickupAndDeliveryVRPToursMemorizer BestMemorizer {
+      get { return (BestPickupAndDeliveryVRPToursMemorizer)OperatorGraph.InitialOperator; }
+    }
+    private BestAverageWorstPickupAndDeliveryVRPToursCalculator BestAverageWorstCalculator {
+      get { return (BestAverageWorstPickupAndDeliveryVRPToursCalculator)BestMemorizer.Successor; }
+    }
+    #endregion
+
+    public BestAverageWorstPickupAndDeliveryVRPToursAnalyzer()
+      : base() {
+      #region Create parameters
+      Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The problem instance."));
+
+      Parameters.Add(new ScopeTreeLookupParameter<IntValue>("PickupViolations", "The pickup violations of the VRP solutions which should be analyzed."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("BestPickupViolations", "The best pickup violations value."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("CurrentBestPickupViolations", "The current best pickup violations value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentAveragePickupViolations", "The current average pickup violations value of all solutions."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("CurrentWorstPickupViolations", "The current worst pickup violations value of all solutions."));
+      Parameters.Add(new ValueLookupParameter<DataTable>("PickupViolationsValues", "The data table to store the current best, current average, current worst, best and best known pickup violations value."));
+
+      Parameters.Add(new ValueLookupParameter<VariableCollection>("Results", "The results collection where the analysis values should be stored."));
+      #endregion
+
+      #region Create operators
+      BestPickupAndDeliveryVRPToursMemorizer bestMemorizer = new BestPickupAndDeliveryVRPToursMemorizer();
+      BestAverageWorstPickupAndDeliveryVRPToursCalculator calculator = new BestAverageWorstPickupAndDeliveryVRPToursCalculator();
+      ResultsCollector resultsCollector = new ResultsCollector();
+
+      //pickup violations
+      bestMemorizer.BestPickupViolationsParameter.ActualName = BestPickupViolationsParameter.Name;
+      bestMemorizer.PickupViolationsParameter.ActualName = PickupViolationsParameter.Name;
+      bestMemorizer.PickupViolationsParameter.Depth = PickupViolationsParameter.Depth;
+
+      calculator.PickupViolationsParameter.ActualName = PickupViolationsParameter.Name;
+      calculator.PickupViolationsParameter.Depth = PickupViolationsParameter.Depth;
+      calculator.BestPickupViolationsParameter.ActualName = CurrentBestPickupViolationsParameter.Name;
+      calculator.AveragePickupViolationsParameter.ActualName = CurrentAveragePickupViolationsParameter.Name;
+      calculator.WorstPickupViolationsParameter.ActualName = CurrentWorstPickupViolationsParameter.Name;
+
+      DataTableValuesCollector pickupViolationsDataTablesCollector = new DataTableValuesCollector();
+      pickupViolationsDataTablesCollector.CollectedValues.Add(new LookupParameter<IntValue>("BestPickupViolations", null, BestPickupViolationsParameter.Name));
+      pickupViolationsDataTablesCollector.CollectedValues.Add(new LookupParameter<IntValue>("CurrentBestPickupViolations", null, CurrentBestPickupViolationsParameter.Name));
+      pickupViolationsDataTablesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("CurrentAveragePickupViolations", null, CurrentAveragePickupViolationsParameter.Name));
+      pickupViolationsDataTablesCollector.CollectedValues.Add(new LookupParameter<IntValue>("CurrentWorstPickupViolations", null, CurrentWorstPickupViolationsParameter.Name));
+      pickupViolationsDataTablesCollector.DataTableParameter.ActualName = PickupViolationsValuesParameter.Name;
+
+      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>(PickupViolationsValuesParameter.Name));
+      #endregion
+
+      #region Create operator graph
+      OperatorGraph.InitialOperator = bestMemorizer;
+      bestMemorizer.Successor = calculator;
+      calculator.Successor = pickupViolationsDataTablesCollector;
+      pickupViolationsDataTablesCollector.Successor = resultsCollector;
+      resultsCollector.Successor = null;
+      #endregion
+
+      Initialize();
+    }
+    [StorableConstructor]
+    private BestAverageWorstPickupAndDeliveryVRPToursAnalyzer(bool deserializing) : base() { }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void Initialize() {
+      PickupViolationsParameter.DepthChanged += new EventHandler(PickupViolationsParameter_DepthChanged);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BestAverageWorstPickupAndDeliveryVRPToursAnalyzer(this, cloner);
+    }
+
+    private BestAverageWorstPickupAndDeliveryVRPToursAnalyzer(BestAverageWorstPickupAndDeliveryVRPToursAnalyzer original, Cloner cloner)
+      : base(original, cloner) {
+      this.Initialize();
+    }
+
+    void PickupViolationsParameter_DepthChanged(object sender, EventArgs e) {
+      BestAverageWorstCalculator.PickupViolationsParameter.Depth = PickupViolationsParameter.Depth;
+      BestMemorizer.PickupViolationsParameter.Depth = PickupViolationsParameter.Depth;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/PickupAndDelivery/BestAverageWorstPickupAndDeliveryVRPToursCalculator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/PickupAndDelivery/BestAverageWorstPickupAndDeliveryVRPToursCalculator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/PickupAndDelivery/BestAverageWorstPickupAndDeliveryVRPToursCalculator.cs	(revision 14416)
@@ -0,0 +1,93 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  [Item("BestAverageWorstPickupAndDeliveryVRPToursCalculator", "An operator which calculates the current best, average and worst properties of VRP tours in the scope tree.")]
+  [StorableClass]
+  public sealed class BestAverageWorstPickupAndDeliveryVRPToursCalculator : SingleSuccessorOperator {
+    public ScopeTreeLookupParameter<IntValue> PickupViolationsParameter {
+      get { return (ScopeTreeLookupParameter<IntValue>)Parameters["PickupViolations"]; }
+    }
+    public ValueLookupParameter<IntValue> BestPickupViolationsParameter {
+      get { return (ValueLookupParameter<IntValue>)Parameters["BestPickupViolations"]; }
+    }
+    public ValueLookupParameter<DoubleValue> AveragePickupViolationsParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["AveragePickupViolations"]; }
+    }
+    public ValueLookupParameter<IntValue> WorstPickupViolationsParameter {
+      get { return (ValueLookupParameter<IntValue>)Parameters["WorstPickupViolations"]; }
+    }
+
+    public BestAverageWorstPickupAndDeliveryVRPToursCalculator()
+      : base() {
+      Parameters.Add(new ScopeTreeLookupParameter<IntValue>("PickupViolations", "The pickup violations of the VRP solutions which should be analyzed."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("BestPickupViolations", "The best pickup violations value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("AveragePickupViolations", "The average pickup violations value of all solutions."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("WorstPickupViolations", "The worst pickup violations value of all solutions."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BestAverageWorstPickupAndDeliveryVRPToursCalculator(this, cloner);
+    }
+
+    private BestAverageWorstPickupAndDeliveryVRPToursCalculator(BestAverageWorstPickupAndDeliveryVRPToursCalculator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    [StorableConstructor]
+    private BestAverageWorstPickupAndDeliveryVRPToursCalculator(bool deserializing) : base(deserializing) { }
+
+    private void UpdatePickupViolations() {
+      ItemArray<IntValue> pickupViolations = PickupViolationsParameter.ActualValue;
+      if (pickupViolations.Length > 0) {
+        int min = int.MaxValue, max = int.MinValue, sum = 0;
+        for (int i = 0; i < pickupViolations.Length; i++) {
+          if (pickupViolations[i].Value < min) min = pickupViolations[i].Value;
+          if (pickupViolations[i].Value > max) max = pickupViolations[i].Value;
+          sum += pickupViolations[i].Value;
+        }
+
+        IntValue best = BestPickupViolationsParameter.ActualValue;
+        if (best == null) BestPickupViolationsParameter.ActualValue = new IntValue(min);
+        else best.Value = min;
+        DoubleValue average = AveragePickupViolationsParameter.ActualValue;
+        if (average == null) AveragePickupViolationsParameter.ActualValue = new DoubleValue(sum / pickupViolations.Length);
+        else average.Value = sum / pickupViolations.Length;
+        IntValue worst = WorstPickupViolationsParameter.ActualValue;
+        if (worst == null) WorstPickupViolationsParameter.ActualValue = new IntValue(max);
+        else worst.Value = max;
+      }
+    }
+
+    public override IOperation Apply() {
+      UpdatePickupViolations();
+
+      return base.Apply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/PickupAndDelivery/BestPickupAndDeliveryVRPToursMemorizer.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/PickupAndDelivery/BestPickupAndDeliveryVRPToursMemorizer.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/PickupAndDelivery/BestPickupAndDeliveryVRPToursMemorizer.cs	(revision 14416)
@@ -0,0 +1,70 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  [Item("BestPickupAndDeliveryVRPToursMemorizer", "An operator that updates the best VRP tour found so far in the scope three.")]
+  [StorableClass]
+  public class BestPickupAndDeliveryVRPToursMemorizer : SingleSuccessorOperator {
+    public ScopeTreeLookupParameter<IntValue> PickupViolationsParameter {
+      get { return (ScopeTreeLookupParameter<IntValue>)Parameters["PickupViolations"]; }
+    }
+
+    public ValueLookupParameter<IntValue> BestPickupViolationsParameter {
+      get { return (ValueLookupParameter<IntValue>)Parameters["BestPickupViolations"]; }
+    }
+
+    public BestPickupAndDeliveryVRPToursMemorizer()
+      : base() {
+      Parameters.Add(new ScopeTreeLookupParameter<IntValue>("PickupViolations", "The pickup violations of the VRP solutions which should be analyzed."));
+
+      Parameters.Add(new ValueLookupParameter<IntValue>("BestPickupViolations", "The best pickup violations found so far."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BestPickupAndDeliveryVRPToursMemorizer(this, cloner);
+    }
+
+    protected BestPickupAndDeliveryVRPToursMemorizer(BestPickupAndDeliveryVRPToursMemorizer original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    [StorableConstructor]
+    protected BestPickupAndDeliveryVRPToursMemorizer(bool deserializing) : base(deserializing) { }
+
+    public override IOperation Apply() {
+      int i = PickupViolationsParameter.ActualValue.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index;
+      if (BestPickupViolationsParameter.ActualValue == null)
+        BestPickupViolationsParameter.ActualValue = new IntValue(PickupViolationsParameter.ActualValue[i].Value);
+      else if (PickupViolationsParameter.ActualValue[i].Value <= BestPickupViolationsParameter.ActualValue.Value)
+        BestPickupViolationsParameter.ActualValue.Value = PickupViolationsParameter.ActualValue[i].Value;
+
+      return base.Apply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/TimeWindowed/BestAverageWorstTimeWindowedVRPToursAnalyzer.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/TimeWindowed/BestAverageWorstTimeWindowedVRPToursAnalyzer.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/TimeWindowed/BestAverageWorstTimeWindowedVRPToursAnalyzer.cs	(revision 14416)
@@ -0,0 +1,208 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  /// <summary>
+  /// An operator which analyzes the best, average and worst quality of solutions in the scope tree.
+  /// </summary>
+  [Item("BestAverageWorstTimeWindowedVRPToursAnalyzer", "An operator which analyzes the best, average and worst properties of the VRP tours in the scope tree.")]
+  [StorableClass]
+  public sealed class BestAverageWorstTimeWindowedVRPToursAnalyzer : AlgorithmOperator, IAnalyzer, ITimeWindowedOperator {
+    #region Parameter properties
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (ILookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> TardinessParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Tardiness"]; }
+    }
+    public ValueLookupParameter<DoubleValue> BestTardinessParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestTardiness"]; }
+    }
+    public ValueLookupParameter<DoubleValue> CurrentBestTardinessParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["CurrentBestTardiness"]; }
+    }
+    public ValueLookupParameter<DoubleValue> CurrentAverageTardinessParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["CurrentAverageTardiness"]; }
+    }
+    public ValueLookupParameter<DoubleValue> CurrentWorstTardinessParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["CurrentWorstTardiness"]; }
+    }
+    public ValueLookupParameter<DataTable> TardinessValuesParameter {
+      get { return (ValueLookupParameter<DataTable>)Parameters["TardinessValues"]; }
+    }
+
+    public ScopeTreeLookupParameter<DoubleValue> TravelTimeParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["TravelTime"]; }
+    }
+    public ValueLookupParameter<DoubleValue> BestTravelTimeParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestTravelTime"]; }
+    }
+    public ValueLookupParameter<DoubleValue> CurrentBestTravelTimeParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["CurrentBestTravelTime"]; }
+    }
+    public ValueLookupParameter<DoubleValue> CurrentAverageTravelTimeParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["CurrentAverageTravelTime"]; }
+    }
+    public ValueLookupParameter<DoubleValue> CurrentWorstTravelTimeParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["CurrentWorstTravelTime"]; }
+    }
+    public ValueLookupParameter<DataTable> TravelTimesParameter {
+      get { return (ValueLookupParameter<DataTable>)Parameters["TravelTimes"]; }
+    }
+
+    public ValueLookupParameter<VariableCollection> ResultsParameter {
+      get { return (ValueLookupParameter<VariableCollection>)Parameters["Results"]; }
+    }
+    #endregion
+
+    #region Properties
+    public bool EnabledByDefault {
+      get { return true; }
+    }
+    private BestTimeWindowedVRPToursMemorizer BestMemorizer {
+      get { return (BestTimeWindowedVRPToursMemorizer)OperatorGraph.InitialOperator; }
+    }
+    private BestAverageWorstTimeWindowedVRPToursCalculator BestAverageWorstCalculator {
+      get { return (BestAverageWorstTimeWindowedVRPToursCalculator)BestMemorizer.Successor; }
+    }
+    #endregion
+
+    public BestAverageWorstTimeWindowedVRPToursAnalyzer()
+      : base() {
+      #region Create parameters
+      Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The problem instance."));
+
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Tardiness", "The tardiness of the VRP solutions which should be analyzed."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestTardiness", "The best tardiness value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentBestTardiness", "The current best tardiness value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentAverageTardiness", "The current average tardiness value of all solutions."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentWorstTardiness", "The current worst tardiness value of all solutions."));
+      Parameters.Add(new ValueLookupParameter<DataTable>("TardinessValues", "The data table to store the current best, current average, current worst, best and best known tardiness value."));
+
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("TravelTime", "The travel time of the VRP solutions which should be analyzed."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestTravelTime", "The best travel time value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentBestTravelTime", "The current best travel time value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentAverageTravelTime", "The current average travel time value of all solutions."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentWorstTravelTime", "The current worst travel time value of all solutions."));
+      Parameters.Add(new ValueLookupParameter<DataTable>("TravelTimes", "The data table to store the current best, current average, current worst, best and best known travel time value."));
+
+      Parameters.Add(new ValueLookupParameter<VariableCollection>("Results", "The results collection where the analysis values should be stored."));
+      #endregion
+
+      #region Create operators
+      BestTimeWindowedVRPToursMemorizer bestMemorizer = new BestTimeWindowedVRPToursMemorizer();
+      BestAverageWorstTimeWindowedVRPToursCalculator calculator = new BestAverageWorstTimeWindowedVRPToursCalculator();
+      ResultsCollector resultsCollector = new ResultsCollector();
+
+      //tardiness
+      bestMemorizer.BestTardinessParameter.ActualName = BestTardinessParameter.Name;
+      bestMemorizer.TardinessParameter.ActualName = TardinessParameter.Name;
+      bestMemorizer.TardinessParameter.Depth = TardinessParameter.Depth;
+
+      calculator.TardinessParameter.ActualName = TardinessParameter.Name;
+      calculator.TardinessParameter.Depth = TardinessParameter.Depth;
+      calculator.BestTardinessParameter.ActualName = CurrentBestTardinessParameter.Name;
+      calculator.AverageTardinessParameter.ActualName = CurrentAverageTardinessParameter.Name;
+      calculator.WorstTardinessParameter.ActualName = CurrentWorstTardinessParameter.Name;
+
+      DataTableValuesCollector tardinessDataTablesCollector = new DataTableValuesCollector();
+      tardinessDataTablesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("BestTardiness", null, BestTardinessParameter.Name));
+      tardinessDataTablesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("CurrentBestTardiness", null, CurrentBestTardinessParameter.Name));
+      tardinessDataTablesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("CurrentAverageTardiness", null, CurrentAverageTardinessParameter.Name));
+      tardinessDataTablesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("CurrentWorstTardiness", null, CurrentWorstTardinessParameter.Name));
+      tardinessDataTablesCollector.DataTableParameter.ActualName = TardinessValuesParameter.Name;
+
+      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>(TardinessValuesParameter.Name));
+
+      //Travel Time
+      bestMemorizer.BestTravelTimeParameter.ActualName = BestTravelTimeParameter.Name;
+      bestMemorizer.TravelTimeParameter.ActualName = TravelTimeParameter.Name;
+      bestMemorizer.TravelTimeParameter.Depth = TravelTimeParameter.Depth;
+
+      calculator.TravelTimeParameter.ActualName = TravelTimeParameter.Name;
+      calculator.TravelTimeParameter.Depth = TravelTimeParameter.Depth;
+      calculator.BestTravelTimeParameter.ActualName = CurrentBestTravelTimeParameter.Name;
+      calculator.AverageTravelTimeParameter.ActualName = CurrentAverageTravelTimeParameter.Name;
+      calculator.WorstTravelTimeParameter.ActualName = CurrentWorstTravelTimeParameter.Name;
+
+      DataTableValuesCollector travelTimeDataTablesCollector = new DataTableValuesCollector();
+      travelTimeDataTablesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("BestTravelTime", null, BestTravelTimeParameter.Name));
+      travelTimeDataTablesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("CurrentBestTravelTime", null, CurrentBestTravelTimeParameter.Name));
+      travelTimeDataTablesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("CurrentAverageTravelTime", null, CurrentAverageTravelTimeParameter.Name));
+      travelTimeDataTablesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("CurrentWorstTravelTime", null, CurrentWorstTravelTimeParameter.Name));
+      travelTimeDataTablesCollector.DataTableParameter.ActualName = TravelTimesParameter.Name;
+
+      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>(TravelTimesParameter.Name));
+      #endregion
+
+      #region Create operator graph
+      OperatorGraph.InitialOperator = bestMemorizer;
+      bestMemorizer.Successor = calculator;
+      calculator.Successor = tardinessDataTablesCollector;
+      tardinessDataTablesCollector.Successor = travelTimeDataTablesCollector;
+      travelTimeDataTablesCollector.Successor = resultsCollector;
+      resultsCollector.Successor = null;
+      #endregion
+
+      Initialize();
+    }
+    [StorableConstructor]
+    private BestAverageWorstTimeWindowedVRPToursAnalyzer(bool deserializing) : base() { }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void Initialize() {
+      TardinessParameter.DepthChanged += new EventHandler(TardinessParameter_DepthChanged);
+      TravelTimeParameter.DepthChanged += new EventHandler(TravelTimeParameter_DepthChanged);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BestAverageWorstTimeWindowedVRPToursAnalyzer(this, cloner);
+    }
+
+    private BestAverageWorstTimeWindowedVRPToursAnalyzer(BestAverageWorstTimeWindowedVRPToursAnalyzer original, Cloner cloner)
+      : base(original, cloner) {
+      this.Initialize();
+    }
+
+    void TardinessParameter_DepthChanged(object sender, EventArgs e) {
+      BestAverageWorstCalculator.TardinessParameter.Depth = TardinessParameter.Depth;
+      BestMemorizer.TardinessParameter.Depth = TardinessParameter.Depth;
+    }
+
+    void TravelTimeParameter_DepthChanged(object sender, EventArgs e) {
+      BestAverageWorstCalculator.TravelTimeParameter.Depth = TravelTimeParameter.Depth;
+      BestMemorizer.TravelTimeParameter.Depth = TravelTimeParameter.Depth;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/TimeWindowed/BestAverageWorstTimeWindowedVRPToursCalculator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/TimeWindowed/BestAverageWorstTimeWindowedVRPToursCalculator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/TimeWindowed/BestAverageWorstTimeWindowedVRPToursCalculator.cs	(revision 14416)
@@ -0,0 +1,134 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  [Item("BestAverageWorstTimeWindowedVRPToursCalculator", "An operator which calculates the current best, average and worst properties of VRP tours in the scope tree.")]
+  [StorableClass]
+  public sealed class BestAverageWorstTimeWindowedVRPToursCalculator : SingleSuccessorOperator {
+    public ScopeTreeLookupParameter<DoubleValue> TardinessParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Tardiness"]; }
+    }
+    public ValueLookupParameter<DoubleValue> BestTardinessParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestTardiness"]; }
+    }
+    public ValueLookupParameter<DoubleValue> AverageTardinessParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["AverageTardiness"]; }
+    }
+    public ValueLookupParameter<DoubleValue> WorstTardinessParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["WorstTardiness"]; }
+    }
+
+    public ScopeTreeLookupParameter<DoubleValue> TravelTimeParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["TravelTime"]; }
+    }
+    public ValueLookupParameter<DoubleValue> BestTravelTimeParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestTravelTime"]; }
+    }
+    public ValueLookupParameter<DoubleValue> AverageTravelTimeParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["AverageTravelTime"]; }
+    }
+    public ValueLookupParameter<DoubleValue> WorstTravelTimeParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["WorstTravelTime"]; }
+    }
+
+    public BestAverageWorstTimeWindowedVRPToursCalculator()
+      : base() {
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Tardiness", "The tardiness of the VRP solutions which should be analyzed."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestTardiness", "The best tardiness value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("AverageTardiness", "The average tardiness value of all solutions."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("WorstTardiness", "The worst tardiness value of all solutions."));
+
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("TravelTime", "The travel times of the VRP solutions which should be analyzed."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestTravelTime", "The best travel time value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("AverageTravelTime", "The average travel time value of all solutions."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("WorstTravelTime", "The worst travel time value of all solutions."));
+    }
+
+    [StorableConstructor]
+    private BestAverageWorstTimeWindowedVRPToursCalculator(bool deserializing) : base(deserializing) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BestAverageWorstTimeWindowedVRPToursCalculator(this, cloner);
+    }
+
+    private BestAverageWorstTimeWindowedVRPToursCalculator(BestAverageWorstTimeWindowedVRPToursCalculator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    private void UpdateTardiness() {
+      ItemArray<DoubleValue> tardiness = TardinessParameter.ActualValue;
+      if (tardiness.Length > 0) {
+        double min = double.MaxValue, max = double.MinValue, sum = 0.0;
+        for (int i = 0; i < tardiness.Length; i++) {
+          if (tardiness[i].Value < min) min = tardiness[i].Value;
+          if (tardiness[i].Value > max) max = tardiness[i].Value;
+          sum += tardiness[i].Value;
+        }
+
+        DoubleValue best = BestTardinessParameter.ActualValue;
+        if (best == null) BestTardinessParameter.ActualValue = new DoubleValue(min);
+        else best.Value = min;
+        DoubleValue average = AverageTardinessParameter.ActualValue;
+        if (average == null) AverageTardinessParameter.ActualValue = new DoubleValue(sum / tardiness.Length);
+        else average.Value = sum / tardiness.Length;
+        DoubleValue worst = WorstTardinessParameter.ActualValue;
+        if (worst == null) WorstTardinessParameter.ActualValue = new DoubleValue(max);
+        else worst.Value = max;
+      }
+    }
+
+    private void UpdateTravelTimes() {
+      ItemArray<DoubleValue> travelTimes = TravelTimeParameter.ActualValue;
+      if (travelTimes.Length > 0) {
+        double min = double.MaxValue, max = double.MinValue, sum = 0.0;
+        for (int i = 0; i < travelTimes.Length; i++) {
+          if (travelTimes[i].Value < min) min = travelTimes[i].Value;
+          if (travelTimes[i].Value > max) max = travelTimes[i].Value;
+          sum += travelTimes[i].Value;
+        }
+
+        DoubleValue best = BestTravelTimeParameter.ActualValue;
+        if (best == null) BestTravelTimeParameter.ActualValue = new DoubleValue(min);
+        else best.Value = min;
+        DoubleValue average = AverageTravelTimeParameter.ActualValue;
+        if (average == null) AverageTravelTimeParameter.ActualValue = new DoubleValue(sum / travelTimes.Length);
+        else average.Value = sum / travelTimes.Length;
+        DoubleValue worst = WorstTravelTimeParameter.ActualValue;
+        if (worst == null) WorstTravelTimeParameter.ActualValue = new DoubleValue(max);
+        else worst.Value = max;
+      }
+    }
+
+    public override IOperation Apply() {
+      UpdateTardiness();
+      UpdateTravelTimes();
+
+      return base.Apply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/TimeWindowed/BestTimeWindowedVRPToursMemorizer.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/TimeWindowed/BestTimeWindowedVRPToursMemorizer.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestAverageWorstTours/TimeWindowed/BestTimeWindowedVRPToursMemorizer.cs	(revision 14416)
@@ -0,0 +1,84 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  [Item("BestTimeWindowedVRPToursMemorizer", "An operator that updates the best VRP tour found so far in the scope three.")]
+  [StorableClass]
+  public class BestTimeWindowedVRPToursMemorizer : SingleSuccessorOperator {
+    public ScopeTreeLookupParameter<DoubleValue> TardinessParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Tardiness"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> TravelTimeParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["TravelTime"]; }
+    }
+
+    public ValueLookupParameter<DoubleValue> BestTardinessParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestTardiness"]; }
+    }
+    public ValueLookupParameter<DoubleValue> BestTravelTimeParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestTravelTime"]; }
+    }
+
+    public BestTimeWindowedVRPToursMemorizer()
+      : base() {
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Tardiness", "The tardiness of the VRP solutions which should be analyzed."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("TravelTime", "The travel times of the VRP solutions which should be analyzed."));
+
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestTardiness", "The best tardiness found so far."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestTravelTime", "The best travel time found so far."));
+    }
+
+    public override IOperation Apply() {
+      int i = TardinessParameter.ActualValue.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index;
+      if (BestTardinessParameter.ActualValue == null)
+        BestTardinessParameter.ActualValue = new DoubleValue(TardinessParameter.ActualValue[i].Value);
+      else if (TardinessParameter.ActualValue[i].Value <= BestTardinessParameter.ActualValue.Value)
+        BestTardinessParameter.ActualValue.Value = TardinessParameter.ActualValue[i].Value;
+
+      i = TravelTimeParameter.ActualValue.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index;
+      if (BestTravelTimeParameter.ActualValue == null)
+        BestTravelTimeParameter.ActualValue = new DoubleValue(TravelTimeParameter.ActualValue[i].Value);
+      else if (TravelTimeParameter.ActualValue[i].Value <= BestTravelTimeParameter.ActualValue.Value)
+        BestTravelTimeParameter.ActualValue.Value = TravelTimeParameter.ActualValue[i].Value;
+
+      return base.Apply();
+    }
+
+    [StorableConstructor]
+    protected BestTimeWindowedVRPToursMemorizer(bool deserializing) : base(deserializing) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BestTimeWindowedVRPToursMemorizer(this, cloner);
+    }
+
+    protected BestTimeWindowedVRPToursMemorizer(BestTimeWindowedVRPToursMemorizer original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestSolution/BestVRPSolutionAnalyzer.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestSolution/BestVRPSolutionAnalyzer.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestSolution/BestVRPSolutionAnalyzer.cs	(revision 14416)
@@ -0,0 +1,186 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Linq;
+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.ProblemInstances;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  /// <summary>
+  /// An operator for analyzing the best solution of Vehicle Routing Problems.
+  /// </summary>
+  [Item("BestVRPSolutionAnalyzer", "An operator for analyzing the best solution of Vehicle Routing Problems.")]
+  [StorableClass]
+  public sealed class BestVRPSolutionAnalyzer : SingleSuccessorOperator, IAnalyzer, IGeneralVRPOperator, ISingleObjectiveOperator {
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (ILookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+    public ScopeTreeLookupParameter<IVRPEncoding> VRPToursParameter {
+      get { return (ScopeTreeLookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+
+    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> DistanceParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Distance"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> VehiclesUtilizedParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["VehiclesUtilized"]; }
+    }
+
+    public LookupParameter<VRPSolution> BestSolutionParameter {
+      get { return (LookupParameter<VRPSolution>)Parameters["BestSolution"]; }
+    }
+    public LookupParameter<VRPSolution> BestValidSolutionParameter {
+      get { return (LookupParameter<VRPSolution>)Parameters["BestValidSolution"]; }
+    }
+    public ValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (ValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    public LookupParameter<DoubleValue> BestKnownQualityParameter {
+      get { return (LookupParameter<DoubleValue>)Parameters["BestKnownQuality"]; }
+    }
+    public LookupParameter<VRPSolution> BestKnownSolutionParameter {
+      get { return (LookupParameter<VRPSolution>)Parameters["BestKnownSolution"]; }
+    }
+
+    public bool EnabledByDefault {
+      get { return true; }
+    }
+
+    [StorableConstructor]
+    private BestVRPSolutionAnalyzer(bool deserializing) : base(deserializing) { }
+
+    public BestVRPSolutionAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The problem instance."));
+      Parameters.Add(new ScopeTreeLookupParameter<IVRPEncoding>("VRPTours", "The VRP tours which should be evaluated."));
+
+      Parameters.Add(new LookupParameter<DoubleValue>("BestKnownQuality", "The quality of the best known solution of this VRP instance."));
+      Parameters.Add(new LookupParameter<VRPSolution>("BestKnownSolution", "The best known solution of this VRP instance."));
+
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The qualities of the VRP solutions which should be analyzed."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Distance", "The distances of the VRP solutions which should be analyzed."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("VehiclesUtilized", "The utilized vehicles of the VRP solutions which should be analyzed."));
+
+      Parameters.Add(new LookupParameter<VRPSolution>("BestSolution", "The best VRP solution."));
+      Parameters.Add(new LookupParameter<VRPSolution>("BestValidSolution", "The best valid VRP solution."));
+      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 BestVRPSolutionAnalyzer(this, cloner);
+    }
+
+    private BestVRPSolutionAnalyzer(BestVRPSolutionAnalyzer original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      #region Backwards Compatibility
+      if (!Parameters.ContainsKey("BestKnownQuality")) {
+        Parameters.Add(new LookupParameter<DoubleValue>("BestKnownQuality", "The quality of the best known solution of this VRP instance."));
+      }
+      if (!Parameters.ContainsKey("BestKnownSolution")) {
+        Parameters.Add(new LookupParameter<VRPSolution>("BestKnownSolution", "The best known solution of this VRP instance."));
+      }
+      #endregion
+    }
+
+    public override IOperation Apply() {
+      IVRPProblemInstance problemInstance = ProblemInstanceParameter.ActualValue;
+      ItemArray<IVRPEncoding> solutions = VRPToursParameter.ActualValue;
+      ResultCollection results = ResultsParameter.ActualValue;
+
+      ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+      ItemArray<DoubleValue> distances = DistanceParameter.ActualValue;
+      ItemArray<DoubleValue> vehiclesUtilizations = VehiclesUtilizedParameter.ActualValue;
+
+      int i = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index;
+      IVRPEncoding best = solutions[i].Clone() as IVRPEncoding;
+      VRPSolution solution = BestSolutionParameter.ActualValue;
+      if (solution == null) {
+        solution = new VRPSolution(problemInstance, best.Clone() as IVRPEncoding, new DoubleValue(qualities[i].Value));
+        BestSolutionParameter.ActualValue = solution;
+        results.Add(new Result("Best VRP Solution", solution));
+
+        results.Add(new Result("Best VRP Solution Distance", new DoubleValue(distances[i].Value)));
+        results.Add(new Result("Best VRP Solution VehicleUtilization", new DoubleValue(vehiclesUtilizations[i].Value)));
+      } else {
+        VRPEvaluation eval = problemInstance.Evaluate(solution.Solution);
+        if (qualities[i].Value <= eval.Quality) {
+          solution.ProblemInstance = problemInstance;
+          solution.Solution = best.Clone() as IVRPEncoding;
+          solution.Quality.Value = qualities[i].Value;
+          (results["Best VRP Solution Distance"].Value as DoubleValue).Value = distances[i].Value;
+          (results["Best VRP Solution VehicleUtilization"].Value as DoubleValue).Value = vehiclesUtilizations[i].Value;
+        }
+      }
+
+      var idx = qualities.Select((x, index) => new { index, x.Value }).Where(index => problemInstance.Feasible(solutions[index.index])).OrderBy(x => x.Value).FirstOrDefault();
+      if (idx != null) {
+        int j = idx.index;
+        IVRPEncoding bestFeasible = solutions[j].Clone() as IVRPEncoding;
+        VRPSolution validSolution = BestValidSolutionParameter.ActualValue;
+        if (validSolution == null) {
+          validSolution = new VRPSolution(problemInstance, best.Clone() as IVRPEncoding, new DoubleValue(qualities[j].Value));
+          BestValidSolutionParameter.ActualValue = validSolution;
+          if (results.ContainsKey("Best valid VRP Solution"))
+            results["Best valid VRP Solution"].Value = validSolution;
+          else
+            results.Add(new Result("Best valid VRP Solution", validSolution));
+
+          results.Add(new Result("Best valid VRP Solution Distance", new DoubleValue(distances[j].Value)));
+          results.Add(new Result("Best valid VRP Solution VehicleUtilization", new DoubleValue(vehiclesUtilizations[j].Value)));
+        } else {
+          if (qualities[j].Value <= validSolution.Quality.Value) {
+            if (ProblemInstanceParameter.ActualValue.Feasible(best)) {
+              validSolution.ProblemInstance = problemInstance;
+              validSolution.Solution = best.Clone() as IVRPEncoding;
+              validSolution.Quality.Value = qualities[j].Value;
+              (results["Best valid VRP Solution Distance"].Value as DoubleValue).Value = distances[j].Value;
+              (results["Best valid VRP Solution VehicleUtilization"].Value as DoubleValue).Value = vehiclesUtilizations[j].Value;
+            }
+          }
+        }
+
+        DoubleValue bestKnownQuality = BestKnownQualityParameter.ActualValue;
+        if (bestKnownQuality == null || qualities[j].Value < bestKnownQuality.Value) {
+          BestKnownQualityParameter.ActualValue = new DoubleValue(qualities[j].Value);
+          BestKnownSolutionParameter.ActualValue = (VRPSolution)validSolution.Clone();
+        }
+      }
+
+      return base.Apply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestSolution/Capacitated/BestCapacitatedVRPSolutionAnalyzer.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestSolution/Capacitated/BestCapacitatedVRPSolutionAnalyzer.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestSolution/Capacitated/BestCapacitatedVRPSolutionAnalyzer.cs	(revision 14416)
@@ -0,0 +1,114 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Linq;
+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.ProblemInstances;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  /// <summary>
+  /// An operator for analyzing the best solution of Vehicle Routing Problems.
+  /// </summary>
+  [Item("BestCapacitatedVRPSolutionAnalyzer", "An operator for analyzing the best solution of capacitated Vehicle Routing Problems.")]
+  [StorableClass]
+  public sealed class BestCapacitatedVRPSolutionAnalyzer : SingleSuccessorOperator, IAnalyzer, ICapacitatedOperator, ISingleObjectiveOperator {
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (ILookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+    public ScopeTreeLookupParameter<IVRPEncoding> VRPToursParameter {
+      get { return (ScopeTreeLookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+
+    public ScopeTreeLookupParameter<DoubleValue> OverloadParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Overload"]; }
+    }
+
+    public LookupParameter<VRPSolution> BestSolutionParameter {
+      get { return (LookupParameter<VRPSolution>)Parameters["BestSolution"]; }
+    }
+    public ValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (ValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    public bool EnabledByDefault {
+      get { return true; }
+    }
+
+    [StorableConstructor]
+    private BestCapacitatedVRPSolutionAnalyzer(bool deserializing) : base(deserializing) { }
+
+    public BestCapacitatedVRPSolutionAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The problem instance."));
+      Parameters.Add(new ScopeTreeLookupParameter<IVRPEncoding>("VRPTours", "The VRP tours which should be evaluated."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The qualities of the VRP solutions which should be analyzed."));
+
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Overload", "The overloads of the VRP solutions which should be analyzed."));
+
+      Parameters.Add(new LookupParameter<VRPSolution>("BestSolution", "The best VRP solution."));
+      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 BestCapacitatedVRPSolutionAnalyzer(this, cloner);
+    }
+
+    private BestCapacitatedVRPSolutionAnalyzer(BestCapacitatedVRPSolutionAnalyzer original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IOperation Apply() {
+      IVRPProblemInstance problemInstance = ProblemInstanceParameter.ActualValue;
+      ItemArray<IVRPEncoding> solutions = VRPToursParameter.ActualValue;
+      ResultCollection results = ResultsParameter.ActualValue;
+
+      ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+      ItemArray<DoubleValue> overloads = OverloadParameter.ActualValue;
+
+      int i = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index;
+
+      VRPSolution solution = BestSolutionParameter.ActualValue;
+      if (solution != null) {
+        if (!results.ContainsKey("Best VRP Solution Overload")) {
+          results.Add(new Result("Best VRP Solution Overload", new DoubleValue(overloads[i].Value)));
+        } else {
+          VRPEvaluation eval = problemInstance.Evaluate(solution.Solution);
+          if (qualities[i].Value <= eval.Quality) {
+            (results["Best VRP Solution Overload"].Value as DoubleValue).Value = overloads[i].Value;
+          }
+        }
+      }
+
+      return base.Apply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestSolution/PickupAndDelivery/BestPickupAndDeliveryVRPSolutionAnalyzer.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestSolution/PickupAndDelivery/BestPickupAndDeliveryVRPSolutionAnalyzer.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestSolution/PickupAndDelivery/BestPickupAndDeliveryVRPSolutionAnalyzer.cs	(revision 14416)
@@ -0,0 +1,115 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Linq;
+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.ProblemInstances;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  /// <summary>
+  /// An operator for analyzing the best solution of Vehicle Routing Problems.
+  /// </summary>
+  [Item("BestPickupAndDeliveryVRPSolutionAnalyzer", "An operator for analyzing the best solution of Pickup and Delivery Routing Problems.")]
+  [StorableClass]
+  public sealed class BestPickupAndDeliveryVRPSolutionAnalyzer : SingleSuccessorOperator, IAnalyzer, IPickupAndDeliveryOperator, ISingleObjectiveOperator {
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (ILookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+    public ScopeTreeLookupParameter<IVRPEncoding> VRPToursParameter {
+      get { return (ScopeTreeLookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+
+    public ScopeTreeLookupParameter<IntValue> PickupViolationsParameter {
+      get { return (ScopeTreeLookupParameter<IntValue>)Parameters["PickupViolations"]; }
+    }
+
+    public LookupParameter<VRPSolution> BestSolutionParameter {
+      get { return (LookupParameter<VRPSolution>)Parameters["BestSolution"]; }
+    }
+    public ValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (ValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    public bool EnabledByDefault {
+      get { return true; }
+    }
+
+    [StorableConstructor]
+    private BestPickupAndDeliveryVRPSolutionAnalyzer(bool deserializing) : base(deserializing) { }
+
+    public BestPickupAndDeliveryVRPSolutionAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The problem instance."));
+      Parameters.Add(new ScopeTreeLookupParameter<IVRPEncoding>("VRPTours", "The VRP tours which should be evaluated."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The qualities of the VRP solutions which should be analyzed."));
+
+      Parameters.Add(new ScopeTreeLookupParameter<IntValue>("PickupViolations", "The pickup violation of the VRP solutions which should be analyzed."));
+
+      Parameters.Add(new LookupParameter<VRPSolution>("BestSolution", "The best VRP solution."));
+      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 BestPickupAndDeliveryVRPSolutionAnalyzer(this, cloner);
+    }
+
+    private BestPickupAndDeliveryVRPSolutionAnalyzer(BestPickupAndDeliveryVRPSolutionAnalyzer original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IOperation Apply() {
+      IVRPProblemInstance problemInstance = ProblemInstanceParameter.ActualValue;
+      ItemArray<IVRPEncoding> solutions = VRPToursParameter.ActualValue;
+      ResultCollection results = ResultsParameter.ActualValue;
+
+      ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+      ItemArray<IntValue> pickupViolations = PickupViolationsParameter.ActualValue;
+
+      int i = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index;
+
+      IVRPEncoding best = solutions[i] as IVRPEncoding;
+      VRPSolution solution = BestSolutionParameter.ActualValue;
+      if (solution != null) {
+        if (!results.ContainsKey("Best VRP Solution PickupViolations")) {
+          results.Add(new Result("Best VRP Solution PickupViolations", new DoubleValue(pickupViolations[i].Value)));
+        } else {
+          VRPEvaluation eval = problemInstance.Evaluate(solution.Solution);
+          if (qualities[i].Value <= eval.Quality) {
+            (results["Best VRP Solution PickupViolations"].Value as DoubleValue).Value = pickupViolations[i].Value;
+          }
+        }
+      }
+
+      return base.Apply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestSolution/TimeWindowed/BestTimeWindowedVRPSolutionAnalyzer.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestSolution/TimeWindowed/BestTimeWindowedVRPSolutionAnalyzer.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestSolution/TimeWindowed/BestTimeWindowedVRPSolutionAnalyzer.cs	(revision 14416)
@@ -0,0 +1,121 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Linq;
+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.ProblemInstances;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  /// <summary>
+  /// An operator for analyzing the best solution of Vehicle Routing Problems.
+  /// </summary>
+  [Item("BestTimeWindowedVRPSolutionAnalyzer", "An operator for analyzing the best solution of time windowed Vehicle Routing Problems.")]
+  [StorableClass]
+  public sealed class BestTimeWindowedVRPSolutionAnalyzer : SingleSuccessorOperator, IAnalyzer, ITimeWindowedOperator, ISingleObjectiveOperator {
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (ILookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+    public ScopeTreeLookupParameter<IVRPEncoding> VRPToursParameter {
+      get { return (ScopeTreeLookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+
+    public ScopeTreeLookupParameter<DoubleValue> TardinessParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Tardiness"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> TravelTimeParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["TravelTime"]; }
+    }
+
+    public LookupParameter<VRPSolution> BestSolutionParameter {
+      get { return (LookupParameter<VRPSolution>)Parameters["BestSolution"]; }
+    }
+    public ValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (ValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    public bool EnabledByDefault {
+      get { return true; }
+    }
+
+    [StorableConstructor]
+    private BestTimeWindowedVRPSolutionAnalyzer(bool deserializing) : base(deserializing) { }
+
+    public BestTimeWindowedVRPSolutionAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The problem instance."));
+      Parameters.Add(new ScopeTreeLookupParameter<IVRPEncoding>("VRPTours", "The VRP tours which should be evaluated."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The qualities of the VRP solutions which should be analyzed."));
+
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Tardiness", "The tardiness of the VRP solutions which should be analyzed."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("TravelTime", "The travel times of the VRP solutions which should be analyzed."));
+
+      Parameters.Add(new LookupParameter<VRPSolution>("BestSolution", "The best VRP solution."));
+      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 BestTimeWindowedVRPSolutionAnalyzer(this, cloner);
+    }
+
+    private BestTimeWindowedVRPSolutionAnalyzer(BestTimeWindowedVRPSolutionAnalyzer original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IOperation Apply() {
+      IVRPProblemInstance problemInstance = ProblemInstanceParameter.ActualValue;
+      ItemArray<IVRPEncoding> solutions = VRPToursParameter.ActualValue;
+      ResultCollection results = ResultsParameter.ActualValue;
+
+      ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+      ItemArray<DoubleValue> tardinesses = TardinessParameter.ActualValue;
+      ItemArray<DoubleValue> travelTimes = TravelTimeParameter.ActualValue;
+
+      int i = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index;
+
+      VRPSolution solution = BestSolutionParameter.ActualValue;
+      if (solution != null) {
+        if (!results.ContainsKey("Best VRP Solution Tardiness")) {
+          results.Add(new Result("Best VRP Solution Tardiness", new DoubleValue(tardinesses[i].Value)));
+          results.Add(new Result("Best VRP Solution TravelTime", new DoubleValue(travelTimes[i].Value)));
+        } else {
+          VRPEvaluation eval = problemInstance.Evaluate(solution.Solution);
+          if (qualities[i].Value <= eval.Quality) {
+            (results["Best VRP Solution Tardiness"].Value as DoubleValue).Value = tardinesses[i].Value;
+            (results["Best VRP Solution TravelTime"].Value as DoubleValue).Value = travelTimes[i].Value;
+          }
+        }
+      }
+
+      return base.Apply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/ConstraintRelaxation/Capacitated/CapacityRelaxationVRPAnalyzer.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/ConstraintRelaxation/Capacitated/CapacityRelaxationVRPAnalyzer.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/ConstraintRelaxation/Capacitated/CapacityRelaxationVRPAnalyzer.cs	(revision 14416)
@@ -0,0 +1,157 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  /// <summary>
+  /// An operator for adaptive constraint relaxation.
+  /// </summary>
+  [Item("CapacityRelaxationVRPAnalyzer", "An operator for adaptively relaxing the capacity constraints.")]
+  [StorableClass]
+  public class CapacityRelaxationVRPAnalyzer : SingleSuccessorOperator, IAnalyzer, ICapacitatedOperator, ISingleObjectiveOperator {
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (ILookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+    public ScopeTreeLookupParameter<IVRPEncoding> VRPToursParameter {
+      get { return (ScopeTreeLookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+
+    public ScopeTreeLookupParameter<DoubleValue> OverloadParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Overload"]; }
+    }
+
+    public IValueParameter<DoubleValue> SigmaParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["Sigma"]; }
+    }
+    public IValueParameter<DoubleValue> PhiParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["Phi"]; }
+    }
+    public IValueParameter<DoubleValue> MinPenaltyFactorParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["MinPenaltyFactor"]; }
+    }
+    public IValueParameter<DoubleValue> MaxPenaltyFactorParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["MaxPenaltyFactor"]; }
+    }
+
+    public ValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (ValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    public bool EnabledByDefault {
+      get { return false; }
+    }
+
+    [StorableConstructor]
+    protected CapacityRelaxationVRPAnalyzer(bool deserializing) : base(deserializing) { }
+
+    public CapacityRelaxationVRPAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The problem instance."));
+      Parameters.Add(new ScopeTreeLookupParameter<IVRPEncoding>("VRPTours", "The VRP tours which should be evaluated."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The qualities of the VRP solutions which should be analyzed."));
+
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Overload", "The overloads of the VRP solutions which should be analyzed."));
+
+      Parameters.Add(new ValueParameter<DoubleValue>("Sigma", "The sigma applied to the penalty factor.", new DoubleValue(0.5)));
+      Parameters.Add(new ValueParameter<DoubleValue>("Phi", "The phi applied to the penalty factor.", new DoubleValue(0.5)));
+      Parameters.Add(new ValueParameter<DoubleValue>("MinPenaltyFactor", "The minimum penalty factor.", new DoubleValue(0.01)));
+      Parameters.Add(new ValueParameter<DoubleValue>("MaxPenaltyFactor", "The maximum penalty factor.", new DoubleValue(100000)));
+
+      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 CapacityRelaxationVRPAnalyzer(this, cloner);
+    }
+
+    protected CapacityRelaxationVRPAnalyzer(CapacityRelaxationVRPAnalyzer original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (!Parameters.ContainsKey("MaxPenaltyFactor")) {
+        Parameters.Add(new ValueParameter<DoubleValue>("MaxPenaltyFactor", "The maximum penalty factor.", new DoubleValue(100000)));
+      }
+      #endregion
+    }
+
+    public override IOperation Apply() {
+      ICapacitatedProblemInstance cvrp = ProblemInstanceParameter.ActualValue as ICapacitatedProblemInstance;
+      ResultCollection results = ResultsParameter.ActualValue;
+
+      ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+      ItemArray<DoubleValue> overloads = OverloadParameter.ActualValue;
+
+      double sigma = SigmaParameter.Value.Value;
+      double phi = PhiParameter.Value.Value;
+      double minPenalty = MinPenaltyFactorParameter.Value.Value;
+      double maxPenalty = MaxPenaltyFactorParameter.Value.Value;
+
+      for (int j = 0; j < qualities.Length; j++) {
+        qualities[j].Value -= overloads[j].Value * cvrp.OverloadPenalty.Value;
+      }
+
+      int validCount = 0;
+      for (int j = 0; j < qualities.Length; j++) {
+        if (overloads[j].Value == 0)
+          validCount++;
+      }
+
+      double factor = 1.0 - ((double)validCount / (double)qualities.Length);
+
+      double min = cvrp.OverloadPenalty.Value / (1 + sigma);
+      double max = cvrp.OverloadPenalty.Value * (1 + phi);
+
+      cvrp.CurrentOverloadPenalty = new DoubleValue(min + (max - min) * factor);
+      if (cvrp.CurrentOverloadPenalty.Value < minPenalty)
+        cvrp.CurrentOverloadPenalty.Value = minPenalty;
+      if (cvrp.CurrentOverloadPenalty.Value > maxPenalty)
+        cvrp.CurrentOverloadPenalty.Value = maxPenalty;
+
+      for (int j = 0; j < qualities.Length; j++) {
+        qualities[j].Value += overloads[j].Value * cvrp.CurrentOverloadPenalty.Value;
+      }
+
+      if (!results.ContainsKey("Current Overload Penalty")) {
+        results.Add(new Result("Current Overload Penalty", new DoubleValue(cvrp.CurrentOverloadPenalty.Value)));
+      } else {
+        (results["Current Overload Penalty"].Value as DoubleValue).Value = cvrp.CurrentOverloadPenalty.Value;
+      }
+
+      return base.Apply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/ConstraintRelaxation/PickupAndDelivery/PickupViolationsRelaxationVRPAnalyzer.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/ConstraintRelaxation/PickupAndDelivery/PickupViolationsRelaxationVRPAnalyzer.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/ConstraintRelaxation/PickupAndDelivery/PickupViolationsRelaxationVRPAnalyzer.cs	(revision 14416)
@@ -0,0 +1,157 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  /// <summary>
+  /// An operator for adaptive constraint relaxation.
+  /// </summary>
+  [Item("PickupViolationsRelaxationVRPAnalyzer", "An operator for adaptively relaxing the pickup constraints.")]
+  [StorableClass]
+  public class PickupViolationsRelaxationVRPAnalyzer : SingleSuccessorOperator, IAnalyzer, IPickupAndDeliveryOperator, ISingleObjectiveOperator {
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (ILookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+    public ScopeTreeLookupParameter<IVRPEncoding> VRPToursParameter {
+      get { return (ScopeTreeLookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+
+    public ScopeTreeLookupParameter<IntValue> PickupViolationsParameter {
+      get { return (ScopeTreeLookupParameter<IntValue>)Parameters["PickupViolations"]; }
+    }
+
+    public IValueParameter<DoubleValue> SigmaParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["Sigma"]; }
+    }
+    public IValueParameter<DoubleValue> PhiParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["Phi"]; }
+    }
+    public IValueParameter<DoubleValue> MinPenaltyFactorParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["MinPenaltyFactor"]; }
+    }
+    public IValueParameter<DoubleValue> MaxPenaltyFactorParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["MaxPenaltyFactor"]; }
+    }
+
+    public ValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (ValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    public bool EnabledByDefault {
+      get { return false; }
+    }
+
+    [StorableConstructor]
+    protected PickupViolationsRelaxationVRPAnalyzer(bool deserializing) : base(deserializing) { }
+
+    public PickupViolationsRelaxationVRPAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The problem instance."));
+      Parameters.Add(new ScopeTreeLookupParameter<IVRPEncoding>("VRPTours", "The VRP tours which should be evaluated."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The qualities of the VRP solutions which should be analyzed."));
+
+      Parameters.Add(new ScopeTreeLookupParameter<IntValue>("PickupViolations", "The pickup violation of the VRP solutions which should be analyzed."));
+
+      Parameters.Add(new ValueParameter<DoubleValue>("Sigma", "The sigma applied to the penalty factor.", new DoubleValue(0.5)));
+      Parameters.Add(new ValueParameter<DoubleValue>("Phi", "The phi applied to the penalty factor.", new DoubleValue(0.5)));
+      Parameters.Add(new ValueParameter<DoubleValue>("MinPenaltyFactor", "The minimum penalty factor.", new DoubleValue(0.01)));
+      Parameters.Add(new ValueParameter<DoubleValue>("MaxPenaltyFactor", "The maximum penalty factor.", new DoubleValue(100000)));
+
+      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 PickupViolationsRelaxationVRPAnalyzer(this, cloner);
+    }
+
+    protected PickupViolationsRelaxationVRPAnalyzer(PickupViolationsRelaxationVRPAnalyzer original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (!Parameters.ContainsKey("MaxPenaltyFactor")) {
+        Parameters.Add(new ValueParameter<DoubleValue>("MaxPenaltyFactor", "The maximum penalty factor.", new DoubleValue(100000)));
+      }
+      #endregion
+    }
+
+    public override IOperation Apply() {
+      IPickupAndDeliveryProblemInstance pdp = ProblemInstanceParameter.ActualValue as IPickupAndDeliveryProblemInstance;
+      ResultCollection results = ResultsParameter.ActualValue;
+
+      ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+      ItemArray<IntValue> pickupViolations = PickupViolationsParameter.ActualValue;
+
+      double sigma = SigmaParameter.Value.Value;
+      double phi = PhiParameter.Value.Value;
+      double minPenalty = MinPenaltyFactorParameter.Value.Value;
+      double maxPenalty = MaxPenaltyFactorParameter.Value.Value;
+
+      for (int j = 0; j < qualities.Length; j++) {
+        qualities[j].Value -= pickupViolations[j].Value * pdp.PickupViolationPenalty.Value;
+      }
+
+      int validCount = 0;
+      for (int j = 0; j < qualities.Length; j++) {
+        if (pickupViolations[j].Value == 0)
+          validCount++;
+      }
+
+      double factor = 1.0 - ((double)validCount / (double)qualities.Length);
+
+      double min = pdp.PickupViolationPenalty.Value / (1 + sigma);
+      double max = pdp.PickupViolationPenalty.Value * (1 + phi);
+
+      pdp.CurrentPickupViolationPenalty = new DoubleValue(min + (max - min) * factor);
+      if (pdp.CurrentPickupViolationPenalty.Value < minPenalty)
+        pdp.CurrentPickupViolationPenalty.Value = minPenalty;
+      if (pdp.CurrentPickupViolationPenalty.Value > maxPenalty)
+        pdp.CurrentPickupViolationPenalty.Value = maxPenalty;
+
+      for (int j = 0; j < qualities.Length; j++) {
+        qualities[j].Value += pickupViolations[j].Value * pdp.CurrentPickupViolationPenalty.Value;
+      }
+
+      if (!results.ContainsKey("Current Pickup Violation Penalty")) {
+        results.Add(new Result("Current Pickup Violation Penalty", new DoubleValue(pdp.CurrentPickupViolationPenalty.Value)));
+      } else {
+        (results["Current Pickup Violation Penalty"].Value as DoubleValue).Value = pdp.CurrentPickupViolationPenalty.Value;
+      }
+
+      return base.Apply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/ConstraintRelaxation/TimeWindowed/TimeWindowRelaxationVRPAnalyzer.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/ConstraintRelaxation/TimeWindowed/TimeWindowRelaxationVRPAnalyzer.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/ConstraintRelaxation/TimeWindowed/TimeWindowRelaxationVRPAnalyzer.cs	(revision 14416)
@@ -0,0 +1,157 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  /// <summary>
+  /// An operator for adaptive constraint relaxation.
+  /// </summary>
+  [Item("TimeWindowRelaxationVRPAnalyzer", "An operator for adaptively relaxing the time window constraints.")]
+  [StorableClass]
+  public class TimeWindowRelaxationVRPAnalyzer : SingleSuccessorOperator, IAnalyzer, ITimeWindowedOperator, ISingleObjectiveOperator {
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (ILookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+    public ScopeTreeLookupParameter<IVRPEncoding> VRPToursParameter {
+      get { return (ScopeTreeLookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+
+    public ScopeTreeLookupParameter<DoubleValue> TardinessParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Tardiness"]; }
+    }
+
+    public IValueParameter<DoubleValue> SigmaParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["Sigma"]; }
+    }
+    public IValueParameter<DoubleValue> PhiParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["Phi"]; }
+    }
+    public IValueParameter<DoubleValue> MinPenaltyFactorParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["MinPenaltyFactor"]; }
+    }
+    public IValueParameter<DoubleValue> MaxPenaltyFactorParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["MaxPenaltyFactor"]; }
+    }
+
+    public ValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (ValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    public bool EnabledByDefault {
+      get { return false; }
+    }
+
+    [StorableConstructor]
+    protected TimeWindowRelaxationVRPAnalyzer(bool deserializing) : base(deserializing) { }
+
+    public TimeWindowRelaxationVRPAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The problem instance."));
+      Parameters.Add(new ScopeTreeLookupParameter<IVRPEncoding>("VRPTours", "The VRP tours which should be evaluated."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The qualities of the VRP solutions which should be analyzed."));
+
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Tardiness", "The tardiness of the VRP solutions which should be analyzed."));
+
+      Parameters.Add(new ValueParameter<DoubleValue>("Sigma", "The sigma applied to the penalty factor.", new DoubleValue(0.5)));
+      Parameters.Add(new ValueParameter<DoubleValue>("Phi", "The phi applied to the penalty factor.", new DoubleValue(0.5)));
+      Parameters.Add(new ValueParameter<DoubleValue>("MinPenaltyFactor", "The minimum penalty factor.", new DoubleValue(0.01)));
+      Parameters.Add(new ValueParameter<DoubleValue>("MaxPenaltyFactor", "The maximum penalty factor.", new DoubleValue(100000)));
+
+      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 TimeWindowRelaxationVRPAnalyzer(this, cloner);
+    }
+
+    protected TimeWindowRelaxationVRPAnalyzer(TimeWindowRelaxationVRPAnalyzer original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (!Parameters.ContainsKey("MaxPenaltyFactor")) {
+        Parameters.Add(new ValueParameter<DoubleValue>("MaxPenaltyFactor", "The maximum penalty factor.", new DoubleValue(100000)));
+      }
+      #endregion
+    }
+
+    public override IOperation Apply() {
+      ITimeWindowedProblemInstance vrptw = ProblemInstanceParameter.ActualValue as ITimeWindowedProblemInstance;
+      ResultCollection results = ResultsParameter.ActualValue;
+
+      ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+      ItemArray<DoubleValue> tardiness = TardinessParameter.ActualValue;
+
+      double sigma = SigmaParameter.Value.Value;
+      double phi = PhiParameter.Value.Value;
+      double minPenalty = MinPenaltyFactorParameter.Value.Value;
+      double maxPenalty = MaxPenaltyFactorParameter.Value.Value;
+
+      for (int j = 0; j < qualities.Length; j++) {
+        qualities[j].Value -= tardiness[j].Value * vrptw.TardinessPenalty.Value;
+      }
+
+      int validCount = 0;
+      for (int j = 0; j < qualities.Length; j++) {
+        if (tardiness[j].Value == 0)
+          validCount++;
+      }
+
+      double factor = 1.0 - ((double)validCount / (double)qualities.Length);
+
+      double min = vrptw.TardinessPenalty.Value / (1 + sigma);
+      double max = vrptw.TardinessPenalty.Value * (1 + phi);
+
+      vrptw.CurrentTardinessPenalty = new DoubleValue(min + (max - min) * factor);
+      if (vrptw.CurrentTardinessPenalty.Value < minPenalty)
+        vrptw.CurrentTardinessPenalty.Value = minPenalty;
+      if (vrptw.CurrentTardinessPenalty.Value > maxPenalty)
+        vrptw.CurrentTardinessPenalty.Value = maxPenalty;
+
+      for (int j = 0; j < qualities.Length; j++) {
+        qualities[j].Value += tardiness[j].Value * vrptw.CurrentTardinessPenalty.Value;
+      }
+
+      if (!results.ContainsKey("Current Tardiness Penalty")) {
+        results.Add(new Result("Current Tardiness Penalty", new DoubleValue(vrptw.CurrentTardinessPenalty.Value)));
+      } else {
+        (results["Current Tardiness Penalty"].Value as DoubleValue).Value = vrptw.CurrentTardinessPenalty.Value;
+      }
+
+      return base.Apply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/VRPSolution.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/VRPSolution.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/VRPSolution.cs	(revision 14416)
@@ -0,0 +1,169 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  /// <summary>
+  /// Represents a VRP solution which can be visualized in the GUI.
+  /// </summary>
+  [Item("VRPSolution", "Represents a VRP solution which can be visualized in the GUI.")]
+  [StorableClass]
+  public sealed class VRPSolution : Item {
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Image; }
+    }
+
+    [Storable]
+    private IVRPProblemInstance problemInstance;
+    public IVRPProblemInstance ProblemInstance {
+      get { return problemInstance; }
+      set {
+        if (problemInstance != value) {
+          if (problemInstance != null) DeregisterProblemInstanceEvents();
+          problemInstance = value;
+          if (problemInstance != null) RegisterProblemInstanceEvents();
+          OnProblemInstanceChanged();
+        }
+      }
+    }
+    [Storable]
+    private IVRPEncoding solution;
+    public IVRPEncoding Solution {
+      get { return solution; }
+      set {
+        if (solution != value) {
+          if (solution != null) DeregisterSolutionEvents();
+          solution = value;
+          if (solution != null) RegisterSolutionEvents();
+          OnSolutionChanged();
+        }
+      }
+    }
+    [Storable]
+    private DoubleValue quality;
+    public DoubleValue Quality {
+      get { return quality; }
+      set {
+        if (quality != value) {
+          if (quality != null) DeregisterQualityEvents();
+          quality = value;
+          if (quality != null) RegisterQualityEvents();
+          OnQualityChanged();
+        }
+      }
+    }
+
+    public VRPSolution() : base() { }
+
+    public VRPSolution(IVRPProblemInstance problemInstance, IVRPEncoding solution, DoubleValue quality)
+      : base() {
+      this.problemInstance = problemInstance;
+      this.solution = solution;
+      this.quality = quality;
+
+      Initialize();
+    }
+    [StorableConstructor]
+    private VRPSolution(bool deserializing) : base(deserializing) { }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void Initialize() {
+      if (problemInstance != null) RegisterProblemInstanceEvents();
+      if (solution != null) RegisterSolutionEvents();
+      if (quality != null) RegisterQualityEvents();
+    }
+
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new VRPSolution(this, cloner);
+    }
+
+    private VRPSolution(VRPSolution original, Cloner cloner)
+      : base(original, cloner) {
+      this.solution = (IVRPEncoding)cloner.Clone(original.solution);
+      this.quality = (DoubleValue)cloner.Clone(original.quality);
+
+      if (original.ProblemInstance != null && cloner.ClonedObjectRegistered(original.ProblemInstance))
+        this.ProblemInstance = (IVRPProblemInstance)cloner.Clone(original.ProblemInstance);
+      else
+        this.ProblemInstance = original.ProblemInstance;
+
+      this.Initialize();
+    }
+
+    #region Events
+    public event EventHandler ProblemInstanceChanged;
+    private void OnProblemInstanceChanged() {
+      var changed = ProblemInstanceChanged;
+      if (changed != null)
+        changed(this, EventArgs.Empty);
+    }
+    public event EventHandler SolutionChanged;
+    private void OnSolutionChanged() {
+      var changed = SolutionChanged;
+      if (changed != null)
+        changed(this, EventArgs.Empty);
+    }
+    public event EventHandler QualityChanged;
+    private void OnQualityChanged() {
+      var changed = QualityChanged;
+      if (changed != null)
+        changed(this, EventArgs.Empty);
+    }
+
+    private void RegisterProblemInstanceEvents() {
+      ProblemInstance.ToStringChanged += new EventHandler(ProblemInstance_ToStringChanged);
+    }
+    private void DeregisterProblemInstanceEvents() {
+      ProblemInstance.ToStringChanged -= new EventHandler(ProblemInstance_ToStringChanged);
+    }
+    private void RegisterSolutionEvents() {
+      Solution.ToStringChanged += new EventHandler(Solution_ToStringChanged);
+    }
+    private void DeregisterSolutionEvents() {
+      Solution.ToStringChanged -= new EventHandler(Solution_ToStringChanged);
+    }
+    private void RegisterQualityEvents() {
+      Quality.ValueChanged += new EventHandler(Quality_ValueChanged);
+    }
+    private void DeregisterQualityEvents() {
+      Quality.ValueChanged -= new EventHandler(Quality_ValueChanged);
+    }
+
+    private void ProblemInstance_ToStringChanged(object sender, EventArgs e) {
+      OnProblemInstanceChanged();
+    }
+    private void Solution_ToStringChanged(object sender, EventArgs e) {
+      OnSolutionChanged();
+    }
+    private void Quality_ValueChanged(object sender, EventArgs e) {
+      OnQualityChanged();
+    }
+    #endregion
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/AlbaEncoding.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/AlbaEncoding.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/AlbaEncoding.cs	(revision 14416)
@@ -0,0 +1,179 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaEncoding", "Represents an Alba encoding of VRP solutions. It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public class AlbaEncoding : General.PermutationEncoding {
+    #region IVRPEncoding Members
+    public override List<Tour> GetTours() {
+      Repair();
+      List<Tour> result = new List<Tour>();
+
+      int cities = ProblemInstance.Cities.Value;
+
+      Tour tour = new Tour();
+      for (int i = 0; i < this.array.Length; i++) {
+        if (this.array[i] >= cities) {
+          if (tour.Stops.Count > 0) {
+            result.Add(tour);
+
+            tour = new Tour();
+          }
+        } else {
+          tour.Stops.Add(this.array[i] + 1);
+        }
+      }
+
+      if (tour.Stops.Count > 0) {
+        result.Add(tour);
+      }
+
+      return result;
+    }
+
+    public override int GetVehicleAssignment(int tour) {
+      int vehicleAssignment = -1;
+      Tour currentTour = GetTours()[tour];
+
+      int lastStop = currentTour.Stops[
+        currentTour.Stops.Count - 1] - 1;
+
+      int lastStopIndex = this.IndexOf(lastStop);
+
+      if (lastStopIndex == this.Length - 1) {
+        int i = this.Length - 1;
+
+        while (vehicleAssignment == -1) {
+          if (this.array[i] >= ProblemInstance.Cities.Value) {
+            vehicleAssignment = this.array[i] - ProblemInstance.Cities.Value;
+          }
+
+          i--;
+        }
+      } else
+        vehicleAssignment = this[lastStopIndex + 1] - this.ProblemInstance.Cities.Value;
+
+      return vehicleAssignment;
+    }
+    #endregion
+
+    public void Repair() {
+      int cities = ProblemInstance.Cities.Value;
+
+      if (this[this.Length - 1] < cities) {
+        int index = this.Length - 2;
+        while (this[index] < cities) {
+          index--;
+        }
+
+        int vehicle = this[index];
+        for (int i = index; i < this.Length - 1; i++)
+          this[i] = this[i + 1];
+        this[Length - 1] = vehicle;
+      }
+    }
+
+    public AlbaEncoding(Permutation permutation, IVRPProblemInstance instance)
+      : base(permutation, instance) {
+    }
+
+    [StorableConstructor]
+    protected AlbaEncoding(bool serializing)
+      : base(serializing) {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaEncoding(this, cloner);
+    }
+
+    protected AlbaEncoding(AlbaEncoding original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static AlbaEncoding ConvertFrom(List<int> routeParam, IVRPProblemInstance instance) {
+      List<int> route = new List<int>(routeParam);
+
+      int cities = instance.Cities.Value;
+
+      for (int i = 0; i < route.Count; i++) {
+        if (route[i] <= 0) {
+          int vehicle = -route[i];
+          route[i] = cities + vehicle;
+        } else {
+          route[i] = route[i] - 1;
+        }
+      }
+
+      return new AlbaEncoding(
+        new Permutation(PermutationTypes.RelativeUndirected, route.ToArray()),
+        instance);
+    }
+
+    public static AlbaEncoding ConvertFrom(IVRPEncoding encoding, IVRPProblemInstance instance) {
+      List<Tour> tours = encoding.GetTours();
+
+      int cities = 0;
+      foreach (Tour tour in tours) {
+        cities += tour.Stops.Count;
+      }
+
+      int emptyVehicles = instance.Vehicles.Value - tours.Count;
+
+      int[] array = new int[cities + tours.Count + emptyVehicles];
+      int delimiter = 0;
+      int arrayIndex = 0;
+
+      foreach (Tour tour in tours) {
+        foreach (int city in tour.Stops) {
+          array[arrayIndex] = city - 1;
+          arrayIndex++;
+        }
+
+        if (arrayIndex != array.Length) {
+          array[arrayIndex] = cities + encoding.GetVehicleAssignment(delimiter);
+
+          delimiter++;
+          arrayIndex++;
+        }
+      }
+
+      for (int i = 0; i < emptyVehicles; i++) {
+        array[arrayIndex] = cities + encoding.GetVehicleAssignment(delimiter);
+
+        delimiter++;
+        arrayIndex++;
+      }
+
+      AlbaEncoding solution = new AlbaEncoding(new Permutation(PermutationTypes.RelativeUndirected, new IntArray(array)), instance);
+
+      return solution;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Creators/AlbaCreator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Creators/AlbaCreator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Creators/AlbaCreator.cs	(revision 14416)
@@ -0,0 +1,53 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaCreator", "A VRP creator.")]
+  [StorableClass]
+  public abstract class AlbaCreator : VRPCreator, IAlbaOperator, IVRPCreator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+
+    [StorableConstructor]
+    protected AlbaCreator(bool deserializing) : base(deserializing) { }
+
+    public AlbaCreator()
+      : base() {
+    }
+
+    protected AlbaCreator(AlbaCreator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IOperation InstrumentedApply() {
+      (VRPToursParameter.ActualValue as AlbaEncoding).Repair();
+
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Creators/RandomCreator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Creators/RandomCreator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Creators/RandomCreator.cs	(revision 14416)
@@ -0,0 +1,95 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("RandomCreator", "Creates a randomly initialized VRP solution.")]
+  [StorableClass]
+  public sealed class RandomCreator : AlbaCreator, IStochasticOperator {
+    #region IStochasticOperator Members
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private RandomCreator(bool deserializing) : base(deserializing) { }
+
+    public RandomCreator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RandomCreator(this, cloner);
+    }
+
+    private RandomCreator(RandomCreator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    private List<int> CreateSolution() {
+      int cities = ProblemInstance.Cities.Value;
+      int vehicles = ProblemInstance.Vehicles.Value;
+
+      int[] perm = new int[cities + vehicles];
+      int[] sortingArray = new int[perm.Length - 2];
+      for (int i = 0; i < cities; i++)
+        perm[i] = i + 1;
+      for (int i = cities; i < cities + vehicles; i++)
+        perm[i] = -(i - cities);
+      for (int i = 0; i < perm.Length - 2; i++) {
+        sortingArray[i] = RandomParameter.ActualValue.Next(perm.Length * 2);
+      }
+      // shuffle perm from 1...n-1 by sorting sortingArray (perm[0] and perm[n] must stay 0)
+      bool done;
+      do {
+        done = true;
+        for (int i = 0; i < perm.Length - 3; i++) {
+          if (sortingArray[i] > sortingArray[i + 1]) {
+            int h = sortingArray[i];
+            sortingArray[i] = sortingArray[i + 1];
+            sortingArray[i + 1] = h;
+            h = perm[i + 1];
+            perm[i + 1] = perm[i + 2];
+            perm[i + 2] = h;
+            done = false;
+          }
+        }
+      } while (!done);
+
+      return new List<int>(perm);
+    }
+
+    public override IOperation InstrumentedApply() {
+      //choose default encoding here
+      VRPToursParameter.ActualValue = AlbaEncoding.ConvertFrom(CreateSolution(), ProblemInstance);
+
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Crossovers/AlbaCrossover.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Crossovers/AlbaCrossover.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Crossovers/AlbaCrossover.cs	(revision 14416)
@@ -0,0 +1,74 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaCrossover", "An operator which crosses two VRP representations.")]
+  [StorableClass]
+  public abstract class AlbaCrossover : VRPCrossover, IAlbaOperator, IVRPCrossover, IStochasticOperator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    [StorableConstructor]
+    protected AlbaCrossover(bool deserializing)
+      : base(deserializing) {
+    }
+
+    public AlbaCrossover()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator which should be used for stochastic manipulation operators."));
+    }
+
+    protected AlbaCrossover(AlbaCrossover original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected abstract AlbaEncoding Crossover(IRandom random, AlbaEncoding parent1, AlbaEncoding parent2);
+
+    public override IOperation InstrumentedApply() {
+      ItemArray<IVRPEncoding> parents = new ItemArray<IVRPEncoding>(ParentsParameter.ActualValue.Length);
+      for (int i = 0; i < ParentsParameter.ActualValue.Length; i++) {
+        IVRPEncoding solution = ParentsParameter.ActualValue[i];
+
+        if (!(solution is AlbaEncoding)) {
+          parents[i] = AlbaEncoding.ConvertFrom(solution, ProblemInstance);
+        } else {
+          parents[i] = solution;
+        }
+      }
+      ParentsParameter.ActualValue = parents;
+
+      ChildParameter.ActualValue =
+        Crossover(RandomParameter.ActualValue, parents[0] as AlbaEncoding, parents[1] as AlbaEncoding);
+      (ChildParameter.ActualValue as AlbaEncoding).Repair();
+
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Crossovers/AlbaPermutationCrossover.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Crossovers/AlbaPermutationCrossover.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Crossovers/AlbaPermutationCrossover.cs	(revision 14416)
@@ -0,0 +1,73 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Encodings.PermutationEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaPermutationCrossover", "An operator which crosses two VRP representations using a standard permutation operator.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public sealed class AlbaPermutationCrossover : AlbaCrossover {
+    public IValueLookupParameter<IPermutationCrossover> InnerCrossoverParameter {
+      get { return (IValueLookupParameter<IPermutationCrossover>)Parameters["InnerCrossover"]; }
+    }
+
+    [StorableConstructor]
+    private AlbaPermutationCrossover(bool deserializing) : base(deserializing) { }
+
+    public AlbaPermutationCrossover()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<IPermutationCrossover>("InnerCrossover", "The permutation crossover.", new EdgeRecombinationCrossover()));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaPermutationCrossover(this, cloner);
+    }
+
+    private AlbaPermutationCrossover(AlbaPermutationCrossover original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override AlbaEncoding Crossover(IRandom random, AlbaEncoding parent1, AlbaEncoding parent2) {
+      //note - the inner crossover is called here and the result is converted to an alba representation
+      //some refactoring should be done here in the future - the crossover operation should be called directly
+      if (parent1.Length != parent2.Length)
+        return parent1.Clone() as AlbaEncoding;
+
+      InnerCrossoverParameter.ActualValue.ParentsParameter.ActualName = ParentsParameter.ActualName;
+      IAtomicOperation op = this.ExecutionContext.CreateOperation(
+        InnerCrossoverParameter.ActualValue, this.ExecutionContext.Scope);
+      op.Operator.Execute((IExecutionContext)op, CancellationToken);
+
+      string childName = InnerCrossoverParameter.ActualValue.ChildParameter.ActualName;
+      if (ExecutionContext.Scope.Variables.ContainsKey(childName)) {
+        Permutation permutation = ExecutionContext.Scope.Variables[childName].Value as Permutation;
+        ExecutionContext.Scope.Variables.Remove(childName);
+
+        return new AlbaEncoding(permutation, ProblemInstance);
+      } else
+        return null;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/IAlbaOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/IAlbaOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/IAlbaOperator.cs	(revision 14416)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  public interface IAlbaOperator :
+    ISingleDepotOperator, IHeterogenousCapacitatedOperator, IMultiDepotOperator, ITimeWindowedOperator {
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/LocalImprovement/AlbaLambdaInterchangeLocalImprovementOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/LocalImprovement/AlbaLambdaInterchangeLocalImprovementOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/LocalImprovement/AlbaLambdaInterchangeLocalImprovementOperator.cs	(revision 14416)
@@ -0,0 +1,140 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Data;
+using HeuristicLab.Common;
+using HeuristicLab.Parameters;
+using HeuristicLab.Operators;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaLambdaInterchangeLocalImprovementOperator", "Takes a solution and finds the local optimum with respect to the lambda interchange neighborhood by decending along the steepest gradient.")]
+  [StorableClass]
+  public class AlbaLambdaInterchangeLocalImprovementOperator : VRPOperator, IStochasticOperator, ILocalImprovementOperator, ISingleObjectiveOperator {
+
+    public IValueLookupParameter<IntValue> MaximumIterationsParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumIterations"]; }
+    }
+
+    public ILookupParameter<IntValue> EvaluatedSolutionsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["EvaluatedSolutions"]; }
+    }
+
+    public ILookupParameter<ResultCollection> ResultsParameter {
+      get { return (ILookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    public ILookupParameter<IVRPEncoding> VRPToursParameter {
+      get { return (ILookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+
+    public IValueParameter<IntValue> LambdaParameter {
+      get { return (IValueParameter<IntValue>)Parameters["Lambda"]; }
+    }
+
+    public IValueParameter<IntValue> SampleSizeParameter {
+      get { return (IValueParameter<IntValue>)Parameters["SampleSize"]; }
+    }
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    [StorableConstructor]
+    protected AlbaLambdaInterchangeLocalImprovementOperator(bool deserializing) : base(deserializing) { }
+    protected AlbaLambdaInterchangeLocalImprovementOperator(AlbaLambdaInterchangeLocalImprovementOperator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public AlbaLambdaInterchangeLocalImprovementOperator()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumIterations", "The maximum amount of iterations that should be performed (note that this operator will abort earlier when a local optimum is reached.", new IntValue(10000)));
+      Parameters.Add(new LookupParameter<IntValue>("EvaluatedSolutions", "The amount of evaluated solutions (here a move is counted only as 4/n evaluated solutions with n being the length of the permutation)."));
+      Parameters.Add(new LookupParameter<ResultCollection>("Results", "The collection where to store results."));
+      Parameters.Add(new LookupParameter<IVRPEncoding>("VRPTours", "The VRP tours to be manipulated."));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality value of the assignment."));
+      Parameters.Add(new ValueParameter<IntValue>("Lambda", "The lambda value.", new IntValue(1)));
+      Parameters.Add(new ValueParameter<IntValue>("SampleSize", "The number of moves to generate.", new IntValue(2000)));
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaLambdaInterchangeLocalImprovementOperator(this, cloner);
+    }
+
+    public static void Apply(AlbaEncoding solution, int maxIterations,
+      int lambda, int samples, IRandom random, IVRPProblemInstance problemInstance, ref double quality, out int evaluatedSolutions) {
+      evaluatedSolutions = 0;
+
+      for (int i = 0; i < maxIterations; i++) {
+        AlbaLambdaInterchangeMove bestMove = null;
+        foreach (AlbaLambdaInterchangeMove move in AlbaStochasticLambdaInterchangeMultiMoveGenerator.GenerateAllMoves(solution, problemInstance, lambda, samples, random)) {
+          AlbaEncoding newSolution = solution.Clone() as AlbaEncoding;
+          AlbaLambdaInterchangeMoveMaker.Apply(newSolution, move);
+          double moveQuality =
+            problemInstance.Evaluate(newSolution).Quality;
+
+          evaluatedSolutions++;
+          if (moveQuality < quality || quality == -1) {
+            quality = moveQuality;
+            bestMove = move;
+          }
+        }
+        if (bestMove != null)
+          AlbaLambdaInterchangeMoveMaker.Apply(solution, bestMove);
+      }
+    }
+
+    public override IOperation InstrumentedApply() {
+      int maxIterations = MaximumIterationsParameter.ActualValue.Value;
+      AlbaEncoding solution = null;
+
+      if (VRPToursParameter.ActualValue is AlbaEncoding)
+        solution = VRPToursParameter.ActualValue as AlbaEncoding;
+      else
+        VRPToursParameter.ActualValue = solution = AlbaEncoding.ConvertFrom(VRPToursParameter.ActualValue, ProblemInstance);
+
+      int lambda = LambdaParameter.Value.Value;
+      int samples = SampleSizeParameter.Value.Value;
+      IRandom random = RandomParameter.ActualValue;
+
+      double quality = QualityParameter.ActualValue.Value;
+      int evaluatedSolutions;
+
+      Apply(solution, maxIterations, lambda, samples, random, ProblemInstance, ref quality, out evaluatedSolutions);
+
+      EvaluatedSolutionsParameter.ActualValue.Value += evaluatedSolutions;
+      QualityParameter.ActualValue.Value = quality;
+
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Manipulators/AlbaCustomerInsertionManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Manipulators/AlbaCustomerInsertionManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Manipulators/AlbaCustomerInsertionManipulator.cs	(revision 14416)
@@ -0,0 +1,73 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaCustomerInsertionManipulator", "An operator which manipulates a VRP representation by inserting a customer in another place.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public sealed class AlbaCustomerInsertionManipulator : AlbaManipulator {
+    [StorableConstructor]
+    private AlbaCustomerInsertionManipulator(bool deserializing) : base(deserializing) { }
+
+    public AlbaCustomerInsertionManipulator()
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaCustomerInsertionManipulator(this, cloner);
+    }
+
+    private AlbaCustomerInsertionManipulator(AlbaCustomerInsertionManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void Manipulate(IRandom random, AlbaEncoding individual) {
+      AlbaEncoding original = (AlbaEncoding)individual.Clone();
+      int cutIndex, insertIndex, number;
+
+      int customer = random.Next(ProblemInstance.Cities.Value);
+      cutIndex = FindCustomerLocation(customer, individual);
+
+      insertIndex = random.Next(original.Length);
+      number = original[cutIndex];
+
+      int i = 0;  // index in new permutation
+      int j = 0;  // index in old permutation
+      while (i < original.Length) {
+        if (j == cutIndex) {
+          j++;
+        }
+        if (i == insertIndex) {
+          individual[i] = number;
+          i++;
+        }
+        if ((i < original.Length) && (j < original.Length)) {
+          individual[i] = original[j];
+          i++;
+          j++;
+        }
+      }
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Manipulators/AlbaCustomerInversionManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Manipulators/AlbaCustomerInversionManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Manipulators/AlbaCustomerInversionManipulator.cs	(revision 14416)
@@ -0,0 +1,69 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaCustomerInversionManipulator", "An operator which manipulates a VRP representation by inverting the order the customers are visited.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public sealed class AlbaCustomerInversionManipulator : AlbaManipulator {
+    [StorableConstructor]
+    private AlbaCustomerInversionManipulator(bool deserializing) : base(deserializing) { }
+
+    public AlbaCustomerInversionManipulator()
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaCustomerInversionManipulator(this, cloner);
+    }
+
+    private AlbaCustomerInversionManipulator(AlbaCustomerInversionManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void Manipulate(IRandom random, AlbaEncoding individual) {
+      int breakPoint1, breakPoint2;
+
+      int customer1 = random.Next(ProblemInstance.Cities.Value);
+      breakPoint1 = FindCustomerLocation(customer1, individual);
+
+      int customer2 = random.Next(ProblemInstance.Cities.Value);
+      breakPoint2 = FindCustomerLocation(customer1, individual);
+
+      List<int> visitingOrder = new List<int>();
+      for (int i = breakPoint1; i <= breakPoint2; i++) {
+        if (individual[i] != 0)
+          visitingOrder.Add(individual[i]);
+      }
+      visitingOrder.Reverse();
+      for (int i = breakPoint1; i <= breakPoint2; i++) {
+        if (individual[i] != 0) {
+          individual[i] = visitingOrder[0];
+          visitingOrder.RemoveAt(0);
+        }
+      }
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Manipulators/AlbaCustomerSwapManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Manipulators/AlbaCustomerSwapManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Manipulators/AlbaCustomerSwapManipulator.cs	(revision 14416)
@@ -0,0 +1,59 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaCustomerSwapManipulator", "An operator which manipulates a VRP representation by swapping two customers.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public sealed class AlbaCustomerSwapManipulator : AlbaManipulator {
+    [StorableConstructor]
+    private AlbaCustomerSwapManipulator(bool deserializing) : base(deserializing) { }
+
+    public AlbaCustomerSwapManipulator()
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaCustomerSwapManipulator(this, cloner);
+    }
+
+    private AlbaCustomerSwapManipulator(AlbaCustomerSwapManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void Manipulate(IRandom random, AlbaEncoding individual) {
+      int index1, index2, temp;
+
+      int customer1 = random.Next(ProblemInstance.Cities.Value);
+      index1 = FindCustomerLocation(customer1, individual);
+
+      int customer2 = random.Next(ProblemInstance.Cities.Value);
+      index2 = FindCustomerLocation(customer2, individual);
+
+      temp = individual[index1];
+      individual[index1] = individual[index2];
+      individual[index2] = temp;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Manipulators/AlbaIntraRouteInversionManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Manipulators/AlbaIntraRouteInversionManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Manipulators/AlbaIntraRouteInversionManipulator.cs	(revision 14416)
@@ -0,0 +1,93 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaIntraRouteInversionManipulator", "An operator which applies the SLS operation to a VRP representation. It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public sealed class AlbaIntraRouteInversionManipulator : AlbaManipulator {
+    [StorableConstructor]
+    private AlbaIntraRouteInversionManipulator(bool deserializing) : base(deserializing) { }
+
+    public AlbaIntraRouteInversionManipulator()
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaIntraRouteInversionManipulator(this, cloner);
+    }
+
+    private AlbaIntraRouteInversionManipulator(AlbaIntraRouteInversionManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static void Apply(AlbaEncoding individual, int index1, int index2) {
+      if (index1 != -1 && index2 != -1) {
+        int breakPoint1 = index1 + 1;
+        int breakPoint2 = index2;
+        for (int i = 0; i <= (breakPoint2 - breakPoint1) / 2; i++) {  // invert permutation between breakpoints
+          int temp = individual[breakPoint1 + i];
+          individual[breakPoint1 + i] = individual[breakPoint2 - i];
+          individual[breakPoint2 - i] = temp;
+        }
+      }
+    }
+
+    protected override void Manipulate(IRandom rand, AlbaEncoding individual) {
+      int index1 = -1;
+      int index2 = -1;
+
+      List<Tour> validTours = new List<Tour>();
+      foreach (Tour tour in individual.GetTours()) {
+        if (tour.Stops.Count >= 4)
+          validTours.Add(tour);
+      }
+
+      if (validTours.Count > 0) {
+        Tour chosenTour = validTours[rand.Next(validTours.Count)];
+        int currentTourStart = -1;
+        for (int i = 0; i < individual.Length; i++) {
+          if (individual[i] + 1 == chosenTour.Stops[0]) {
+            currentTourStart = i;
+            break;
+          }
+        }
+
+        int currentTourEnd = currentTourStart;
+        while (currentTourEnd < individual.Length &&
+          individual[currentTourEnd] < ProblemInstance.Cities.Value) {
+          currentTourEnd++;
+        }
+
+        int tourLength = currentTourEnd - currentTourStart;
+        int a = rand.Next(tourLength - 3);
+        index1 = currentTourStart + a;
+        index2 = currentTourStart + rand.Next(a + 2, tourLength - 1);
+      }
+
+      Apply(individual, index1, index2);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Manipulators/AlbaLambdaInterchangeManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Manipulators/AlbaLambdaInterchangeManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Manipulators/AlbaLambdaInterchangeManipulator.cs	(revision 14416)
@@ -0,0 +1,136 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaLambdaInterchangeManipulator", "An operator which applies the lambda interchange operation to a VRP representation. It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public sealed class AlbaLambdaInterchangeManipulator : AlbaManipulator {
+    public IValueParameter<IntValue> LambdaParameter {
+      get { return (IValueParameter<IntValue>)Parameters["Lambda"]; }
+    }
+
+    [StorableConstructor]
+    private AlbaLambdaInterchangeManipulator(bool deserializing) : base(deserializing) { }
+
+    public AlbaLambdaInterchangeManipulator()
+      : base() {
+      Parameters.Add(new ValueParameter<IntValue>("Lambda", "The lambda value.", new IntValue(1)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaLambdaInterchangeManipulator(this, cloner);
+    }
+
+    private AlbaLambdaInterchangeManipulator(AlbaLambdaInterchangeManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static void Apply(AlbaEncoding individual, int tour1Index, int position1, int length1,
+      int tour2Index, int position2, int length2) {
+      List<Tour> tours = individual.GetTours();
+
+      Tour tour1 = tours[tour1Index];
+      int tour1Start = -1;
+      for (int i = 0; i < individual.Length; i++) {
+        if (individual[i] == tour1.Stops[0] - 1) {
+          tour1Start = i;
+          break;
+        }
+      }
+
+      Tour tour2 = tours[tour2Index];
+      int tour2Start = -1;
+      for (int i = 0; i < individual.Length; i++) {
+        if (individual[i] == tour2.Stops[0] - 1) {
+          tour2Start = i;
+          break;
+        }
+      }
+
+      AlbaEncoding original = individual.Clone() as AlbaEncoding;
+      int index = 0;
+
+      int start1 = tour1Start + position1;
+      int end1 = start1 + length1;
+
+      int start2 = tour2Start + position2;
+      int end2 = start2 + length2;
+
+      for (int i = 0; i < original.Length; i++) {
+        if (index == start1) {
+          if (end2 - start2 == 0)
+            index = end1;
+          else
+            index = start2;
+        } else if (index == start2) {
+          if (end1 - start1 == 0)
+            index = end2;
+          else
+            index = start1;
+        } else if (index == end1) {
+          index = end2;
+        } else if (index == end2) {
+          index = end1;
+        }
+
+        individual[i] = original[index];
+
+        index++;
+      }
+    }
+
+    protected override void Manipulate(IRandom rand, AlbaEncoding individual) {
+      List<Tour> tours = individual.GetTours();
+      if (tours.Count > 1) {
+        int lambda = LambdaParameter.Value.Value;
+
+        int route1Index = rand.Next(tours.Count);
+        Tour route1 = tours[route1Index];
+
+
+        int route2Index = rand.Next(tours.Count - 1);
+        if (route2Index >= route1Index)
+          route2Index += 1;
+        Tour route2 = tours[route2Index];
+
+        int length1 = rand.Next(Math.Min(lambda + 1, route1.Stops.Count + 1));
+        int index1 = rand.Next(route1.Stops.Count - length1 + 1);
+
+        int l2Min = 0;
+        if (length1 == 0)
+          l2Min = 1;
+        int length2 = rand.Next(l2Min, Math.Min(lambda + 1, route2.Stops.Count + 1));
+        int index2 = rand.Next(route2.Stops.Count - length2 + 1);
+
+        Apply(individual, route1Index, index1, length1,
+          route2Index, index2, length2);
+      }
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Manipulators/AlbaManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Manipulators/AlbaManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Manipulators/AlbaManipulator.cs	(revision 14416)
@@ -0,0 +1,76 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaManipulator", "An operator which manipulates a VRP representation.")]
+  [StorableClass]
+  public abstract class AlbaManipulator : VRPManipulator, IAlbaOperator, IVRPManipulator, IStochasticOperator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    [StorableConstructor]
+    protected AlbaManipulator(bool deserializing) : base(deserializing) { }
+
+    public AlbaManipulator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator which should be used for stochastic manipulation operators."));
+    }
+
+    protected AlbaManipulator(AlbaManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected abstract void Manipulate(IRandom random, AlbaEncoding individual);
+
+    protected int FindCustomerLocation(int customer, AlbaEncoding individual) {
+      int pos = -1;
+      for (int i = 0; i < individual.Length; i++) {
+        if (individual[i] == customer) {
+          pos = i;
+          break;
+        }
+      }
+
+      return pos;
+    }
+
+    public override IOperation InstrumentedApply() {
+      IVRPEncoding solution = VRPToursParameter.ActualValue;
+      if (!(solution is AlbaEncoding)) {
+        VRPToursParameter.ActualValue = AlbaEncoding.ConvertFrom(solution, ProblemInstance);
+      }
+
+      Manipulate(RandomParameter.ActualValue, VRPToursParameter.ActualValue as AlbaEncoding);
+      (VRPToursParameter.ActualValue as AlbaEncoding).Repair();
+
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Manipulators/AlbaPermutationManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Manipulators/AlbaPermutationManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Manipulators/AlbaPermutationManipulator.cs	(revision 14416)
@@ -0,0 +1,60 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Encodings.PermutationEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaPermutationManipulator", "An operator which manipulates a VRP representation by using a standard permutation manipulator.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public sealed class AlbaPermutationManipualtor : AlbaManipulator {
+    public IValueLookupParameter<IPermutationManipulator> InnerManipulatorParameter {
+      get { return (IValueLookupParameter<IPermutationManipulator>)Parameters["InnerManipulator"]; }
+    }
+
+    [StorableConstructor]
+    private AlbaPermutationManipualtor(bool deserializing) : base(deserializing) { }
+
+    public AlbaPermutationManipualtor()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<IPermutationManipulator>("InnerManipulator", "The permutation manipulator.", new TranslocationManipulator()));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaPermutationManipualtor(this, cloner);
+    }
+
+    private AlbaPermutationManipualtor(AlbaPermutationManipualtor original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void Manipulate(IRandom random, AlbaEncoding individual) {
+      InnerManipulatorParameter.ActualValue.PermutationParameter.ActualName = VRPToursParameter.ActualName;
+
+      IAtomicOperation op = this.ExecutionContext.CreateOperation(
+        InnerManipulatorParameter.ActualValue, this.ExecutionContext.Scope);
+      op.Operator.Execute((IExecutionContext)op, CancellationToken);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/AlbaMoveEvaluator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/AlbaMoveEvaluator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/AlbaMoveEvaluator.cs	(revision 14416)
@@ -0,0 +1,42 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaMoveEvaluator", "Evaluates an Alba VRP move.")]
+  [StorableClass]
+  public abstract class AlbaMoveEvaluator : VRPMoveEvaluator, IAlbaOperator {
+    [StorableConstructor]
+    protected AlbaMoveEvaluator(bool deserializing) : base(deserializing) { }
+
+    public AlbaMoveEvaluator()
+      : base() {
+    }
+
+    protected AlbaMoveEvaluator(AlbaMoveEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/AlbaMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/AlbaMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/AlbaMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,52 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaMoveGenerator", "Generates Alba VRP moves.")]
+  [StorableClass]
+  public abstract class AlbaMoveGenerator : VRPMoveGenerator, IAlbaOperator {
+    [StorableConstructor]
+    protected AlbaMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public AlbaMoveGenerator()
+      : base() {
+    }
+
+    protected AlbaMoveGenerator(AlbaMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IOperation InstrumentedApply() {
+      IVRPEncoding solution = VRPToursParameter.ActualValue;
+      if (!(solution is AlbaEncoding)) {
+        VRPToursParameter.ActualValue = AlbaEncoding.ConvertFrom(solution, ProblemInstance);
+      }
+
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/AlbaMoveMaker.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/AlbaMoveMaker.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/AlbaMoveMaker.cs	(revision 14416)
@@ -0,0 +1,42 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaMoveMaker", "Makes an Alba VRP move.")]
+  [StorableClass]
+  public abstract class AlbaMoveMaker : VRPMoveMaker, IAlbaOperator {
+    [StorableConstructor]
+    protected AlbaMoveMaker(bool deserializing) : base(deserializing) { }
+
+    public AlbaMoveMaker()
+      : base() {
+    }
+
+    protected AlbaMoveMaker(AlbaMoveMaker original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/AlbaExhaustiveIntraRouteInversionMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/AlbaExhaustiveIntraRouteInversionMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/AlbaExhaustiveIntraRouteInversionMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,80 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaExhaustiveIntraRouteInversionGenerator", "Generates all possible intra route inversion moves from a given VRP encoding.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public sealed class AlbaExhaustiveIntraRouteInversionGenerator : AlbaIntraRouteInversionMoveGenerator, IExhaustiveMoveGenerator, IAlbaIntraRouteInversionMoveOperator {
+    [StorableConstructor]
+    private AlbaExhaustiveIntraRouteInversionGenerator(bool deserializing) : base(deserializing) { }
+
+    public AlbaExhaustiveIntraRouteInversionGenerator()
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaExhaustiveIntraRouteInversionGenerator(this, cloner);
+    }
+
+    private AlbaExhaustiveIntraRouteInversionGenerator(AlbaExhaustiveIntraRouteInversionGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override AlbaIntraRouteInversionMove[] GenerateMoves(AlbaEncoding individual, IVRPProblemInstance problemInstance) {
+      List<AlbaIntraRouteInversionMove> moves = new List<AlbaIntraRouteInversionMove>();
+
+      int currentTourStart = 0;
+      int currentTourEnd = 0;
+      while (currentTourEnd != individual.Length) {
+        currentTourEnd = currentTourStart;
+        while (individual[currentTourEnd] < problemInstance.Cities.Value &&
+          currentTourEnd < individual.Length) {
+          currentTourEnd++;
+        }
+
+        int tourLength = currentTourEnd - currentTourStart;
+        if (tourLength >= 4) {
+          for (int i = 0; i <= tourLength - 4; i++) {
+            for (int j = i + 2; j <= tourLength - 2; j++) {
+              AlbaIntraRouteInversionMove move = new AlbaIntraRouteInversionMove(
+                currentTourStart + i,
+                currentTourStart + j,
+                individual);
+
+              moves.Add(move);
+            }
+          }
+        }
+
+        currentTourStart = currentTourEnd;
+      }
+
+      return moves.ToArray();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/AlbaIntraRouteInversionEvaluator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/AlbaIntraRouteInversionEvaluator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/AlbaIntraRouteInversionEvaluator.cs	(revision 14416)
@@ -0,0 +1,63 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Alba;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  [Item("AlbaIntraRouteInversionMoveEvaluator", "Evaluates a intra route inversion move for a VRP representation.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public sealed class AlbaIntraRouteInversionMoveEvaluator : AlbaMoveEvaluator, IAlbaIntraRouteInversionMoveOperator {
+    public ILookupParameter<AlbaIntraRouteInversionMove> IntraRouteInversionMoveParameter {
+      get { return (ILookupParameter<AlbaIntraRouteInversionMove>)Parameters["AlbaIntraRouteInversionMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return IntraRouteInversionMoveParameter; }
+    }
+
+    [StorableConstructor]
+    private AlbaIntraRouteInversionMoveEvaluator(bool deserializing) : base(deserializing) { }
+
+    public AlbaIntraRouteInversionMoveEvaluator()
+      : base() {
+      Parameters.Add(new LookupParameter<AlbaIntraRouteInversionMove>("AlbaIntraRouteInversionMove", "The move to evaluate."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaIntraRouteInversionMoveEvaluator(this, cloner);
+    }
+
+    private AlbaIntraRouteInversionMoveEvaluator(AlbaIntraRouteInversionMoveEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void EvaluateMove() {
+      AlbaEncoding newSolution = IntraRouteInversionMoveParameter.ActualValue.Permutation.Clone() as AlbaEncoding;
+      AlbaIntraRouteInversionMoveMaker.Apply(newSolution, IntraRouteInversionMoveParameter.ActualValue);
+
+      UpdateEvaluation(newSolution);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/AlbaIntraRouteInversionMove.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/AlbaIntraRouteInversionMove.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/AlbaIntraRouteInversionMove.cs	(revision 14416)
@@ -0,0 +1,84 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Encodings.PermutationEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaIntraRouteInversionMove", "Item that describes an intra route inversion move on a VRP representation.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public class AlbaIntraRouteInversionMove : TwoIndexMove, IVRPMove {
+    public IVRPEncoding Individual { get { return Permutation as AlbaEncoding; } }
+
+    [StorableConstructor]
+    protected AlbaIntraRouteInversionMove(bool deserializing) : base(deserializing) { }
+
+    protected AlbaIntraRouteInversionMove(AlbaIntraRouteInversionMove original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public AlbaIntraRouteInversionMove()
+      : base() {
+    }
+
+    public AlbaIntraRouteInversionMove(int index1, int index2)
+      : base(index1, index2, null) {
+    }
+
+    public AlbaIntraRouteInversionMove(int index1, int index2, AlbaEncoding permutation)
+      : base(index1, index2, null) {
+      this.Permutation = permutation.Clone() as AlbaEncoding;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaIntraRouteInversionMove(this, cloner);
+    }
+
+    #region IVRPMove Members
+
+    public VRPMoveEvaluator GetMoveEvaluator() {
+      return new AlbaIntraRouteInversionMoveEvaluator();
+    }
+
+    public VRPMoveMaker GetMoveMaker() {
+      return new AlbaIntraRouteInversionMoveMaker();
+    }
+
+    public ITabuMaker GetTabuMaker() {
+      return null;
+    }
+
+    public ITabuChecker GetTabuChecker() {
+      return null;
+    }
+
+    public ITabuChecker GetSoftTabuChecker() {
+      return null;
+    }
+
+    #endregion
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/AlbaIntraRouteInversionMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/AlbaIntraRouteInversionMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/AlbaIntraRouteInversionMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,75 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaIntraRouteInversionMoveGenerator", "Generates intra route inversion moves from a given VRP encoding.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public abstract class AlbaIntraRouteInversionMoveGenerator : AlbaMoveGenerator, IExhaustiveMoveGenerator, IAlbaIntraRouteInversionMoveOperator {
+    public ILookupParameter<AlbaIntraRouteInversionMove> IntraRouteInversionMoveParameter {
+      get { return (ILookupParameter<AlbaIntraRouteInversionMove>)Parameters["AlbaIntraRouteInversionMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return IntraRouteInversionMoveParameter; }
+    }
+
+    protected ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+
+    [StorableConstructor]
+    protected AlbaIntraRouteInversionMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public AlbaIntraRouteInversionMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<AlbaIntraRouteInversionMove>("AlbaIntraRouteInversionMove", "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 AlbaIntraRouteInversionMoveGenerator(AlbaIntraRouteInversionMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected abstract AlbaIntraRouteInversionMove[] GenerateMoves(AlbaEncoding individual, IVRPProblemInstance problemInstance);
+
+    public override IOperation InstrumentedApply() {
+      IOperation next = base.InstrumentedApply();
+
+      AlbaEncoding individual = VRPToursParameter.ActualValue as AlbaEncoding;
+      AlbaIntraRouteInversionMove[] 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(IntraRouteInversionMoveParameter.ActualName, moves[i]));
+      }
+      CurrentScopeParameter.ActualValue.SubScopes.AddRange(moveScopes);
+
+      return next;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/AlbaIntraRouteInversionMoveMaker.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/AlbaIntraRouteInversionMoveMaker.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/AlbaIntraRouteInversionMoveMaker.cs	(revision 14416)
@@ -0,0 +1,67 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaIntraRouteInversionMoveMaker", "Peforms the SLS move on a given VRP encoding and updates the quality.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public class AlbaIntraRouteInversionMoveMaker : AlbaMoveMaker, IAlbaIntraRouteInversionMoveOperator, IMoveMaker {
+    public ILookupParameter<AlbaIntraRouteInversionMove> IntraRouteInversionMoveParameter {
+      get { return (ILookupParameter<AlbaIntraRouteInversionMove>)Parameters["AlbaIntraRouteInversionMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return IntraRouteInversionMoveParameter; }
+    }
+
+    [StorableConstructor]
+    protected AlbaIntraRouteInversionMoveMaker(bool deserializing) : base(deserializing) { }
+
+    public AlbaIntraRouteInversionMoveMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<AlbaIntraRouteInversionMove>("AlbaIntraRouteInversionMove", "The move to make."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaIntraRouteInversionMoveMaker(this, cloner);
+    }
+
+    protected AlbaIntraRouteInversionMoveMaker(AlbaIntraRouteInversionMoveMaker original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static void Apply(AlbaEncoding solution, AlbaIntraRouteInversionMove move) {
+      AlbaIntraRouteInversionManipulator.Apply(solution, move.Index1, move.Index2);
+    }
+
+    protected override void PerformMove() {
+      AlbaIntraRouteInversionMove move = IntraRouteInversionMoveParameter.ActualValue;
+
+      Apply(move.Individual as AlbaEncoding, move);
+      VRPToursParameter.ActualValue = move.Individual as AlbaEncoding;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/AlbaStochasticIntraRouteInversionMutliMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/AlbaStochasticIntraRouteInversionMutliMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/AlbaStochasticIntraRouteInversionMutliMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,73 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaStochasticIntraRouteInversionMultiMoveGenerator", "Generates multiple random intra route inversion moves from a given VRP encoding.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public sealed class AlbaStochasticIntraRouteInversionMultiMoveGenerator : AlbaIntraRouteInversionMoveGenerator, IStochasticOperator,
+    IMultiMoveGenerator, IAlbaIntraRouteInversionMoveOperator, IMultiVRPMoveGenerator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public IValueLookupParameter<IntValue> SampleSizeParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["SampleSize"]; }
+    }
+
+    [StorableConstructor]
+    private AlbaStochasticIntraRouteInversionMultiMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public AlbaStochasticIntraRouteInversionMultiMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("SampleSize", "The number of moves to generate."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaStochasticIntraRouteInversionMultiMoveGenerator(this, cloner);
+    }
+
+    private AlbaStochasticIntraRouteInversionMultiMoveGenerator(AlbaStochasticIntraRouteInversionMultiMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override AlbaIntraRouteInversionMove[] GenerateMoves(AlbaEncoding individual, IVRPProblemInstance problemInstance) {
+      int sampleSize = SampleSizeParameter.ActualValue.Value;
+
+      AlbaIntraRouteInversionMove[] moves = new AlbaIntraRouteInversionMove[sampleSize];
+      for (int i = 0; i < sampleSize; i++) {
+        moves[i] = AlbaStochasticIntraRouteInversionSingleMoveGenerator.Apply(
+          individual, problemInstance.Cities.Value, RandomParameter.ActualValue);
+      }
+
+      return moves;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/AlbaStochasticIntraRouteInversionSingleMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/AlbaStochasticIntraRouteInversionSingleMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/AlbaStochasticIntraRouteInversionSingleMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,108 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaStochasticIntraRouteInversionSingleMoveGenerator", "Generates one random intra route inversion move from a given VRP encoding.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public sealed class AlbaStochasticIntraRouteInversionSingleMoveGenerator : AlbaIntraRouteInversionMoveGenerator,
+    IStochasticOperator, ISingleMoveGenerator, IAlbaIntraRouteInversionMoveOperator {
+    #region IMultiVRPMoveOperator Members
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return (ILookupParameter)Parameters["AlbaIntraRouteInversionMove"]; }
+    }
+
+    #endregion
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    [StorableConstructor]
+    private AlbaStochasticIntraRouteInversionSingleMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public AlbaStochasticIntraRouteInversionSingleMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaStochasticIntraRouteInversionSingleMoveGenerator(this, cloner);
+    }
+
+    private AlbaStochasticIntraRouteInversionSingleMoveGenerator(AlbaStochasticIntraRouteInversionSingleMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static AlbaIntraRouteInversionMove Apply(AlbaEncoding individual, int cities, IRandom rand) {
+      int index1 = -1;
+      int index2 = -1;
+
+      List<Tour> validTours = new List<Tour>();
+      foreach (Tour tour in individual.GetTours()) {
+        if (tour.Stops.Count >= 4)
+          validTours.Add(tour);
+      }
+
+      if (validTours.Count > 0) {
+        Tour chosenTour = validTours[rand.Next(validTours.Count)];
+        int currentTourStart = -1;
+        for (int i = 0; i < individual.Length; i++) {
+          if (individual[i] + 1 == chosenTour.Stops[0]) {
+            currentTourStart = i;
+            break;
+          }
+        }
+
+        int currentTourEnd = currentTourStart;
+        while (currentTourEnd < individual.Length &&
+          individual[currentTourEnd] < cities) {
+          currentTourEnd++;
+        }
+
+        int tourLength = currentTourEnd - currentTourStart;
+        int a = rand.Next(tourLength - 3);
+        index1 = currentTourStart + a;
+        index2 = currentTourStart + rand.Next(a + 2, tourLength - 1);
+      }
+
+      return new AlbaIntraRouteInversionMove(index1, index2, individual);
+    }
+
+    protected override AlbaIntraRouteInversionMove[] GenerateMoves(AlbaEncoding individual, IVRPProblemInstance problemInstance) {
+      List<AlbaIntraRouteInversionMove> moves = new List<AlbaIntraRouteInversionMove>();
+
+      AlbaIntraRouteInversionMove move = Apply(individual, problemInstance.Cities.Value, RandomParameter.ActualValue);
+      if (move != null)
+        moves.Add(move);
+
+      return moves.ToArray();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/IAlbaIntraRouteInversionMoveOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/IAlbaIntraRouteInversionMoveOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/IntraRouteInversion/IAlbaIntraRouteInversionMoveOperator.cs	(revision 14416)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  public interface IAlbaIntraRouteInversionMoveOperator : IVRPMoveOperator {
+    ILookupParameter<AlbaIntraRouteInversionMove> IntraRouteInversionMoveParameter { get; }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/AlbaExhaustiveLambdaInterchangeMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/AlbaExhaustiveLambdaInterchangeMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/AlbaExhaustiveLambdaInterchangeMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,77 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaExhaustiveLambdaInterchangeMoveGenerator", "Generates all possible lambda interchange moves from a given VRP encoding.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public sealed class AlbaExhaustiveLambdaInterchangeMoveGenerator : AlbaLambdaInterchangeMoveGenerator, IExhaustiveMoveGenerator, IAlbaLambdaInterchangeMoveOperator {
+    [StorableConstructor]
+    private AlbaExhaustiveLambdaInterchangeMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public AlbaExhaustiveLambdaInterchangeMoveGenerator()
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaExhaustiveLambdaInterchangeMoveGenerator(this, cloner);
+    }
+
+    private AlbaExhaustiveLambdaInterchangeMoveGenerator(AlbaExhaustiveLambdaInterchangeMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override AlbaLambdaInterchangeMove[] GenerateMoves(AlbaEncoding individual, IVRPProblemInstance problemInstance, int lambda) {
+      List<AlbaLambdaInterchangeMove> moves = new List<AlbaLambdaInterchangeMove>();
+
+      List<Tour> tours = individual.GetTours();
+
+      for (int tour1Index = 0; tour1Index < tours.Count; tour1Index++) {
+        Tour tour1 = tours[tour1Index];
+        for (int tour2Index = tour1Index + 1; tour2Index < tours.Count; tour2Index++) {
+          Tour tour2 = tours[tour2Index];
+
+          for (int length1 = 0; length1 <= Math.Min(lambda, tour1.Stops.Count); length1++) {
+            for (int length2 = 0; length2 <= Math.Min(lambda, tour2.Stops.Count); length2++) {
+              if (length1 != 0 || length2 != 0) {
+                for (int index1 = 0; index1 < tour1.Stops.Count - length1 + 1; index1++) {
+                  for (int index2 = 0; index2 < tour2.Stops.Count - length2 + 1; index2++) {
+                    moves.Add(new AlbaLambdaInterchangeMove(tour1Index, index1, length1,
+                      tour2Index, index2, length2, individual));
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+
+      return moves.ToArray();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/AlbaLambdaInterchangeMove.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/AlbaLambdaInterchangeMove.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/AlbaLambdaInterchangeMove.cs	(revision 14416)
@@ -0,0 +1,124 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaLambdaInterchangeMove", "Item that describes a lambda move on a VRP representation.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public class AlbaLambdaInterchangeMove : Item, IVRPMove {
+    [Storable]
+    public IVRPEncoding Individual { get; protected set; }
+
+    [Storable]
+    public int Tour1 { get; protected set; }
+
+    [Storable]
+    public int Position1 { get; protected set; }
+
+    [Storable]
+    public int Length1 { get; protected set; }
+
+    [Storable]
+    public int Tour2 { get; protected set; }
+
+    [Storable]
+    public int Position2 { get; protected set; }
+
+    [Storable]
+    public int Length2 { get; protected set; }
+
+    public AlbaLambdaInterchangeMove()
+      : base() {
+      Tour1 = -1;
+      Position1 = -1;
+      Length1 = -1;
+
+      Tour2 = -1;
+      Position2 = -1;
+      Length2 = -1;
+
+      Individual = null;
+    }
+
+    public AlbaLambdaInterchangeMove(int tour1, int position1, int length1,
+      int tour2, int position2, int length2, AlbaEncoding permutation) {
+      Tour1 = tour1;
+      Position1 = position1;
+      Length1 = length1;
+
+      Tour2 = tour2;
+      Position2 = position2;
+      Length2 = length2;
+
+      this.Individual = permutation.Clone() as AlbaEncoding;
+    }
+
+    [StorableConstructor]
+    protected AlbaLambdaInterchangeMove(bool deserializing) : base(deserializing) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaLambdaInterchangeMove(this, cloner);
+    }
+
+    protected AlbaLambdaInterchangeMove(AlbaLambdaInterchangeMove original, Cloner cloner)
+      : base(original, cloner) {
+      this.Tour1 = original.Tour1;
+      this.Position1 = original.Position1;
+      this.Length1 = original.Length1;
+
+      this.Tour2 = original.Tour2;
+      this.Position2 = original.Position2;
+      this.Length2 = original.Length2;
+
+      this.Individual = cloner.Clone(Individual) as AlbaEncoding;
+    }
+
+    #region IVRPMove Members
+
+    public VRPMoveEvaluator GetMoveEvaluator() {
+      return new AlbaLambdaInterchangeMoveEvaluator();
+    }
+
+    public VRPMoveMaker GetMoveMaker() {
+      return new AlbaLambdaInterchangeMoveMaker();
+    }
+
+    public ITabuMaker GetTabuMaker() {
+      return null;
+    }
+
+    public ITabuChecker GetTabuChecker() {
+      return null;
+    }
+
+    public ITabuChecker GetSoftTabuChecker() {
+      return null;
+    }
+
+    #endregion
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/AlbaLambdaInterchangeMoveEvaluator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/AlbaLambdaInterchangeMoveEvaluator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/AlbaLambdaInterchangeMoveEvaluator.cs	(revision 14416)
@@ -0,0 +1,63 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Alba;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  [Item("AlbaLambdaInterchangeMoveEvaluator", "Evaluates a lamnbda interchange move for a VRP representation.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public sealed class AlbaLambdaInterchangeMoveEvaluator : AlbaMoveEvaluator, IAlbaLambdaInterchangeMoveOperator {
+    public ILookupParameter<AlbaLambdaInterchangeMove> LambdaInterchangeMoveParameter {
+      get { return (ILookupParameter<AlbaLambdaInterchangeMove>)Parameters["AlbaLambdaInterchangeMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return LambdaInterchangeMoveParameter; }
+    }
+
+    [StorableConstructor]
+    private AlbaLambdaInterchangeMoveEvaluator(bool deserializing) : base(deserializing) { }
+
+    public AlbaLambdaInterchangeMoveEvaluator()
+      : base() {
+      Parameters.Add(new LookupParameter<AlbaLambdaInterchangeMove>("AlbaLambdaInterchangeMove", "The move to evaluate."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaLambdaInterchangeMoveEvaluator(this, cloner);
+    }
+
+    private AlbaLambdaInterchangeMoveEvaluator(AlbaLambdaInterchangeMoveEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void EvaluateMove() {
+      AlbaEncoding newSolution = LambdaInterchangeMoveParameter.ActualValue.Individual.Clone() as AlbaEncoding;
+      AlbaLambdaInterchangeMoveMaker.Apply(newSolution, LambdaInterchangeMoveParameter.ActualValue);
+
+      UpdateEvaluation(newSolution);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/AlbaLambdaInterchangeMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/AlbaLambdaInterchangeMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/AlbaLambdaInterchangeMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,85 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaLambdaInterchangeMoveGenerator", "Generates lambda interchange moves from a given VRP encoding.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public abstract class AlbaLambdaInterchangeMoveGenerator : AlbaMoveGenerator, IExhaustiveMoveGenerator, IAlbaLambdaInterchangeMoveOperator {
+    #region IAlbaLambdaInterchangeMoveOperator Members
+
+    public ILookupParameter<AlbaLambdaInterchangeMove> LambdaInterchangeMoveParameter {
+      get { return (ILookupParameter<AlbaLambdaInterchangeMove>)Parameters["AlbaLambdaInterchangeMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return LambdaInterchangeMoveParameter; }
+    }
+
+    protected ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+
+    public IValueParameter<IntValue> LambdaParameter {
+      get { return (IValueParameter<IntValue>)Parameters["Lambda"]; }
+    }
+
+    #endregion
+
+    [StorableConstructor]
+    protected AlbaLambdaInterchangeMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public AlbaLambdaInterchangeMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<AlbaLambdaInterchangeMove>("AlbaLambdaInterchangeMove", "The moves that should be generated in subscopes."));
+      Parameters.Add(new ScopeParameter("CurrentScope", "The current scope where the moves should be added as subscopes."));
+      Parameters.Add(new ValueParameter<IntValue>("Lambda", "The lambda value.", new IntValue(1)));
+    }
+
+    protected AlbaLambdaInterchangeMoveGenerator(AlbaLambdaInterchangeMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected abstract AlbaLambdaInterchangeMove[] GenerateMoves(AlbaEncoding individual, IVRPProblemInstance problemInstance, int lambda);
+
+    public override IOperation InstrumentedApply() {
+      IOperation next = base.InstrumentedApply();
+
+      AlbaEncoding individual = VRPToursParameter.ActualValue as AlbaEncoding;
+      AlbaLambdaInterchangeMove[] moves = GenerateMoves(individual, ProblemInstanceParameter.ActualValue, LambdaParameter.Value.Value);
+      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(LambdaInterchangeMoveParameter.ActualName, moves[i]));
+      }
+      CurrentScopeParameter.ActualValue.SubScopes.AddRange(moveScopes);
+
+      return next;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/AlbaLambdaInterchangeMoveMaker.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/AlbaLambdaInterchangeMoveMaker.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/AlbaLambdaInterchangeMoveMaker.cs	(revision 14416)
@@ -0,0 +1,73 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaLambdaInterchangeMoveMaker", "Peforms a lambda interchange moves on a given VRP encoding and updates the quality. It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public class AlbaLambdaInterchangeMoveMaker : AlbaMoveMaker, IAlbaLambdaInterchangeMoveOperator, IMoveMaker {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    public ILookupParameter<AlbaLambdaInterchangeMove> LambdaInterchangeMoveParameter {
+      get { return (ILookupParameter<AlbaLambdaInterchangeMove>)Parameters["AlbaLambdaInterchangeMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return LambdaInterchangeMoveParameter; }
+    }
+
+    [StorableConstructor]
+    protected AlbaLambdaInterchangeMoveMaker(bool deserializing) : base(deserializing) { }
+
+    public AlbaLambdaInterchangeMoveMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<AlbaLambdaInterchangeMove>("AlbaLambdaInterchangeMove", "The move to make."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaLambdaInterchangeMoveMaker(this, cloner);
+    }
+
+    protected AlbaLambdaInterchangeMoveMaker(AlbaLambdaInterchangeMoveMaker original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static void Apply(AlbaEncoding solution, AlbaLambdaInterchangeMove move) {
+      AlbaLambdaInterchangeManipulator.Apply(
+        solution,
+        move.Tour1, move.Position1, move.Length1,
+        move.Tour2, move.Position2, move.Length2);
+    }
+
+    protected override void PerformMove() {
+      AlbaLambdaInterchangeMove move = LambdaInterchangeMoveParameter.ActualValue;
+
+      Apply(move.Individual as AlbaEncoding, move);
+      VRPToursParameter.ActualValue = move.Individual;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/AlbaStochasticLambdaInterchangeMutliMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/AlbaStochasticLambdaInterchangeMutliMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/AlbaStochasticLambdaInterchangeMutliMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,75 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaStochasticLambdaInterchangeMultiMoveGenerator", "Generates multiple random lambda interchange moves from a given VRP encoding.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public sealed class AlbaStochasticLambdaInterchangeMultiMoveGenerator : AlbaLambdaInterchangeMoveGenerator, IStochasticOperator,
+    IMultiMoveGenerator, IAlbaLambdaInterchangeMoveOperator, IMultiVRPMoveGenerator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public IValueLookupParameter<IntValue> SampleSizeParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["SampleSize"]; }
+    }
+
+    [StorableConstructor]
+    private AlbaStochasticLambdaInterchangeMultiMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public AlbaStochasticLambdaInterchangeMultiMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("SampleSize", "The number of moves to generate."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaStochasticLambdaInterchangeMultiMoveGenerator(this, cloner);
+    }
+
+    private AlbaStochasticLambdaInterchangeMultiMoveGenerator(AlbaStochasticLambdaInterchangeMultiMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static AlbaLambdaInterchangeMove[] GenerateAllMoves(AlbaEncoding individual, IVRPProblemInstance problemInstance, int lambda, int sampleSize, IRandom rand) {
+      AlbaLambdaInterchangeMove[] moves = new AlbaLambdaInterchangeMove[sampleSize];
+      for (int i = 0; i < sampleSize; i++) {
+        moves[i] = AlbaStochasticLambdaInterchangeSingleMoveGenerator.Apply(
+          individual, problemInstance.Cities.Value, lambda, rand);
+      }
+
+      return moves;
+    }
+
+    protected override AlbaLambdaInterchangeMove[] GenerateMoves(AlbaEncoding individual, IVRPProblemInstance problemInstance, int lambda) {
+      return GenerateAllMoves(individual, problemInstance, lambda, SampleSizeParameter.ActualValue.Value, RandomParameter.ActualValue);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/AlbaStochasticLambdaInterchangeSingleMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/AlbaStochasticLambdaInterchangeSingleMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/AlbaStochasticLambdaInterchangeSingleMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,102 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaStochasticLambdaInterchangeSingleMoveGenerator", "Generates one random lambda interchange move from a given VRP encoding.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public sealed class AlbaStochasticLambdaInterchangeSingleMoveGenerator : AlbaLambdaInterchangeMoveGenerator,
+    IStochasticOperator, ISingleMoveGenerator, IAlbaLambdaInterchangeMoveOperator {
+    #region IMultiVRPMoveOperator Members
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return (ILookupParameter)Parameters["AlbaLambdaInterchangeMove"]; }
+    }
+
+    #endregion
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    [StorableConstructor]
+    private AlbaStochasticLambdaInterchangeSingleMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public AlbaStochasticLambdaInterchangeSingleMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaStochasticLambdaInterchangeSingleMoveGenerator(this, cloner);
+    }
+
+    private AlbaStochasticLambdaInterchangeSingleMoveGenerator(AlbaStochasticLambdaInterchangeSingleMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static AlbaLambdaInterchangeMove Apply(AlbaEncoding individual, int cities, int lambda, IRandom rand) {
+      List<Tour> tours = individual.GetTours();
+
+      if (tours.Count > 1) {
+        int route1Index = rand.Next(tours.Count);
+        Tour route1 = tours[route1Index];
+
+        int route2Index = rand.Next(tours.Count - 1);
+        if (route2Index >= route1Index)
+          route2Index += 1;
+
+        Tour route2 = tours[route2Index];
+
+        int length1 = rand.Next(Math.Min(lambda + 1, route1.Stops.Count + 1));
+        int index1 = rand.Next(route1.Stops.Count - length1 + 1);
+
+        int l2Min = 0;
+        if (length1 == 0)
+          l2Min = 1;
+        int length2 = rand.Next(l2Min, Math.Min(lambda + 1, route2.Stops.Count + 1));
+        int index2 = rand.Next(route2.Stops.Count - length2 + 1);
+
+        return new AlbaLambdaInterchangeMove(route1Index, index1, length1, route2Index, index2, length2, individual);
+      } else {
+        return new AlbaLambdaInterchangeMove(0, 0, 0, 0, 0, 0, individual);
+      }
+    }
+
+    protected override AlbaLambdaInterchangeMove[] GenerateMoves(AlbaEncoding individual, IVRPProblemInstance problemInstance, int lambda) {
+      List<AlbaLambdaInterchangeMove> moves = new List<AlbaLambdaInterchangeMove>();
+
+      AlbaLambdaInterchangeMove move = Apply(individual, problemInstance.Cities.Value, lambda, RandomParameter.ActualValue);
+      if (move != null)
+        moves.Add(move);
+
+      return moves.ToArray();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/IAlbaLambdaInterchangeMoveOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/IAlbaLambdaInterchangeMoveOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/LambdaInterchange/IAlbaLambdaInterchangeMoveOperator.cs	(revision 14416)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  public interface IAlbaLambdaInterchangeMoveOperator : IVRPMoveOperator {
+    ILookupParameter<AlbaLambdaInterchangeMove> LambdaInterchangeMoveParameter { get; }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaStochasticTranslocationSingleMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaStochasticTranslocationSingleMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaStochasticTranslocationSingleMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,96 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Encodings.PermutationEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaStochasticTranslocationSingleMoveGenerator", "An operator which generates a single translocation move for a VRP representation.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public sealed class AlbaStochasticTranslocationSingleMoveGenerator : AlbaMoveGenerator, IAlbaTranslocationMoveOperator {
+    [Storable]
+    private TranslocationMoveGenerator generator = new StochasticTranslocationSingleMoveGenerator();
+
+    public ILookupParameter<TranslocationMove> TranslocationMoveParameter {
+      get {
+        return generator.TranslocationMoveParameter;
+      }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return TranslocationMoveParameter; }
+    }
+
+    public ILookupParameter<Permutation> PermutationParameter {
+      get {
+        return generator.PermutationParameter;
+      }
+    }
+
+    public IValueLookupParameter<IntValue> SampleSizeParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["SampleSize"]; }
+    }
+
+    [StorableConstructor]
+    private AlbaStochasticTranslocationSingleMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public AlbaStochasticTranslocationSingleMoveGenerator()
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaStochasticTranslocationSingleMoveGenerator(this, cloner);
+    }
+
+    private AlbaStochasticTranslocationSingleMoveGenerator(AlbaStochasticTranslocationSingleMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IOperation InstrumentedApply() {
+      IOperation next = base.InstrumentedApply();
+
+      IVRPEncoding solution = VRPToursParameter.ActualValue;
+
+      generator.PermutationParameter.ActualName = VRPToursParameter.ActualName;
+      IAtomicOperation op = this.ExecutionContext.CreateChildOperation(generator);
+      op.Operator.Execute((IExecutionContext)op, CancellationToken);
+
+      foreach (IScope scope in this.ExecutionContext.Scope.SubScopes) {
+        IVariable moveVariable = scope.Variables[
+          TranslocationMoveParameter.ActualName];
+
+        if (moveVariable.Value is TranslocationMove &&
+          !(moveVariable.Value is AlbaTranslocationMove)) {
+          TranslocationMove move = moveVariable.Value as TranslocationMove;
+          moveVariable.Value =
+            new AlbaTranslocationMove(
+              move.Index1, move.Index2, move.Index3, solution as AlbaEncoding);
+        }
+      }
+
+      return next;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaTranslocationMove.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaTranslocationMove.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaTranslocationMove.cs	(revision 14416)
@@ -0,0 +1,84 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Encodings.PermutationEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaTranslocationMove", "Item that describes a translocation move on a VRP representation.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public class AlbaTranslocationMove : TranslocationMove, IVRPMove {
+    public IVRPEncoding Individual { get { return Permutation as AlbaEncoding; } }
+
+    public AlbaTranslocationMove(int index1, int index2, int index3) :
+      base(index1, index2, index3) {
+    }
+
+    public AlbaTranslocationMove(int index1, int index2, int index3, AlbaEncoding individual) :
+      base(index1, index2, index3, individual.Clone() as AlbaEncoding) {
+    }
+
+    [StorableConstructor]
+    protected AlbaTranslocationMove(bool deserializing) : base(deserializing) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaTranslocationMove(this, cloner);
+    }
+
+    protected AlbaTranslocationMove(AlbaTranslocationMove original, Cloner cloner)
+      : base(original, cloner) {
+      this.Index1 = original.Index1;
+      this.Index2 = original.Index2;
+      this.Index3 = original.Index3;
+
+      this.Permutation = cloner.Clone(Permutation) as AlbaEncoding;
+    }
+
+    #region IVRPMove Members
+
+    public VRPMoveEvaluator GetMoveEvaluator() {
+      return new AlbaTranslocationMoveEvaluator();
+    }
+
+    public VRPMoveMaker GetMoveMaker() {
+      return new AlbaTranslocationMoveMaker();
+    }
+
+    public ITabuMaker GetTabuMaker() {
+      return new AlbaTranslocationMoveTabuMaker();
+    }
+
+    public ITabuChecker GetTabuChecker() {
+      return new AlbaTranslocationMoveHardTabuCriterion();
+    }
+
+    public ITabuChecker GetSoftTabuChecker() {
+      return new AlbaTranslocationMoveSoftTabuCriterion();
+    }
+
+    #endregion
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaTranslocationMoveEvaluator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaTranslocationMoveEvaluator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaTranslocationMoveEvaluator.cs	(revision 14416)
@@ -0,0 +1,67 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Encodings.PermutationEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Alba;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  [Item("AlbaTranslocationMoveEvaluator", "Evaluates a translocation or insertion move (3-opt) for a VRP representation.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public sealed class AlbaTranslocationMoveEvaluator : AlbaMoveEvaluator, IAlbaTranslocationMoveOperator {
+    public ILookupParameter<TranslocationMove> TranslocationMoveParameter {
+      get { return (ILookupParameter<TranslocationMove>)Parameters["TranslocationMove"]; }
+      set { Parameters["TranslocationMove"].ActualValue = value.ActualValue; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return TranslocationMoveParameter; }
+    }
+
+    [StorableConstructor]
+    private AlbaTranslocationMoveEvaluator(bool deserializing) : base(deserializing) { }
+
+    public AlbaTranslocationMoveEvaluator()
+      : base() {
+      Parameters.Add(new LookupParameter<TranslocationMove>("TranslocationMove", "The move to evaluate."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaTranslocationMoveEvaluator(this, cloner);
+    }
+
+    private AlbaTranslocationMoveEvaluator(AlbaTranslocationMoveEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void EvaluateMove() {
+      TranslocationMove move = TranslocationMoveParameter.ActualValue;
+      //perform move
+      AlbaEncoding newSolution = move.Permutation.Clone() as AlbaEncoding;
+      TranslocationManipulator.Apply(newSolution, move.Index1, move.Index2, move.Index3);
+
+      UpdateEvaluation(newSolution);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaTranslocationMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaTranslocationMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaTranslocationMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,107 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Encodings.PermutationEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaTranslocationMoveGenerator", "An operator which generates translocation moves for a VRP representation.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public sealed class AlbaTranslocationMoveGenerator : AlbaMoveGenerator, IAlbaTranslocationMoveOperator, IMultiMoveGenerator {
+    public IValueLookupParameter<TranslocationMoveGenerator> TranslocationMoveGeneratorParameter {
+      get { return (IValueLookupParameter<TranslocationMoveGenerator>)Parameters["TranslocationMoveGenerator"]; }
+    }
+
+    private IPermutationMoveOperator PermutationMoveOperatorParameter {
+      get { return TranslocationMoveGeneratorParameter.Value; }
+      set {
+        TranslocationMoveGeneratorParameter.Value = value as TranslocationMoveGenerator;
+        if (TranslocationMoveGeneratorParameter.Value is IMultiMoveGenerator) {
+          ((IMultiMoveGenerator)TranslocationMoveGeneratorParameter.Value).SampleSizeParameter.ActualName = SampleSizeParameter.Name;
+        }
+      }
+    }
+
+    public ILookupParameter<TranslocationMove> TranslocationMoveParameter {
+      get {
+        if (TranslocationMoveGeneratorParameter.Value != null)
+          return TranslocationMoveGeneratorParameter.Value.TranslocationMoveParameter;
+        else
+          return null;
+      }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return TranslocationMoveParameter; }
+    }
+
+    public ILookupParameter<Permutation> PermutationParameter {
+      get {
+        if (TranslocationMoveGeneratorParameter.Value != null)
+          return TranslocationMoveGeneratorParameter.Value.PermutationParameter;
+        else
+          return null;
+      }
+    }
+
+    public IValueLookupParameter<IntValue> SampleSizeParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["SampleSize"]; }
+    }
+
+    [StorableConstructor]
+    private AlbaTranslocationMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public AlbaTranslocationMoveGenerator()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<TranslocationMoveGenerator>("TranslocationMoveGenerator", "The move generator.",
+        new StochasticTranslocationMultiMoveGenerator()));
+      Parameters.Add(new ValueLookupParameter<IntValue>("SampleSize", "The number of moves to generate."));
+
+      ((IMultiMoveGenerator)TranslocationMoveGeneratorParameter.Value).SampleSizeParameter.ActualName = SampleSizeParameter.Name;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaTranslocationMoveGenerator(this, cloner);
+    }
+
+    private AlbaTranslocationMoveGenerator(AlbaTranslocationMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IOperation InstrumentedApply() {
+      IOperation next = base.InstrumentedApply();
+
+      IVRPEncoding solution = VRPToursParameter.ActualValue;
+
+      PermutationMoveOperatorParameter.PermutationParameter.ActualName = VRPToursParameter.ActualName;
+      IAtomicOperation op = this.ExecutionContext.CreateChildOperation(PermutationMoveOperatorParameter);
+      op.Operator.Execute((IExecutionContext)op, CancellationToken);
+
+      return next;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaTranslocationMoveHardTabuCriterion.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaTranslocationMoveHardTabuCriterion.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaTranslocationMoveHardTabuCriterion.cs	(revision 14416)
@@ -0,0 +1,95 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Encodings.PermutationEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaTranslocationMoveHardTabuCriterion", "An operator which checks if translocation moves are tabu using a hard criterion for a VRP representation.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public sealed class AlbaTranslocationMoveHardTabuCriterion : VRPMoveOperator, IAlbaTranslocationMoveOperator, ITabuChecker, IAlbaOperator {
+    [Storable]
+    private TranslocationMoveHardTabuCriterion tabuChecker;
+    private IPermutationMoveOperator PermutationMoveOperatorParameter {
+      get { return tabuChecker; }
+      set { tabuChecker = value as TranslocationMoveHardTabuCriterion; }
+    }
+
+    public ILookupParameter<TranslocationMove> TranslocationMoveParameter {
+      get { return tabuChecker.TranslocationMoveParameter; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return TranslocationMoveParameter; }
+    }
+
+    public ILookupParameter<Permutation> PermutationParameter {
+      get { return tabuChecker.PermutationParameter; }
+    }
+
+    public ILookupParameter<BoolValue> MoveTabuParameter {
+      get { return tabuChecker.MoveTabuParameter; }
+    }
+
+    public ILookupParameter<DoubleValue> MoveQualityParameter {
+      get { return tabuChecker.MoveQualityParameter; }
+    }
+
+    public IValueLookupParameter<BoolValue> MaximizationParameter {
+      get { return tabuChecker.MaximizationParameter; }
+    }
+
+    [StorableConstructor]
+    private AlbaTranslocationMoveHardTabuCriterion(bool deserializing) : base(deserializing) { }
+
+    public AlbaTranslocationMoveHardTabuCriterion()
+      : base() {
+      tabuChecker = new TranslocationMoveHardTabuCriterion();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaTranslocationMoveHardTabuCriterion(this, cloner);
+    }
+
+    private AlbaTranslocationMoveHardTabuCriterion(AlbaTranslocationMoveHardTabuCriterion original, Cloner cloner)
+      : base(original, cloner) {
+      tabuChecker = cloner.Clone(original.tabuChecker);
+    }
+
+    public override IOperation InstrumentedApply() {
+      IOperation next = base.InstrumentedApply();
+
+      IVRPEncoding solution = VRPToursParameter.ActualValue;
+
+      PermutationMoveOperatorParameter.PermutationParameter.ActualName = VRPToursParameter.ActualName;
+      IAtomicOperation op = this.ExecutionContext.CreateChildOperation(PermutationMoveOperatorParameter);
+      op.Operator.Execute((IExecutionContext)op, CancellationToken);
+
+      return next;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaTranslocationMoveMaker.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaTranslocationMoveMaker.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaTranslocationMoveMaker.cs	(revision 14416)
@@ -0,0 +1,74 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Encodings.PermutationEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaTranslocationMoveMaker", "An operator which makes translocation moves for a VRP representation.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public sealed class AlbaTranslocationMoveMaker : AlbaMoveMaker, IAlbaTranslocationMoveOperator {
+    [Storable]
+    private TranslocationMoveMaker moveMaker;
+
+    public ILookupParameter<TranslocationMove> TranslocationMoveParameter {
+      get { return moveMaker.TranslocationMoveParameter; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return TranslocationMoveParameter; }
+    }
+
+    public ILookupParameter<Permutation> PermutationParameter {
+      get { return moveMaker.PermutationParameter; }
+    }
+
+    [StorableConstructor]
+    private AlbaTranslocationMoveMaker(bool deserializing) : base(deserializing) { }
+
+    public AlbaTranslocationMoveMaker()
+      : base() {
+      moveMaker = new TranslocationMoveMaker();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaTranslocationMoveMaker(this, cloner);
+    }
+
+    private AlbaTranslocationMoveMaker(AlbaTranslocationMoveMaker original, Cloner cloner)
+      : base(original, cloner) {
+      moveMaker = cloner.Clone(original.moveMaker);
+    }
+
+    protected override void PerformMove() {
+      IVariable moveVariable = this.ExecutionContext.Scope.Variables[
+        TranslocationMoveParameter.ActualName];
+      TranslocationMove move = moveVariable.Value as TranslocationMove;
+      VRPToursParameter.ActualValue = move.Permutation as AlbaEncoding;
+
+      moveMaker.PermutationParameter.ActualName = VRPToursParameter.ActualName;
+      IAtomicOperation op = this.ExecutionContext.CreateChildOperation(moveMaker);
+      op.Operator.Execute((IExecutionContext)op, CancellationToken);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaTranslocationMoveSoftTabuCriterion.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaTranslocationMoveSoftTabuCriterion.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaTranslocationMoveSoftTabuCriterion.cs	(revision 14416)
@@ -0,0 +1,95 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Encodings.PermutationEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaTranslocationMoveSoftTabuCriterion", "An operator which checks if translocation moves are tabu using a soft criterion for a VRP representation.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public sealed class AlbaTranslocationMoveSoftTabuCriterion : VRPMoveOperator, IAlbaTranslocationMoveOperator, ITabuChecker, IAlbaOperator {
+    [Storable]
+    private TranslocationMoveSoftTabuCriterion tabuChecker;
+    private IPermutationMoveOperator PermutationMoveOperatorParameter {
+      get { return tabuChecker; }
+      set { tabuChecker = value as TranslocationMoveSoftTabuCriterion; }
+    }
+
+    public ILookupParameter<TranslocationMove> TranslocationMoveParameter {
+      get { return tabuChecker.TranslocationMoveParameter; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return TranslocationMoveParameter; }
+    }
+
+    public ILookupParameter<Permutation> PermutationParameter {
+      get { return tabuChecker.PermutationParameter; }
+    }
+
+    public ILookupParameter<BoolValue> MoveTabuParameter {
+      get { return tabuChecker.MoveTabuParameter; }
+    }
+
+    public ILookupParameter<DoubleValue> MoveQualityParameter {
+      get { return tabuChecker.MoveQualityParameter; }
+    }
+
+    public IValueLookupParameter<BoolValue> MaximizationParameter {
+      get { return tabuChecker.MaximizationParameter; }
+    }
+
+    [StorableConstructor]
+    private AlbaTranslocationMoveSoftTabuCriterion(bool deserializing) : base(deserializing) { }
+
+    public AlbaTranslocationMoveSoftTabuCriterion()
+      : base() {
+      tabuChecker = new TranslocationMoveSoftTabuCriterion();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaTranslocationMoveSoftTabuCriterion(this, cloner);
+    }
+
+    private AlbaTranslocationMoveSoftTabuCriterion(AlbaTranslocationMoveSoftTabuCriterion original, Cloner cloner)
+      : base(original, cloner) {
+      tabuChecker = cloner.Clone(original.tabuChecker);
+    }
+
+    public override IOperation InstrumentedApply() {
+      IOperation next = base.InstrumentedApply();
+
+      IVRPEncoding solution = VRPToursParameter.ActualValue;
+
+      PermutationMoveOperatorParameter.PermutationParameter.ActualName = VRPToursParameter.ActualName;
+      IAtomicOperation op = this.ExecutionContext.CreateChildOperation(PermutationMoveOperatorParameter);
+      op.Operator.Execute((IExecutionContext)op, CancellationToken);
+
+      return next;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaTranslocationMoveTabuMaker.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaTranslocationMoveTabuMaker.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/AlbaTranslocationMoveTabuMaker.cs	(revision 14416)
@@ -0,0 +1,95 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Encodings.PermutationEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  [Item("AlbaTranslocationMoveTabuMaker", "An operator which makes translocation moves tabu for a VRP representation.  It is implemented as described in Alba, E. and Dorronsoro, B. (2004). Solving the Vehicle Routing Problem by Using Cellular Genetic Algorithms.")]
+  [StorableClass]
+  public sealed class AlbaTranslocationMoveTabuMaker : VRPMoveOperator, IAlbaTranslocationMoveOperator, ITabuMaker, IAlbaOperator {
+    [Storable]
+    private TranslocationMoveTabuMaker moveTabuMaker;
+    private IPermutationMoveOperator PermutationMoveOperatorParameter {
+      get { return moveTabuMaker; }
+      set { moveTabuMaker = value as TranslocationMoveTabuMaker; }
+    }
+
+    public ILookupParameter<Permutation> PermutationParameter {
+      get { return moveTabuMaker.PermutationParameter; }
+    }
+
+    public ILookupParameter<TranslocationMove> TranslocationMoveParameter {
+      get { return moveTabuMaker.TranslocationMoveParameter; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return TranslocationMoveParameter; }
+    }
+
+    public ILookupParameter<DoubleValue> MoveQualityParameter {
+      get { return moveTabuMaker.MoveQualityParameter; }
+    }
+
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return moveTabuMaker.QualityParameter; }
+    }
+
+    public IValueLookupParameter<BoolValue> MaximizationParameter {
+      get { return moveTabuMaker.MaximizationParameter; }
+    }
+
+    [StorableConstructor]
+    private AlbaTranslocationMoveTabuMaker(bool deserializing) : base(deserializing) { }
+
+    public AlbaTranslocationMoveTabuMaker()
+      : base() {
+      moveTabuMaker = new TranslocationMoveTabuMaker();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlbaTranslocationMoveTabuMaker(this, cloner);
+    }
+
+    private AlbaTranslocationMoveTabuMaker(AlbaTranslocationMoveTabuMaker original, Cloner cloner)
+      : base(original, cloner) {
+      moveTabuMaker = cloner.Clone(original.moveTabuMaker);
+    }
+
+    public override IOperation InstrumentedApply() {
+      IOperation next = base.InstrumentedApply();
+
+      IVRPEncoding solution = VRPToursParameter.ActualValue;
+
+      PermutationMoveOperatorParameter.PermutationParameter.ActualName = VRPToursParameter.ActualName;
+      IAtomicOperation op = this.ExecutionContext.CreateChildOperation(PermutationMoveOperatorParameter);
+      op.Operator.Execute((IExecutionContext)op, CancellationToken);
+
+      return next;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/IAlbaTranslocationMoveOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/IAlbaTranslocationMoveOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Moves/ThreeOpt/IAlbaTranslocationMoveOperator.cs	(revision 14416)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
+  public interface IAlbaTranslocationMoveOperator : IVRPMoveOperator {
+    ILookupParameter<TranslocationMove> TranslocationMoveParameter { get; }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/Crossovers/GVRCrossover.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/Crossovers/GVRCrossover.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/Crossovers/GVRCrossover.cs	(revision 14416)
@@ -0,0 +1,122 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.GVR {
+  [Item("GVRCrossover", "The GVR crossover operation. It is implemented as described in Pereira, F.B. et al (2002). GVR: a New Genetic Representation for the Vehicle Routing Problem. AICS 2002, LNAI 2464, pp. 95-102.")]
+  [StorableClass]
+  public sealed class GVRCrossover : VRPCrossover, IStochasticOperator, IGVROperator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    [StorableConstructor]
+    private GVRCrossover(bool deserializing) : base(deserializing) { }
+
+    public GVRCrossover() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator which should be used for stochastic manipulation operators."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GVRCrossover(this, cloner);
+    }
+
+    private GVRCrossover(GVRCrossover original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    private GVREncoding Crossover(IRandom random, GVREncoding parent1, GVREncoding parent2) {
+      GVREncoding child = parent1.Clone() as GVREncoding;
+
+      Tour tour = parent2.Tours[random.Next(parent2.Tours.Count)];
+      int breakPoint1 = random.Next(tour.Stops.Count);
+      int length = random.Next(1, tour.Stops.Count - breakPoint1 + 1);
+      List<int> subroute = tour.Stops.GetRange(breakPoint1, length);
+
+      //remove duplicates
+      List<Tour> toBeRemoved = new List<Tour>();
+
+      foreach (Tour route in child.Tours) {
+        foreach (int city in subroute) {
+          route.Stops.Remove(city);
+        }
+
+        if (route.Stops.Count == 0)
+          toBeRemoved.Add(route);
+      }
+      foreach (Tour route in toBeRemoved) {
+        child.Tours.Remove(route);
+      }
+
+      //choose nearest customer
+      double minDistance = -1;
+      int customer = -1;
+      for (int i = 1; i <= ProblemInstance.Cities.Value; i++) {
+        if (!subroute.Contains(i)) {
+          double distance = ProblemInstance.GetDistance(subroute[0], i, child);
+
+          if (customer == -1 || distance < minDistance) {
+            customer = i;
+            minDistance = distance;
+          }
+        }
+      }
+
+      //insert
+      if (customer != -1) {
+        Tour newTour;
+        int newPosition;
+        child.FindCustomer(customer, out newTour, out newPosition);
+        newTour.Stops.InsertRange(newPosition + 1, subroute);
+      } else {
+        //special case -> only one tour, whole tour has been chosen as subroute
+        child = parent1.Clone() as GVREncoding;
+      }
+
+      return child;
+    }
+
+    public override IOperation InstrumentedApply() {
+      ItemArray<IVRPEncoding> parents = new ItemArray<IVRPEncoding>(ParentsParameter.ActualValue.Length);
+      for (int i = 0; i < ParentsParameter.ActualValue.Length; i++) {
+        IVRPEncoding solution = ParentsParameter.ActualValue[i];
+        if (!(solution is GVREncoding)) {
+          parents[i] = GVREncoding.ConvertFrom(solution, ProblemInstance);
+        } else {
+          parents[i] = solution;
+        }
+      }
+      ParentsParameter.ActualValue = parents;
+
+      ChildParameter.ActualValue = Crossover(RandomParameter.ActualValue, parents[0] as GVREncoding, parents[1] as GVREncoding);
+
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/GVREncoding.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/GVREncoding.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/GVREncoding.cs	(revision 14416)
@@ -0,0 +1,131 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.GVR {
+  [Item("GVREncoding", "Represents a potvin encoding of VRP solutions. It is implemented as described in Pereira, F.B. et al (2002). GVR: a New Genetic Representation for the Vehicle Routing Problem. AICS 2002, LNAI 2464, pp. 95-102.")]
+  [StorableClass]
+  public class GVREncoding : TourEncoding {
+    public override List<Tour> GetTours() {
+      List<Tour> tours = new List<Tour>();
+
+      foreach (Tour tour in base.Tours) {
+        Tour newTour = new Tour();
+        double currentDemand = 0;
+
+        DoubleValue capacity = new DoubleValue(double.MaxValue);
+        if (ProblemInstance is IHomogenousCapacitatedProblemInstance) {
+          capacity.Value = (ProblemInstance as IHomogenousCapacitatedProblemInstance).Capacity.Value;
+        }
+
+
+        foreach (int city in tour.Stops) {
+          currentDemand += ProblemInstance.GetDemand(city);
+
+          if (currentDemand > capacity.Value) {
+            if (newTour.Stops.Count > 0)
+              tours.Add(newTour);
+
+            newTour = new Tour();
+            newTour.Stops.Add(city);
+            currentDemand = ProblemInstance.GetDemand(city);
+          } else {
+            newTour.Stops.Add(city);
+          }
+        }
+
+        if (newTour.Stops.Count > 0)
+          tours.Add(newTour);
+      }
+
+      //repair if there are too many vehicles used
+      while (tours.Count > ProblemInstance.Vehicles.Value) {
+        Tour tour = tours[tours.Count - 1];
+        tours[tours.Count - 2].Stops.AddRange(tour.Stops);
+
+        tours.Remove(tour);
+      }
+
+      return tours;
+    }
+
+    public GVREncoding(IVRPProblemInstance problemInstance)
+      : base(problemInstance) {
+    }
+
+    [StorableConstructor]
+    protected GVREncoding(bool serializing)
+      : base(serializing) {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GVREncoding(this, cloner);
+    }
+
+    protected GVREncoding(GVREncoding original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static GVREncoding ConvertFrom(IVRPEncoding encoding, IVRPProblemInstance problemInstance) {
+      GVREncoding solution = new GVREncoding(problemInstance);
+
+      TourEncoding.ConvertFrom(encoding, solution, problemInstance);
+
+      return solution;
+    }
+
+    public static GVREncoding ConvertFrom(List<int> route, IVRPProblemInstance problemInstance) {
+      GVREncoding solution = new GVREncoding(problemInstance);
+
+      TourEncoding.ConvertFrom(route, solution);
+
+      return solution;
+    }
+
+    internal void FindCustomer(int customer, out Tour tour, out int index) {
+      tour = null;
+      index = -1;
+
+      int currentTour = 0;
+      while (tour == null && currentTour < Tours.Count) {
+        int currentCity = 0;
+        while (tour == null && currentCity < Tours[currentTour].Stops.Count) {
+          if (Tours[currentTour].Stops[currentCity] == customer) {
+            tour = Tours[currentTour];
+            index = currentCity;
+          }
+
+          currentCity++;
+        }
+
+        currentTour++;
+      }
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/IGVROperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/IGVROperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/IGVROperator.cs	(revision 14416)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.GVR {
+  public interface IGVROperator :
+    ISingleDepotOperator, IHomogenousCapacitatedOperator, ITimeWindowedOperator {
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/Manipulators/GVRDisplacementManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/Manipulators/GVRDisplacementManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/Manipulators/GVRDisplacementManipulator.cs	(revision 14416)
@@ -0,0 +1,72 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.GVR {
+  [Item("GVRDisplacementManipulator", "An operator which manipulates a GVR representation by applying a displacement operation. It is implemented as described in Pereira, F.B. et al (2002). GVR: a New Genetic Representation for the Vehicle Routing Problem. AICS 2002, LNAI 2464, pp. 95-102.")]
+  [StorableClass]
+  public sealed class GVRDisplacementManipulator : GVRManipulator {
+    [StorableConstructor]
+    private GVRDisplacementManipulator(bool deserializing) : base(deserializing) { }
+
+    public GVRDisplacementManipulator()
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GVRDisplacementManipulator(this, cloner);
+    }
+
+    private GVRDisplacementManipulator(GVRDisplacementManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void Manipulate(IRandom random, GVREncoding individual) {
+      Tour tour = individual.Tours[random.Next(individual.Tours.Count)];
+      int breakPoint1 = random.Next(tour.Stops.Count);
+      int length = random.Next(1, tour.Stops.Count - breakPoint1 + 1);
+
+      List<int> displaced = tour.Stops.GetRange(breakPoint1, length);
+      tour.Stops.RemoveRange(breakPoint1, length);
+      //with a probability of 1/(2*V) create a new tour, else insert at another position
+      if (individual.GetTours().Count > 0 &&
+        individual.GetTours().Count < ProblemInstance.Vehicles.Value &&
+        random.Next(individual.GetTours().Count * 2) == 0) {
+        Tour newTour = new Tour();
+        newTour.Stops.InsertRange(0, displaced);
+
+        individual.Tours.Add(newTour);
+      } else {
+        Tour newTour = individual.Tours[random.Next(individual.Tours.Count)];
+        int newPosition = newTour.Stops.Count;
+
+        newTour.Stops.InsertRange(newPosition, displaced);
+      }
+
+      if (tour.Stops.Count == 0)
+        individual.Tours.Remove(tour);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/Manipulators/GVRInsertionManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/Manipulators/GVRInsertionManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/Manipulators/GVRInsertionManipulator.cs	(revision 14416)
@@ -0,0 +1,72 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.GVR {
+  [Item("GVRInsertionManipulator", "An operator which manipulates a GVR representation by inserting a customer at another location. It is implemented as described in Pereira, F.B. et al (2002). GVR: a New Genetic Representation for the Vehicle Routing Problem. AICS 2002, LNAI 2464, pp. 95-102.")]
+  [StorableClass]
+  public sealed class GVRInsertionManipulator : GVRManipulator {
+    [StorableConstructor]
+    private GVRInsertionManipulator(bool deserializing) : base(deserializing) { }
+
+    public GVRInsertionManipulator()
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GVRInsertionManipulator(this, cloner);
+    }
+
+    private GVRInsertionManipulator(GVRInsertionManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void Manipulate(IRandom random, GVREncoding individual) {
+      int customer = random.Next(1, individual.Cities + 1);
+      Tour tour;
+      int position;
+      individual.FindCustomer(customer, out tour, out position);
+
+      tour.Stops.RemoveAt(position);
+
+      //with a probability of 1/(2*V) create a new tour, else insert at another position
+      if (individual.GetTours().Count > 0 &&
+        individual.GetTours().Count < ProblemInstance.Vehicles.Value &&
+        random.Next(individual.GetTours().Count * 2) == 0) {
+        Tour newTour = new Tour();
+        newTour.Stops.Add(customer);
+
+        individual.Tours.Add(newTour);
+      } else {
+        Tour newTour = individual.Tours[random.Next(individual.Tours.Count)];
+        int newPosition = random.Next(newTour.Stops.Count + 1);
+
+        newTour.Stops.Insert(newPosition, customer);
+      }
+
+      if (tour.Stops.Count == 0)
+        individual.Tours.Remove(tour);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/Manipulators/GVRInversionManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/Manipulators/GVRInversionManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/Manipulators/GVRInversionManipulator.cs	(revision 14416)
@@ -0,0 +1,53 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.GVR {
+  [Item("GVRInversionManipulator", "An operator which manipulates a GVR representation by inverting a subroute. It is implemented as described in Pereira, F.B. et al (2002). GVR: a New Genetic Representation for the Vehicle Routing Problem. AICS 2002, LNAI 2464, pp. 95-102.")]
+  [StorableClass]
+  public sealed class GVRInversionManipulator : GVRManipulator {
+    [StorableConstructor]
+    private GVRInversionManipulator(bool deserializing) : base(deserializing) { }
+
+    public GVRInversionManipulator()
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GVRInversionManipulator(this, cloner);
+    }
+
+    private GVRInversionManipulator(GVRInversionManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void Manipulate(IRandom random, GVREncoding individual) {
+      Tour tour = individual.Tours[random.Next(individual.Tours.Count)];
+      int breakPoint1 = random.Next(tour.Stops.Count);
+      int length = random.Next(1, tour.Stops.Count - breakPoint1 + 1);
+
+      tour.Stops.Reverse(breakPoint1, length);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/Manipulators/GVRManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/Manipulators/GVRManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/Manipulators/GVRManipulator.cs	(revision 14416)
@@ -0,0 +1,62 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.GVR {
+  [Item("GVRManipulator", "A VRP manipulation operation.")]
+  [StorableClass]
+  public abstract class GVRManipulator : VRPManipulator, IStochasticOperator, IGVROperator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    [StorableConstructor]
+    protected GVRManipulator(bool deserializing) : base(deserializing) { }
+
+    public GVRManipulator() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator which should be used for stochastic manipulation operators."));
+    }
+
+    protected GVRManipulator(GVRManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected abstract void Manipulate(IRandom random, GVREncoding individual);
+
+    public override IOperation InstrumentedApply() {
+      IVRPEncoding solution = VRPToursParameter.ActualValue;
+      if (!(solution is GVREncoding)) {
+        VRPToursParameter.ActualValue = GVREncoding.ConvertFrom(solution, ProblemInstance);
+      }
+
+      Manipulate(RandomParameter.ActualValue, VRPToursParameter.ActualValue as GVREncoding);
+
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/Manipulators/GVRSwapManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/Manipulators/GVRSwapManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/GVR/Manipulators/GVRSwapManipulator.cs	(revision 14416)
@@ -0,0 +1,62 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.GVR {
+  [Item("GVRSwapManipulator", "An operator which manipulates a GVR representation by swapping two customers. It is implemented as described in Pereira, F.B. et al (2002). GVR: a New Genetic Representation for the Vehicle Routing Problem. AICS 2002, LNAI 2464, pp. 95-102.")]
+  [StorableClass]
+  public sealed class GVRSwapManipulator : GVRManipulator {
+    [StorableConstructor]
+    private GVRSwapManipulator(bool deserializing) : base(deserializing) { }
+
+    public GVRSwapManipulator()
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GVRSwapManipulator(this, cloner);
+    }
+
+    private GVRSwapManipulator(GVRSwapManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void Manipulate(IRandom random, GVREncoding individual) {
+      int customer1 = random.Next(1, individual.Cities + 1);
+      int customer2 = random.Next(1, individual.Cities + 1);
+
+      Tour tour1;
+      int pos1;
+      individual.FindCustomer(customer1, out tour1, out pos1);
+
+      Tour tour2;
+      int pos2;
+      individual.FindCustomer(customer2, out tour2, out pos2);
+
+      int temp = tour1.Stops[pos1];
+      tour1.Stops[pos1] = tour2.Stops[pos2];
+      tour2.Stops[pos2] = temp;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Creators/MultiVRPSolutionCreator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Creators/MultiVRPSolutionCreator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Creators/MultiVRPSolutionCreator.cs	(revision 14416)
@@ -0,0 +1,104 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+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;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.General {
+  [Item("MultiVRPSolutionCreator", "Randomly selects and applies one of its creator every time it is called.")]
+  [StorableClass]
+  public class MultiVRPSolutionCreator : StochasticMultiBranch<IVRPCreator>, IVRPCreator, IGeneralVRPOperator, IMultiVRPOperator, IStochasticOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    protected override bool CreateChildOperation {
+      get { return true; }
+    }
+
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (LookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+
+    public ILookupParameter<IVRPEncoding> VRPToursParameter {
+      get { return (ILookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+
+    [StorableConstructor]
+    protected MultiVRPSolutionCreator(bool deserializing) : base(deserializing) { }
+    public MultiVRPSolutionCreator()
+      : base() {
+      Parameters.Add(new LookupParameter<IVRPEncoding>("VRPTours", "The new VRP tours."));
+
+      Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The VRP problem instance"));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MultiVRPSolutionCreator(this, cloner);
+    }
+
+    protected MultiVRPSolutionCreator(MultiVRPSolutionCreator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void Operators_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<IVRPCreator>> e) {
+      base.Operators_ItemsReplaced(sender, e);
+      ParameterizeCreators();
+    }
+
+    protected override void Operators_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IVRPCreator>> e) {
+      base.Operators_ItemsAdded(sender, e);
+      ParameterizeCreators();
+    }
+
+    public void SetOperators(IEnumerable<IOperator> operators) {
+      foreach (IOperator op in operators) {
+        if (op is IVRPCreator && !(op is MultiVRPSolutionCreator)) {
+          Operators.Add(op.Clone() as IVRPCreator, true);
+        }
+      }
+    }
+
+    private void ParameterizeCreators() {
+      foreach (IVRPCreator creator in Operators.OfType<IVRPCreator>()) {
+        creator.VRPToursParameter.ActualName = VRPToursParameter.Name;
+        creator.ProblemInstanceParameter.ActualName = ProblemInstanceParameter.Name;
+      }
+      foreach (IStochasticOperator creator in Operators.OfType<IStochasticOperator>()) {
+        creator.RandomParameter.ActualName = RandomParameter.Name;
+      }
+    }
+
+    public override IOperation InstrumentedApply() {
+      if (Operators.Count == 0) throw new InvalidOperationException(Name + ": Please add at least one VRP creator to choose from.");
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Creators/VRPCreator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Creators/VRPCreator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Creators/VRPCreator.cs	(revision 14416)
@@ -0,0 +1,48 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.General {
+  [Item("VRPCreator", "Creates a VRP solution.")]
+  [StorableClass]
+  public abstract class VRPCreator : VRPOperator, IVRPCreator {
+    public ILookupParameter<IVRPEncoding> VRPToursParameter {
+      get { return (ILookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+
+    [StorableConstructor]
+    protected VRPCreator(bool deserializing) : base(deserializing) { }
+
+    public VRPCreator()
+      : base() {
+      Parameters.Add(new LookupParameter<IVRPEncoding>("VRPTours", "The VRP tours to be created."));
+    }
+
+    protected VRPCreator(VRPCreator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Crossovers/BiasedMultiVRPSolutionCrossover.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Crossovers/BiasedMultiVRPSolutionCrossover.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Crossovers/BiasedMultiVRPSolutionCrossover.cs	(revision 14416)
@@ -0,0 +1,165 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Linq;
+using HeuristicLab.Analysis;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.General {
+  [Item("BiasedMultiVRPSolutionCrossover", "Randomly selects and applies one of its crossovers every time it is called based on the success progress.")]
+  [StorableClass]
+  public class BiasedMultiVRPSolutionCrossover : MultiVRPSolutionCrossover {
+    public ValueLookupParameter<DoubleArray> ActualProbabilitiesParameter {
+      get { return (ValueLookupParameter<DoubleArray>)Parameters["ActualProbabilities"]; }
+    }
+
+    public ValueLookupParameter<StringValue> SuccessProgressAnalyisis {
+      get { return (ValueLookupParameter<StringValue>)Parameters["SuccessProgressAnalysis"]; }
+    }
+
+    public ValueLookupParameter<DoubleValue> Factor {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["Factor"]; }
+    }
+
+    public ValueParameter<DoubleValue> LowerBoundParameter {
+      get { return (ValueParameter<DoubleValue>)Parameters["LowerBound"]; }
+    }
+
+    public ValueParameter<IntValue> DepthParameter {
+      get { return (ValueParameter<IntValue>)Parameters["Depth"]; }
+    }
+
+    [StorableConstructor]
+    protected BiasedMultiVRPSolutionCrossover(bool deserializing) : base(deserializing) { }
+    protected BiasedMultiVRPSolutionCrossover(BiasedMultiVRPSolutionCrossover original, Cloner cloner) : base(original, cloner) { }
+    public BiasedMultiVRPSolutionCrossover()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<DoubleArray>("ActualProbabilities", "The array of relative probabilities for each operator."));
+      Parameters.Add(new ValueLookupParameter<StringValue>("SuccessProgressAnalysis", "The success progress analyisis to be considered",
+        new StringValue("ExecutedCrossoverOperator")));
+
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("Factor", "The factor with which the probabilities should be updated", new DoubleValue(0.2)));
+      Parameters.Add(new ValueParameter<DoubleValue>("LowerBound", "The depth of the individuals in the scope tree.", new DoubleValue(0.01)));
+      Parameters.Add(new ValueParameter<IntValue>("Depth", "The depth of the individuals in the scope tree.", new IntValue(1)));
+
+      SelectedOperatorParameter.ActualName = "SelectedCrossoverOperator";
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BiasedMultiVRPSolutionCrossover(this, cloner);
+    }
+
+    public override void InitializeState() {
+      base.InitializeState();
+
+      ActualProbabilitiesParameter.Value = null;
+    }
+
+    public override IOperation InstrumentedApply() {
+      IOperator successor = null;
+
+      if (ActualProbabilitiesParameter.ActualValue == null) {
+        ActualProbabilitiesParameter.Value = ProbabilitiesParameter.ActualValue.Clone() as DoubleArray;
+      } else {
+        String key = "SuccessfulOffspringAnalyzer Results";
+
+        ResultCollection results = null;
+        IScope scope = ExecutionContext.Parent.Scope;
+        int depth = 1;
+        while (scope != null && depth < DepthParameter.Value.Value) {
+          scope = scope.Parent;
+          depth++;
+        }
+        if (scope != null)
+          results = scope.Variables["Results"].Value as ResultCollection;
+
+        if (results != null && results.ContainsKey(key)) {
+          ResultCollection successProgressAnalysisResult = results[key].Value as ResultCollection;
+          key = SuccessProgressAnalyisis.Value.Value;
+
+          if (successProgressAnalysisResult.ContainsKey(key)) {
+            DataTable successProgressAnalysis = successProgressAnalysisResult[key].Value as DataTable;
+
+            for (int i = 0; i < Operators.Count; i++) {
+              IOperator current = Operators[i];
+
+              if (successProgressAnalysis.Rows.ContainsKey(current.Name)) {
+                DataRow row = successProgressAnalysis.Rows[current.Name];
+
+                double sum = 0.0;
+                ObservableList<double> usages = row.Values;
+
+                sum += (double)usages.Last();
+
+                ActualProbabilitiesParameter.ActualValue[i] += (sum / ActualProbabilitiesParameter.ActualValue[i]) * Factor.Value.Value;
+              }
+            }
+          }
+        }
+
+        //normalize
+        double max = ActualProbabilitiesParameter.ActualValue.Max();
+        for (int i = 0; i < ActualProbabilitiesParameter.ActualValue.Length; i++) {
+          ActualProbabilitiesParameter.ActualValue[i] /= max;
+          ActualProbabilitiesParameter.ActualValue[i] =
+            Math.Max(LowerBoundParameter.Value.Value,
+            ActualProbabilitiesParameter.ActualValue[i]);
+        }
+      }
+
+      //////////////// code has to be duplicated since ActualProbabilitiesParameter.ActualValue are updated and used for operator selection
+      IRandom random = RandomParameter.ActualValue;
+      DoubleArray probabilities = ActualProbabilitiesParameter.ActualValue;
+      if (probabilities.Length != Operators.Count) {
+        throw new InvalidOperationException(Name + ": The list of probabilities has to match the number of operators");
+      }
+      var checkedOperators = Operators.CheckedItems;
+      if (checkedOperators.Count() > 0) {
+        // select a random operator from the checked operators
+        successor = checkedOperators.SampleProportional(random, 1, checkedOperators.Select(x => probabilities[x.Index]), false, false).First().Value;
+      }
+
+      IOperation successorOp = null;
+      if (Successor != null)
+        successorOp = ExecutionContext.CreateOperation(Successor);
+      OperationCollection next = new OperationCollection(successorOp);
+      if (successor != null) {
+        SelectedOperatorParameter.ActualValue = new StringValue(successor.Name);
+
+        if (CreateChildOperation)
+          next.Insert(0, ExecutionContext.CreateChildOperation(successor));
+        else next.Insert(0, ExecutionContext.CreateOperation(successor));
+      } else {
+        SelectedOperatorParameter.ActualValue = new StringValue("");
+      }
+
+      return next;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Crossovers/MultiVRPSolutionCrossover.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Crossovers/MultiVRPSolutionCrossover.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Crossovers/MultiVRPSolutionCrossover.cs	(revision 14416)
@@ -0,0 +1,115 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+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;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.General {
+  [Item("MultiVRPSolutionCrossover", "Randomly selects and applies one of its crossovers every time it is called.")]
+  [StorableClass]
+  public class MultiVRPSolutionCrossover : StochasticMultiBranch<IVRPCrossover>, IVRPCrossover, IGeneralVRPOperator, IMultiVRPOperator, IStochasticOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    protected override bool CreateChildOperation {
+      get { return true; }
+    }
+
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (LookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+
+    public ILookupParameter<ItemArray<IVRPEncoding>> ParentsParameter {
+      get { return (ScopeTreeLookupParameter<IVRPEncoding>)Parameters["Parents"]; }
+    }
+
+    public ILookupParameter<IVRPEncoding> ChildParameter {
+      get { return (ILookupParameter<IVRPEncoding>)Parameters["Child"]; }
+    }
+
+
+    [StorableConstructor]
+    protected MultiVRPSolutionCrossover(bool deserializing) : base(deserializing) { }
+    public MultiVRPSolutionCrossover()
+      : base() {
+      Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The VRP problem instance"));
+
+      Parameters.Add(new ScopeTreeLookupParameter<IVRPEncoding>("Parents", "The parent permutations which should be crossed."));
+      ParentsParameter.ActualName = "VRPTours";
+      Parameters.Add(new LookupParameter<IVRPEncoding>("Child", "The child permutation resulting from the crossover."));
+      ChildParameter.ActualName = "VRPTours";
+
+      SelectedOperatorParameter.ActualName = "SelectedCrossoverOperator";
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MultiVRPSolutionCrossover(this, cloner);
+    }
+
+    protected MultiVRPSolutionCrossover(MultiVRPSolutionCrossover original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void Operators_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<IVRPCrossover>> e) {
+      base.Operators_ItemsReplaced(sender, e);
+      ParameterizeCrossovers();
+    }
+
+    protected override void Operators_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IVRPCrossover>> e) {
+      base.Operators_ItemsAdded(sender, e);
+      ParameterizeCrossovers();
+    }
+
+    public void SetOperators(IEnumerable<IOperator> operators) {
+      foreach (IOperator op in operators) {
+        if (op is IVRPCrossover && !(op is MultiVRPSolutionCrossover)) {
+          Operators.Add(op.Clone() as IVRPCrossover, true);
+        }
+      }
+    }
+
+    private void ParameterizeCrossovers() {
+      foreach (IVRPCrossover crossover in Operators.OfType<IVRPCrossover>()) {
+        crossover.ChildParameter.ActualName = ChildParameter.Name;
+        crossover.ParentsParameter.ActualName = ParentsParameter.Name;
+        crossover.ProblemInstanceParameter.ActualName = ProblemInstanceParameter.Name;
+      }
+      foreach (IStochasticOperator crossover in Operators.OfType<IStochasticOperator>()) {
+        crossover.RandomParameter.ActualName = RandomParameter.Name;
+      }
+    }
+
+    public override IOperation InstrumentedApply() {
+      if (Operators.Count == 0) throw new InvalidOperationException(Name + ": Please add at least one permutation crossover to choose from.");
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Crossovers/RandomParentCloneCrossover.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Crossovers/RandomParentCloneCrossover.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Crossovers/RandomParentCloneCrossover.cs	(revision 14416)
@@ -0,0 +1,76 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.General.Crossovers {
+  [Item("RandomParentCloneCrossover", "An operator which randomly chooses one parent and returns a clone.")]
+  [StorableClass]
+  public sealed class RandomParentCloneCrossover : VRPOperator, IStochasticOperator, IGeneralVRPOperator, IVRPCrossover {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public ILookupParameter<ItemArray<IVRPEncoding>> ParentsParameter {
+      get { return (ScopeTreeLookupParameter<IVRPEncoding>)Parameters["Parents"]; }
+    }
+
+    public ILookupParameter<IVRPEncoding> ChildParameter {
+      get { return (ILookupParameter<IVRPEncoding>)Parameters["Child"]; }
+    }
+
+    [StorableConstructor]
+    private RandomParentCloneCrossover(bool deserializing) : base(deserializing) { }
+
+    public RandomParentCloneCrossover()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator which should be used for stochastic manipulation operators."));
+
+      Parameters.Add(new ScopeTreeLookupParameter<IVRPEncoding>("Parents", "The parent permutations which should be crossed."));
+      ParentsParameter.ActualName = "VRPTours";
+      Parameters.Add(new LookupParameter<IVRPEncoding>("Child", "The child permutation resulting from the crossover."));
+      ChildParameter.ActualName = "VRPTours";
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RandomParentCloneCrossover(this, cloner);
+    }
+
+    private RandomParentCloneCrossover(RandomParentCloneCrossover original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IOperation InstrumentedApply() {
+      if (RandomParameter.ActualValue.Next() < 0.5)
+        ChildParameter.ActualValue = ParentsParameter.ActualValue[0].Clone() as IVRPEncoding;
+      else
+        ChildParameter.ActualValue = ParentsParameter.ActualValue[1].Clone() as IVRPEncoding;
+
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Crossovers/VRPCrossover.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Crossovers/VRPCrossover.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Crossovers/VRPCrossover.cs	(revision 14416)
@@ -0,0 +1,55 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.General {
+  [Item("VRPCrossover", "Crosses VRP solutions.")]
+  [StorableClass]
+  public abstract class VRPCrossover : VRPOperator, IVRPCrossover {
+    public ILookupParameter<ItemArray<IVRPEncoding>> ParentsParameter {
+      get { return (ScopeTreeLookupParameter<IVRPEncoding>)Parameters["Parents"]; }
+    }
+
+    public ILookupParameter<IVRPEncoding> ChildParameter {
+      get { return (ILookupParameter<IVRPEncoding>)Parameters["Child"]; }
+    }
+
+    [StorableConstructor]
+    protected VRPCrossover(bool deserializing) : base(deserializing) { }
+
+    public VRPCrossover()
+      : base() {
+      Parameters.Add(new ScopeTreeLookupParameter<IVRPEncoding>("Parents", "The parent permutations which should be crossed."));
+      ParentsParameter.ActualName = "VRPTours";
+      Parameters.Add(new LookupParameter<IVRPEncoding>("Child", "The child permutation resulting from the crossover."));
+      ChildParameter.ActualName = "VRPTours";
+    }
+
+    protected VRPCrossover(VRPCrossover original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Manipulators/BiasedMultiVRPSolutionManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Manipulators/BiasedMultiVRPSolutionManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Manipulators/BiasedMultiVRPSolutionManipulator.cs	(revision 14416)
@@ -0,0 +1,166 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Linq;
+using HeuristicLab.Analysis;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.General {
+  [Item("BiasedMultiVRPSolutionManipulator", "Randomly selects and applies one of its crossovers every time it is called based on the success progress.")]
+  [StorableClass]
+  public class BiasedMultiVRPSolutionManipulator : MultiVRPSolutionManipulator {
+    public ValueLookupParameter<DoubleArray> ActualProbabilitiesParameter {
+      get { return (ValueLookupParameter<DoubleArray>)Parameters["ActualProbabilities"]; }
+    }
+
+    public ValueLookupParameter<StringValue> SuccessProgressAnalyisis {
+      get { return (ValueLookupParameter<StringValue>)Parameters["SuccessProgressAnalysis"]; }
+    }
+
+    public ValueLookupParameter<DoubleValue> Factor {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["Factor"]; }
+    }
+
+    public ValueParameter<DoubleValue> LowerBoundParameter {
+      get { return (ValueParameter<DoubleValue>)Parameters["LowerBound"]; }
+    }
+
+    public ValueParameter<IntValue> DepthParameter {
+      get { return (ValueParameter<IntValue>)Parameters["Depth"]; }
+    }
+
+    [StorableConstructor]
+    protected BiasedMultiVRPSolutionManipulator(bool deserializing) : base(deserializing) { }
+    protected BiasedMultiVRPSolutionManipulator(BiasedMultiVRPSolutionManipulator original, Cloner cloner) : base(original, cloner) { }
+    public BiasedMultiVRPSolutionManipulator()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<DoubleArray>("ActualProbabilities", "The array of relative probabilities for each operator."));
+      Parameters.Add(new ValueLookupParameter<StringValue>("SuccessProgressAnalysis", "The success progress analyisis to be considered",
+        new StringValue("ExecutedMutationOperator")));
+
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("Factor", "The factor with which the probabilities should be updated", new DoubleValue(0.2)));
+      Parameters.Add(new ValueParameter<DoubleValue>("LowerBound", "The depth of the individuals in the scope tree.", new DoubleValue(0.01)));
+      Parameters.Add(new ValueParameter<IntValue>("Depth", "The depth of the individuals in the scope tree.", new IntValue(1)));
+
+      SelectedOperatorParameter.ActualName = "SelectedManipulationOperator";
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BiasedMultiVRPSolutionManipulator(this, cloner);
+    }
+
+    public override void InitializeState() {
+      base.InitializeState();
+
+      ActualProbabilitiesParameter.Value = null;
+    }
+
+    public override IOperation InstrumentedApply() {
+      IOperator successor = null;
+
+      if (ActualProbabilitiesParameter.ActualValue == null) {
+        ActualProbabilitiesParameter.Value = ProbabilitiesParameter.ActualValue.Clone() as DoubleArray;
+      } else {
+        String key = "SuccessfulOffspringAnalyzer Results";
+
+        ResultCollection results = null;
+        IScope scope = ExecutionContext.Parent.Scope;
+        int depth = 1;
+        while (scope != null && depth < DepthParameter.Value.Value) {
+          scope = scope.Parent;
+          depth++;
+        }
+        if (scope != null)
+          results = scope.Variables["Results"].Value as ResultCollection;
+
+        if (results != null && results.ContainsKey(key)) {
+          ResultCollection successProgressAnalysisResult = results[key].Value as ResultCollection;
+          key = SuccessProgressAnalyisis.Value.Value;
+
+          if (successProgressAnalysisResult.ContainsKey(key)) {
+            DataTable successProgressAnalysis = successProgressAnalysisResult[key].Value as DataTable;
+
+            for (int i = 0; i < Operators.Count; i++) {
+              IOperator current = Operators[i];
+
+              if (successProgressAnalysis.Rows.ContainsKey(current.Name)) {
+                DataRow row = successProgressAnalysis.Rows[current.Name];
+
+                double sum = 0.0;
+                ObservableList<double> usages = row.Values;
+
+                sum += usages.Last();
+
+                ActualProbabilitiesParameter.ActualValue[i] += (sum / ActualProbabilitiesParameter.ActualValue[i]) * Factor.Value.Value;
+              }
+            }
+          }
+        }
+
+        //normalize
+        double max = ActualProbabilitiesParameter.ActualValue.Max();
+        for (int i = 0; i < ActualProbabilitiesParameter.ActualValue.Length; i++) {
+          ActualProbabilitiesParameter.ActualValue[i] /= max;
+          ActualProbabilitiesParameter.ActualValue[i] =
+            Math.Max(LowerBoundParameter.Value.Value,
+            ActualProbabilitiesParameter.ActualValue[i]);
+        }
+      }
+
+      //////////////// code has to be duplicated since ActualProbabilitiesParameter.ActualValue are updated and used for operator selection
+      IRandom random = RandomParameter.ActualValue;
+      DoubleArray probabilities = ActualProbabilitiesParameter.ActualValue;
+      if (probabilities.Length != Operators.Count) {
+        throw new InvalidOperationException(Name + ": The list of probabilities has to match the number of operators");
+      }
+      var checkedOperators = Operators.CheckedItems;
+      if (checkedOperators.Count() > 0) {
+        // select a random operator from the checked operators
+        successor =
+          checkedOperators.SampleProportional(random, 1, checkedOperators.Select(x => probabilities[x.Index]), false, false).First().Value;
+      }
+
+      IOperation successorOp = null;
+      if (Successor != null)
+        successorOp = ExecutionContext.CreateOperation(Successor);
+      OperationCollection next = new OperationCollection(successorOp);
+      if (successor != null) {
+        SelectedOperatorParameter.ActualValue = new StringValue(successor.Name);
+
+        if (CreateChildOperation)
+          next.Insert(0, ExecutionContext.CreateChildOperation(successor));
+        else next.Insert(0, ExecutionContext.CreateOperation(successor));
+      } else {
+        SelectedOperatorParameter.ActualValue = new StringValue("");
+      }
+
+      return next;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Manipulators/MultiVRPSolutionManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Manipulators/MultiVRPSolutionManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Manipulators/MultiVRPSolutionManipulator.cs	(revision 14416)
@@ -0,0 +1,106 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+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;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.General {
+  [Item("MultiVRPSolutionManipulator", "Randomly selects and applies one of its manipulators every time it is called.")]
+  [StorableClass]
+  public class MultiVRPSolutionManipulator : StochasticMultiBranch<IVRPManipulator>, IVRPManipulator, IGeneralVRPOperator, IMultiVRPOperator, IStochasticOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    protected override bool CreateChildOperation {
+      get { return true; }
+    }
+
+    public ILookupParameter<IVRPEncoding> VRPToursParameter {
+      get { return (ILookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+
+
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (LookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+
+    [StorableConstructor]
+    protected MultiVRPSolutionManipulator(bool deserializing) : base(deserializing) { }
+    public MultiVRPSolutionManipulator()
+      : base() {
+      Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The VRP problem instance"));
+      Parameters.Add(new LookupParameter<IVRPEncoding>("VRPTours", "The VRP tours to be manipulated."));
+
+      SelectedOperatorParameter.ActualName = "SelectedManipulationOperator";
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MultiVRPSolutionManipulator(this, cloner);
+    }
+
+    protected MultiVRPSolutionManipulator(MultiVRPSolutionManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void Operators_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<IVRPManipulator>> e) {
+      base.Operators_ItemsReplaced(sender, e);
+      ParameterizeManipulators();
+    }
+
+    protected override void Operators_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IVRPManipulator>> e) {
+      base.Operators_ItemsAdded(sender, e);
+      ParameterizeManipulators();
+    }
+
+    public void SetOperators(IEnumerable<IOperator> operators) {
+      foreach (IOperator op in operators) {
+        if (op is IVRPManipulator && !(op is MultiVRPSolutionManipulator)) {
+          Operators.Add(op.Clone() as IVRPManipulator, !(op is IVRPLocalSearchManipulator));
+        }
+      }
+    }
+
+    private void ParameterizeManipulators() {
+      foreach (IVRPManipulator manipulator in Operators.OfType<IVRPManipulator>()) {
+        manipulator.VRPToursParameter.ActualName = VRPToursParameter.Name;
+        manipulator.ProblemInstanceParameter.ActualName = ProblemInstanceParameter.Name;
+      }
+      foreach (IStochasticOperator manipulator in Operators.OfType<IStochasticOperator>()) {
+        manipulator.RandomParameter.ActualName = RandomParameter.Name;
+      }
+    }
+
+    public override IOperation InstrumentedApply() {
+      if (Operators.Count == 0) throw new InvalidOperationException(Name + ": Please add at least one permutation manipulator to choose from.");
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Manipulators/VRPManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Manipulators/VRPManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Manipulators/VRPManipulator.cs	(revision 14416)
@@ -0,0 +1,48 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.General {
+  [Item("VRPManipulator", "Manipulates a VRP solution.")]
+  [StorableClass]
+  public abstract class VRPManipulator : VRPOperator, IVRPManipulator {
+    public ILookupParameter<IVRPEncoding> VRPToursParameter {
+      get { return (ILookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+
+    [StorableConstructor]
+    protected VRPManipulator(bool deserializing) : base(deserializing) { }
+
+    public VRPManipulator()
+      : base() {
+      Parameters.Add(new LookupParameter<IVRPEncoding>("VRPTours", "The VRP tours to be manipulated."));
+    }
+
+    protected VRPManipulator(VRPManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/Interfaces/IMultiVRPMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/Interfaces/IMultiVRPMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/Interfaces/IMultiVRPMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,27 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Optimization;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.General {
+  public interface IMultiVRPMoveGenerator : IMultiVRPMoveOperator, ISingleMoveGenerator {
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/Interfaces/IMultiVRPMoveOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/Interfaces/IMultiVRPMoveOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/Interfaces/IMultiVRPMoveOperator.cs	(revision 14416)
@@ -0,0 +1,27 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.General {
+  public interface IMultiVRPMoveOperator : IVRPMoveOperator {
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/Interfaces/IVRPMove.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/Interfaces/IVRPMove.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/Interfaces/IVRPMove.cs	(revision 14416)
@@ -0,0 +1,33 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Optimization;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.General {
+  public interface IVRPMove : IItem {
+    VRPMoveEvaluator GetMoveEvaluator();
+    VRPMoveMaker GetMoveMaker();
+    ITabuMaker GetTabuMaker();
+    ITabuChecker GetTabuChecker();
+    ITabuChecker GetSoftTabuChecker();
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/MultiVRPMoveOperator/MultiVRPMoveEvaluator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/MultiVRPMoveOperator/MultiVRPMoveEvaluator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/MultiVRPMoveOperator/MultiVRPMoveEvaluator.cs	(revision 14416)
@@ -0,0 +1,67 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  [Item("MultiVRPMoveEvaluator", "Evaluates a move for the VRP representation.")]
+  [StorableClass]
+  public sealed class MultiVRPMoveEvaluator : VRPMoveEvaluator, IMultiVRPMoveOperator, IGeneralVRPOperator {
+    public override ILookupParameter VRPMoveParameter {
+      get { return (ILookupParameter)Parameters["VRPMove"]; }
+    }
+
+    [StorableConstructor]
+    private MultiVRPMoveEvaluator(bool deserializing) : base(deserializing) { }
+
+    public MultiVRPMoveEvaluator()
+      : base() {
+      Parameters.Add(new LookupParameter<IVRPMove>("VRPMove", "The generated moves."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MultiVRPMoveEvaluator(this, cloner);
+    }
+
+    private MultiVRPMoveEvaluator(MultiVRPMoveEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void EvaluateMove() { }
+
+    public override IOperation InstrumentedApply() {
+      IVRPMove move = VRPMoveParameter.ActualValue as IVRPMove;
+
+      VRPMoveEvaluator moveEvaluator = move.GetMoveEvaluator();
+      moveEvaluator.VRPMoveParameter.ActualName = VRPMoveParameter.Name;
+
+      OperationCollection next = new OperationCollection(base.InstrumentedApply());
+      next.Insert(0, ExecutionContext.CreateOperation(moveEvaluator));
+
+      return next;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/MultiVRPMoveOperator/MultiVRPMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/MultiVRPMoveOperator/MultiVRPMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/MultiVRPMoveOperator/MultiVRPMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,192 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Collections;
+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.Encodings.Alba;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.General {
+  [Item("MultiVRPMoveGenerator", "Randomly selects and applies its move generators.")]
+  [StorableClass]
+  public class MultiVRPMoveGenerator : CheckedMultiOperator<IMultiVRPMoveGenerator>, IMultiVRPMoveOperator,
+    IStochasticOperator, IMoveGenerator, IGeneralVRPOperator, IMultiVRPOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+
+    public IValueLookupParameter<IntValue> SelectedOperatorsParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["SelectedOperators"]; }
+    }
+
+    public ILookupParameter<IVRPEncoding> VRPToursParameter {
+      get { return (ILookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+
+    public ILookupParameter VRPMoveParameter {
+      get { return (ILookupParameter)Parameters["VRPMove"]; }
+    }
+
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (LookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+
+    public IVRPProblemInstance ProblemInstance {
+      get { return ProblemInstanceParameter.ActualValue; }
+    }
+
+    public ValueLookupParameter<DoubleArray> ProbabilitiesParameter {
+      get { return (ValueLookupParameter<DoubleArray>)Parameters["Probabilities"]; }
+    }
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public DoubleArray Probabilities {
+      get { return ProbabilitiesParameter.Value; }
+      set { ProbabilitiesParameter.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected MultiVRPMoveGenerator(bool deserializing) : base(deserializing) { }
+    public MultiVRPMoveGenerator()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<IntValue>("SelectedOperators", "The number of selected operators.", new IntValue(1)));
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator which should be used for stochastic manipulation operators."));
+      Parameters.Add(new ValueLookupParameter<DoubleArray>("Probabilities", "The array of relative probabilities for each operator.", new DoubleArray()));
+      Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The VRP problem instance"));
+
+      Parameters.Add(new LookupParameter<IVRPEncoding>("VRPTours", "The VRP tours."));
+      Parameters.Add(new LookupParameter<IVRPMove>("VRPMove", "The generated moves."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MultiVRPMoveGenerator(this, cloner);
+    }
+
+    protected MultiVRPMoveGenerator(MultiVRPMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public void SetOperators(IEnumerable<IOperator> operators) {
+      foreach (IOperator op in operators) {
+        if (op is IMultiVRPMoveGenerator && !(op is MultiOperator<IMultiVRPMoveGenerator>)) {
+          Operators.Add(op.Clone() as IMultiVRPMoveGenerator, !(op is IAlbaOperator || op is PotvinVehicleAssignmentMultiMoveGenerator));
+        }
+      }
+    }
+
+    protected override void Operators_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<IMultiVRPMoveGenerator>> e) {
+      base.Operators_ItemsRemoved(sender, e);
+      if (Probabilities != null && Probabilities.Length > Operators.Count) {
+        List<double> probs = new List<double>(Probabilities.Cast<double>());
+        var sorted = e.Items.OrderByDescending(x => x.Index);
+        foreach (IndexedItem<IMultiVRPMoveGenerator> item in sorted)
+          if (probs.Count > item.Index) probs.RemoveAt(item.Index);
+        Probabilities = new DoubleArray(probs.ToArray());
+      }
+    }
+
+    protected override void Operators_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<IMultiVRPMoveGenerator>> e) {
+      base.Operators_ItemsReplaced(sender, e);
+      ParameterizeMoveGenerators();
+    }
+
+    protected override void Operators_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IMultiVRPMoveGenerator>> e) {
+      base.Operators_ItemsAdded(sender, e);
+      ParameterizeMoveGenerators();
+
+      if (Probabilities != null && Probabilities.Length < Operators.Count) {
+        double avg = (Probabilities.Where(x => x > 0).Count() > 0) ? (Probabilities.Where(x => x > 0).Average()) : (1);
+        // add the average of all probabilities in the respective places (the new operators)
+        var added = e.Items.OrderBy(x => x.Index).ToList();
+        int insertCount = 0;
+        DoubleArray probs = new DoubleArray(Operators.Count);
+        for (int i = 0; i < Operators.Count; i++) {
+          if (insertCount < added.Count && i == added[insertCount].Index) {
+            probs[i] = avg;
+            insertCount++;
+          } else if (i - insertCount < Probabilities.Length) {
+            probs[i] = Probabilities[i - insertCount];
+          } else probs[i] = avg;
+        }
+        Probabilities = probs;
+      }
+    }
+
+    private void ParameterizeMoveGenerators() {
+      foreach (IMultiVRPMoveOperator moveGenerator in Operators.OfType<IMultiVRPMoveOperator>()) {
+        moveGenerator.ProblemInstanceParameter.ActualName = ProblemInstanceParameter.Name;
+        moveGenerator.VRPToursParameter.ActualName = VRPToursParameter.Name;
+        moveGenerator.VRPMoveParameter.ActualName = VRPMoveParameter.Name;
+      }
+      foreach (IStochasticOperator moveGenerator in Operators.OfType<IStochasticOperator>()) {
+        moveGenerator.RandomParameter.ActualName = RandomParameter.Name;
+      }
+    }
+
+    public override IOperation InstrumentedApply() {
+      if (Operators.Count == 0) throw new InvalidOperationException(Name + ": Please add at least one VRP move generator choose from.");
+      OperationCollection next = new OperationCollection(base.InstrumentedApply());
+
+      for (int i = 0; i < SelectedOperatorsParameter.ActualValue.Value; i++) {
+        IRandom random = RandomParameter.ActualValue;
+        DoubleArray probabilities = ProbabilitiesParameter.ActualValue;
+        if (probabilities.Length != Operators.Count) {
+          throw new InvalidOperationException(Name + ": The list of probabilities has to match the number of operators");
+        }
+        IOperator successor = null;
+        var checkedOperators = Operators.CheckedItems;
+        if (checkedOperators.Count() > 0) {
+          // select a random operator from the checked operators
+          double sum = (from indexedItem in checkedOperators select probabilities[indexedItem.Index]).Sum();
+          if (sum == 0) throw new InvalidOperationException(Name + ": All selected operators have zero probability.");
+          double r = random.NextDouble() * sum;
+          sum = 0;
+          foreach (var indexedItem in checkedOperators) {
+            sum += probabilities[indexedItem.Index];
+            if (sum > r) {
+              successor = indexedItem.Value;
+              break;
+            }
+          }
+        }
+
+        if (successor != null) {
+          next.Insert(0, ExecutionContext.CreateChildOperation(successor));
+        }
+      }
+
+      return next;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/MultiVRPMoveOperator/MultiVRPMoveMaker.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/MultiVRPMoveOperator/MultiVRPMoveMaker.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/MultiVRPMoveOperator/MultiVRPMoveMaker.cs	(revision 14416)
@@ -0,0 +1,61 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.General {
+  [Item("MultiVRPMoveMaker", "Peforms a lambda interchange moves on a given VRP encoding and updates the quality.")]
+  [StorableClass]
+  public class MultiVRPMoveMaker : VRPMoveMaker, IMultiVRPMoveOperator, IGeneralVRPOperator {
+    public override ILookupParameter VRPMoveParameter {
+      get { return (ILookupParameter)Parameters["VRPMove"]; }
+    }
+
+    [StorableConstructor]
+    protected MultiVRPMoveMaker(bool deserializing) : base(deserializing) { }
+
+    public MultiVRPMoveMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<IVRPMove>("VRPMove", "The move."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MultiVRPMoveMaker(this, cloner);
+    }
+
+    protected MultiVRPMoveMaker(MultiVRPMoveMaker original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void PerformMove() {
+      IVRPMove move = VRPMoveParameter.ActualValue as IVRPMove;
+
+      VRPMoveMaker moveMaker = move.GetMoveMaker();
+      moveMaker.VRPMoveParameter.ActualName = VRPMoveParameter.Name;
+      IAtomicOperation op = this.ExecutionContext.CreateOperation(moveMaker);
+      op.Operator.Execute((IExecutionContext)op, CancellationToken);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/MultiVRPMoveOperator/MultiVRPMoveTabuChecker.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/MultiVRPMoveOperator/MultiVRPMoveTabuChecker.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/MultiVRPMoveOperator/MultiVRPMoveTabuChecker.cs	(revision 14416)
@@ -0,0 +1,109 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.General {
+  [Item("MultiVRPMoveTabuChecker", "Checks if a VRP move is tabu.")]
+  [StorableClass]
+  public class MultiVRPMoveTabuChecker : SingleSuccessorOperator, IMultiVRPMoveOperator, ITabuChecker, IGeneralVRPOperator {
+    public ILookupParameter VRPMoveParameter {
+      get { return (ILookupParameter)Parameters["VRPMove"]; }
+    }
+
+    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 BoolValue UseAspirationCriterion {
+      get { return UseAspirationCriterionParameter.Value; }
+      set { UseAspirationCriterionParameter.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected MultiVRPMoveTabuChecker(bool deserializing) : base(deserializing) { }
+
+    public MultiVRPMoveTabuChecker()
+      : base() {
+      Parameters.Add(new LookupParameter<IVRPMove>("VRPMove", "The move."));
+      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."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MultiVRPMoveTabuChecker(this, cloner);
+    }
+
+    protected MultiVRPMoveTabuChecker(MultiVRPMoveTabuChecker original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IOperation Apply() {
+      IVRPMove move = VRPMoveParameter.ActualValue as IVRPMove;
+
+      ITabuChecker tabuChecker;
+      if (UseAspirationCriterion.Value)
+        tabuChecker = move.GetSoftTabuChecker();
+      else
+        tabuChecker = move.GetTabuChecker();
+
+      (tabuChecker as IVRPMoveOperator).VRPMoveParameter.ActualName = VRPMoveParameter.Name;
+
+      OperationCollection next = new OperationCollection(base.Apply());
+      next.Insert(0, ExecutionContext.CreateOperation(tabuChecker));
+
+      return next;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/MultiVRPMoveOperator/MultiVRPMoveTabuMaker.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/MultiVRPMoveOperator/MultiVRPMoveTabuMaker.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/MultiVRPMoveOperator/MultiVRPMoveTabuMaker.cs	(revision 14416)
@@ -0,0 +1,97 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.General {
+  [Item("MultiVRPMoveTabuMaker", "A multi VRP move tabu maker.")]
+  [StorableClass]
+  public class MultiVRPMoveTabuMaker : SingleSuccessorOperator, IMultiVRPMoveOperator, ITabuMaker, IGeneralVRPOperator, ISingleObjectiveOperator {
+    public ILookupParameter VRPMoveParameter {
+      get { return (ILookupParameter)Parameters["VRPMove"]; }
+    }
+    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<IVRPEncoding> VRPToursParameter {
+      get { return (ILookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (LookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+
+    [StorableConstructor]
+    protected MultiVRPMoveTabuMaker(bool deserializing) : base(deserializing) { }
+
+    public MultiVRPMoveTabuMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<IVRPMove>("VRPMove", "The move."));
+      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<IVRPEncoding>("VRPTours", "The VRP tours considered in the move."));
+      Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The VRP problem instance"));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MultiVRPMoveTabuMaker(this, cloner);
+    }
+
+    protected MultiVRPMoveTabuMaker(MultiVRPMoveTabuMaker original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IOperation Apply() {
+      IVRPMove move = VRPMoveParameter.ActualValue as IVRPMove;
+
+      ITabuMaker moveTabuMaker = move.GetTabuMaker();
+      (moveTabuMaker as IVRPMoveOperator).VRPMoveParameter.ActualName = VRPMoveParameter.Name;
+
+      OperationCollection next = new OperationCollection(base.Apply());
+      next.Insert(0, ExecutionContext.CreateOperation(moveTabuMaker));
+
+      return next;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/VRPMoveAttribute.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/VRPMoveAttribute.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/VRPMoveAttribute.cs	(revision 14416)
@@ -0,0 +1,49 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.General {
+  [Item("VRPMoveAttribute", "Base class for specifying a move attribute")]
+  [StorableClass]
+  public class VRPMoveAttribute : Item {
+    [Storable]
+    public double MoveQuality { get; protected set; }
+
+    [StorableConstructor]
+    protected VRPMoveAttribute(bool deserializing) : base(deserializing) { }
+    protected VRPMoveAttribute(VRPMoveAttribute original, Cloner cloner)
+      : base(original, cloner) {
+      this.MoveQuality = original.MoveQuality;
+    }
+    public VRPMoveAttribute() : this(0) { }
+    public VRPMoveAttribute(double moveQuality)
+      : base() {
+      MoveQuality = moveQuality;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new VRPMoveAttribute(this, cloner);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/VRPMoveEvaluator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/VRPMoveEvaluator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/VRPMoveEvaluator.cs	(revision 14416)
@@ -0,0 +1,84 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.General {
+  [Item("VRPMoveEvaluator", "Evaluates a VRP move.")]
+  [StorableClass]
+  public abstract class VRPMoveEvaluator : VRPMoveOperator, ISingleObjectiveMoveEvaluator {
+    public const string MovePrefix = "Move";
+
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ILookupParameter<DoubleValue> MoveQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; }
+    }
+    public ILookupParameter<DoubleValue> MovePenaltyParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MovePenalty"]; }
+    }
+
+    [StorableConstructor]
+    protected VRPMoveEvaluator(bool deserializing) : base(deserializing) { }
+
+    public VRPMoveEvaluator()
+      : base() {
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality of the solution."));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", "The relative quality of the move."));
+      Parameters.Add(new LookupParameter<DoubleValue>("MovePenalty", "The penalty applied to the move."));
+    }
+
+    protected VRPMoveEvaluator(VRPMoveEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    //helper method to evaluate an updated individual
+    protected void UpdateEvaluation(IVRPEncoding updatedTours) {
+      IVRPEvaluator evaluator = ProblemInstance.MoveEvaluator;
+
+      try {
+        this.ExecutionContext.Scope.Variables.Add(new Variable(evaluator.VRPToursParameter.ActualName,
+          updatedTours));
+
+        IAtomicOperation op = this.ExecutionContext.CreateChildOperation(evaluator);
+        op.Operator.Execute((IExecutionContext)op, CancellationToken);
+      }
+      finally {
+        this.ExecutionContext.Scope.Variables.Remove(evaluator.VRPToursParameter.ActualName);
+      }
+    }
+
+    protected abstract void EvaluateMove();
+
+    public override IOperation InstrumentedApply() {
+      EvaluateMove();
+
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/VRPMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/VRPMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/VRPMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,43 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.General {
+  [Item("VRPMoveGenerator", "Generates moves for a VRP solution.")]
+  [StorableClass]
+  public abstract class
+    VRPMoveGenerator : VRPMoveOperator, IMoveGenerator {
+    [StorableConstructor]
+    protected VRPMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public VRPMoveGenerator()
+      : base() {
+    }
+
+    protected VRPMoveGenerator(VRPMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/VRPMoveMaker.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/VRPMoveMaker.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/VRPMoveMaker.cs	(revision 14416)
@@ -0,0 +1,107 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.General {
+  [Item("VRPMoveMaker", "Performs a VRP move.")]
+  [StorableClass]
+  public abstract class VRPMoveMaker : VRPMoveOperator, IMoveMaker, ISingleObjectiveOperator {
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ILookupParameter<DoubleValue> MoveQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; }
+    }
+    public ILookupParameter<DoubleValue> MovePenaltyParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MovePenalty"]; }
+    }
+
+    [StorableConstructor]
+    protected VRPMoveMaker(bool deserializing) : base(deserializing) { }
+
+    public VRPMoveMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality of the solution."));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", "The relative quality of the move."));
+      Parameters.Add(new LookupParameter<DoubleValue>("MovePenalty", "The penalty applied to the move."));
+    }
+
+    protected VRPMoveMaker(VRPMoveMaker original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected abstract void PerformMove();
+
+    private void UpdateMoveEvaluation() {
+      IVRPEvaluator evaluator = ProblemInstance.SolutionEvaluator;
+      ICollection<IParameter> addedParameters = new List<IParameter>();
+
+      try {
+        foreach (IParameter parameter in evaluator.Parameters) {
+          if (parameter is ILookupParameter
+            && parameter != evaluator.VRPToursParameter
+            && parameter != evaluator.ProblemInstanceParameter) {
+            ILookupParameter evaluatorParameter = parameter as ILookupParameter;
+
+            string resultName = evaluatorParameter.ActualName;
+            if (!this.Parameters.ContainsKey(resultName)) {
+              ILookupParameter resultParameter = new LookupParameter<IItem>(resultName);
+              resultParameter.ExecutionContext = ExecutionContext;
+              this.Parameters.Add(resultParameter);
+              addedParameters.Add(resultParameter);
+            }
+
+            string moveResultName = VRPMoveEvaluator.MovePrefix + resultName;
+            if (!this.Parameters.ContainsKey(moveResultName)) {
+              ILookupParameter moveResultParameter = new LookupParameter<IItem>(moveResultName);
+              moveResultParameter.ExecutionContext = ExecutionContext;
+              this.Parameters.Add(moveResultParameter);
+              addedParameters.Add(moveResultParameter);
+            }
+
+            ILookupParameter result = Parameters[resultName] as ILookupParameter;
+            ILookupParameter moveResult = Parameters[moveResultName] as ILookupParameter;
+            result.ActualValue = moveResult.ActualValue;
+          }
+        }
+      } finally {
+        foreach (IParameter parameter in addedParameters) {
+          this.Parameters.Remove(parameter);
+        }
+      }
+    }
+
+    public override IOperation InstrumentedApply() {
+      PerformMove();
+      UpdateMoveEvaluation();
+
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/VRPMoveOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/VRPMoveOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/Moves/VRPMoveOperator.cs	(revision 14416)
@@ -0,0 +1,49 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.General {
+  [Item("VRPMoveOperator", "A VRP move operator.")]
+  [StorableClass]
+  public abstract class VRPMoveOperator : VRPOperator, IVRPMoveOperator {
+    public ILookupParameter<IVRPEncoding> VRPToursParameter {
+      get { return (ILookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+
+    public abstract ILookupParameter VRPMoveParameter { get; }
+
+    [StorableConstructor]
+    protected VRPMoveOperator(bool deserializing) : base(deserializing) { }
+
+    public VRPMoveOperator() {
+      Parameters.Add(new LookupParameter<IVRPEncoding>("VRPTours", "The VRP tours considered in the move."));
+    }
+
+    protected VRPMoveOperator(VRPMoveOperator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/PermutationEncoding.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/PermutationEncoding.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/PermutationEncoding.cs	(revision 14416)
@@ -0,0 +1,87 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.General {
+  [Item("PermutationEncoding", "Represents a base class for permutation encodings of VRP solutions.")]
+  [StorableClass]
+  public abstract class PermutationEncoding : Permutation, IVRPEncoding {
+    #region IVRPEncoding Members
+    public abstract List<Tour> GetTours();
+
+    public virtual int GetTourIndex(Tour tour) {
+      int index = -1;
+
+      List<Tour> tours = GetTours();
+      for (int i = 0; i < tours.Count; i++) {
+        if (tours[i].IsEqual(tour)) {
+          index = i;
+          break;
+        }
+      }
+
+      return index;
+    }
+
+    public virtual int GetVehicleAssignment(int tour) {
+      return tour;
+    }
+    #endregion
+
+    [Storable]
+    protected IVRPProblemInstance ProblemInstance { get; set; }
+
+    protected PermutationEncoding(PermutationEncoding original, Cloner cloner)
+      : base(original, cloner) {
+      this.readOnly = original.readOnly;
+
+      if (original.ProblemInstance != null && cloner.ClonedObjectRegistered(original.ProblemInstance))
+        this.ProblemInstance = (IVRPProblemInstance)cloner.Clone(original.ProblemInstance);
+      else
+        this.ProblemInstance = original.ProblemInstance;
+    }
+
+    public PermutationEncoding(Permutation permutation, IVRPProblemInstance problemInstance)
+      : base(PermutationTypes.RelativeUndirected) {
+      this.array = new int[permutation.Length];
+      for (int i = 0; i < array.Length; i++)
+        this.array[i] = permutation[i];
+
+      this.ProblemInstance = problemInstance;
+    }
+
+    [StorableConstructor]
+    protected PermutationEncoding(bool serializing)
+      : base() {
+    }
+
+    public int IndexOf(int city) {
+      return Array.IndexOf(this.array, city);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/ShakingOperators/VehicleRoutingShakingOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/ShakingOperators/VehicleRoutingShakingOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/ShakingOperators/VehicleRoutingShakingOperator.cs	(revision 14416)
@@ -0,0 +1,99 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  [Item("VRPShakingOperator", "A shaking operator for VNS that applies available mutation operators.")]
+  [StorableClass]
+  public class VehicleRoutingShakingOperator : ShakingOperator<IVRPManipulator>, IVRPMultiNeighborhoodShakingOperator, IGeneralVRPOperator, IStochasticOperator {
+    #region Parameters
+    public ILookupParameter<IVRPEncoding> VRPToursParameter {
+      get { return (ILookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (LookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+
+    public IVRPProblemInstance ProblemInstance {
+      get { return ProblemInstanceParameter.ActualValue; }
+    }
+
+    #endregion
+
+    [StorableConstructor]
+    protected VehicleRoutingShakingOperator(bool deserializing) : base(deserializing) { }
+    protected VehicleRoutingShakingOperator(VehicleRoutingShakingOperator original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new VehicleRoutingShakingOperator(this, cloner);
+    }
+    public VehicleRoutingShakingOperator()
+      : base() {
+      Parameters.Add(new LookupParameter<IVRPEncoding>("VRPTours", "The vrp tour encoding to shake."));
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator that will be used for stochastic shaking operators."));
+      Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The VRP problem instance"));
+     
+      foreach (IVRPManipulator shaker in ApplicationManager.Manager.GetInstances<IVRPManipulator>().OrderBy(x => x.Name))
+        if (!(shaker is MultiVRPSolutionManipulator)) Operators.Add(shaker, !(shaker is IVRPLocalSearchManipulator));
+    }
+
+    #region Wiring of some parameters
+    protected override void Operators_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IVRPManipulator>> e) {
+      base.Operators_ItemsAdded(sender, e);
+      ParameterizeOperators(e.Items);
+    }
+
+    protected override void Operators_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<IVRPManipulator>> e) {
+      base.Operators_ItemsReplaced(sender, e);
+      ParameterizeOperators(e.Items);
+    }
+
+    private void ParameterizeOperators(IEnumerable<IndexedItem<IVRPManipulator>> items) {
+      if (items.Any()) {
+        foreach (IStochasticOperator op in items.Select(x => x.Value).OfType<IStochasticOperator>())
+          op.RandomParameter.ActualName = RandomParameter.Name;
+        foreach (IVRPManipulator op in items.Select(x => x.Value).OfType<IVRPManipulator>()) {
+          op.VRPToursParameter.ActualName = VRPToursParameter.Name;
+          if (op.ProblemInstanceParameter != null) op.ProblemInstanceParameter.ActualName = ProblemInstanceParameter.Name;
+        }
+      }
+    }
+    #endregion
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/TourEncoding.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/TourEncoding.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/General/TourEncoding.cs	(revision 14416)
@@ -0,0 +1,143 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using System.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.General {
+  [Item("TourEncoding", "Represents a base class for tour encodings of VRP solutions.")]
+  [StorableClass]
+  public abstract class TourEncoding : Item, IVRPEncoding {
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Class; }
+    }
+
+    #region IVRPEncoding Members
+    public virtual void Repair() {
+      List<Tour> toBeRemoved = new List<Tour>();
+      foreach (Tour tour in Tours) {
+        if (tour.Stops.Count == 0)
+          toBeRemoved.Add(tour);
+      }
+
+      foreach (Tour tour in toBeRemoved)
+        Tours.Remove(tour);
+
+      while (Tours.Count > ProblemInstance.Vehicles.Value) {
+        Tour tour = Tours[Tours.Count - 1];
+        Tours[Tours.Count - 2].Stops.AddRange(tour.Stops);
+
+        Tours.Remove(tour);
+      }
+    }
+
+    public virtual List<Tour> GetTours() {
+      List<Tour> result = new List<Tour>();
+      foreach (Tour tour in Tours)
+        result.Add(tour.Clone() as Tour);
+
+      return result;
+    }
+
+    public int GetTourIndex(Tour tour) {
+      int index = -1;
+
+      for (int i = 0; i < Tours.Count; i++) {
+        if (Tours[i].IsEqual(tour)) {
+          index = i;
+          break;
+        }
+      }
+
+      return index;
+    }
+
+    public virtual int GetVehicleAssignment(int tour) {
+      return tour;
+    }
+
+    public int Cities {
+      get {
+        int cities = 0;
+
+        foreach (Tour tour in Tours) {
+          cities += tour.Stops.Count;
+        }
+
+        return cities;
+      }
+    }
+    #endregion
+
+    [Storable]
+    public ItemList<Tour> Tours { get; set; }
+
+    [Storable]
+    protected IVRPProblemInstance ProblemInstance { get; set; }
+
+    public TourEncoding(IVRPProblemInstance problemInstance) {
+      Tours = new ItemList<Tour>();
+
+      ProblemInstance = problemInstance;
+    }
+
+    [StorableConstructor]
+    protected TourEncoding(bool serializing)
+      : base(serializing) {
+    }
+
+    protected TourEncoding(TourEncoding original, Cloner cloner)
+      : base(original, cloner) {
+      this.Tours = (ItemList<Tour>)cloner.Clone(original.Tours);
+      if (original.ProblemInstance != null && cloner.ClonedObjectRegistered(original.ProblemInstance))
+        this.ProblemInstance = (IVRPProblemInstance)cloner.Clone(original.ProblemInstance);
+      else
+        this.ProblemInstance = original.ProblemInstance;
+    }
+
+    public static void ConvertFrom(IVRPEncoding encoding, TourEncoding solution, IVRPProblemInstance problemInstance) {
+      solution.Tours = new ItemList<Tour>(encoding.GetTours());
+      solution.Repair();
+    }
+
+    public static void ConvertFrom(List<int> route, TourEncoding solution) {
+      solution.Tours = new ItemList<Tour>();
+
+      Tour tour = new Tour();
+      for (int i = 0; i < route.Count; i++) {
+        if (route[i] <= 0) {
+          if (tour.Stops.Count > 0) {
+            solution.Tours.Add(tour);
+            tour = new Tour();
+          }
+        } else {
+          tour.Stops.Add(route[i]);
+        }
+      }
+
+      solution.Repair();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Creators/IterativeInsertionCreator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Creators/IterativeInsertionCreator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Creators/IterativeInsertionCreator.cs	(revision 14416)
@@ -0,0 +1,148 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("IterativeInsertionCreator", "Creates a randomly initialized VRP solution.")]
+  [StorableClass]
+  public sealed class IterativeInsertionCreator : PotvinCreator, IStochasticOperator {
+    #region IStochasticOperator Members
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    #endregion
+
+    public IValueParameter<BoolValue> AdhereTimeWindowsParameter {
+      get { return (IValueParameter<BoolValue>)Parameters["AdhereTimeWindows"]; }
+    }
+
+    [StorableConstructor]
+    private IterativeInsertionCreator(bool deserializing) : base(deserializing) { }
+
+    public IterativeInsertionCreator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator."));
+      Parameters.Add(new ValueParameter<BoolValue>("AdhereTimeWindows", "Specifies if the time windows should be considered during construction.", new BoolValue(true)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new IterativeInsertionCreator(this, cloner);
+    }
+
+    private IterativeInsertionCreator(IterativeInsertionCreator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    private static double CalculateAngleToDepot(IVRPProblemInstance instance, int city) {
+      double dx = instance.GetCoordinates(0)[0];
+      double dy = instance.GetCoordinates(0)[1];
+
+      double cx = instance.GetCoordinates(city)[0];
+      double cy = instance.GetCoordinates(city)[1];
+
+      double alpha = Math.Atan((cx - dx) / (dy - cy)) * (180.0 / Math.PI);
+      if (cx > dx && cy > dy)
+        alpha = (90.0 + alpha) + 90.0;
+      else if (cx < dx && cy > dy)
+        alpha = alpha + 180.0;
+      else if (cx < dx && cy < dy)
+        alpha = (90.0 + alpha) + 270.0;
+
+      return alpha;
+    }
+
+    public static PotvinEncoding CreateSolution(IVRPProblemInstance instance, IRandom random, bool adhereTimeWindows) {
+      PotvinEncoding result = new PotvinEncoding(instance);
+
+      IPickupAndDeliveryProblemInstance pdp = instance as IPickupAndDeliveryProblemInstance;
+
+      List<int> customers = new List<int>();
+      for (int i = 1; i <= instance.Cities.Value; i++)
+        if (pdp == null || pdp.GetDemand(i) >= 0)
+          customers.Add(i);
+
+      customers.Sort((city1, city2) => {
+        double angle1 = CalculateAngleToDepot(instance, city1);
+        double angle2 = CalculateAngleToDepot(instance, city2);
+
+        return angle1.CompareTo(angle2);
+      });
+
+      Tour currentTour = new Tour();
+      result.Tours.Add(currentTour);
+
+      int j = random.Next(customers.Count);
+      for (int i = 0; i < customers.Count; i++) {
+        int index = (i + j) % customers.Count;
+
+        int stopIdx = 0;
+        if (currentTour.Stops.Count > 0)
+          stopIdx = result.FindBestInsertionPlace(currentTour, customers[index]);
+        currentTour.Stops.Insert(stopIdx, customers[index]);
+
+        if (pdp != null) {
+          stopIdx = result.FindBestInsertionPlace(currentTour, pdp.GetPickupDeliveryLocation(customers[index]));
+          currentTour.Stops.Insert(stopIdx, pdp.GetPickupDeliveryLocation(customers[index]));
+        }
+
+        CVRPEvaluation evaluation = instance.EvaluateTour(currentTour, result) as CVRPEvaluation;
+        if (result.Tours.Count < instance.Vehicles.Value &&
+          ((adhereTimeWindows && !instance.Feasible(evaluation)) || ((!adhereTimeWindows) && evaluation.Overload > double.Epsilon))) {
+          currentTour.Stops.Remove(customers[index]);
+          if (pdp != null)
+            currentTour.Stops.Remove(pdp.GetPickupDeliveryLocation(customers[index]));
+
+          if (currentTour.Stops.Count == 0)
+            result.Tours.Remove(currentTour);
+          currentTour = new Tour();
+          result.Tours.Add(currentTour);
+
+          currentTour.Stops.Add(customers[index]);
+          if (pdp != null) {
+            currentTour.Stops.Add(pdp.GetPickupDeliveryLocation(customers[index]));
+          }
+        }
+      }
+
+      if (currentTour.Stops.Count == 0)
+        result.Tours.Remove(currentTour);
+
+      return result;
+    }
+
+    public override IOperation InstrumentedApply() {
+      VRPToursParameter.ActualValue = CreateSolution(ProblemInstance, RandomParameter.ActualValue, AdhereTimeWindowsParameter.Value.Value);
+
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Creators/PotvinCreator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Creators/PotvinCreator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Creators/PotvinCreator.cs	(revision 14416)
@@ -0,0 +1,47 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinCreator", "A VRP creator.")]
+  [StorableClass]
+  public abstract class PotvinCreator : VRPCreator, IPotvinOperator, IVRPCreator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+
+    [StorableConstructor]
+    protected PotvinCreator(bool deserializing) : base(deserializing) { }
+
+    public PotvinCreator()
+      : base() {
+    }
+
+    protected PotvinCreator(PotvinCreator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Creators/PushForwardInsertionCreator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Creators/PushForwardInsertionCreator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Creators/PushForwardInsertionCreator.cs	(revision 14416)
@@ -0,0 +1,380 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PushForwardInsertionCreator", "The push forward insertion heuristic. It is implemented as described in Sam, and Thangiah, R. (1999). A Hybrid Genetic Algorithms, Simulated Annealing and Tabu Search Heuristic for Vehicle Routing Problems with Time Windows. Practical Handbook of Genetic Algorithms, Volume III, pp 347–381.")]
+  [StorableClass]
+  public sealed class PushForwardInsertionCreator : 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 PushForwardInsertionCreator(bool deserializing) : base(deserializing) { }
+
+    public PushForwardInsertionCreator()
+      : 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 PushForwardInsertionCreator(this, cloner);
+    }
+
+    private PushForwardInsertionCreator(PushForwardInsertionCreator 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) {
+      double distance = 0.0;
+
+      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 int GetNearestDepot(IVRPProblemInstance problemInstance, List<int> depots, int customer,
+      double alpha, double beta, double gamma, out double minCost) {
+      int nearest = -1;
+      minCost = double.MaxValue;
+
+      int depotCount = 1;
+      IMultiDepotProblemInstance mdp = problemInstance as IMultiDepotProblemInstance;
+      if (mdp != null) {
+        depotCount = mdp.Depots.Value;
+      }
+
+      foreach (int depot in depots) {
+        double x0 = problemInstance.Coordinates[depot, 0];
+        double y0 = problemInstance.Coordinates[depot, 1];
+
+        double distance = GetDistance(customer + depotCount - 1, depot, problemInstance);
+
+        double dueTime = 0;
+        if (problemInstance is ITimeWindowedProblemInstance)
+          dueTime = (problemInstance as ITimeWindowedProblemInstance).DueTime[customer + depotCount - 1];
+        if (dueTime == double.MaxValue)
+          dueTime = 0;
+
+        double x = problemInstance.Coordinates[customer + depotCount - 1, 0];
+        double y = problemInstance.Coordinates[customer + depotCount - 1, 1];
+
+        double cost = alpha * distance + // distance 0 <-> City[i]
+                      -beta * dueTime + // latest arrival time
+                      -gamma * ((Math.Atan2(y - y0, x - x0) + Math.PI) / (2.0 * Math.PI) * distance); // polar angle
+
+        if (cost < minCost) {
+          minCost = cost;
+          nearest = depot;
+        }
+      }
+
+      return nearest;
+    }
+
+    private static List<int> SortCustomers(IVRPProblemInstance problemInstance, List<int> customers, List<int> depots,
+      Dictionary<int, int> depotAssignment,
+      double alpha, double beta, double gamma) {
+      List<int> sortedCustomers = new List<int>();
+      depotAssignment.Clear();
+
+      List<double> costList = new List<double>();
+
+      for (int i = 0; i < customers.Count; i++) {
+        double cost;
+        int depot = GetNearestDepot(problemInstance, depots, customers[i],
+          alpha, beta, gamma,
+          out cost);
+        depotAssignment[customers[i]] = depot;
+
+        int index = 0;
+        while (index < costList.Count && costList[index] < cost) index++;
+        costList.Insert(index, cost);
+        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;
+    }
+
+    public static PotvinEncoding CreateSolution(IVRPProblemInstance problemInstance, IRandom random,
+      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;
+
+      double alpha, beta, gamma;
+      alpha = N(alphaValue, Math.Sqrt(alphaVariance), random);
+      beta = N(betaValue, Math.Sqrt(betaVariance), random);
+      gamma = N(gammaValue, Math.Sqrt(gammaVariance), random);
+
+      List<int> unroutedCustomers = new List<int>();
+      for (int i = 1; i <= problemInstance.Cities.Value; i++) {
+        if (pdp == null || (problemInstance.GetDemand(i) >= 0))
+          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);
+          }
+        }
+      }
+
+      RemoveUnusedDepots(depots, vehicles);
+      Dictionary<int, int> depotAssignment = new Dictionary<int, int>();
+
+      unroutedCustomers = SortCustomers(
+        problemInstance, unroutedCustomers, depots, depotAssignment,
+        alpha, beta, gamma);
+
+      /////////
+      Tour tour = new Tour();
+      result.Tours.Add(tour);
+      int currentCustomer = unroutedCustomers[0];
+      unroutedCustomers.RemoveAt(0);
+
+      int currentDepot = depotAssignment[currentCustomer];
+      int currentVehicle = vehicles[currentDepot][0];
+      vehicles[currentDepot].RemoveAt(0);
+      if (RemoveUnusedDepots(depots, vehicles)) {
+        unroutedCustomers = SortCustomers(
+        problemInstance, unroutedCustomers, depots, depotAssignment,
+        alpha, beta, gamma);
+      }
+
+      result.VehicleAssignment[result.Tours.Count - 1] = currentVehicle;
+
+      tour.Stops.Add(currentCustomer);
+      if (pdp != null) {
+        tour.Stops.Add(pdp.GetPickupDeliveryLocation(currentCustomer));
+      }
+      ////////
+
+      while (unroutedCustomers.Count > 0) {
+        double minimumCost = double.MaxValue;
+        int customer = -1;
+        int indexOfMinimumCost = -1;
+        int indexOfMinimumCost2 = -1;
+
+        foreach (int unrouted in unroutedCustomers) {
+          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) {
+              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 && feasible) {
+                  customer = unrouted;
+                  minimumCost = cost;
+                  indexOfMinimumCost = i;
+                  indexOfMinimumCost2 = j;
+                }
+              }
+            } else {
+              double cost = tourCost;
+              bool feasible = problemInstance.Feasible(eval);
+              if (cost < minimumCost && feasible) {
+                customer = unrouted;
+                minimumCost = cost;
+                indexOfMinimumCost = i;
+              }
+            }
+
+            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) {
+            tour.Stops.Insert(indexOfMinimumCost2, pdp.GetPickupDeliveryLocation(customer));
+          }
+
+          unroutedCustomers.Remove(customer);
+        } else { // no feasible customer found
+          tour = new Tour();
+          result.Tours.Add(tour);
+          currentCustomer = unroutedCustomers[0];
+          unroutedCustomers.RemoveAt(0);
+
+          currentDepot = depotAssignment[currentCustomer];
+          currentVehicle = vehicles[currentDepot][0];
+          vehicles[currentDepot].RemoveAt(0);
+          if (RemoveUnusedDepots(depots, vehicles)) {
+            unroutedCustomers = SortCustomers(
+            problemInstance, unroutedCustomers, depots, depotAssignment,
+            alpha, beta, gamma);
+          }
+
+          result.VehicleAssignment[result.Tours.Count - 1] = currentVehicle;
+
+          tour.Stops.Add(currentCustomer);
+          if (pdp != null) {
+            tour.Stops.Add(pdp.GetPickupDeliveryLocation(currentCustomer));
+          }
+        }
+      }
+
+      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);
+          }
+        }
+      }
+
+      return result;
+    }
+
+    public override IOperation InstrumentedApply() {
+      VRPToursParameter.ActualValue = CreateSolution(ProblemInstance, RandomParameter.ActualValue,
+        Alpha.Value.Value, Beta.Value.Value, Gamma.Value.Value,
+        AlphaVariance.Value.Value, BetaVariance.Value.Value, GammaVariance.Value.Value);
+
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Crossovers/PotvinCrossover.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Crossovers/PotvinCrossover.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Crossovers/PotvinCrossover.cs	(revision 14416)
@@ -0,0 +1,165 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinCrossover", "A VRP crossover operation.")]
+  [StorableClass]
+  public abstract class PotvinCrossover : VRPCrossover, IStochasticOperator, IPotvinOperator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public IValueParameter<BoolValue> AllowInfeasibleSolutions {
+      get { return (IValueParameter<BoolValue>)Parameters["AllowInfeasibleSolutions"]; }
+    }
+
+    [StorableConstructor]
+    protected PotvinCrossover(bool deserializing) : base(deserializing) { }
+
+    public PotvinCrossover() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator which should be used for stochastic manipulation operators."));
+      Parameters.Add(new ValueParameter<BoolValue>("AllowInfeasibleSolutions", "Indicates if infeasible solutions should be allowed.", new BoolValue(false)));
+    }
+
+    protected PotvinCrossover(PotvinCrossover original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected abstract PotvinEncoding Crossover(IRandom random, PotvinEncoding parent1, PotvinEncoding parent2);
+
+    protected static bool FindInsertionPlace(PotvinEncoding individual, int city, bool allowInfeasible,
+        out int route, out int place) {
+      return individual.FindInsertionPlace(
+        city, -1, allowInfeasible,
+        out route, out place);
+    }
+
+    protected static Tour FindRoute(PotvinEncoding solution, int city) {
+      Tour found = null;
+
+      foreach (Tour tour in solution.Tours) {
+        if (tour.Stops.Contains(city)) {
+          found = tour;
+          break;
+        }
+      }
+
+      return found;
+    }
+
+    protected static bool RouteUnrouted(PotvinEncoding solution, bool allowInfeasible) {
+      bool success = true;
+      int index = 0;
+      while (index < solution.Unrouted.Count && success) {
+        int unrouted = solution.Unrouted[index];
+
+        int route, place;
+        if (FindInsertionPlace(solution, unrouted, allowInfeasible,
+          out route, out place)) {
+          solution.Tours[route].Stops.Insert(place, unrouted);
+        } else {
+          success = false;
+        }
+
+        index++;
+      }
+
+      for (int i = 0; i < index; i++)
+        solution.Unrouted.RemoveAt(0);
+
+      return success;
+    }
+
+    protected static bool Repair(IRandom random, PotvinEncoding solution, Tour newTour, IVRPProblemInstance instance, bool allowInfeasible) {
+      bool success = true;
+
+      //remove duplicates from new tour      
+      for (int i = 0; i < newTour.Stops.Count; i++) {
+        for (int j = 0; j < newTour.Stops.Count; j++) {
+          if (newTour.Stops[i] == newTour.Stops[j] && i != j) {
+            if (random.NextDouble() < 0.5)
+              newTour.Stops[i] = 0;
+            else
+              newTour.Stops[j] = 0;
+          }
+        }
+      }
+      while (newTour.Stops.Contains(0))
+        newTour.Stops.Remove(0);
+
+      //remove duplicates from old tours
+      for (int i = 0; i < newTour.Stops.Count; i++) {
+        foreach (Tour tour in solution.Tours) {
+          if (tour != newTour && tour.Stops.Contains(newTour.Stops[i])) {
+            tour.Stops.Remove(newTour.Stops[i]);
+          }
+        }
+      }
+
+      //remove empty tours
+      List<Tour> toBeDeleted = new List<Tour>();
+      foreach (Tour tour in solution.Tours) {
+        if (tour.Stops.Count == 0)
+          toBeDeleted.Add(tour);
+      }
+      foreach (Tour tour in toBeDeleted) {
+        solution.Tours.Remove(tour);
+      }
+
+      if (newTour.Stops.Count > 0 && !allowInfeasible && !instance.TourFeasible(newTour, solution))
+        return false;
+
+      //route unrouted vehicles
+      success = RouteUnrouted(solution, allowInfeasible);
+
+      return success;
+    }
+
+    public override IOperation InstrumentedApply() {
+      ItemArray<IVRPEncoding> parents = new ItemArray<IVRPEncoding>(ParentsParameter.ActualValue.Length);
+      for (int i = 0; i < ParentsParameter.ActualValue.Length; i++) {
+        IVRPEncoding solution = ParentsParameter.ActualValue[i];
+
+        if (!(solution is PotvinEncoding)) {
+          parents[i] = PotvinEncoding.ConvertFrom(solution, ProblemInstance);
+        } else {
+          parents[i] = solution;
+        }
+      }
+      ParentsParameter.ActualValue = parents;
+
+      ChildParameter.ActualValue = Crossover(RandomParameter.ActualValue, parents[0] as PotvinEncoding, parents[1] as PotvinEncoding);
+      (ChildParameter.ActualValue as PotvinEncoding).Repair();
+
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Crossovers/PotvinInsertionBasedCrossover.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Crossovers/PotvinInsertionBasedCrossover.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Crossovers/PotvinInsertionBasedCrossover.cs	(revision 14416)
@@ -0,0 +1,285 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 System.Collections.Generic;
+using HeuristicLab.Data;
+using System;
+using HeuristicLab.Parameters;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinInsertionBasedCrossover", "The IBX crossover for VRP representations. It is implemented as described in Berger, J and Solois, M and Begin, R (1998). A hybrid genetic algorithm for the vehicle routing problem with time windows. LNCS 1418. Springer, London 114-127.")]
+  [StorableClass]
+  public sealed class PotvinInsertionBasedCrossover : PotvinCrossover {
+    public IValueParameter<IntValue> Length {
+      get { return (IValueParameter<IntValue>)Parameters["Length"]; }
+    }
+
+    [StorableConstructor]
+    private PotvinInsertionBasedCrossover(bool deserializing) : base(deserializing) { }
+    private PotvinInsertionBasedCrossover(PotvinInsertionBasedCrossover original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinInsertionBasedCrossover(this, cloner);
+    }
+    public PotvinInsertionBasedCrossover()
+      : base() {
+      Parameters.Add(new ValueParameter<IntValue>("Length", "The maximum length of the replaced route.", new IntValue(1)));
+    }
+
+    private static int SelectRandomTourBiasedByLength(IRandom random, PotvinEncoding individual) {
+      int tourIndex = -1;
+
+      double sum = 0.0;
+      double[] probabilities = new double[individual.Tours.Count];
+      for (int i = 0; i < individual.Tours.Count; i++) {
+        probabilities[i] = 1.0 / ((double)individual.Tours[i].Stops.Count / (double)individual.Cities);
+        sum += probabilities[i];
+      }
+
+      double rand = random.NextDouble() * sum;
+      double cumulatedProbabilities = 0.0;
+      int index = 0;
+      while (tourIndex == -1 && index < probabilities.Length) {
+        if (cumulatedProbabilities <= rand && rand <= cumulatedProbabilities + probabilities[index])
+          tourIndex = index;
+
+        cumulatedProbabilities += probabilities[index];
+        index++;
+      }
+
+      return tourIndex;
+    }
+
+    private double CalculateCentroidDistance(Tour t1, Tour t2, IVRPProblemInstance instance) {
+      double xSum = 0;
+      double ySum = 0;
+      double c1X, c1Y, c2X, c2Y;
+
+      for (int i = 0; i < t1.Stops.Count; i++) {
+        xSum += instance.GetCoordinates(t1.Stops[i])[0];
+        ySum += instance.GetCoordinates(t1.Stops[i])[1];
+      }
+      c1X = xSum / t1.Stops.Count;
+      c1Y = ySum / t1.Stops.Count;
+
+      for (int i = 0; i < t2.Stops.Count; i++) {
+        xSum += instance.GetCoordinates(t2.Stops[i])[0];
+        ySum += instance.GetCoordinates(t2.Stops[i])[1];
+      }
+      c2X = xSum / t1.Stops.Count;
+      c2Y = ySum / t1.Stops.Count;
+
+      return Math.Sqrt(
+           (c1X - c2X) * (c1X - c2X) +
+           (c1Y - c2Y) * (c1Y - c2Y));
+    }
+
+    private double CalculateMeanCentroidDistance(Tour t1, IList<Tour> tours, IVRPProblemInstance instance) {
+      double sum = 0;
+
+      for (int i = 0; i < tours.Count; i++) {
+        sum += CalculateCentroidDistance(t1, tours[i], instance);
+      }
+
+      return sum / tours.Count;
+    }
+
+    private int SelectCityBiasedByNeighborDistance(IRandom random, Tour tour, IVRPEncoding solution) {
+      int cityIndex = -1;
+
+      double sum = 0.0;
+      double[] probabilities = new double[tour.Stops.Count];
+      for (int i = 0; i < tour.Stops.Count; i++) {
+        int next;
+        if (i + 1 >= tour.Stops.Count)
+          next = 0;
+        else
+          next = tour.Stops[i + 1];
+        double distance = ProblemInstance.GetDistance(
+          tour.Stops[i], next, solution);
+
+        int prev;
+        if (i - 1 < 0)
+          prev = 0;
+        else
+          prev = tour.Stops[i - 1];
+        distance += ProblemInstance.GetDistance(
+          tour.Stops[i], prev, solution);
+
+        probabilities[i] = distance;
+        sum += probabilities[i];
+      }
+
+      double rand = random.NextDouble() * sum;
+      double cumulatedProbabilities = 0.0;
+      int index = 0;
+      while (cityIndex == -1 && index < probabilities.Length) {
+        if (cumulatedProbabilities <= rand && rand <= cumulatedProbabilities + probabilities[index])
+          cityIndex = index;
+
+        cumulatedProbabilities += probabilities[index];
+        index++;
+      }
+
+      return cityIndex;
+    }
+
+    private bool FindRouteInsertionPlace(
+      PotvinEncoding individual,
+      Tour tour,
+      int city, bool allowInfeasible, out int place) {
+      place = -1;
+
+      if (tour.Stops.Contains(city))
+        return false;
+
+      if (tour.Stops.Count == 0) {
+        place = 0;
+        return true;
+      }
+
+      double minDetour = 0;
+      VRPEvaluation eval = ProblemInstance.EvaluateTour(tour, individual);
+      bool originalFeasible = ProblemInstance.Feasible(eval);
+
+      for (int i = 0; i <= tour.Stops.Count; i++) {
+        bool feasible;
+        double detour = ProblemInstance.GetInsertionCosts(eval, individual, city, 0, i, out feasible);
+        if (feasible || allowInfeasible) {
+          if (place < 0 || detour < minDetour) {
+            place = i;
+            minDetour = detour;
+          }
+        }
+      }
+
+      return place >= 0;
+    }
+
+    private ICollection<int> GetUnrouted(PotvinEncoding solution, int cities) {
+      HashSet<int> undiscovered = new HashSet<int>();
+      for (int i = 1; i <= cities; i++) {
+        undiscovered.Add(i);
+      }
+
+      foreach (Tour tour in solution.Tours) {
+        foreach (int city in tour.Stops)
+          undiscovered.Remove(city);
+      }
+
+      return undiscovered;
+    }
+
+    protected override PotvinEncoding Crossover(IRandom random, PotvinEncoding parent1, PotvinEncoding parent2) {
+      PotvinEncoding child = parent1.Clone() as PotvinEncoding;
+      child.Tours.Clear();
+
+      bool allowInfeasible = AllowInfeasibleSolutions.Value.Value;
+
+      List<Tour> R1 = new List<Tour>();
+      PotvinEncoding p1Clone = parent1.Clone() as PotvinEncoding;
+
+      int length = Math.Min(Length.Value.Value, parent1.Tours.Count) + 1;
+      int k = 1;
+      if(length > 1)
+        k = random.Next(1, length);
+      for (int i = 0; i < k; i++) {
+        int index = SelectRandomTourBiasedByLength(random, p1Clone);
+        R1.Add(p1Clone.Tours[index]);
+        p1Clone.Tours.RemoveAt(index);
+      }
+
+      foreach (Tour r1 in R1) {
+        List<int> R2 = new List<int>();
+
+        double r = CalculateMeanCentroidDistance(r1, parent2.Tours, ProblemInstance);
+        foreach (Tour tour in parent2.Tours) {
+          if (CalculateCentroidDistance(r1, tour, ProblemInstance) <= r) {
+            R2.AddRange(tour.Stops);
+          }
+        }
+
+        Tour childTour = new Tour();
+        child.Tours.Add(childTour);
+        childTour.Stops.AddRange(r1.Stops);
+
+        //DESTROY - remove cities from r1
+        int removed = 1;
+        if(r1.Stops.Count > 1)
+          removed = random.Next(1, r1.Stops.Count + 1);
+        for (int i = 0; i < removed; i++) {
+          childTour.Stops.RemoveAt(SelectCityBiasedByNeighborDistance(random, childTour, child));
+        }
+
+        //REPAIR - add cities from R2
+        int maxCount = 1;
+        if(R2.Count > 1)
+          maxCount = random.Next(1, Math.Min(5, R2.Count));
+        int count = 0;
+
+        while (count < maxCount && R2.Count != 0) {
+          int index = random.Next(R2.Count);
+          int city = R2[index];
+          R2.RemoveAt(index);
+
+          int place = -1;
+          bool found = FindRouteInsertionPlace(child, childTour, city, allowInfeasible, out place); 
+          if (found) {
+            childTour.Stops.Insert(place, city);
+
+            if (!Repair(random, child, childTour, ProblemInstance, allowInfeasible)) {
+              childTour.Stops.RemoveAt(place);
+            } else {
+              count++;
+            }
+          }
+        }
+
+        Repair(random, child, childTour, ProblemInstance, allowInfeasible);
+      }
+
+      for (int i = 0; i < p1Clone.Tours.Count; i++) {
+        Tour childTour = p1Clone.Tours[i].Clone() as Tour;
+        child.Tours.Add(childTour);
+        Repair(random, child, childTour, ProblemInstance, allowInfeasible);
+      }
+
+      //route unrouted customers
+      child.Unrouted.AddRange(GetUnrouted(child, ProblemInstance.Cities.Value));
+      bool success = RouteUnrouted(child, allowInfeasible);
+
+      if (success || allowInfeasible)
+        return child;
+      else {
+        if (random.NextDouble() < 0.5)
+          return parent1.Clone() as PotvinEncoding;
+        else
+          return parent2.Clone() as PotvinEncoding;
+      }
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Crossovers/PotvinRouteBasedCrossover.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Crossovers/PotvinRouteBasedCrossover.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Crossovers/PotvinRouteBasedCrossover.cs	(revision 14416)
@@ -0,0 +1,93 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Encodings.PermutationEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinRouteBasedCrossover", "The RBX crossover for a VRP representations.  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.")]
+  [StorableClass]
+  public sealed class PotvinRouteBasedCrossover : PotvinCrossover {
+    [StorableConstructor]
+    private PotvinRouteBasedCrossover(bool deserializing) : base(deserializing) { }
+
+    public PotvinRouteBasedCrossover()
+      : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinRouteBasedCrossover(this, cloner);
+    }
+
+    private PotvinRouteBasedCrossover(PotvinRouteBasedCrossover original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static PotvinEncoding Apply(IRandom random, PotvinEncoding parent1, PotvinEncoding parent2, IVRPProblemInstance problemInstance, bool allowInfeasible) {
+      PotvinEncoding child = parent2.Clone() as PotvinEncoding;
+
+      if (parent1.Tours.Count > 0 && child.Tours.Count > 0) {
+        int tourParent1 = random.Next(parent1.Tours.Count);
+        Tour replacing = parent1.Tours[tourParent1].Clone() as Tour;
+
+        int tourParent2 = random.Next(child.Tours.Count);
+        Tour replaced = child.Tours[tourParent2];
+
+        child.Tours.Remove(replaced);
+        child.Tours.Insert(tourParent2, replacing);
+
+        Permutation vehicleAssignment = child.VehicleAssignment;
+
+        int vehicle = vehicleAssignment[tourParent2];
+        int vehicle2 = parent1.VehicleAssignment[tourParent1];
+        vehicleAssignment[tourParent2] = vehicle2;
+
+        for (int i = 0; i < vehicleAssignment.Length; i++) {
+          if (vehicleAssignment[i] == vehicle2 && i != tourParent2) {
+            vehicleAssignment[i] = vehicle;
+            break;
+          }
+        }
+
+        foreach (int city in replaced.Stops)
+          if (FindRoute(child, city) == null && !child.Unrouted.Contains(city))
+            child.Unrouted.Add(city);
+
+        if (Repair(random, child, replacing, problemInstance, allowInfeasible) || allowInfeasible)
+          return child;
+        else {
+          if (random.NextDouble() < 0.5)
+            return parent1.Clone() as PotvinEncoding;
+          else
+            return parent2.Clone() as PotvinEncoding;
+        }
+      } else {
+        return child;
+      }
+    }
+
+    protected override PotvinEncoding Crossover(IRandom random, PotvinEncoding parent1, PotvinEncoding parent2) {
+      return Apply(random, parent1, parent2, ProblemInstance, AllowInfeasibleSolutions.Value.Value);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Crossovers/PotvinSequenceBasedCrossover.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Crossovers/PotvinSequenceBasedCrossover.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Crossovers/PotvinSequenceBasedCrossover.cs	(revision 14416)
@@ -0,0 +1,95 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinSequenceBasedCrossover", "The SBX crossover for a VRP representations.  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.")]
+  [StorableClass]
+  public sealed class PotvinSequenceBasedCrossover : PotvinCrossover {
+    [StorableConstructor]
+    private PotvinSequenceBasedCrossover(bool deserializing) : base(deserializing) { }
+
+    public PotvinSequenceBasedCrossover()
+      : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinSequenceBasedCrossover(this, cloner);
+    }
+
+    private PotvinSequenceBasedCrossover(PotvinSequenceBasedCrossover original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static PotvinEncoding Apply(IRandom random, PotvinEncoding parent1, PotvinEncoding parent2, IVRPProblemInstance problemInstance, bool allowInfeasible) {
+      PotvinEncoding child = parent1.Clone() as PotvinEncoding;
+      Tour newTour = new Tour();
+
+      int cities = problemInstance.Cities.Value;
+
+      if (cities > 0) {
+        int breakPoint1 = random.Next(1, cities + 1);
+        Tour tour1 = FindRoute(child, breakPoint1);
+        breakPoint1 = tour1.Stops.IndexOf(breakPoint1);
+
+        for (int i = 0; i < breakPoint1; i++)
+          newTour.Stops.Add(tour1.Stops[i]);
+
+        int breakPoint2 = random.Next(1, cities + 1);
+        Tour tour2 = FindRoute(parent2, breakPoint2);
+        breakPoint2 = tour2.Stops.IndexOf(breakPoint2);
+
+        for (int i = breakPoint2; i < tour2.Stops.Count; i++)
+          newTour.Stops.Add(tour2.Stops[i]);
+
+        int tour1Index = child.Tours.IndexOf(tour1);
+        child.Tours.Remove(tour1);
+        child.Tours.Insert(tour1Index, newTour);
+
+        foreach (int city in tour1.Stops)
+          if (FindRoute(child, city) == null && !child.Unrouted.Contains(city))
+            child.Unrouted.Add(city);
+
+        foreach (int city in tour2.Stops)
+          if (FindRoute(child, city) == null && !child.Unrouted.Contains(city))
+            child.Unrouted.Add(city);
+
+        if (Repair(random, child, newTour, problemInstance, allowInfeasible) || allowInfeasible) {
+          return child;
+        } else {
+          if (random.NextDouble() < 0.5)
+            return parent1.Clone() as PotvinEncoding;
+          else
+            return parent2.Clone() as PotvinEncoding;
+        }
+      } else {
+        return child;
+      }
+    }
+
+    protected override PotvinEncoding Crossover(IRandom random, PotvinEncoding parent1, PotvinEncoding parent2) {
+      return Apply(random, parent1, parent2, ProblemInstance, AllowInfeasibleSolutions.Value.Value);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/IPotvinOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/IPotvinOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/IPotvinOperator.cs	(revision 14416)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  public interface IPotvinOperator :
+    ISingleDepotOperator, IHomogenousCapacitatedOperator, ITimeWindowedOperator,
+    IMultiDepotOperator, IHeterogenousCapacitatedOperator {
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinLocalSearchManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinLocalSearchManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinLocalSearchManipulator.cs	(revision 14416)
@@ -0,0 +1,147 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinLocalSearchManipulator", "The LSM 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.")]
+  [StorableClass]
+  public sealed class PotvinLocalSearchManipulator : PotvinManipulator, IVRPLocalSearchManipulator {
+    public IValueParameter<IntValue> Iterations {
+      get { return (IValueParameter<IntValue>)Parameters["Iterations"]; }
+    }
+
+    [StorableConstructor]
+    private PotvinLocalSearchManipulator(bool deserializing) : base(deserializing) { }
+
+    public PotvinLocalSearchManipulator()
+      : base() {
+      Parameters.Add(new ValueParameter<IntValue>("Iterations", "The number of max iterations.", new IntValue(100)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinLocalSearchManipulator(this, cloner);
+    }
+
+    private PotvinLocalSearchManipulator(PotvinLocalSearchManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    private static bool FindBetterInsertionPlace(
+      PotvinEncoding individual, IVRPProblemInstance instance, int tour, int city, int length,
+      out int insertionTour, out int insertionPlace) {
+      bool insertionFound = false;
+      insertionTour = -1;
+      insertionPlace = 1;
+
+      List<int> toBeDeleted = individual.Tours[tour].Stops.GetRange(city, length);
+      double distance = individual.GetTourLength(individual.Tours[tour]);
+      individual.Tours[tour].Stops.RemoveRange(city, length);
+      double removalBenefit = distance - individual.GetTourLength(individual.Tours[tour]);
+
+      int currentTour = 0;
+      while (currentTour < individual.Tours.Count && !insertionFound) {
+        int currentCity = 0;
+        while (currentCity <= individual.Tours[currentTour].Stops.Count && !insertionFound) {
+          distance = individual.GetTourLength(individual.Tours[currentTour]);
+          individual.Tours[currentTour].Stops.InsertRange(currentCity, toBeDeleted);
+          if (instance.TourFeasible(individual.Tours[currentTour], individual)) {
+            double lengthIncrease =
+              individual.GetTourLength(individual.Tours[currentTour]) - distance;
+            if (removalBenefit > lengthIncrease) {
+              insertionTour = currentTour;
+              insertionPlace = currentCity;
+
+              insertionFound = true;
+            }
+          }
+          individual.Tours[currentTour].Stops.RemoveRange(currentCity, length);
+
+          currentCity++;
+        }
+        currentTour++;
+      }
+
+      individual.Tours[tour].Stops.InsertRange(city, toBeDeleted);
+
+      return insertionFound;
+    }
+
+    public static void ApplyManipulation(IRandom random, PotvinEncoding individual, IVRPProblemInstance instance, int maxIterations) {
+      //only apply to feasible individuals
+      if (instance.Feasible(individual)) {
+        bool insertionFound;
+        int iterations = 0;
+
+        do {
+          insertionFound = false;
+          int length = 3;
+          while (length > 0 && !insertionFound) {
+            int tour = 0;
+            while (tour < individual.Tours.Count && !insertionFound) {
+              int city = 0;
+              while (city <= individual.Tours[tour].Stops.Count - length && !insertionFound) {
+                int insertionTour, insertionPlace;
+                if (FindBetterInsertionPlace(individual, instance, tour, city, length,
+                 out insertionTour, out insertionPlace)) {
+                  insertionFound = true;
+
+                  List<int> toBeInserted = individual.Tours[tour].Stops.GetRange(city, length);
+
+                  individual.Tours[tour].Stops.RemoveRange(city, length);
+                  individual.Tours[insertionTour].Stops.InsertRange(
+                    insertionPlace,
+                    toBeInserted);
+                }
+                city++;
+              }
+              tour++;
+            }
+            length--;
+          }
+          iterations++;
+        } while (insertionFound &&
+          iterations < maxIterations);
+
+        IList<Tour> toBeRemoved = new List<Tour>();
+        foreach (Tour tour in individual.Tours) {
+          if (tour.Stops.Count == 0)
+            toBeRemoved.Add(tour);
+        }
+
+        foreach (Tour tour in toBeRemoved) {
+          individual.Tours.Remove(tour);
+        }
+      }
+    }
+ 
+
+    protected override void Manipulate(IRandom random, PotvinEncoding individual) {
+      ApplyManipulation(random, individual, ProblemInstance, Iterations.Value.Value);     
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinManipulator.cs	(revision 14416)
@@ -0,0 +1,101 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinManipulator", "A VRP manipulation operation.")]
+  [StorableClass]
+  public abstract class PotvinManipulator : VRPManipulator, IStochasticOperator, IPotvinOperator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public IValueParameter<BoolValue> AllowInfeasibleSolutions {
+      get { return (IValueParameter<BoolValue>)Parameters["AllowInfeasibleSolutions"]; }
+    }
+
+    [StorableConstructor]
+    protected PotvinManipulator(bool deserializing) : base(deserializing) { }
+
+    public PotvinManipulator() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator which should be used for stochastic manipulation operators."));
+      Parameters.Add(new ValueParameter<BoolValue>("AllowInfeasibleSolutions", "Indicates if infeasible solutions should be allowed.", new BoolValue(false)));
+    }
+
+    protected PotvinManipulator(PotvinManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected abstract void Manipulate(IRandom random, PotvinEncoding individual);
+
+    protected static int SelectRandomTourBiasedByLength(IRandom random, PotvinEncoding individual, IVRPProblemInstance instance) {
+      int tourIndex = -1;
+
+      double sum = 0.0;
+      double[] probabilities = new double[individual.Tours.Count];
+      for (int i = 0; i < individual.Tours.Count; i++) {
+        probabilities[i] = 1.0 / ((double)individual.Tours[i].Stops.Count / (double)instance.Cities.Value);
+        sum += probabilities[i];
+      }
+
+      for (int i = 0; i < probabilities.Length; i++)
+        probabilities[i] = probabilities[i] / sum;
+
+      double rand = random.NextDouble();
+      double cumulatedProbabilities = 0.0;
+      int index = 0;
+      while (tourIndex == -1 && index < probabilities.Length) {
+        if (cumulatedProbabilities <= rand && rand <= cumulatedProbabilities + probabilities[index])
+          tourIndex = index;
+
+        cumulatedProbabilities += probabilities[index];
+        index++;
+      }
+
+      return tourIndex;
+    }
+
+    protected static bool FindInsertionPlace(PotvinEncoding individual, int city, int routeToAvoid, bool allowInfeasible, out int route, out int place) {
+      return individual.FindInsertionPlace(
+        city, routeToAvoid, allowInfeasible, out route, out place);
+    }
+
+    public override IOperation InstrumentedApply() {
+      IVRPEncoding solution = VRPToursParameter.ActualValue;
+      if (!(solution is PotvinEncoding)) {
+        VRPToursParameter.ActualValue = PotvinEncoding.ConvertFrom(solution, ProblemInstance);
+      }
+
+      Manipulate(RandomParameter.ActualValue, VRPToursParameter.ActualValue as PotvinEncoding);
+      (VRPToursParameter.ActualValue as PotvinEncoding).Repair();
+
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinOneLevelExchangeManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinOneLevelExchangeManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinOneLevelExchangeManipulator.cs	(revision 14416)
@@ -0,0 +1,75 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinOneLevelExchangeMainpulator", "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.")]
+  [StorableClass]
+  public sealed class PotvinOneLevelExchangeMainpulator : PotvinManipulator {
+    [StorableConstructor]
+    private PotvinOneLevelExchangeMainpulator(bool deserializing) : base(deserializing) { }
+
+    public PotvinOneLevelExchangeMainpulator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinOneLevelExchangeMainpulator(this, cloner);
+    }
+
+    private PotvinOneLevelExchangeMainpulator(PotvinOneLevelExchangeMainpulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static void ApplyManipulation(IRandom random, PotvinEncoding individual, IVRPProblemInstance instance, bool allowInfeasible) {
+      int selectedIndex = SelectRandomTourBiasedByLength(random, individual, instance);
+      if (selectedIndex >= 0) {
+        Tour route1 =
+          individual.Tours[selectedIndex];
+
+        int count = route1.Stops.Count;
+        int i = 0;
+        while (i < count) {
+          int insertedRoute, insertedPlace;
+
+          int city = route1.Stops[i];
+          route1.Stops.Remove(city);
+
+          if (FindInsertionPlace(individual, city, selectedIndex, allowInfeasible, out insertedRoute, out insertedPlace)) {
+            individual.Tours[insertedRoute].Stops.Insert(insertedPlace, city);
+          } else {
+            route1.Stops.Insert(i, city);
+            i++;
+          }
+
+          count = route1.Stops.Count;
+        }
+      }
+    }
+
+    protected override void Manipulate(IRandom random, PotvinEncoding individual) {
+      bool allowInfeasible = AllowInfeasibleSolutions.Value.Value;
+      ApplyManipulation(random, individual, ProblemInstance, allowInfeasible);      
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinPairwiseOneLevelExchangeManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinPairwiseOneLevelExchangeManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinPairwiseOneLevelExchangeManipulator.cs	(revision 14416)
@@ -0,0 +1,161 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.ProblemInstances;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPairwiseOneLevelExchangeMainpulator", "The 1M operator which manipulates a PDP representation. It has been adapted to pickup and delivery from 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 PotvinPairwiseOneLevelExchangeMainpulator : PotvinManipulator {
+    [StorableConstructor]
+    private PotvinPairwiseOneLevelExchangeMainpulator(bool deserializing) : base(deserializing) { }
+
+    public PotvinPairwiseOneLevelExchangeMainpulator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinPairwiseOneLevelExchangeMainpulator(this, cloner);
+    }
+
+    private PotvinPairwiseOneLevelExchangeMainpulator(PotvinPairwiseOneLevelExchangeMainpulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static bool PairwiseMove(PotvinEncoding individual, IVRPProblemInstance instance, int city, bool allowInfeasible) {
+      bool success;
+
+      IPickupAndDeliveryProblemInstance pdp = instance 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 = individual.Tours.Find(t => t.Stops.Contains(dest));
+        int j = destRoute.Stops.IndexOf(dest);
+
+        route1.Stops.Remove(city);
+        destRoute.Stops.Remove(dest);
+
+        int routeToAvoid = -1;
+        if (route1 == destRoute)
+          routeToAvoid = individual.Tours.IndexOf(route1);
+
+        int source, target;
+        if (instance.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];
+            VRPEvaluation eval = instance.EvaluateTour(tour, individual);
+            individual.InsertPair(tour, source, target, instance);
+            VRPEvaluation evalNew = instance.EvaluateTour(tour, individual);
+
+            double delta = evalNew.Quality - eval.Quality;
+
+            if (delta < bestQuality &&
+               (instance.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);
+          }
+        }
+
+        if (bestTour >= 0) {
+          if (bestPositionTarget < bestPositionSource) {
+            individual.Tours[bestTour].Stops.Insert(bestPositionTarget, target);
+            individual.Tours[bestTour].Stops.Insert(bestPositionSource, source);
+          } else {
+            individual.Tours[bestTour].Stops.Insert(bestPositionSource, source);
+            individual.Tours[bestTour].Stops.Insert(bestPositionTarget, target);
+          }
+
+          success = true;
+        } else {
+          if (j < i) {
+            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;
+    }
+
+    public static void ApplyManipulation(IRandom random, PotvinEncoding individual, IPickupAndDeliveryProblemInstance pdp, bool allowInfeasible) {
+      int selectedIndex = SelectRandomTourBiasedByLength(random, individual, pdp);
+      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, pdp, city, allowInfeasible))
+            i++;
+
+          count = route1.Stops.Count;
+        }
+      }
+    }
+
+
+    protected override void Manipulate(IRandom random, PotvinEncoding individual) {
+      bool allowInfeasible = AllowInfeasibleSolutions.Value.Value;
+
+      IPickupAndDeliveryProblemInstance pdp = ProblemInstance as IPickupAndDeliveryProblemInstance;
+
+      if (pdp != null) {
+        ApplyManipulation(random, individual, pdp, allowInfeasible);
+      }
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinPairwiseTwoLevelExchangeManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinPairwiseTwoLevelExchangeManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinPairwiseTwoLevelExchangeManipulator.cs	(revision 14416)
@@ -0,0 +1,196 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Encodings.PermutationEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPairwiseTwoLevelExchangeManipulator", "The 2M operator which manipulates a VRP representation.   It has been adapted to pickup and delivery from 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 PotvinPairwiseTwoLevelExchangeManipulator : PotvinManipulator {
+    [StorableConstructor]
+    private PotvinPairwiseTwoLevelExchangeManipulator(bool deserializing) : base(deserializing) { }
+
+    public PotvinPairwiseTwoLevelExchangeManipulator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinPairwiseTwoLevelExchangeManipulator(this, cloner);
+    }
+
+    private PotvinPairwiseTwoLevelExchangeManipulator(PotvinPairwiseTwoLevelExchangeManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    private static PotvinEncoding ReplacePair(PotvinEncoding individual, IVRPProblemInstance instance, int replaced, int replacing, bool allowInfeasible) {
+      individual = individual.Clone() as PotvinEncoding;
+      IPickupAndDeliveryProblemInstance pdp = instance 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 = 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 = individual.Tours.Find(t => t.Stops.Contains(replacingSource));
+      Tour replacingTargetTour = individual.Tours.Find(t => t.Stops.Contains(replacingTarget));
+
+      replacingSourceTour.Stops.Remove(replacingSource);
+      replacingTargetTour.Stops.Remove(replacingTarget);
+
+      replacedSourceTour.Stops[replacedSourceTour.Stops.IndexOf(replacedSource)] = replacingSource;
+      if (!allowInfeasible && !instance.TourFeasible(replacedSourceTour, individual))
+        return null;
+
+      replacedTargetTour.Stops[replacedTargetTour.Stops.IndexOf(replacedTarget)] = replacingTarget;
+      if (!allowInfeasible && !instance.TourFeasible(replacedTargetTour, individual))
+        return null;
+
+      double bestQuality = double.MaxValue;
+      int bestTour = -1;
+      int bestPositionSource = -1;
+      int bestPositionTarget = -1;
+
+      int routeToAvoid = individual.Tours.IndexOf(replacingSourceTour);
+
+      for (int tourIdx = 0; tourIdx < individual.Tours.Count; tourIdx++) {
+        if (tourIdx != routeToAvoid) {
+          Tour tour = individual.Tours[tourIdx];
+          VRPEvaluation eval = instance.EvaluateTour(tour, individual);
+          individual.InsertPair(tour, replacedSource, replacedTarget, instance);
+          VRPEvaluation evalNew = instance.EvaluateTour(tour, individual);
+
+          double delta = evalNew.Quality - eval.Quality;
+
+          if (delta < bestQuality &&
+              (instance.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);
+        }
+      }
+
+      if (bestTour != -1) {
+        if (bestPositionTarget < bestPositionSource) {
+          individual.Tours[bestTour].Stops.Insert(bestPositionTarget, replacedTarget);
+          individual.Tours[bestTour].Stops.Insert(bestPositionSource, replacedSource);
+        } else {
+          individual.Tours[bestTour].Stops.Insert(bestPositionSource, replacedSource);
+          individual.Tours[bestTour].Stops.Insert(bestPositionTarget, replacedTarget);
+        }
+
+        return individual;
+      } else {
+        return null;
+      }
+    }
+
+    public static PotvinEncoding ApplyManipulation(IRandom random, PotvinEncoding individual, IPickupAndDeliveryProblemInstance pdp, bool allowInfeasible) {
+      PotvinEncoding result = null;
+      
+      int selectedIndex = SelectRandomTourBiasedByLength(random, individual, pdp);
+      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;
+
+          while (customer1Position < route1.Stops.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) != customer2) {
+                    result = ReplacePair(individual, pdp, customer2, customer1, allowInfeasible);
+                    if (result != null) {
+                      individual = result;
+
+                      route1 = individual.Tours[selectedIndex];
+                      performed = true;
+                      break;
+                    }
+                  }
+                }
+              }
+
+              if (performed) {
+                break;
+              }
+            }
+
+            if (!performed)
+              customer1Position++;
+            else
+              break;
+          }
+        }
+      }
+
+      return result;
+    }
+
+    protected override void Manipulate(IRandom random, PotvinEncoding individual) {
+      bool allowInfeasible = AllowInfeasibleSolutions.Value.Value;
+      IPickupAndDeliveryProblemInstance pdp = ProblemInstance as IPickupAndDeliveryProblemInstance;
+
+      if (pdp != null) {
+        PotvinEncoding result = ApplyManipulation(random, individual, pdp, allowInfeasible);
+        if (result != null) {
+          VRPToursParameter.ActualValue = result;
+        }        
+      }
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinTwoLevelExchangeManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinTwoLevelExchangeManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinTwoLevelExchangeManipulator.cs	(revision 14416)
@@ -0,0 +1,101 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinTwoLevelExchangeManipulator", "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.")]
+  [StorableClass]
+  public sealed class PotvinTwoLevelExchangeManipulator : PotvinManipulator {
+    [StorableConstructor]
+    private PotvinTwoLevelExchangeManipulator(bool deserializing) : base(deserializing) { }
+
+    public PotvinTwoLevelExchangeManipulator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinTwoLevelExchangeManipulator(this, cloner);
+    }
+
+    private PotvinTwoLevelExchangeManipulator(PotvinTwoLevelExchangeManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static void ApplyManipulation(IRandom random, PotvinEncoding individual, IVRPProblemInstance instance, bool allowInfeasible) {
+      int selectedIndex = SelectRandomTourBiasedByLength(random, individual, instance);
+      if (selectedIndex >= 0) {
+        Tour route1 = individual.Tours[selectedIndex];
+
+        bool performed = false;
+        int customer1Position = 0;
+        while (customer1Position < route1.Stops.Count) {
+          performed = false;
+
+          foreach (Tour tour in individual.Tours) {
+            if (tour != route1) {
+              for (int customer2Position = 0; customer2Position < tour.Stops.Count; customer2Position++) {
+                int customer1 = route1.Stops[customer1Position];
+                int customer2 = tour.Stops[customer2Position];
+
+                //customer1 can be feasibly inserted at the location of customer2
+                tour.Stops[customer2Position] = customer1;
+                route1.Stops.RemoveAt(customer1Position);
+
+                if (instance.TourFeasible(tour, individual)) {
+                  int routeIdx, place;
+                  if (FindInsertionPlace(individual,
+                    customer2, selectedIndex, allowInfeasible, out routeIdx, out place)) {
+                    individual.Tours[routeIdx].Stops.Insert(place, customer2);
+
+                    //two-level exchange has been performed
+                    performed = true;
+                    break;
+                  } else {
+                    tour.Stops[customer2Position] = customer2;
+                    route1.Stops.Insert(customer1Position, customer1);
+                  }
+                } else {
+                  tour.Stops[customer2Position] = customer2;
+                  route1.Stops.Insert(customer1Position, customer1);
+                }
+              }
+            }
+
+            if (performed)
+              break;
+          }
+
+          if (!performed)
+            customer1Position++;
+        }
+      }
+    }
+      
+
+    protected override void Manipulate(IRandom random, PotvinEncoding individual) {
+      bool allowInfeasible = AllowInfeasibleSolutions.Value.Value;
+
+      ApplyManipulation(random, individual, ProblemInstance, allowInfeasible);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinVehicleAssignmentManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinVehicleAssignmentManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Manipulators/PotvinVehicleAssignmentManipulator.cs	(revision 14416)
@@ -0,0 +1,77 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Encodings.PermutationEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinVehicleAssignmentMainpulator", "A manipulator that changes the vehicle assignment")]
+  [StorableClass]
+  public sealed class PotvinVehicleAssignmentMainpulator : VRPManipulator, ITimeWindowedOperator,
+    IMultiDepotOperator, IHeterogenousCapacitatedOperator {
+    public IValueParameter<IPermutationManipulator> VehicleAssignmentManipuator {
+      get { return (IValueParameter<IPermutationManipulator>)Parameters["VehicleAssignmentManipuator"]; }
+    }
+
+    public ILookupParameter<Permutation> VehicleAssignmentParameter {
+      get { return (ILookupParameter<Permutation>)Parameters["VehicleAssignment"]; }
+    }
+
+    [StorableConstructor]
+    private PotvinVehicleAssignmentMainpulator(bool deserializing) : base(deserializing) { }
+
+    public PotvinVehicleAssignmentMainpulator()
+      : base() {
+      Parameters.Add(new ValueParameter<IPermutationManipulator>("VehicleAssignmentManipuator",
+      "The operator used to menipulate the vehicle assignments.", new Swap2Manipulator()));
+      Parameters.Add(new LookupParameter<Permutation>("VehicleAssignment"));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinVehicleAssignmentMainpulator(this, cloner);
+    }
+
+    private PotvinVehicleAssignmentMainpulator(PotvinVehicleAssignmentMainpulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IOperation InstrumentedApply() {
+      IVRPEncoding solution = VRPToursParameter.ActualValue;
+      if (!(solution is PotvinEncoding)) {
+        VRPToursParameter.ActualValue = PotvinEncoding.ConvertFrom(solution, ProblemInstance);
+      }
+
+      OperationCollection next = new OperationCollection(base.InstrumentedApply());
+
+      VehicleAssignmentParameter.ActualValue = (VRPToursParameter.ActualValue as PotvinEncoding).VehicleAssignment;
+      VehicleAssignmentManipuator.Value.PermutationParameter.ActualName = VehicleAssignmentParameter.ActualName;
+      next.Insert(0, ExecutionContext.CreateOperation(VehicleAssignmentManipuator.Value));
+
+      return next;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/IPotvinCustomerRelocationMoveOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/IPotvinCustomerRelocationMoveOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/IPotvinCustomerRelocationMoveOperator.cs	(revision 14416)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  public interface IPotvinCustomerRelocationMoveOperator : IVRPMoveOperator {
+    ILookupParameter<PotvinCustomerRelocationMove> CustomerRelocationMoveParameter { get; }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationExhaustiveMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationExhaustiveMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationExhaustiveMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,71 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinCustomerRelocationExhaustiveMoveGenerator", "Generates customer relocation moves from a given VRP encoding.")]
+  [StorableClass]
+  public sealed class PotvinCustomerRelocationExhaustiveMoveGenerator : PotvinCustomerRelocationMoveGenerator, IExhaustiveMoveGenerator {
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinCustomerRelocationExhaustiveMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private PotvinCustomerRelocationExhaustiveMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinCustomerRelocationExhaustiveMoveGenerator()
+      : base() {
+    }
+
+    private PotvinCustomerRelocationExhaustiveMoveGenerator(PotvinCustomerRelocationExhaustiveMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override PotvinCustomerRelocationMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<PotvinCustomerRelocationMove> result = new List<PotvinCustomerRelocationMove>();
+
+      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) {
+              PotvinCustomerRelocationMove move = new PotvinCustomerRelocationMove(
+                individual.Tours[i].Stops[j], i, k, individual);
+
+              result.Add(move);
+            }
+          }
+        }
+      }
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMove.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMove.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMove.cs	(revision 14416)
@@ -0,0 +1,104 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinCustomerRelocationMove", "Item that describes a relocation move on a VRP representation.")]
+  [StorableClass]
+  public class PotvinCustomerRelocationMove : 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 PotvinCustomerRelocationMove()
+      : base() {
+      City = -1;
+      Tour = -1;
+
+      Individual = null;
+    }
+
+    public PotvinCustomerRelocationMove(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 PotvinCustomerRelocationMove(this, cloner);
+    }
+
+    protected PotvinCustomerRelocationMove(PotvinCustomerRelocationMove 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;
+    }
+
+    [StorableConstructor]
+    protected PotvinCustomerRelocationMove(bool deserializing) : base(deserializing) { }
+
+    #region IVRPMove Members
+
+    public VRPMoveEvaluator GetMoveEvaluator() {
+      return new PotvinCustomerRelocationMoveEvaluator();
+    }
+
+    public VRPMoveMaker GetMoveMaker() {
+      return new PotvinCustomerRelocationMoveMaker();
+    }
+
+    public ITabuMaker GetTabuMaker() {
+      return new PotvinCustomerRelocationMoveTabuMaker();
+    }
+
+    public ITabuChecker GetTabuChecker() {
+      return new PotvinCustomerRelocationMoveTabuCriterion();
+    }
+
+    public ITabuChecker GetSoftTabuChecker() {
+      PotvinCustomerRelocationMoveTabuCriterion tabuChecker = new PotvinCustomerRelocationMoveTabuCriterion();
+      tabuChecker.UseAspirationCriterion.Value = true;
+
+      return tabuChecker;
+    }
+
+    #endregion
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMoveAttribute.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMoveAttribute.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMoveAttribute.cs	(revision 14416)
@@ -0,0 +1,67 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinCustomerRelocationMoveAttribute", "Customer relocation move attribute")]
+  [StorableClass]
+  public class PotvinCustomerRelocationMoveAttribute : VRPMoveAttribute {
+    [Storable]
+    public int Tour { get; private set; }
+    [Storable]
+    public int City { get; private set; }
+
+    [StorableConstructor]
+    protected PotvinCustomerRelocationMoveAttribute(bool deserializing) : base(deserializing) { }
+    protected PotvinCustomerRelocationMoveAttribute(PotvinCustomerRelocationMoveAttribute original, Cloner cloner)
+      : base(original, cloner) {
+      this.Tour = original.Tour;
+      this.City = original.City;
+    }
+    public PotvinCustomerRelocationMoveAttribute(double moveQuality, int tour, int city)
+      : base(moveQuality) {
+      Tour = tour;
+      City = city;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinCustomerRelocationMoveAttribute(this, cloner);
+    }
+
+    public override int GetHashCode() {
+      return Tour.GetHashCode() + City.GetHashCode();
+    }
+
+    public override bool Equals(object obj) {
+      if (obj is PotvinCustomerRelocationMoveAttribute) {
+        PotvinCustomerRelocationMoveAttribute other = obj as PotvinCustomerRelocationMoveAttribute;
+
+        return Tour == other.Tour && City == other.City;
+      } else {
+        return base.Equals(obj);
+      }
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMoveEvaluator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMoveEvaluator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMoveEvaluator.cs	(revision 14416)
@@ -0,0 +1,100 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinCustomerRelocationMoveEvaluator", "Evaluates a customer relocation move for a VRP representation. ")]
+  [StorableClass]
+  public sealed class PotvinCustomerRelocationMoveEvaluator : PotvinMoveEvaluator, IPotvinCustomerRelocationMoveOperator {
+    public ILookupParameter<PotvinCustomerRelocationMove> CustomerRelocationMoveParameter {
+      get { return (ILookupParameter<PotvinCustomerRelocationMove>)Parameters["PotvinCustomerRelocationMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return CustomerRelocationMoveParameter; }
+    }
+
+    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 PotvinCustomerRelocationMoveEvaluator(bool deserializing) : base(deserializing) { }
+
+    public PotvinCustomerRelocationMoveEvaluator()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinCustomerRelocationMove>("PotvinCustomerRelocationMove", "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 PotvinCustomerRelocationMoveEvaluator(this, cloner);
+    }
+
+    private PotvinCustomerRelocationMoveEvaluator(PotvinCustomerRelocationMoveEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void EvaluateMove() {
+      PotvinCustomerRelocationMove move = CustomerRelocationMoveParameter.ActualValue;
+
+      PotvinEncoding newSolution = CustomerRelocationMoveParameter.ActualValue.Individual.Clone() as PotvinEncoding;
+      PotvinCustomerRelocationMoveMaker.Apply(newSolution, move, ProblemInstance);
+
+      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/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,74 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinCustomerRelocationMoveGenerator", "Generates customer relocation moves from a given VRP encoding.")]
+  [StorableClass]
+  public abstract class PotvinCustomerRelocationMoveGenerator : PotvinMoveGenerator, IPotvinCustomerRelocationMoveOperator {
+    public ILookupParameter<PotvinCustomerRelocationMove> CustomerRelocationMoveParameter {
+      get { return (ILookupParameter<PotvinCustomerRelocationMove>)Parameters["PotvinCustomerRelocationMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return CustomerRelocationMoveParameter; }
+    }
+
+    protected ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+
+    [StorableConstructor]
+    protected PotvinCustomerRelocationMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinCustomerRelocationMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinCustomerRelocationMove>("PotvinCustomerRelocationMove", "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 PotvinCustomerRelocationMoveGenerator(PotvinCustomerRelocationMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected abstract PotvinCustomerRelocationMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance);
+
+    public override IOperation InstrumentedApply() {
+      IOperation next = base.InstrumentedApply();
+
+      PotvinEncoding individual = VRPToursParameter.ActualValue as PotvinEncoding;
+      PotvinCustomerRelocationMove[] 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(CustomerRelocationMoveParameter.ActualName, moves[i]));
+      }
+      CurrentScopeParameter.ActualValue.SubScopes.AddRange(moveScopes);
+
+      return next;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMoveMaker.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMoveMaker.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMoveMaker.cs	(revision 14416)
@@ -0,0 +1,118 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinCustomerRelocationMoveMaker", "Peforms the customer relocation move on a given VRP encoding and updates the quality.")]
+  [StorableClass]
+  public class PotvinCustomerRelocationMoveMaker : PotvinMoveMaker, IPotvinCustomerRelocationMoveOperator, IMoveMaker {
+    public ILookupParameter<PotvinCustomerRelocationMove> CustomerRelocationMoveParameter {
+      get { return (ILookupParameter<PotvinCustomerRelocationMove>)Parameters["PotvinCustomerRelocationMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return CustomerRelocationMoveParameter; }
+    }
+
+    public ILookupParameter<VariableCollection> MemoriesParameter {
+      get { return (ILookupParameter<VariableCollection>)Parameters["Memories"]; }
+    }
+
+    public IValueParameter<StringValue> AdditionFrequencyMemoryKeyParameter {
+      get { return (IValueParameter<StringValue>)Parameters["AdditionFrequencyMemoryKey"]; }
+    }
+
+    [StorableConstructor]
+    protected PotvinCustomerRelocationMoveMaker(bool deserializing) : base(deserializing) { }
+
+    public PotvinCustomerRelocationMoveMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinCustomerRelocationMove>("PotvinCustomerRelocationMove", "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 PotvinCustomerRelocationMoveMaker(this, cloner);
+    }
+
+    protected PotvinCustomerRelocationMoveMaker(PotvinCustomerRelocationMoveMaker original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static void Apply(PotvinEncoding solution, PotvinCustomerRelocationMove 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 (oldTour.Stops.Count == 0)
+        solution.Tours.Remove(oldTour);*/
+
+      int place = solution.FindBestInsertionPlace(tour, move.City);
+      tour.Stops.Insert(place, move.City);
+
+      solution.Repair();
+    }
+
+    protected override void PerformMove() {
+      PotvinCustomerRelocationMove move = CustomerRelocationMoveParameter.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/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMoveTabuCriterion.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMoveTabuCriterion.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMoveTabuCriterion.cs	(revision 14416)
@@ -0,0 +1,114 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Linq;
+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;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinCustomerRelocationTabuCriterion", @"Checks if a certain customer relocation move is tabu.")]
+  [StorableClass]
+  public class PotvinCustomerRelocationMoveTabuCriterion : SingleSuccessorOperator, IPotvinCustomerRelocationMoveOperator, ITabuChecker, IPotvinOperator, IVRPMoveOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+
+    public ILookupParameter<PotvinCustomerRelocationMove> CustomerRelocationMoveParameter {
+      get { return (ILookupParameter<PotvinCustomerRelocationMove>)Parameters["PotvinCustomerRelocationMove"]; }
+    }
+    public ILookupParameter VRPMoveParameter {
+      get { return CustomerRelocationMoveParameter; }
+    }
+    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 BoolValue UseAspirationCriterion {
+      get { return UseAspirationCriterionParameter.Value; }
+      set { UseAspirationCriterionParameter.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected PotvinCustomerRelocationMoveTabuCriterion(bool deserializing) : base(deserializing) { }
+    protected PotvinCustomerRelocationMoveTabuCriterion(PotvinCustomerRelocationMoveTabuCriterion original, Cloner cloner) : base(original, cloner) { }
+    public PotvinCustomerRelocationMoveTabuCriterion()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinCustomerRelocationMove>("PotvinCustomerRelocationMove", "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."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinCustomerRelocationMoveTabuCriterion(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      ItemList<IItem> tabuList = TabuListParameter.ActualValue;
+      double moveQuality = MoveQualityParameter.ActualValue.Value;
+      bool useAspiration = UseAspirationCriterion.Value;
+      bool isTabu = false;
+      PotvinCustomerRelocationMove move = CustomerRelocationMoveParameter.ActualValue;
+
+      foreach (var attribute in tabuList.OfType<PotvinCustomerRelocationMoveAttribute>()) {
+        if (!useAspiration || moveQuality >= attribute.MoveQuality) {
+          if (attribute.City == move.City && attribute.Tour == move.Tour) {
+            isTabu = true;
+            break;
+          }
+        }
+      }
+
+      MoveTabuParameter.ActualValue = new BoolValue(isTabu);
+      return base.Apply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMoveTabuMaker.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMoveTabuMaker.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMoveTabuMaker.cs	(revision 14416)
@@ -0,0 +1,67 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinCustomerRelocationMoveTabuMaker", "Declares a given customer relocation move as tabu.")]
+  [StorableClass]
+  public class PotvinCustomerRelocationMoveTabuMaker : TabuMaker, IPotvinCustomerRelocationMoveOperator, IPotvinOperator {
+    public ILookupParameter<PotvinCustomerRelocationMove> CustomerRelocationMoveParameter {
+      get { return (ILookupParameter<PotvinCustomerRelocationMove>)Parameters["PotvinCustomerRelocationMove"]; }
+    }
+    public ILookupParameter VRPMoveParameter {
+      get { return CustomerRelocationMoveParameter; }
+    }
+    public ILookupParameter<IVRPEncoding> VRPToursParameter {
+      get { return (ILookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (LookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+
+    [StorableConstructor]
+    protected PotvinCustomerRelocationMoveTabuMaker(bool deserializing) : base(deserializing) { }
+    protected PotvinCustomerRelocationMoveTabuMaker(PotvinCustomerRelocationMoveTabuMaker original, Cloner cloner) : base(original, cloner) { }
+    public PotvinCustomerRelocationMoveTabuMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinCustomerRelocationMove>("PotvinCustomerRelocationMove", "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"));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinCustomerRelocationMoveTabuMaker(this, cloner);
+    }
+
+    protected override IItem GetTabuAttribute(bool maximization, double quality, double moveQuality) {
+      PotvinCustomerRelocationMove move = CustomerRelocationMoveParameter.ActualValue;
+      double baseQuality = moveQuality;
+      //if (quality < moveQuality) baseQuality = quality; // we make an uphill move, the lower bound is the solution quality
+      return new PotvinCustomerRelocationMoveAttribute(baseQuality, move.OldTour, move.City);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMultiMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMultiMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationMultiMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,71 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinCustomerRelocationMultiMoveGenerator", "Generates customer relocation moves from a given VRP encoding.")]
+  [StorableClass]
+  public sealed class PotvinCustomerRelocationMultiMoveGenerator : PotvinCustomerRelocationMoveGenerator, 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 PotvinCustomerRelocationMultiMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private PotvinCustomerRelocationMultiMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinCustomerRelocationMultiMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("SampleSize", "The number of moves to generate."));
+    }
+
+    private PotvinCustomerRelocationMultiMoveGenerator(PotvinCustomerRelocationMultiMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override PotvinCustomerRelocationMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<PotvinCustomerRelocationMove> result = new List<PotvinCustomerRelocationMove>();
+
+      for (int i = 0; i < SampleSizeParameter.ActualValue.Value; i++) {
+        result.Add(PotvinCustomerRelocationSingleMoveGenerator.Apply(individual, ProblemInstance, RandomParameter.ActualValue));
+      }
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationSingleMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationSingleMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/CustomerRelocation/PotvinCustomerRelocationSingleMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,89 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinCustomerRelocationSingleMoveGenerator", "Generates a single customer relocation move from a given VRP encoding.")]
+  [StorableClass]
+  public sealed class PotvinCustomerRelocationSingleMoveGenerator : PotvinCustomerRelocationMoveGenerator,
+    ISingleMoveGenerator {
+    #region IMultiVRPMoveOperator Members
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return (ILookupParameter)Parameters["PotvinCustomerRelocationMove"]; }
+    }
+
+    #endregion
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinCustomerRelocationSingleMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private PotvinCustomerRelocationSingleMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinCustomerRelocationSingleMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+    }
+
+    private PotvinCustomerRelocationSingleMoveGenerator(PotvinCustomerRelocationSingleMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static PotvinCustomerRelocationMove Apply(PotvinEncoding individual, IVRPProblemInstance problemInstance, IRandom rand) {
+      int city = 1 + rand.Next(individual.Cities);
+      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 PotvinCustomerRelocationMove(city, oldTourIndex, newTourIndex, individual);
+    }
+
+    protected override PotvinCustomerRelocationMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<PotvinCustomerRelocationMove> result = new List<PotvinCustomerRelocationMove>();
+
+      PotvinCustomerRelocationMove move = Apply(individual, ProblemInstance, RandomParameter.ActualValue);
+      if (move != null)
+        result.Add(move);
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/IPotvinPDExchangeMoveOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/IPotvinPDExchangeMoveOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/IPotvinPDExchangeMoveOperator.cs	(revision 14416)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  public interface IPotvinPDExchangeMoveOperator : IVRPMoveOperator {
+    ILookupParameter<PotvinPDExchangeMove> PDExchangeMoveParameter { get; }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeExhaustiveMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeExhaustiveMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeExhaustiveMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,88 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDExchangeExhaustiveMoveGenerator", "Generates exchange moves from a given PDP encoding.")]
+  [StorableClass]
+  public sealed class PotvinPDExchangeExhaustiveMoveGenerator : PotvinPDExchangeMoveGenerator, IExhaustiveMoveGenerator {
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinPDExchangeExhaustiveMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private PotvinPDExchangeExhaustiveMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinPDExchangeExhaustiveMoveGenerator()
+      : base() {
+    }
+
+    private PotvinPDExchangeExhaustiveMoveGenerator(PotvinPDExchangeExhaustiveMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override PotvinPDExchangeMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<PotvinPDExchangeMove> result = new List<PotvinPDExchangeMove>();
+      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) {
+                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) {
+                    bool valid = pdp == null ||
+                      (pdp.GetPickupDeliveryLocation(city2) != pdp.GetPickupDeliveryLocation(city1) &&
+                       pdp.GetPickupDeliveryLocation(city2) != city1 &&
+                       pdp.GetPickupDeliveryLocation(city1) != city2);
+
+                    if (valid) {
+                      PotvinPDExchangeMove move = new PotvinPDExchangeMove(
+                        city1, i, k, city2, individual);
+
+                      result.Add(move);
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeMove.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeMove.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeMove.cs	(revision 14416)
@@ -0,0 +1,136 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDExchangeMove", "Item that describes a exchange move on a PDP representation.")]
+  [StorableClass]
+  public class PotvinPDExchangeMove : 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 PotvinPDExchangeMove()
+      : base() {
+      City = -1;
+      Tour = -1;
+
+      Individual = null;
+    }
+
+    public PotvinPDExchangeMove(int city, int oldTour, int tour, int replaced, PotvinEncoding individual) {
+      City = city;
+      OldTour = oldTour;
+      Tour = tour;
+      Replaced = replaced;
+
+      this.Individual = individual.Clone() as PotvinEncoding;
+    }
+
+    [StorableConstructor]
+    protected PotvinPDExchangeMove(bool deserializing) : base(deserializing) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinPDExchangeMove(this, cloner);
+    }
+
+    protected PotvinPDExchangeMove(PotvinPDExchangeMove 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 PotvinPDExchangeMoveEvaluator moveEvaluator;
+    public VRPMoveEvaluator GetMoveEvaluator() {
+      if (moveEvaluator == null)
+        moveEvaluator = new PotvinPDExchangeMoveEvaluator();
+
+      return moveEvaluator;
+    }
+
+    [ThreadStatic]
+    private static PotvinPDExchangeMoveMaker moveMaker;
+    public VRPMoveMaker GetMoveMaker() {
+      if (moveMaker == null)
+        moveMaker = new PotvinPDExchangeMoveMaker();
+
+      return moveMaker;
+    }
+
+    [ThreadStatic]
+    private static PotvinPDExchangeMoveTabuMaker tabuMaker;
+    public ITabuMaker GetTabuMaker() {
+      if (tabuMaker == null)
+        tabuMaker = new PotvinPDExchangeMoveTabuMaker();
+
+      return tabuMaker;
+    }
+
+    [ThreadStatic]
+    private static PotvinPDExchangeTabuCriterion tabuChecker;
+    public ITabuChecker GetTabuChecker() {
+      if (tabuChecker == null) {
+        tabuChecker = new PotvinPDExchangeTabuCriterion();
+        tabuChecker.UseAspirationCriterion.Value = false;
+      }
+
+      return tabuChecker;
+    }
+
+    [ThreadStatic]
+    private static PotvinPDExchangeTabuCriterion softTabuChecker;
+    public ITabuChecker GetSoftTabuChecker() {
+      if (softTabuChecker == null) {
+        softTabuChecker = new PotvinPDExchangeTabuCriterion();
+        softTabuChecker.UseAspirationCriterion.Value = true;
+      }
+
+      return softTabuChecker;
+    }
+
+    #endregion
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeMoveEvaluator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeMoveEvaluator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeMoveEvaluator.cs	(revision 14416)
@@ -0,0 +1,81 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDExchangeMoveEvaluator", "Evaluates a exchange move for a PDP representation. ")]
+  [StorableClass]
+  public sealed class PotvinPDExchangeMoveEvaluator : PotvinMoveEvaluator, IPotvinPDExchangeMoveOperator {
+    public ILookupParameter<PotvinPDExchangeMove> PDExchangeMoveParameter {
+      get { return (ILookupParameter<PotvinPDExchangeMove>)Parameters["PotvinPDExchangeMove"]; }
+    }
+
+    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 PotvinPDExchangeMoveEvaluator(bool deserializing) : base(deserializing) { }
+
+    public PotvinPDExchangeMoveEvaluator()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinPDExchangeMove>("PotvinPDExchangeMove", "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 PotvinPDExchangeMoveEvaluator(this, cloner);
+    }
+
+    private PotvinPDExchangeMoveEvaluator(PotvinPDExchangeMoveEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void EvaluateMove() {
+      PotvinPDExchangeMove move = PDExchangeMoveParameter.ActualValue;
+
+      PotvinEncoding newSolution = PDExchangeMoveParameter.ActualValue.Individual.Clone() as PotvinEncoding;
+      PotvinPDExchangeMoveMaker.Apply(newSolution, move, ProblemInstance);
+
+      UpdateEvaluation(newSolution);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,74 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDExchangeMoveGenerator", "Generates exchange moves from a given PDP encoding.")]
+  [StorableClass]
+  public abstract class PotvinPDExchangeMoveGenerator : PotvinMoveGenerator, IPotvinPDExchangeMoveOperator {
+    public ILookupParameter<PotvinPDExchangeMove> PDExchangeMoveParameter {
+      get { return (ILookupParameter<PotvinPDExchangeMove>)Parameters["PotvinPDExchangeMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return PDExchangeMoveParameter; }
+    }
+
+    protected ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+
+    [StorableConstructor]
+    protected PotvinPDExchangeMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinPDExchangeMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinPDExchangeMove>("PotvinPDExchangeMove", "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 PotvinPDExchangeMoveGenerator(PotvinPDExchangeMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected abstract PotvinPDExchangeMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance);
+
+    public override IOperation InstrumentedApply() {
+      IOperation next = base.InstrumentedApply();
+
+      PotvinEncoding individual = VRPToursParameter.ActualValue as PotvinEncoding;
+      PotvinPDExchangeMove[] 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/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeMoveMaker.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeMoveMaker.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeMoveMaker.cs	(revision 14416)
@@ -0,0 +1,102 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDExchangeMoveMaker", "Peforms the exchange move on a given PDP encoding and updates the quality.")]
+  [StorableClass]
+  public class PotvinPDExchangeMoveMaker : PotvinMoveMaker, IPotvinPDExchangeMoveOperator, IMoveMaker {
+    public ILookupParameter<PotvinPDExchangeMove> PDExchangeMoveParameter {
+      get { return (ILookupParameter<PotvinPDExchangeMove>)Parameters["PotvinPDExchangeMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return PDExchangeMoveParameter; }
+    }
+
+    [StorableConstructor]
+    protected PotvinPDExchangeMoveMaker(bool deserializing) : base(deserializing) { }
+
+    public PotvinPDExchangeMoveMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinPDExchangeMove>("PotvinPDExchangeMove", "The moves that should be made."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinPDExchangeMoveMaker(this, cloner);
+    }
+
+    protected PotvinPDExchangeMoveMaker(PotvinPDExchangeMoveMaker original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static void Apply(PotvinEncoding solution, PotvinPDExchangeMove 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;
+
+        int location = pdp.GetPickupDeliveryLocation(move.City);
+        Tour oldTour2 = solution.Tours.Find(t => t.Stops.Contains(location));
+        oldTour2.Stops.Remove(location);
+
+        location = pdp.GetPickupDeliveryLocation(move.Replaced);
+        oldTour2 = solution.Tours.Find(t => t.Stops.Contains(location));
+
+        oldTour2.Stops.Remove(location);
+        tour.Stops.Remove(move.Replaced);
+
+        solution.InsertPair(tour, move.City, pdp.GetPickupDeliveryLocation(move.City), problemInstance);
+        solution.InsertPair(oldTour, move.Replaced, pdp.GetPickupDeliveryLocation(move.Replaced), problemInstance);
+      } 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);
+      }
+
+      solution.Repair();
+    }
+
+    protected override void PerformMove() {
+      PotvinPDExchangeMove move = PDExchangeMoveParameter.ActualValue;
+
+      PotvinEncoding newSolution = move.Individual.Clone() as PotvinEncoding;
+      Apply(newSolution, move, ProblemInstance);
+      VRPToursParameter.ActualValue = newSolution;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeMoveTabuCriterion.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeMoveTabuCriterion.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeMoveTabuCriterion.cs	(revision 14416)
@@ -0,0 +1,165 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDExchangeTabuCriterion", @"Checks if a certain exchange move is tabu.")]
+  [StorableClass]
+  public class PotvinPDExchangeTabuCriterion : SingleSuccessorOperator, IPotvinPDExchangeMoveOperator, ITabuChecker, IPotvinOperator, IVRPMoveOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+
+    public ILookupParameter<PotvinPDExchangeMove> PDExchangeMoveParameter {
+      get { return (ILookupParameter<PotvinPDExchangeMove>)Parameters["PotvinPDExchangeMove"]; }
+    }
+    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 PotvinPDExchangeTabuCriterion(bool deserializing) : base(deserializing) { }
+    protected PotvinPDExchangeTabuCriterion(PotvinPDExchangeTabuCriterion original, Cloner cloner) : base(original, cloner) { }
+    public PotvinPDExchangeTabuCriterion()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinPDExchangeMove>("PotvinPDExchangeMove", "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 PotvinPDExchangeTabuCriterion(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      ItemList<IItem> tabuList = TabuListParameter.ActualValue;
+      double moveQuality = MoveQualityParameter.ActualValue.Value;
+      bool useAspiration = UseAspirationCriterion.Value;
+      bool isTabu = false;
+      PotvinPDExchangeMove move = PDExchangeMoveParameter.ActualValue;
+
+      foreach (IItem tabuMove in tabuList) {
+        PotvinPDRelocateMoveAttribute attribute = tabuMove as PotvinPDRelocateMoveAttribute;
+
+        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/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeMoveTabuMaker.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeMoveTabuMaker.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeMoveTabuMaker.cs	(revision 14416)
@@ -0,0 +1,142 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDExchangeMoveTabuMaker", "Declares a given exchange move as tabu.")]
+  [StorableClass]
+  public class PotvinPDExchangeMoveTabuMaker : SingleSuccessorOperator, ITabuMaker, IPotvinPDExchangeMoveOperator, IPotvinOperator, ISingleObjectiveOperator {
+    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<PotvinPDExchangeMove> PDExchangeMoveParameter {
+      get { return (ILookupParameter<PotvinPDExchangeMove>)Parameters["PotvinPDExchangeMove"]; }
+    }
+    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 PotvinPDExchangeMoveTabuMaker(bool deserializing) : base(deserializing) { }
+    protected PotvinPDExchangeMoveTabuMaker(PotvinPDExchangeMoveTabuMaker original, Cloner cloner) : base(original, cloner) { }
+    public PotvinPDExchangeMoveTabuMaker()
+      : 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<PotvinPDExchangeMove>("PotvinPDExchangeMove", "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 PotvinPDExchangeMoveTabuMaker(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);
+      }
+
+      PotvinPDExchangeMove 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 PotvinPDRelocateMoveAttribute(baseQuality, move.OldTour, move.City, distance, overload, tardiness, pickupViolations));
+      tabuList.Add(new PotvinPDRelocateMoveAttribute(baseQuality, move.Tour, move.Replaced, distance, overload, tardiness, pickupViolations));
+      return base.Apply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeMultiMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeMultiMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeMultiMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,73 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDExchangeMultiMoveGenerator", "Generates exchange moves from a given PDP encoding.")]
+  [StorableClass]
+  public sealed class PotvinPDExchangeMultiMoveGenerator : PotvinPDExchangeMoveGenerator, 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 PotvinPDExchangeMultiMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private PotvinPDExchangeMultiMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinPDExchangeMultiMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("SampleSize", "The number of moves to generate."));
+    }
+
+    private PotvinPDExchangeMultiMoveGenerator(PotvinPDExchangeMultiMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override PotvinPDExchangeMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<PotvinPDExchangeMove> result = new List<PotvinPDExchangeMove>();
+
+      for (int i = 0; i < SampleSizeParameter.ActualValue.Value; i++) {
+        var move = PotvinPDExchangeSingleMoveGenerator.Apply(individual, ProblemInstance, RandomParameter.ActualValue);
+        if (move != null)
+          result.Add(move);
+      }
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeSingleMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeSingleMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDExchange/PotvinPDExchangeSingleMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,111 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDExchangeSingleMoveGenerator", "Generates a single exchange move from a given PDP encoding.")]
+  [StorableClass]
+  public sealed class PotvinPDExchangeSingleMoveGenerator : PotvinPDExchangeMoveGenerator,
+    ISingleMoveGenerator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinPDExchangeSingleMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private PotvinPDExchangeSingleMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinPDExchangeSingleMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+    }
+
+    private PotvinPDExchangeSingleMoveGenerator(PotvinPDExchangeSingleMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static PotvinPDExchangeMove 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) {
+        PotvinPDExchangeMove 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 - 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) != 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 PotvinPDExchangeMove(city, oldTourIndex, newTourIndex, replaced, individual);
+          }
+        }
+
+        return move;
+      } else {
+        return null;
+      }
+    }
+
+    protected override PotvinPDExchangeMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<PotvinPDExchangeMove> result = new List<PotvinPDExchangeMove>();
+
+      PotvinPDExchangeMove move = Apply(individual, ProblemInstance, RandomParameter.ActualValue);
+      if (move != null)
+        result.Add(move);
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/IPotvinPDRearrangeMoveOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/IPotvinPDRearrangeMoveOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/IPotvinPDRearrangeMoveOperator.cs	(revision 14416)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  public interface IPotvinPDRearrangeMoveOperator : IVRPMoveOperator {
+    ILookupParameter<PotvinPDRearrangeMove> PDRearrangeMoveParameter { get; }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeExhaustiveMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeExhaustiveMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeExhaustiveMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,64 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDRearrangeExhaustiveMoveGenerator", "Generates rearrange moves from a given PDP encoding.")]
+  [StorableClass]
+  public sealed class PotvinPDRearrangeExhaustiveMoveGenerator : PotvinPDRearrangeMoveGenerator, IExhaustiveMoveGenerator {
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinPDRearrangeExhaustiveMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private PotvinPDRearrangeExhaustiveMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinPDRearrangeExhaustiveMoveGenerator()
+      : base() {
+    }
+
+    private PotvinPDRearrangeExhaustiveMoveGenerator(PotvinPDRearrangeExhaustiveMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override PotvinPDRearrangeMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<PotvinPDRearrangeMove> result = new List<PotvinPDRearrangeMove>();
+      IPickupAndDeliveryProblemInstance pdp = problemInstance as IPickupAndDeliveryProblemInstance;
+
+      for (int i = 1; i <= problemInstance.Cities.Value; i++) {
+        if (pdp == null || pdp.GetDemand(i) >= 0) {
+          int tour = individual.Tours.FindIndex(t => t.Stops.Contains(i));
+
+          result.Add(new PotvinPDRearrangeMove(i, tour, individual));
+        }
+      }
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeMove.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeMove.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeMove.cs	(revision 14416)
@@ -0,0 +1,126 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDRearrangeMove", "Item that describes a rearrange move on a PDP representation.")]
+  [StorableClass]
+  public class PotvinPDRearrangeMove : Item, IVRPMove {
+    [Storable]
+    public IVRPEncoding Individual { get; protected set; }
+
+    [Storable]
+    public int City { get; protected set; }
+
+    [Storable]
+    public int Tour { get; protected set; }
+
+    public PotvinPDRearrangeMove()
+      : base() {
+      City = -1;
+      Tour = -1;
+
+      Individual = null;
+    }
+
+    public PotvinPDRearrangeMove(int city, int tour, PotvinEncoding individual) {
+      City = city;
+      Tour = tour;
+
+      this.Individual = individual.Clone() as PotvinEncoding;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinPDRearrangeMove(this, cloner);
+    }
+
+    protected PotvinPDRearrangeMove(PotvinPDRearrangeMove original, Cloner cloner)
+      : base(original, cloner) {
+      this.City = original.City;
+      this.Tour = original.Tour;
+
+      this.Individual = cloner.Clone(Individual) as PotvinEncoding;
+    }
+
+    [StorableConstructor]
+    protected PotvinPDRearrangeMove(bool deserializing) : base(deserializing) { }
+
+    #region IVRPMove Members
+
+    [ThreadStatic]
+    private static PotvinPDRearrangeMoveEvaluator moveEvaluator;
+    public VRPMoveEvaluator GetMoveEvaluator() {
+      if (moveEvaluator == null)
+        moveEvaluator = new PotvinPDRearrangeMoveEvaluator();
+
+      return moveEvaluator;
+    }
+
+    [ThreadStatic]
+    private static PotvinPDRearrangeMoveMaker moveMaker;
+    public VRPMoveMaker GetMoveMaker() {
+      if (moveMaker == null)
+        moveMaker = new PotvinPDRearrangeMoveMaker();
+
+      return moveMaker;
+    }
+
+    [ThreadStatic]
+    private static PotvinPDRearrangeMoveTabuMaker tabuMaker;
+    public ITabuMaker GetTabuMaker() {
+      if (tabuMaker == null)
+        tabuMaker = new PotvinPDRearrangeMoveTabuMaker();
+
+      return tabuMaker;
+    }
+
+    [ThreadStatic]
+    private static PotvinPDRearrangeTabuCriterion tabuChecker;
+    public ITabuChecker GetTabuChecker() {
+      if (tabuChecker == null) {
+        tabuChecker = new PotvinPDRearrangeTabuCriterion();
+        tabuChecker.UseAspirationCriterion.Value = false;
+      }
+
+      return tabuChecker;
+    }
+
+    [ThreadStatic]
+    private static PotvinPDRearrangeTabuCriterion softTabuChecker;
+    public ITabuChecker GetSoftTabuChecker() {
+      if (softTabuChecker == null) {
+        softTabuChecker = new PotvinPDRearrangeTabuCriterion();
+        softTabuChecker.UseAspirationCriterion.Value = true;
+      }
+
+      return softTabuChecker;
+    }
+
+    #endregion
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeMoveEvaluator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeMoveEvaluator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeMoveEvaluator.cs	(revision 14416)
@@ -0,0 +1,81 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDRearrangeMoveEvaluator", "Evaluates a rearrange move for a PDP representation. ")]
+  [StorableClass]
+  public sealed class PotvinPDRearrangeMoveEvaluator : PotvinMoveEvaluator, IPotvinPDRearrangeMoveOperator {
+    public ILookupParameter<PotvinPDRearrangeMove> PDRearrangeMoveParameter {
+      get { return (ILookupParameter<PotvinPDRearrangeMove>)Parameters["PotvinPDRearrangeMove"]; }
+    }
+
+    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 PotvinPDRearrangeMoveEvaluator(bool deserializing) : base(deserializing) { }
+
+    public PotvinPDRearrangeMoveEvaluator()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinPDRearrangeMove>("PotvinPDRearrangeMove", "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 PotvinPDRearrangeMoveEvaluator(this, cloner);
+    }
+
+    private PotvinPDRearrangeMoveEvaluator(PotvinPDRearrangeMoveEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void EvaluateMove() {
+      PotvinPDRearrangeMove move = PDRearrangeMoveParameter.ActualValue;
+
+      PotvinEncoding newSolution = PDRearrangeMoveParameter.ActualValue.Individual.Clone() as PotvinEncoding;
+      PotvinPDRearrangeMoveMaker.Apply(newSolution, move, ProblemInstance);
+
+      UpdateEvaluation(newSolution);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,74 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDRearrangeMoveGenerator", "Generates rearrange moves from a given PDP encoding.")]
+  [StorableClass]
+  public abstract class PotvinPDRearrangeMoveGenerator : PotvinMoveGenerator, IPotvinPDRearrangeMoveOperator {
+    public ILookupParameter<PotvinPDRearrangeMove> PDRearrangeMoveParameter {
+      get { return (ILookupParameter<PotvinPDRearrangeMove>)Parameters["PotvinPDRearrangeMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return PDRearrangeMoveParameter; }
+    }
+
+    protected ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+
+    [StorableConstructor]
+    protected PotvinPDRearrangeMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinPDRearrangeMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinPDRearrangeMove>("PotvinPDRearrangeMove", "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 PotvinPDRearrangeMoveGenerator(PotvinPDRearrangeMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected abstract PotvinPDRearrangeMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance);
+
+    public override IOperation InstrumentedApply() {
+      IOperation next = base.InstrumentedApply();
+
+      PotvinEncoding individual = VRPToursParameter.ActualValue as PotvinEncoding;
+      PotvinPDRearrangeMove[] 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/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeMoveMaker.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeMoveMaker.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeMoveMaker.cs	(revision 14416)
@@ -0,0 +1,89 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDRearrangeMoveMaker", "Peforms the rearrange move on a given PDP encoding and updates the quality.")]
+  [StorableClass]
+  public class PotvinPDRearrangeMoveMaker : PotvinMoveMaker, IPotvinPDRearrangeMoveOperator, IMoveMaker {
+    public ILookupParameter<PotvinPDRearrangeMove> PDRearrangeMoveParameter {
+      get { return (ILookupParameter<PotvinPDRearrangeMove>)Parameters["PotvinPDRearrangeMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return PDRearrangeMoveParameter; }
+    }
+
+    [StorableConstructor]
+    protected PotvinPDRearrangeMoveMaker(bool deserializing) : base(deserializing) { }
+
+    public PotvinPDRearrangeMoveMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinPDRearrangeMove>("PotvinPDRearrangeMove", "The moves that should be made."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinPDRearrangeMoveMaker(this, cloner);
+    }
+
+    protected PotvinPDRearrangeMoveMaker(PotvinPDRearrangeMoveMaker original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static void Apply(PotvinEncoding solution, PotvinPDRearrangeMove 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 tour2 = solution.Tours.Find(t => t.Stops.Contains(location));
+        int position2 = tour2.Stops.IndexOf(location);
+
+        tour.Stops.Remove(move.City);
+        tour2.Stops.Remove(location);
+
+        solution.InsertPair(tour, move.City, location, problemInstance, position, position2);
+      } else {
+        tour.Stops.Remove(move.City);
+        int place = solution.FindBestInsertionPlace(tour, move.City, position);
+        tour.Stops.Insert(place, move.City);
+      }
+
+      solution.Repair();
+    }
+
+    protected override void PerformMove() {
+      PotvinPDRearrangeMove move = PDRearrangeMoveParameter.ActualValue;
+
+      PotvinEncoding newSolution = move.Individual.Clone() as PotvinEncoding;
+      Apply(newSolution, move, ProblemInstance);
+      VRPToursParameter.ActualValue = newSolution;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeMoveTabuCriterion.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeMoveTabuCriterion.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeMoveTabuCriterion.cs	(revision 14416)
@@ -0,0 +1,164 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDRearrangeTabuCriterion", @"Checks if a certain rearrange move is tabu.")]
+  [StorableClass]
+  public class PotvinPDRearrangeTabuCriterion : SingleSuccessorOperator, IPotvinPDRearrangeMoveOperator, ITabuChecker, IPotvinOperator, IVRPMoveOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+
+    public ILookupParameter<PotvinPDRearrangeMove> PDRearrangeMoveParameter {
+      get { return (ILookupParameter<PotvinPDRearrangeMove>)Parameters["PotvinPDRearrangeMove"]; }
+    }
+    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 PotvinPDRearrangeTabuCriterion(bool deserializing) : base(deserializing) { }
+    protected PotvinPDRearrangeTabuCriterion(PotvinPDRearrangeTabuCriterion original, Cloner cloner) : base(original, cloner) { }
+    public PotvinPDRearrangeTabuCriterion()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinPDRearrangeMove>("PotvinPDRearrangeMove", "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 PotvinPDRearrangeTabuCriterion(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      ItemList<IItem> tabuList = TabuListParameter.ActualValue;
+      double moveQuality = MoveQualityParameter.ActualValue.Value;
+      bool useAspiration = UseAspirationCriterion.Value;
+      bool isTabu = false;
+      PotvinPDRearrangeMove move = PDRearrangeMoveParameter.ActualValue;
+
+      foreach (IItem tabuMove in tabuList) {
+        PotvinPDRelocateMoveAttribute attribute = tabuMove as PotvinPDRelocateMoveAttribute;
+
+        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/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeMoveTabuMaker.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeMoveTabuMaker.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeMoveTabuMaker.cs	(revision 14416)
@@ -0,0 +1,103 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDRearrangeMoveTabuMaker", "Declares a given rearrange move as tabu.")]
+  [StorableClass]
+  public class PotvinPDRearrangeMoveTabuMaker : TabuMaker, IPotvinPDRearrangeMoveOperator, IPotvinOperator, IVRPMoveOperator {
+    public ILookupParameter<PotvinPDRearrangeMove> PDRearrangeMoveParameter {
+      get { return (ILookupParameter<PotvinPDRearrangeMove>)Parameters["PotvinPDRearrangeMove"]; }
+    }
+    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 PotvinPDRearrangeMoveTabuMaker(bool deserializing) : base(deserializing) { }
+    protected PotvinPDRearrangeMoveTabuMaker(PotvinPDRearrangeMoveTabuMaker original, Cloner cloner) : base(original, cloner) { }
+    public PotvinPDRearrangeMoveTabuMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinPDRearrangeMove>("PotvinPDRearrangeMove", "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 PotvinPDRearrangeMoveTabuMaker(this, cloner);
+    }
+
+    protected override IItem GetTabuAttribute(bool maximization, double quality, double moveQuality) {
+      PotvinPDRearrangeMove 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 PotvinPDRelocateMoveAttribute(baseQuality, move.Tour, move.City, distance, overload, tardiness, pickupViolations);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeMultiMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeMultiMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeMultiMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,73 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDRearrangeMultiMoveGenerator", "Generates rearrange moves from a given PDP encoding.")]
+  [StorableClass]
+  public sealed class PotvinPDRearrangeMultiMoveGenerator : PotvinPDRearrangeMoveGenerator, 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 PotvinPDRearrangeMultiMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private PotvinPDRearrangeMultiMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinPDRearrangeMultiMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("SampleSize", "The number of moves to generate."));
+    }
+
+    private PotvinPDRearrangeMultiMoveGenerator(PotvinPDRearrangeMultiMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override PotvinPDRearrangeMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<PotvinPDRearrangeMove> result = new List<PotvinPDRearrangeMove>();
+
+      for (int i = 0; i < SampleSizeParameter.ActualValue.Value; i++) {
+        var move = PotvinPDRearrangeSingleMoveGenerator.Apply(individual, ProblemInstance, RandomParameter.ActualValue);
+        if (move != null)
+          result.Add(move);
+      }
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeSingleMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeSingleMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDRearrange/PotvinPDRearrangeSingleMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,84 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDRearrangeSingleMoveGenerator", "Generates a single rearrange move from a given PDP encoding.")]
+  [StorableClass]
+  public sealed class PotvinPDRearrangeSingleMoveGenerator : PotvinPDRearrangeMoveGenerator,
+    ISingleMoveGenerator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinPDRearrangeSingleMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private PotvinPDRearrangeSingleMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinPDRearrangeSingleMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+    }
+
+    private PotvinPDRearrangeSingleMoveGenerator(PotvinPDRearrangeSingleMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static PotvinPDRearrangeMove 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 > 0) {
+        int city = cities[rand.Next(cities.Count)];
+        int tour = individual.Tours.FindIndex(t => t.Stops.Contains(city));
+        return new PotvinPDRearrangeMove(city, tour, individual);
+      } else {
+        return null;
+      }
+    }
+
+    protected override PotvinPDRearrangeMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<PotvinPDRearrangeMove> result = new List<PotvinPDRearrangeMove>();
+
+      PotvinPDRearrangeMove move = Apply(individual, ProblemInstance, RandomParameter.ActualValue);
+      if (move != null)
+        result.Add(move);
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/IPotvinPDShiftMoveOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/IPotvinPDShiftMoveOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/IPotvinPDShiftMoveOperator.cs	(revision 14416)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  public interface IPotvinPDShiftMoveOperator : IVRPMoveOperator {
+    ILookupParameter<PotvinPDShiftMove> PDShiftMoveParameter { get; }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftExhaustiveMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftExhaustiveMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftExhaustiveMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,76 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDShiftExhaustiveMoveGenerator", "Generates shift moves from a given PDP encoding.")]
+  [StorableClass]
+  public sealed class PotvinPDShiftExhaustiveMoveGenerator : PotvinPDShiftMoveGenerator, IExhaustiveMoveGenerator {
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinPDShiftExhaustiveMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private PotvinPDShiftExhaustiveMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinPDShiftExhaustiveMoveGenerator()
+      : base() {
+    }
+
+    private PotvinPDShiftExhaustiveMoveGenerator(PotvinPDShiftExhaustiveMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override PotvinPDShiftMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<PotvinPDShiftMove> result = new List<PotvinPDShiftMove>();
+      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) {
+                PotvinPDShiftMove move = new PotvinPDShiftMove(
+                  city, i, k, individual);
+
+                result.Add(move);
+              }
+            }
+          }
+        }
+      }
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftMove.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftMove.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftMove.cs	(revision 14416)
@@ -0,0 +1,130 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDShiftMove", "Item that describes a shift move on a PDP representation.")]
+  [StorableClass]
+  public class PotvinPDShiftMove : 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 PotvinPDShiftMove()
+      : base() {
+      City = -1;
+      Tour = -1;
+
+      Individual = null;
+    }
+
+    public PotvinPDShiftMove(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 PotvinPDShiftMove(this, cloner);
+    }
+
+    protected PotvinPDShiftMove(PotvinPDShiftMove 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;
+    }
+
+    [StorableConstructor]
+    protected PotvinPDShiftMove(bool deserializing) : base(deserializing) { }
+
+    #region IVRPMove Members
+
+    [ThreadStatic]
+    private static PotvinPDShiftMoveEvaluator moveEvaluator;
+    public VRPMoveEvaluator GetMoveEvaluator() {
+      if (moveEvaluator == null)
+        moveEvaluator = new PotvinPDShiftMoveEvaluator();
+
+      return moveEvaluator;
+    }
+
+    [ThreadStatic]
+    private static PotvinPDShiftMoveMaker moveMaker;
+    public VRPMoveMaker GetMoveMaker() {
+      if (moveMaker == null)
+        moveMaker = new PotvinPDShiftMoveMaker();
+
+      return moveMaker;
+    }
+
+    [ThreadStatic]
+    private static PotvinPDShiftMoveTabuMaker tabuMaker;
+    public ITabuMaker GetTabuMaker() {
+      if (tabuMaker == null)
+        tabuMaker = new PotvinPDShiftMoveTabuMaker();
+
+      return tabuMaker;
+    }
+
+    [ThreadStatic]
+    private static PotvinPDShiftTabuCriterion tabuChecker;
+    public ITabuChecker GetTabuChecker() {
+      if (tabuChecker == null) {
+        tabuChecker = new PotvinPDShiftTabuCriterion();
+        tabuChecker.UseAspirationCriterion.Value = false;
+      }
+
+      return tabuChecker;
+    }
+
+    [ThreadStatic]
+    private static PotvinPDShiftTabuCriterion softTabuChecker;
+    public ITabuChecker GetSoftTabuChecker() {
+      if (softTabuChecker == null) {
+        softTabuChecker = new PotvinPDShiftTabuCriterion();
+        softTabuChecker.UseAspirationCriterion.Value = true;
+      }
+
+      return softTabuChecker;
+    }
+    #endregion
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftMoveEvaluator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftMoveEvaluator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftMoveEvaluator.cs	(revision 14416)
@@ -0,0 +1,81 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDShiftMoveEvaluator", "Evaluates a shift move for a PDP representation. ")]
+  [StorableClass]
+  public sealed class PotvinPDShiftMoveEvaluator : PotvinMoveEvaluator, IPotvinPDShiftMoveOperator {
+    public ILookupParameter<PotvinPDShiftMove> PDShiftMoveParameter {
+      get { return (ILookupParameter<PotvinPDShiftMove>)Parameters["PotvinPDShiftMove"]; }
+    }
+
+    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 PotvinPDShiftMoveEvaluator(bool deserializing) : base(deserializing) { }
+
+    public PotvinPDShiftMoveEvaluator()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinPDShiftMove>("PotvinPDShiftMove", "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 PotvinPDShiftMoveEvaluator(this, cloner);
+    }
+
+    private PotvinPDShiftMoveEvaluator(PotvinPDShiftMoveEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void EvaluateMove() {
+      PotvinPDShiftMove move = PDShiftMoveParameter.ActualValue;
+
+      PotvinEncoding newSolution = PDShiftMoveParameter.ActualValue.Individual.Clone() as PotvinEncoding;
+      PotvinPDShiftMoveMaker.Apply(newSolution, move, ProblemInstance);
+
+      UpdateEvaluation(newSolution);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,74 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDShiftMoveGenerator", "Generates shift moves from a given PDP encoding.")]
+  [StorableClass]
+  public abstract class PotvinPDShiftMoveGenerator : PotvinMoveGenerator, IPotvinPDShiftMoveOperator {
+    public ILookupParameter<PotvinPDShiftMove> PDShiftMoveParameter {
+      get { return (ILookupParameter<PotvinPDShiftMove>)Parameters["PotvinPDShiftMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return PDShiftMoveParameter; }
+    }
+
+    protected ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+
+    [StorableConstructor]
+    protected PotvinPDShiftMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinPDShiftMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinPDShiftMove>("PotvinPDShiftMove", "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 PotvinPDShiftMoveGenerator(PotvinPDShiftMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected abstract PotvinPDShiftMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance);
+
+    public override IOperation InstrumentedApply() {
+      IOperation next = base.InstrumentedApply();
+
+      PotvinEncoding individual = VRPToursParameter.ActualValue as PotvinEncoding;
+      PotvinPDShiftMove[] 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/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftMoveMaker.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftMoveMaker.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftMoveMaker.cs	(revision 14416)
@@ -0,0 +1,128 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDShiftMoveMaker", "Peforms the shift move on a given PDP encoding and updates the quality.")]
+  [StorableClass]
+  public class PotvinPDShiftMoveMaker : PotvinMoveMaker, IPotvinPDShiftMoveOperator, IMoveMaker {
+    public ILookupParameter<PotvinPDShiftMove> PDShiftMoveParameter {
+      get { return (ILookupParameter<PotvinPDShiftMove>)Parameters["PotvinPDShiftMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return PDShiftMoveParameter; }
+    }
+
+    [StorableConstructor]
+    protected PotvinPDShiftMoveMaker(bool deserializing) : base(deserializing) { }
+
+    public PotvinPDShiftMoveMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinPDShiftMove>("PotvinPDShiftMove", "The moves that should be made."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinPDShiftMoveMaker(this, cloner);
+    }
+
+    protected PotvinPDShiftMoveMaker(PotvinPDShiftMoveMaker original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static void Apply(PotvinEncoding solution, PotvinPDShiftMove 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);
+        Tour oldTour2 = solution.Tours.Find(t => t.Stops.Contains(location));
+        oldTour2.Stops.Remove(location);
+
+        solution.InsertPair(tour, move.City, location, problemInstance);
+      } else {
+        int place = solution.FindBestInsertionPlace(tour, move.City);
+        tour.Stops.Insert(place, move.City);
+      }
+
+      if (newTour) {
+        List<int> vehicles = new List<int>();
+        for (int i = move.Tour; i < problemInstance.Vehicles.Value; i++) {
+          vehicles.Add(solution.GetVehicleAssignment(i));
+        }
+
+        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;
+      }
+
+      solution.Repair();
+    }
+
+    protected override void PerformMove() {
+      PotvinPDShiftMove move = PDShiftMoveParameter.ActualValue;
+
+      PotvinEncoding newSolution = move.Individual.Clone() as PotvinEncoding;
+      Apply(newSolution, move, ProblemInstance);
+      VRPToursParameter.ActualValue = newSolution;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftMoveTabuCriterion.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftMoveTabuCriterion.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftMoveTabuCriterion.cs	(revision 14416)
@@ -0,0 +1,164 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDShiftTabuCriterion", @"Checks if a certain shift move is tabu.")]
+  [StorableClass]
+  public class PotvinPDShiftTabuCriterion : SingleSuccessorOperator, IPotvinPDShiftMoveOperator, ITabuChecker, IPotvinOperator, IVRPMoveOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+
+    public ILookupParameter<PotvinPDShiftMove> PDShiftMoveParameter {
+      get { return (ILookupParameter<PotvinPDShiftMove>)Parameters["PotvinPDShiftMove"]; }
+    }
+    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 PotvinPDShiftTabuCriterion(bool deserializing) : base(deserializing) { }
+    protected PotvinPDShiftTabuCriterion(PotvinPDShiftTabuCriterion original, Cloner cloner) : base(original, cloner) { }
+    public PotvinPDShiftTabuCriterion()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinPDShiftMove>("PotvinPDShiftMove", "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 PotvinPDShiftTabuCriterion(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      ItemList<IItem> tabuList = TabuListParameter.ActualValue;
+      double moveQuality = MoveQualityParameter.ActualValue.Value;
+      bool useAspiration = UseAspirationCriterion.Value;
+      bool isTabu = false;
+      PotvinPDShiftMove move = PDShiftMoveParameter.ActualValue;
+
+      foreach (IItem tabuMove in tabuList) {
+        PotvinPDRelocateMoveAttribute attribute = tabuMove as PotvinPDRelocateMoveAttribute;
+
+        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/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftMoveTabuMaker.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftMoveTabuMaker.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftMoveTabuMaker.cs	(revision 14416)
@@ -0,0 +1,103 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDShiftMoveTabuMaker", "Declares a given shift move as tabu.")]
+  [StorableClass]
+  public class PotvinPDShiftMoveTabuMaker : TabuMaker, IPotvinPDShiftMoveOperator, IPotvinOperator, IVRPMoveOperator {
+    public ILookupParameter<PotvinPDShiftMove> PDShiftMoveParameter {
+      get { return (ILookupParameter<PotvinPDShiftMove>)Parameters["PotvinPDShiftMove"]; }
+    }
+    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 PotvinPDShiftMoveTabuMaker(bool deserializing) : base(deserializing) { }
+    protected PotvinPDShiftMoveTabuMaker(PotvinPDShiftMoveTabuMaker original, Cloner cloner) : base(original, cloner) { }
+    public PotvinPDShiftMoveTabuMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinPDShiftMove>("PotvinPDShiftMove", "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 PotvinPDShiftMoveTabuMaker(this, cloner);
+    }
+
+    protected override IItem GetTabuAttribute(bool maximization, double quality, double moveQuality) {
+      PotvinPDShiftMove 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 PotvinPDRelocateMoveAttribute(baseQuality, move.OldTour, move.City, distance, overload, tardiness, pickupViolations);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftMultiMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftMultiMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftMultiMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,73 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDShiftMultiMoveGenerator", "Generates shift moves from a given PDP encoding.")]
+  [StorableClass]
+  public sealed class PotvinPDShiftMultiMoveGenerator : PotvinPDShiftMoveGenerator, 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 PotvinPDShiftMultiMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private PotvinPDShiftMultiMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinPDShiftMultiMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("SampleSize", "The number of moves to generate."));
+    }
+
+    private PotvinPDShiftMultiMoveGenerator(PotvinPDShiftMultiMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override PotvinPDShiftMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<PotvinPDShiftMove> result = new List<PotvinPDShiftMove>();
+
+      for (int i = 0; i < SampleSizeParameter.ActualValue.Value; i++) {
+        var move = PotvinPDShiftSingleMoveGenerator.Apply(individual, ProblemInstance, RandomParameter.ActualValue);
+        if (move != null)
+          result.Add(move);
+      }
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftSingleMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftSingleMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PDShift/PotvinPDShiftSingleMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,94 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDShiftSingleMoveGenerator", "Generates a single shift move from a given PDP encoding.")]
+  [StorableClass]
+  public sealed class PotvinPDShiftSingleMoveGenerator : PotvinPDShiftMoveGenerator,
+    ISingleMoveGenerator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinPDShiftSingleMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private PotvinPDShiftSingleMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinPDShiftSingleMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+    }
+
+    private PotvinPDShiftSingleMoveGenerator(PotvinPDShiftSingleMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static PotvinPDShiftMove 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) {
+        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 PotvinPDShiftMove(city, oldTourIndex, newTourIndex, individual);
+      } else {
+        return null;
+      }
+    }
+
+    protected override PotvinPDShiftMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<PotvinPDShiftMove> result = new List<PotvinPDShiftMove>();
+
+      PotvinPDShiftMove move = Apply(individual, ProblemInstance, RandomParameter.ActualValue);
+      if (move != null)
+        result.Add(move);
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PotvinPDRelocateMoveAttribute.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PotvinPDRelocateMoveAttribute.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PickupDelivery/PotvinPDRelocateMoveAttribute.cs	(revision 14416)
@@ -0,0 +1,85 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinPDRelocateMoveAttribute", "PD relocation move attribute")]
+  [StorableClass]
+  public class PotvinPDRelocateMoveAttribute : VRPMoveAttribute {
+    [Storable]
+    public int Tour { get; private set; }
+    [Storable]
+    public int City { get; private 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 PotvinPDRelocateMoveAttribute(bool deserializing) : base(deserializing) { }
+    protected PotvinPDRelocateMoveAttribute(PotvinPDRelocateMoveAttribute 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 PotvinPDRelocateMoveAttribute(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 PotvinPDRelocateMoveAttribute(this, cloner);
+    }
+
+    public override int GetHashCode() {
+      return Tour.GetHashCode() + City.GetHashCode();
+    }
+
+    public override bool Equals(object obj) {
+      if (obj is PotvinPDRelocateMoveAttribute) {
+        PotvinPDRelocateMoveAttribute other = obj as PotvinPDRelocateMoveAttribute;
+
+        return Tour == other.Tour && City == other.City;
+      } else {
+        return base.Equals(obj);
+      }
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PotvinMoveEvaluator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PotvinMoveEvaluator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PotvinMoveEvaluator.cs	(revision 14416)
@@ -0,0 +1,42 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinMoveEvaluator", "Evaluates a Potvin VRP move.")]
+  [StorableClass]
+  public abstract class PotvinMoveEvaluator : VRPMoveEvaluator, IPotvinOperator {
+    [StorableConstructor]
+    protected PotvinMoveEvaluator(bool deserializing) : base(deserializing) { }
+
+    public PotvinMoveEvaluator()
+      : base() {
+    }
+
+    protected PotvinMoveEvaluator(PotvinMoveEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PotvinMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PotvinMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PotvinMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,52 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinMoveGenerator", "Generates Potvin VRP moves.")]
+  [StorableClass]
+  public abstract class PotvinMoveGenerator : VRPMoveGenerator, IPotvinOperator {
+    [StorableConstructor]
+    protected PotvinMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinMoveGenerator()
+      : base() {
+    }
+
+    protected PotvinMoveGenerator(PotvinMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IOperation InstrumentedApply() {
+      IVRPEncoding solution = VRPToursParameter.ActualValue;
+      if (!(solution is PotvinEncoding)) {
+        VRPToursParameter.ActualValue = PotvinEncoding.ConvertFrom(solution, ProblemInstance);
+      }
+
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PotvinMoveMaker.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PotvinMoveMaker.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/PotvinMoveMaker.cs	(revision 14416)
@@ -0,0 +1,42 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinMoveMaker", "Makes a Potvin VRP move.")]
+  [StorableClass]
+  public abstract class PotvinMoveMaker : VRPMoveMaker, IPotvinOperator {
+    [StorableConstructor]
+    protected PotvinMoveMaker(bool deserializing) : base(deserializing) { }
+
+    public PotvinMoveMaker()
+      : base() {
+    }
+
+    protected PotvinMoveMaker(PotvinMoveMaker original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/IPotvinTwoOptStarMoveOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/IPotvinTwoOptStarMoveOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/IPotvinTwoOptStarMoveOperator.cs	(revision 14416)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  public interface IPotvinTwoOptStarMoveOperator : IVRPMoveOperator {
+    ILookupParameter<PotvinTwoOptStarMove> TwoOptStarMoveParameter { get; }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarExhaustiveMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarExhaustiveMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarExhaustiveMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,66 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinTwoOptStarExhaustiveMoveGenerator", "Generates two opt star moves from a given VRP encoding.")]
+  [StorableClass]
+  public sealed class PotvinTwoOptStarExhaustiveMoveGenerator : PotvinTwoOptStarMoveGenerator, IExhaustiveMoveGenerator {
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinTwoOptStarExhaustiveMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private PotvinTwoOptStarExhaustiveMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinTwoOptStarExhaustiveMoveGenerator()
+      : base() {
+    }
+
+    private PotvinTwoOptStarExhaustiveMoveGenerator(PotvinTwoOptStarExhaustiveMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override PotvinTwoOptStarMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<PotvinTwoOptStarMove> result = new List<PotvinTwoOptStarMove>();
+
+      for (int tour1 = 0; tour1 < individual.Tours.Count; tour1++) {
+        for (int tour2 = tour1 + 1; tour2 < individual.Tours.Count; tour2++) {
+          for (int index1 = 0; index1 <= individual.Tours[tour1].Stops.Count; index1++) {
+            for (int index2 = 0; index2 <= individual.Tours[tour2].Stops.Count; index2++) {
+              if ((index1 != individual.Tours[tour1].Stops.Count || index2 != individual.Tours[tour2].Stops.Count) &&
+                  (index1 != 0 || index2 != 0))
+                result.Add(new PotvinTwoOptStarMove(tour1, index1, tour2, index2, individual));
+            }
+          }
+        }
+      }
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMove.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMove.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMove.cs	(revision 14416)
@@ -0,0 +1,111 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinTwoOptStarMove", "Item that describes a two opt star move on a VRP representation.")]
+  [StorableClass]
+  public class PotvinTwoOptStarMove : Item, IVRPMove {
+    [Storable]
+    public IVRPEncoding Individual { get; protected set; }
+
+    [Storable]
+    public int Tour1 { get; protected set; }
+
+    [Storable]
+    public int X1 { get; protected set; }
+
+    [Storable]
+    public int Tour2 { get; protected set; }
+
+    [Storable]
+    public int X2 { get; protected set; }
+
+    public PotvinTwoOptStarMove()
+      : base() {
+      X1 = -1;
+      Tour1 = -1;
+      X2 = -1;
+      Tour2 = -1;
+
+      Individual = null;
+    }
+
+    public PotvinTwoOptStarMove(int tour1, int x1, int tour2, int x2, PotvinEncoding individual) {
+      Tour1 = tour1;
+      X1 = x1;
+      Tour2 = tour2;
+      X2 = x2;
+
+      this.Individual = individual.Clone() as PotvinEncoding;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinTwoOptStarMove(this, cloner);
+    }
+
+    protected PotvinTwoOptStarMove(PotvinTwoOptStarMove original, Cloner cloner)
+      : base(original, cloner) {
+      this.Tour1 = original.Tour1;
+      this.X1 = original.X1;
+      this.Tour2 = original.Tour2;
+      this.X2 = original.X2;
+
+      this.Individual = cloner.Clone(Individual) as PotvinEncoding;
+    }
+
+    [StorableConstructor]
+    protected PotvinTwoOptStarMove(bool deserializing) : base(deserializing) { }
+
+    #region IVRPMove Members
+
+    public VRPMoveEvaluator GetMoveEvaluator() {
+      return new PotvinTwoOptStarMoveEvaluator();
+    }
+
+    public VRPMoveMaker GetMoveMaker() {
+      return new PotvinTwoOptStarMoveMaker();
+    }
+
+    public ITabuMaker GetTabuMaker() {
+      return new PotvinTwoOptStarMoveTabuMaker();
+    }
+
+    public ITabuChecker GetTabuChecker() {
+      return new PotvinTwoOptStarMoveTabuCriterion();
+    }
+
+    public ITabuChecker GetSoftTabuChecker() {
+      PotvinTwoOptStarMoveTabuCriterion tabuChecker = new PotvinTwoOptStarMoveTabuCriterion();
+      tabuChecker.UseAspirationCriterion.Value = true;
+
+      return tabuChecker;
+    }
+
+    #endregion
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMoveAttribute.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMoveAttribute.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMoveAttribute.cs	(revision 14416)
@@ -0,0 +1,81 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinTwoOptStarMoveAttribute", "Two opt star move attribute")]
+  [StorableClass]
+  public class PotvinTwoOptStarMoveAttribute : VRPMoveAttribute {
+    [Storable]
+    public int Tour { get; private set; }
+    [Storable]
+    public int City { get; private set; }
+
+    [Storable]
+    public double Distance { get; private set; }
+    [Storable]
+    public double Overload { get; private set; }
+    [Storable]
+    public double Tardiness { get; private set; }
+
+    [StorableConstructor]
+    protected PotvinTwoOptStarMoveAttribute(bool deserializing) : base(deserializing) { }
+    protected PotvinTwoOptStarMoveAttribute(PotvinTwoOptStarMoveAttribute 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;
+    }
+    public PotvinTwoOptStarMoveAttribute(double moveQuality, int tour, int city,
+      double distance, double overload, double tardiness)
+      : base(moveQuality) {
+      Tour = tour;
+      City = city;
+      Distance = distance;
+      Overload = overload;
+      Tardiness = tardiness;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinTwoOptStarMoveAttribute(this, cloner);
+    }
+
+    public override int GetHashCode() {
+      return Tour.GetHashCode() + City.GetHashCode();
+    }
+
+    public override bool Equals(object obj) {
+      if (obj is PotvinTwoOptStarMoveAttribute) {
+        PotvinTwoOptStarMoveAttribute other = obj as PotvinTwoOptStarMoveAttribute;
+
+        return Tour == other.Tour && City == other.City;
+      } else {
+        return base.Equals(obj);
+      }
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMoveEvaluator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMoveEvaluator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMoveEvaluator.cs	(revision 14416)
@@ -0,0 +1,63 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinTwoOptStarMoveEvaluator", "Evaluates a two opt star move for a VRP representation. ")]
+  [StorableClass]
+  public sealed class PotvinTwoOptStarMoveEvaluator : PotvinMoveEvaluator, IPotvinTwoOptStarMoveOperator {
+    public ILookupParameter<PotvinTwoOptStarMove> TwoOptStarMoveParameter {
+      get { return (ILookupParameter<PotvinTwoOptStarMove>)Parameters["PotvinTwoOptStarMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return TwoOptStarMoveParameter; }
+    }
+    [StorableConstructor]
+    private PotvinTwoOptStarMoveEvaluator(bool deserializing) : base(deserializing) { }
+
+    public PotvinTwoOptStarMoveEvaluator()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinTwoOptStarMove>("PotvinTwoOptStarMove", "The move that should be evaluated."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinTwoOptStarMoveEvaluator(this, cloner);
+    }
+
+    private PotvinTwoOptStarMoveEvaluator(PotvinTwoOptStarMoveEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void EvaluateMove() {
+      PotvinTwoOptStarMove move = TwoOptStarMoveParameter.ActualValue;
+
+      PotvinEncoding newSolution = TwoOptStarMoveParameter.ActualValue.Individual.Clone() as PotvinEncoding;
+      PotvinTwoOptStarMoveMaker.Apply(newSolution, move, ProblemInstance);
+
+      UpdateEvaluation(newSolution);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,74 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinTwoOptStarMoveGenerator", "Generates two opt star moves from a given VRP encoding.")]
+  [StorableClass]
+  public abstract class PotvinTwoOptStarMoveGenerator : PotvinMoveGenerator, IPotvinTwoOptStarMoveOperator {
+    public ILookupParameter<PotvinTwoOptStarMove> TwoOptStarMoveParameter {
+      get { return (ILookupParameter<PotvinTwoOptStarMove>)Parameters["PotvinTwoOptStarMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return TwoOptStarMoveParameter; }
+    }
+
+    protected ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+
+    [StorableConstructor]
+    protected PotvinTwoOptStarMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinTwoOptStarMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinTwoOptStarMove>("PotvinTwoOptStarMove", "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 PotvinTwoOptStarMoveGenerator(PotvinTwoOptStarMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected abstract PotvinTwoOptStarMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance);
+
+    public override IOperation InstrumentedApply() {
+      IOperation next = base.InstrumentedApply();
+
+      PotvinEncoding individual = VRPToursParameter.ActualValue as PotvinEncoding;
+      PotvinTwoOptStarMove[] 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(TwoOptStarMoveParameter.ActualName, moves[i]));
+      }
+      CurrentScopeParameter.ActualValue.SubScopes.AddRange(moveScopes);
+
+      return next;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMoveMaker.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMoveMaker.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMoveMaker.cs	(revision 14416)
@@ -0,0 +1,106 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinTwoOptStarMoveMaker", "Peforms the two opt star move on a given VRP encoding and updates the quality.")]
+  [StorableClass]
+  public class PotvinTwoOptStarMoveMaker : PotvinMoveMaker, IPotvinTwoOptStarMoveOperator, IMoveMaker {
+    public ILookupParameter<PotvinTwoOptStarMove> TwoOptStarMoveParameter {
+      get { return (ILookupParameter<PotvinTwoOptStarMove>)Parameters["PotvinTwoOptStarMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return TwoOptStarMoveParameter; }
+    }
+
+    [StorableConstructor]
+    protected PotvinTwoOptStarMoveMaker(bool deserializing) : base(deserializing) { }
+
+    public PotvinTwoOptStarMoveMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinTwoOptStarMove>("PotvinTwoOptStarMove", "The moves that should be made."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinTwoOptStarMoveMaker(this, cloner);
+    }
+
+    protected PotvinTwoOptStarMoveMaker(PotvinTwoOptStarMoveMaker original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static void GetSegments(PotvinTwoOptStarMove move, out List<int> segmentX1, out List<int> segmentX2) {
+      PotvinEncoding solution = move.Individual as PotvinEncoding;
+
+      Tour route1 = solution.Tours[move.Tour1];
+      Tour route2 = solution.Tours[move.Tour2];
+
+      int x1 = move.X1;
+      int x2 = move.X2;
+
+      int count = route1.Stops.Count - x1;
+      segmentX1 = new List<int>();
+      if (count > 0) {
+        segmentX1 = route1.Stops.GetRange(x1, count);
+      }
+
+      count = route2.Stops.Count - x2;
+      segmentX2 = new List<int>();
+      if (count > 0) {
+        segmentX2 = route2.Stops.GetRange(x2, count);
+      }
+    }
+
+    public static void Apply(PotvinEncoding solution, PotvinTwoOptStarMove move, IVRPProblemInstance problemInstance) {
+      List<int> segmentX1;
+      List<int> segmentX2;
+      GetSegments(move, out segmentX1, out segmentX2);
+
+      Tour route1 = solution.Tours[move.Tour1];
+      Tour route2 = solution.Tours[move.Tour2];
+
+      foreach (int stop in segmentX1)
+        route1.Stops.Remove(stop);
+      route1.Stops.AddRange(segmentX2);
+
+      foreach (int stop in segmentX2)
+        route2.Stops.Remove(stop);
+      route2.Stops.AddRange(segmentX1);
+    }
+
+    protected override void PerformMove() {
+      PotvinTwoOptStarMove move = TwoOptStarMoveParameter.ActualValue;
+
+      PotvinEncoding newSolution = move.Individual.Clone() as PotvinEncoding;
+      Apply(newSolution, move, ProblemInstance);
+      newSolution.Repair();
+      VRPToursParameter.ActualValue = newSolution;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMoveTabuCriterion.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMoveTabuCriterion.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMoveTabuCriterion.cs	(revision 14416)
@@ -0,0 +1,166 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+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;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinTwoOptStarTabuCriterion", @"Checks if a certain two opt star move is tabu.")]
+  [StorableClass]
+  public class PotvinTwoOptStarMoveTabuCriterion : SingleSuccessorOperator, IPotvinTwoOptStarMoveOperator, ITabuChecker, IPotvinOperator, IVRPMoveOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+
+    public ILookupParameter<PotvinTwoOptStarMove> TwoOptStarMoveParameter {
+      get { return (ILookupParameter<PotvinTwoOptStarMove>)Parameters["PotvinTwoOptStarMove"]; }
+    }
+    public ILookupParameter VRPMoveParameter {
+      get { return TwoOptStarMoveParameter; }
+    }
+    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 PotvinTwoOptStarMoveTabuCriterion(bool deserializing) : base(deserializing) { }
+    protected PotvinTwoOptStarMoveTabuCriterion(PotvinTwoOptStarMoveTabuCriterion original, Cloner cloner) : base(original, cloner) { }
+    public PotvinTwoOptStarMoveTabuCriterion()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinTwoOptStarMove>("PotvinTwoOptStarMove", "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 PotvinTwoOptStarMoveTabuCriterion(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      ItemList<IItem> tabuList = TabuListParameter.ActualValue;
+      double moveQuality = MoveQualityParameter.ActualValue.Value;
+      bool useAspiration = UseAspirationCriterion.Value;
+      bool isTabu = false;
+      PotvinTwoOptStarMove move = TwoOptStarMoveParameter.ActualValue;
+
+      List<int> segmentX1;
+      List<int> segmentX2;
+      PotvinTwoOptStarMoveMaker.GetSegments(move, out segmentX1, out segmentX2);
+
+      foreach (IItem tabuMove in tabuList) {
+        PotvinTwoOptStarMoveAttribute attribute = tabuMove as PotvinTwoOptStarMoveAttribute;
+
+        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;
+
+          if (!useAspiration || moveQuality >= quality) {
+            if (attribute.Tour == move.Tour1 && segmentX2.Contains(attribute.City) ||
+                attribute.Tour == move.Tour2 && segmentX1.Contains(attribute.City)) {
+              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/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMoveTabuMaker.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMoveTabuMaker.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMoveTabuMaker.cs	(revision 14416)
@@ -0,0 +1,145 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+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;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinTwoOptStarMoveTabuMaker", "Declares a given two opt star move as tabu.")]
+  [StorableClass]
+  public class PotvinTwoOptStarMoveTabuMaker : SingleSuccessorOperator, ITabuMaker, IPotvinTwoOptStarMoveOperator, IPotvinOperator, ISingleObjectiveOperator {
+    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<PotvinTwoOptStarMove> TwoOptStarMoveParameter {
+      get { return (ILookupParameter<PotvinTwoOptStarMove>)Parameters["PotvinTwoOptStarMove"]; }
+    }
+    public ILookupParameter VRPMoveParameter {
+      get { return TwoOptStarMoveParameter; }
+    }
+    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"]; }
+    }
+
+    [StorableConstructor]
+    protected PotvinTwoOptStarMoveTabuMaker(bool deserializing) : base(deserializing) { }
+    protected PotvinTwoOptStarMoveTabuMaker(PotvinTwoOptStarMoveTabuMaker original, Cloner cloner) : base(original, cloner) { }
+    public PotvinTwoOptStarMoveTabuMaker()
+      : 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<PotvinTwoOptStarMove>("PotvinTwoOptStarMove", "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"));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinTwoOptStarMoveTabuMaker(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);
+      }
+
+      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;
+
+      PotvinTwoOptStarMove move = TwoOptStarMoveParameter.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
+
+      List<int> segmentX1;
+      List<int> segmentX2;
+      PotvinTwoOptStarMoveMaker.GetSegments(move, out segmentX1, out segmentX2);
+
+      foreach (int city in segmentX1) {
+        tabuList.Add(new PotvinTwoOptStarMoveAttribute(baseQuality, move.Tour1, city, distance, overload, tardiness));
+      }
+
+      foreach (int city in segmentX2) {
+        tabuList.Add(new PotvinTwoOptStarMoveAttribute(baseQuality, move.Tour2, city, distance, overload, tardiness));
+      }
+
+      return base.Apply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMultiMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMultiMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarMultiMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,71 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinTwoOptStarMultiMoveGenerator", "Generates two opt star moves from a given VRP encoding.")]
+  [StorableClass]
+  public sealed class PotvinTwoOptStarMultiMoveGenerator : PotvinTwoOptStarMoveGenerator, 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 PotvinTwoOptStarMultiMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private PotvinTwoOptStarMultiMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinTwoOptStarMultiMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("SampleSize", "The number of moves to generate."));
+    }
+
+    private PotvinTwoOptStarMultiMoveGenerator(PotvinTwoOptStarMultiMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override PotvinTwoOptStarMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<PotvinTwoOptStarMove> result = new List<PotvinTwoOptStarMove>();
+
+      for (int i = 0; i < SampleSizeParameter.ActualValue.Value; i++) {
+        result.Add(PotvinTwoOptStarSingleMoveGenerator.Apply(individual, ProblemInstance, RandomParameter.ActualValue));
+      }
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarSingleMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarSingleMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/TwoOptStar/PotvinTwoOptStarSingleMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,88 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinTwoOptStarSingleMoveGenerator", "Generates a single two opt star move from a given VRP encoding.")]
+  [StorableClass]
+  public sealed class PotvinTwoOptStarSingleMoveGenerator : PotvinTwoOptStarMoveGenerator,
+    ISingleMoveGenerator {
+    #region IMultiVRPMoveOperator Members
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return (ILookupParameter)Parameters["PotvinTwoOptStarMove"]; }
+    }
+
+    #endregion
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinTwoOptStarSingleMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private PotvinTwoOptStarSingleMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinTwoOptStarSingleMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+    }
+
+    private PotvinTwoOptStarSingleMoveGenerator(PotvinTwoOptStarSingleMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static PotvinTwoOptStarMove Apply(PotvinEncoding individual, IVRPProblemInstance problemInstance, IRandom rand) {
+      int route1Idx = rand.Next(individual.Tours.Count);
+      int route2Idx = rand.Next(individual.Tours.Count - 1);
+      if (route2Idx >= route1Idx)
+        route2Idx++;
+
+      Tour route1 = individual.Tours[route1Idx];
+      Tour route2 = individual.Tours[route2Idx];
+
+      int x1 = rand.Next(route1.Stops.Count + 1);
+      int x2 = rand.Next(route2.Stops.Count + 1);
+
+      return new PotvinTwoOptStarMove(route1Idx, x1, route2Idx, x2, individual);
+    }
+
+    protected override PotvinTwoOptStarMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<PotvinTwoOptStarMove> result = new List<PotvinTwoOptStarMove>();
+
+      PotvinTwoOptStarMove move = Apply(individual, ProblemInstance, RandomParameter.ActualValue);
+      if (move != null)
+        result.Add(move);
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/IPotvinVehicleAssignmentMoveOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/IPotvinVehicleAssignmentMoveOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/IPotvinVehicleAssignmentMoveOperator.cs	(revision 14416)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  public interface IPotvinVehicleAssignmentMoveOperator : IVRPMoveOperator {
+    ILookupParameter<PotvinVehicleAssignmentMove> VehicleAssignmentMoveParameter { get; }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentExhaustiveMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentExhaustiveMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentExhaustiveMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,61 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinVehicleAssignmentExhaustiveMoveGenerator", "Generates vehicle assignment moves from a given VRP encoding.")]
+  [StorableClass]
+  public sealed class PotvinVehicleAssignmentExhaustiveMoveGenerator : PotvinVehicleAssignmentMoveGenerator, IExhaustiveMoveGenerator {
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinVehicleAssignmentExhaustiveMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private PotvinVehicleAssignmentExhaustiveMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinVehicleAssignmentExhaustiveMoveGenerator()
+      : base() {
+    }
+
+    private PotvinVehicleAssignmentExhaustiveMoveGenerator(PotvinVehicleAssignmentExhaustiveMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override PotvinVehicleAssignmentMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<PotvinVehicleAssignmentMove> result = new List<PotvinVehicleAssignmentMove>();
+
+      for (int i = 0; i < individual.Tours.Count; i++) {
+        for (int j = i + 1; j < problemInstance.Vehicles.Value; j++) {
+          result.Add(new PotvinVehicleAssignmentMove(i, j, individual));
+        }
+
+      }
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMove.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMove.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMove.cs	(revision 14416)
@@ -0,0 +1,100 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinVehicleAssignmentMove", "Item that describes a relocation move on a VRP representation.")]
+  [StorableClass]
+  public class PotvinVehicleAssignmentMove : Item, IVRPMove {
+    [Storable]
+    public IVRPEncoding Individual { get; protected set; }
+
+    [Storable]
+    public int Tour1 { get; protected set; }
+
+    [Storable]
+    public int Tour2 { get; protected set; }
+
+
+    public PotvinVehicleAssignmentMove()
+      : base() {
+      Tour1 = -1;
+      Tour2 = -1;
+
+      Individual = null;
+    }
+
+    public PotvinVehicleAssignmentMove(int tour1, int tour2, PotvinEncoding individual) {
+      Tour1 = tour1;
+      Tour2 = tour2;
+
+      this.Individual = individual.Clone() as PotvinEncoding;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinVehicleAssignmentMove(this, cloner);
+    }
+
+    protected PotvinVehicleAssignmentMove(PotvinVehicleAssignmentMove original, Cloner cloner)
+      : base(original, cloner) {
+      this.Tour1 = original.Tour1;
+      this.Tour2 = original.Tour2;
+
+      this.Individual = cloner.Clone(Individual) as PotvinEncoding;
+    }
+
+    [StorableConstructor]
+    protected PotvinVehicleAssignmentMove(bool deserializing) : base(deserializing) { }
+
+    #region IVRPMove Members
+
+    public VRPMoveEvaluator GetMoveEvaluator() {
+      return new PotvinVehicleAssignmentMoveEvaluator();
+    }
+
+    public VRPMoveMaker GetMoveMaker() {
+      return new PotvinVehicleAssignmentMoveMaker();
+    }
+
+    public ITabuMaker GetTabuMaker() {
+      return new PotvinVehicleAssignmentMoveTabuMaker();
+    }
+
+    public ITabuChecker GetTabuChecker() {
+      return new PotvinVehicleAssignmentMoveTabuCriterion();
+    }
+
+    public ITabuChecker GetSoftTabuChecker() {
+      PotvinVehicleAssignmentMoveTabuCriterion tabuChecker = new PotvinVehicleAssignmentMoveTabuCriterion();
+      tabuChecker.UseAspirationCriterion.Value = true;
+
+      return tabuChecker;
+    }
+
+    #endregion
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMoveAttribute.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMoveAttribute.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMoveAttribute.cs	(revision 14416)
@@ -0,0 +1,81 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinVehicleAssignmentMoveAttribute", "vehicle assignment move attribute")]
+  [StorableClass]
+  public class PotvinVehicleAssignmentMoveAttribute : VRPMoveAttribute {
+    [Storable]
+    public int Tour { get; private set; }
+    [Storable]
+    public int Vehicle { get; private set; }
+
+    [Storable]
+    public double Distance { get; private set; }
+    [Storable]
+    public double Overload { get; private set; }
+    [Storable]
+    public double Tardiness { get; private set; }
+
+    [StorableConstructor]
+    protected PotvinVehicleAssignmentMoveAttribute(bool deserializing) : base(deserializing) { }
+    protected PotvinVehicleAssignmentMoveAttribute(PotvinVehicleAssignmentMoveAttribute original, Cloner cloner)
+      : base(original, cloner) {
+      this.Tour = original.Tour;
+      this.Vehicle = original.Vehicle;
+      this.Distance = original.Distance;
+      this.Overload = original.Overload;
+      this.Tardiness = original.Tardiness;
+    }
+    public PotvinVehicleAssignmentMoveAttribute(double moveQuality, int tour, int vehicle,
+      double distance, double overload, double tardiness)
+      : base(moveQuality) {
+      Tour = tour;
+      Vehicle = vehicle;
+      Distance = distance;
+      Overload = overload;
+      Tardiness = tardiness;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinVehicleAssignmentMoveAttribute(this, cloner);
+    }
+
+    public override int GetHashCode() {
+      return Tour.GetHashCode() + Vehicle.GetHashCode();
+    }
+
+    public override bool Equals(object obj) {
+      if (obj is PotvinVehicleAssignmentMoveAttribute) {
+        PotvinVehicleAssignmentMoveAttribute other = obj as PotvinVehicleAssignmentMoveAttribute;
+
+        return Tour == other.Tour && Vehicle == other.Vehicle;
+      } else {
+        return base.Equals(obj);
+      }
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMoveEvaluator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMoveEvaluator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMoveEvaluator.cs	(revision 14416)
@@ -0,0 +1,64 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinVehicleAssignmentMoveEvaluator", "Evaluates a vehicle assignment move for a VRP representation. ")]
+  [StorableClass]
+  public sealed class PotvinVehicleAssignmentMoveEvaluator : PotvinMoveEvaluator, IPotvinVehicleAssignmentMoveOperator {
+    public ILookupParameter<PotvinVehicleAssignmentMove> VehicleAssignmentMoveParameter {
+      get { return (ILookupParameter<PotvinVehicleAssignmentMove>)Parameters["PotvinVehicleAssignmentMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return VehicleAssignmentMoveParameter; }
+    }
+
+    [StorableConstructor]
+    private PotvinVehicleAssignmentMoveEvaluator(bool deserializing) : base(deserializing) { }
+
+    public PotvinVehicleAssignmentMoveEvaluator()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinVehicleAssignmentMove>("PotvinVehicleAssignmentMove", "The move that should be evaluated."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinVehicleAssignmentMoveEvaluator(this, cloner);
+    }
+
+    private PotvinVehicleAssignmentMoveEvaluator(PotvinVehicleAssignmentMoveEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void EvaluateMove() {
+      PotvinVehicleAssignmentMove move = VehicleAssignmentMoveParameter.ActualValue;
+
+      PotvinEncoding newSolution = VehicleAssignmentMoveParameter.ActualValue.Individual.Clone() as PotvinEncoding;
+      PotvinVehicleAssignmentMoveMaker.Apply(newSolution, move, ProblemInstance);
+
+      UpdateEvaluation(newSolution);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,74 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinVehicleAssignmentMoveGenerator", "Generates vehicle assignment moves from a given VRP encoding.")]
+  [StorableClass]
+  public abstract class PotvinVehicleAssignmentMoveGenerator : PotvinMoveGenerator, IPotvinVehicleAssignmentMoveOperator {
+    public ILookupParameter<PotvinVehicleAssignmentMove> VehicleAssignmentMoveParameter {
+      get { return (ILookupParameter<PotvinVehicleAssignmentMove>)Parameters["PotvinVehicleAssignmentMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return VehicleAssignmentMoveParameter; }
+    }
+
+    protected ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+
+    [StorableConstructor]
+    protected PotvinVehicleAssignmentMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinVehicleAssignmentMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinVehicleAssignmentMove>("PotvinVehicleAssignmentMove", "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 PotvinVehicleAssignmentMoveGenerator(PotvinVehicleAssignmentMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected abstract PotvinVehicleAssignmentMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance);
+
+    public override IOperation InstrumentedApply() {
+      IOperation next = base.InstrumentedApply();
+
+      PotvinEncoding individual = VRPToursParameter.ActualValue as PotvinEncoding;
+      PotvinVehicleAssignmentMove[] 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(VehicleAssignmentMoveParameter.ActualName, moves[i]));
+      }
+      CurrentScopeParameter.ActualValue.SubScopes.AddRange(moveScopes);
+
+      return next;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMoveMaker.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMoveMaker.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMoveMaker.cs	(revision 14416)
@@ -0,0 +1,86 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinVehicleAssignmentMoveMaker", "Peforms the vehicle assignment move on a given VRP encoding and updates the quality.")]
+  [StorableClass]
+  public class PotvinVehicleAssignmentMoveMaker : PotvinMoveMaker, IPotvinVehicleAssignmentMoveOperator, IMoveMaker {
+    public ILookupParameter<PotvinVehicleAssignmentMove> VehicleAssignmentMoveParameter {
+      get { return (ILookupParameter<PotvinVehicleAssignmentMove>)Parameters["PotvinVehicleAssignmentMove"]; }
+    }
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return VehicleAssignmentMoveParameter; }
+    }
+
+    public ILookupParameter<VariableCollection> MemoriesParameter {
+      get { return (ILookupParameter<VariableCollection>)Parameters["Memories"]; }
+    }
+
+    public IValueParameter<StringValue> AdditionFrequencyMemoryKeyParameter {
+      get { return (IValueParameter<StringValue>)Parameters["AdditionFrequencyMemoryKey"]; }
+    }
+
+    [StorableConstructor]
+    protected PotvinVehicleAssignmentMoveMaker(bool deserializing) : base(deserializing) { }
+
+    public PotvinVehicleAssignmentMoveMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinVehicleAssignmentMove>("PotvinVehicleAssignmentMove", "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 PotvinVehicleAssignmentMoveMaker(this, cloner);
+    }
+
+    protected PotvinVehicleAssignmentMoveMaker(PotvinVehicleAssignmentMoveMaker original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static void Apply(PotvinEncoding solution, PotvinVehicleAssignmentMove move, IVRPProblemInstance problemInstance) {
+      int vehicle1 = solution.VehicleAssignment[move.Tour1];
+      int vehicle2 = solution.VehicleAssignment[move.Tour2];
+
+      solution.VehicleAssignment[move.Tour1] = vehicle2;
+      solution.VehicleAssignment[move.Tour2] = vehicle1;
+    }
+
+    protected override void PerformMove() {
+      PotvinVehicleAssignmentMove move = VehicleAssignmentMoveParameter.ActualValue;
+
+      PotvinEncoding newSolution = move.Individual.Clone() as PotvinEncoding;
+      Apply(newSolution, move, ProblemInstance);
+      newSolution.Repair();
+      VRPToursParameter.ActualValue = newSolution;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMoveTabuCriterion.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMoveTabuCriterion.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMoveTabuCriterion.cs	(revision 14416)
@@ -0,0 +1,165 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinVehicleAssignmentMoveTabuCriterion", @"Checks if a certain vehicle assignment move is tabu.")]
+  [StorableClass]
+  public class PotvinVehicleAssignmentMoveTabuCriterion : SingleSuccessorOperator, IPotvinVehicleAssignmentMoveOperator, ITabuChecker, IPotvinOperator, IVRPMoveOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+
+    public ILookupParameter<PotvinVehicleAssignmentMove> VehicleAssignmentMoveParameter {
+      get { return (ILookupParameter<PotvinVehicleAssignmentMove>)Parameters["PotvinVehicleAssignmentMove"]; }
+    }
+    public ILookupParameter VRPMoveParameter {
+      get { return VehicleAssignmentMoveParameter; }
+    }
+    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 PotvinVehicleAssignmentMoveTabuCriterion(bool deserializing) : base(deserializing) { }
+    protected PotvinVehicleAssignmentMoveTabuCriterion(PotvinVehicleAssignmentMoveTabuCriterion original, Cloner cloner) : base(original, cloner) { }
+    public PotvinVehicleAssignmentMoveTabuCriterion()
+      : base() {
+      Parameters.Add(new LookupParameter<PotvinVehicleAssignmentMove>("PotvinVehicleAssignmentMove", "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 PotvinVehicleAssignmentMoveTabuCriterion(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      ItemList<IItem> tabuList = TabuListParameter.ActualValue;
+      double moveQuality = MoveQualityParameter.ActualValue.Value;
+      bool useAspiration = UseAspirationCriterion.Value;
+      bool isTabu = false;
+      PotvinVehicleAssignmentMove move = VehicleAssignmentMoveParameter.ActualValue;
+
+      foreach (IItem tabuMove in tabuList) {
+        PotvinVehicleAssignmentMoveAttribute attribute = tabuMove as PotvinVehicleAssignmentMoveAttribute;
+
+        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;
+
+          if (!useAspiration || moveQuality >= quality) {
+            if (attribute.Tour == move.Tour1 && attribute.Vehicle == move.Individual.GetVehicleAssignment(move.Tour2)) {
+              isTabu = true;
+              break;
+            }
+
+            if (attribute.Tour == move.Tour2 && attribute.Vehicle == move.Individual.GetVehicleAssignment(move.Tour1)) {
+              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/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMoveTabuMaker.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMoveTabuMaker.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMoveTabuMaker.cs	(revision 14416)
@@ -0,0 +1,137 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinVehicleAssignmentMoveTabuMaker", "Declares a given vehicle assignment move as tabu.")]
+  [StorableClass]
+  public class PotvinVehicleAssignmentMoveTabuMaker : SingleSuccessorOperator, ITabuMaker, IPotvinVehicleAssignmentMoveOperator, IPotvinOperator, ISingleObjectiveOperator {
+    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<PotvinVehicleAssignmentMove> VehicleAssignmentMoveParameter {
+      get { return (ILookupParameter<PotvinVehicleAssignmentMove>)Parameters["PotvinVehicleAssignmentMove"]; }
+    }
+    public ILookupParameter VRPMoveParameter {
+      get { return VehicleAssignmentMoveParameter; }
+    }
+    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"]; }
+    }
+
+    [StorableConstructor]
+    protected PotvinVehicleAssignmentMoveTabuMaker(bool deserializing) : base(deserializing) { }
+    protected PotvinVehicleAssignmentMoveTabuMaker(PotvinVehicleAssignmentMoveTabuMaker original, Cloner cloner) : base(original, cloner) { }
+    public PotvinVehicleAssignmentMoveTabuMaker()
+      : 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<PotvinVehicleAssignmentMove>("PotvinVehicleAssignmentMove", "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"));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinVehicleAssignmentMoveTabuMaker(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);
+      }
+
+      PotvinVehicleAssignmentMove move = VehicleAssignmentMoveParameter.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;
+
+      tabuList.Add(new PotvinVehicleAssignmentMoveAttribute(baseQuality, move.Tour1, move.Individual.GetVehicleAssignment(move.Tour1),
+        distance, overload, tardiness));
+      tabuList.Add(new PotvinVehicleAssignmentMoveAttribute(baseQuality, move.Tour2, move.Individual.GetVehicleAssignment(move.Tour2),
+        distance, overload, tardiness));
+
+      return base.Apply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMultiMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMultiMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentMultiMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,73 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinVehicleAssignmentMultiMoveGenerator", "Generates vehicle assignment moves from a given VRP encoding.")]
+  [StorableClass]
+  public sealed class PotvinVehicleAssignmentMultiMoveGenerator : PotvinVehicleAssignmentMoveGenerator, 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 PotvinVehicleAssignmentMultiMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private PotvinVehicleAssignmentMultiMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinVehicleAssignmentMultiMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("SampleSize", "The number of moves to generate."));
+    }
+
+    private PotvinVehicleAssignmentMultiMoveGenerator(PotvinVehicleAssignmentMultiMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override PotvinVehicleAssignmentMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<PotvinVehicleAssignmentMove> result = new List<PotvinVehicleAssignmentMove>();
+
+      for (int i = 0; i < SampleSizeParameter.ActualValue.Value; i++) {
+        var move = PotvinVehicleAssignmentSingleMoveGenerator.Apply(individual, ProblemInstance, RandomParameter.ActualValue);
+        if (move != null)
+          result.Add(move);
+      }
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentSingleMoveGenerator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentSingleMoveGenerator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Moves/VehicleAssignment/PotvinVehicleAssignmentSingleMoveGenerator.cs	(revision 14416)
@@ -0,0 +1,87 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinVehicleAssignmentSingleMoveGenerator", "Generates a single vehicle assignment move from a given VRP encoding.")]
+  [StorableClass]
+  public sealed class PotvinVehicleAssignmentSingleMoveGenerator : PotvinVehicleAssignmentMoveGenerator,
+    ISingleMoveGenerator {
+    #region IMultiVRPMoveOperator Members
+
+    public override ILookupParameter VRPMoveParameter {
+      get { return (ILookupParameter)Parameters["PotvinVehicleAssignmentMove"]; }
+    }
+
+    #endregion
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinVehicleAssignmentSingleMoveGenerator(this, cloner);
+    }
+
+    [StorableConstructor]
+    private PotvinVehicleAssignmentSingleMoveGenerator(bool deserializing) : base(deserializing) { }
+
+    public PotvinVehicleAssignmentSingleMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+    }
+
+    private PotvinVehicleAssignmentSingleMoveGenerator(PotvinVehicleAssignmentSingleMoveGenerator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static PotvinVehicleAssignmentMove Apply(PotvinEncoding individual, IVRPProblemInstance problemInstance, IRandom rand) {
+      if (individual.Tours.Count > 1) {
+        int tour1 = rand.Next(individual.Tours.Count);
+        int tour2 = rand.Next(problemInstance.Vehicles.Value);
+
+        while (tour2 == tour1)
+          tour2 = rand.Next(problemInstance.Vehicles.Value);
+
+        return new PotvinVehicleAssignmentMove(tour1, tour2, individual);
+      } else {
+        return null;
+      }
+    }
+
+    protected override PotvinVehicleAssignmentMove[] GenerateMoves(PotvinEncoding individual, IVRPProblemInstance problemInstance) {
+      List<PotvinVehicleAssignmentMove> result = new List<PotvinVehicleAssignmentMove>();
+
+      PotvinVehicleAssignmentMove move = Apply(individual, ProblemInstance, RandomParameter.ActualValue);
+      if (move != null)
+        result.Add(move);
+
+      return result.ToArray();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/PotvinEncoding.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/PotvinEncoding.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/PotvinEncoding.cs	(revision 14416)
@@ -0,0 +1,246 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("PotvinEncoding", "Represents a potvin encoding of VRP solutions. 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.")]
+  [StorableClass]
+  public class PotvinEncoding : TourEncoding {
+    [Storable]
+    public List<int> Unrouted { get; set; }
+
+    // VehicleAssignment[tour] retreives the assigned vehicle for the given tour
+    [Storable]
+    public Permutation VehicleAssignment { get; private set; }
+
+    public PotvinEncoding(IVRPProblemInstance instance)
+      : base(instance) {
+      Unrouted = new List<int>();
+      VehicleAssignment = new Permutation(PermutationTypes.Absolute, instance.Vehicles.Value);
+    }
+
+    [StorableConstructor]
+    protected PotvinEncoding(bool serializing)
+      : base(serializing) {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PotvinEncoding(this, cloner);
+    }
+
+    protected PotvinEncoding(PotvinEncoding original, Cloner cloner)
+      : base(original, cloner) {
+      this.Unrouted = new List<int>(original.Unrouted);
+      this.VehicleAssignment = cloner.Clone<Permutation>(original.VehicleAssignment);
+    }
+
+    public override void Repair() {
+      List<Tour> toBeRemoved = new List<Tour>();
+      foreach (Tour tour in Tours) {
+        if (tour.Stops.Count == 0)
+          toBeRemoved.Add(tour);
+      }
+
+      foreach (Tour tour in toBeRemoved) {
+        int index = Tours.IndexOf(tour);
+        Tours.Remove(tour);
+        if (index < VehicleAssignment.Length) {
+          int vehicle = VehicleAssignment[index];
+          int max = System.Math.Min(VehicleAssignment.Length - 1, Tours.Count);
+
+          for (int i = index; i < max; i++) {
+            VehicleAssignment[i] = VehicleAssignment[i + 1];
+          }
+          VehicleAssignment[max] = vehicle;
+        }
+      }
+
+      while (Tours.Count > ProblemInstance.Vehicles.Value) {
+        Tour tour = Tours[Tours.Count - 1];
+        Tours[Tours.Count - 2].Stops.AddRange(tour.Stops);
+
+        Tours.Remove(tour);
+      }
+    }
+
+    public override int GetVehicleAssignment(int tour) {
+      return VehicleAssignment[tour];
+    }
+
+    public static PotvinEncoding ConvertFrom(IVRPEncoding encoding, IVRPProblemInstance instance) {
+      PotvinEncoding solution = new PotvinEncoding(instance);
+
+      TourEncoding.ConvertFrom(encoding, solution, instance);
+
+      List<int> vehicles = new List<int>();
+      for (int i = 0; i < instance.Vehicles.Value; i++)
+        vehicles.Add(i);
+
+      int[] assignment = new int[instance.Vehicles.Value];
+      for (int i = 0; i < assignment.Length; i++)
+        assignment[i] = -1;
+
+      for (int i = 0; i < solution.Tours.Count; i++) {
+        int vehicle = encoding.GetVehicleAssignment(i);
+        assignment[i] = vehicle;
+        vehicles.Remove(vehicle);
+      }
+
+      for (int i = 0; i < instance.Vehicles.Value; i++) {
+        if (assignment[i] == -1) {
+          int vehicle = vehicles[0];
+          assignment[i] = vehicle;
+          vehicles.RemoveAt(0);
+        }
+      }
+
+      solution.VehicleAssignment = new Permutation(PermutationTypes.Absolute, assignment);
+
+      return solution;
+    }
+
+    public static PotvinEncoding ConvertFrom(List<int> route, IVRPProblemInstance instance) {
+      PotvinEncoding solution = new PotvinEncoding(instance);
+
+      solution.Tours = new ItemList<Tour>();
+
+      Tour tour = new Tour();
+      int routeIdx = 0;
+      for (int i = 0; i < route.Count; i++) {
+        if (route[i] <= 0) {
+          if (tour.Stops.Count > 0) {
+            solution.Tours.Add(tour);
+            tour = new Tour();
+          }
+          int vehicle = -route[i];
+          solution.VehicleAssignment[routeIdx] = vehicle;
+          routeIdx++;
+        } else {
+          tour.Stops.Add(route[i]);
+        }
+      }
+
+      solution.Repair();
+
+      return solution;
+    }
+
+    public double GetTourLength(Tour tour) {
+      return tour.GetTourLength(ProblemInstance, this);
+    }
+
+    public int FindBestInsertionPlace(Tour tour, int city, int positionToAvoid = -1) {
+      if (tour.Stops.Count == 0)
+        return 0;
+
+      int place = -1;
+      double minQuality = -1;
+
+      VRPEvaluation eval = ProblemInstance.EvaluateTour(tour, this);
+
+      for (int i = 0; i <= tour.Stops.Count; i++) {
+        if (positionToAvoid != i) {
+          bool feasible;
+          double quality = ProblemInstance.GetInsertionCosts(eval, this, city, 0, i, out feasible);
+          if (place < 0 || quality < minQuality) {
+            place = i;
+            minQuality = quality;
+          }
+        }
+      }
+
+      if (place == -1)
+        place = 0;
+
+      return place;
+    }
+
+    public void InsertPair(Tour tour, int source, int target, IVRPProblemInstance problemInstance, int positionToAvoid = -1, int positionToAvoid2 = -1) {
+      int stops = tour.Stops.Count;
+      VRPEvaluation eval = problemInstance.EvaluateTour(tour, this);
+      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, this);
+        double sourceCosts = tourEval.Quality - eval.Quality;
+
+        for (int j = i + 1; j <= stops + 1; j++) {
+          if (positionToAvoid != i || positionToAvoid2 != j || stops == 0) {
+            bool feasible;
+            double targetCosts = problemInstance.GetInsertionCosts(tourEval, this, target, 0, j, out feasible);
+
+            double costs = sourceCosts + targetCosts;
+            if (costs < minCosts) {
+              minCosts = costs;
+              sourceLocation = i;
+              targetLocation = j;
+            }
+          }
+        }
+        tour.Stops.Remove(source);
+      }
+
+      tour.Stops.Insert(sourceLocation, source);
+      tour.Stops.Insert(targetLocation, target);
+    }
+
+    public bool FindInsertionPlace(int city, int routeToAvoid, bool allowInfeasible, out int route, out int place) {
+      route = -1;
+      place = -1;
+      double minDetour = double.MaxValue;
+
+      VRPEvaluation eval = ProblemInstance.Evaluate(this);
+      bool originalFeasible = ProblemInstance.Feasible(eval);
+
+      for (int tour = 0; tour < Tours.Count; tour++) {
+        if (tour != routeToAvoid) {
+          double length = eval.Quality;
+
+          for (int i = 0; i <= Tours[tour].Stops.Count; i++) {
+            bool feasible;
+            double detour = ProblemInstance.GetInsertionCosts(eval, this, city, tour, i, out feasible);
+
+            if (feasible || allowInfeasible) {
+              if (route < 0 || detour < minDetour) {
+                route = tour;
+                place = i;
+                minDetour = detour;
+              }
+            }
+          }
+        }
+      }
+
+      return route >= 0 && place >= 0;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/Crossovers/PrinsCrossover.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/Crossovers/PrinsCrossover.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/Crossovers/PrinsCrossover.cs	(revision 14416)
@@ -0,0 +1,72 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Prins {
+  [Item("PrinsCrossover", "An operator which crosses two VRP representations.")]
+  [StorableClass]
+  public abstract class PrinsCrossover : VRPCrossover, IStochasticOperator, IPrinsOperator {
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    [StorableConstructor]
+    protected PrinsCrossover(bool deserializing) : base(deserializing) { }
+
+    public PrinsCrossover()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator which should be used for stochastic manipulation operators."));
+    }
+
+    protected PrinsCrossover(PrinsCrossover original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected abstract PrinsEncoding Crossover(IRandom random, PrinsEncoding parent1, PrinsEncoding parent2);
+
+    public override IOperation InstrumentedApply() {
+      ItemArray<IVRPEncoding> parents = new ItemArray<IVRPEncoding>(ParentsParameter.ActualValue.Length);
+      for (int i = 0; i < ParentsParameter.ActualValue.Length; i++) {
+        IVRPEncoding solution = ParentsParameter.ActualValue[i];
+
+        if (!(solution is PrinsEncoding)) {
+          parents[i] = PrinsEncoding.ConvertFrom(solution, ProblemInstance);
+        } else {
+          parents[i] = solution;
+        }
+      }
+      ParentsParameter.ActualValue = parents;
+
+      ChildParameter.ActualValue =
+        Crossover(RandomParameter.ActualValue, parents[0] as PrinsEncoding, parents[1] as PrinsEncoding);
+
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/Crossovers/PrinsPermutationCrossover.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/Crossovers/PrinsPermutationCrossover.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/Crossovers/PrinsPermutationCrossover.cs	(revision 14416)
@@ -0,0 +1,74 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Encodings.PermutationEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Prins {
+  [Item("PrinsPermutationCrossover", "An operator which crosses two VRP representations using a standard permutation operator.  It is implemented as described in Prins, C. (2004). A simple and effective evolutionary algorithm for the vehicle routing problem. Computers & Operations Research, 12:1985-2002.")]
+  [StorableClass]
+  public sealed class PrinsPermutationCrossover : PrinsCrossover, IPrinsOperator {
+    public IValueLookupParameter<IPermutationCrossover> InnerCrossoverParameter {
+      get { return (IValueLookupParameter<IPermutationCrossover>)Parameters["InnerCrossover"]; }
+    }
+
+    [StorableConstructor]
+    private PrinsPermutationCrossover(bool deserializing) : base(deserializing) { }
+
+    public PrinsPermutationCrossover()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<IPermutationCrossover>("InnerCrossover", "The permutation crossover.", new OrderCrossover()));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PrinsPermutationCrossover(this, cloner);
+    }
+
+    private PrinsPermutationCrossover(PrinsPermutationCrossover original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override PrinsEncoding Crossover(IRandom random, PrinsEncoding parent1, PrinsEncoding parent2) {
+      if (parent1.Length != parent2.Length)
+        return parent1.Clone() as PrinsEncoding;
+
+      //note - the inner crossover is called here and the result is converted to a prins representation
+      //some refactoring should be done here in the future - the crossover operation should be called directly
+
+      InnerCrossoverParameter.ActualValue.ParentsParameter.ActualName = ParentsParameter.ActualName;
+      IAtomicOperation op = this.ExecutionContext.CreateOperation(
+        InnerCrossoverParameter.ActualValue, this.ExecutionContext.Scope);
+      op.Operator.Execute((IExecutionContext)op, CancellationToken);
+
+      string childName = InnerCrossoverParameter.ActualValue.ChildParameter.ActualName;
+      if (ExecutionContext.Scope.Variables.ContainsKey(childName)) {
+        Permutation permutation = ExecutionContext.Scope.Variables[childName].Value as Permutation;
+        ExecutionContext.Scope.Variables.Remove(childName);
+
+        return new PrinsEncoding(permutation, ProblemInstance);
+      } else
+        return null;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/IPrinsOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/IPrinsOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/IPrinsOperator.cs	(revision 14416)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Prins {
+  public interface IPrinsOperator :
+    ISingleDepotOperator, IHomogenousCapacitatedOperator, ITimeWindowedOperator {
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/Manipulators/PrinsExhaustiveLSManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/Manipulators/PrinsExhaustiveLSManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/Manipulators/PrinsExhaustiveLSManipulator.cs	(revision 14416)
@@ -0,0 +1,82 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Prins {
+  [Item("PrinsExhaustiveLSManipulator", "An operator which manipulates a VRP representation by using the exhaustive Prins local search.  It is implemented as described in Prins, C. (2004). A simple and effective evolutionary algorithm for the vehicle routing problem. Computers & Operations Research, 12:1985-2002.")]
+  [StorableClass]
+  public sealed class PrinsExhaustiveLSManipulator : PrinsLSManipulator {
+    [StorableConstructor]
+    private PrinsExhaustiveLSManipulator(bool deserializing) : base(deserializing) { }
+
+    public PrinsExhaustiveLSManipulator()
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PrinsExhaustiveLSManipulator(this, cloner);
+    }
+
+    private PrinsExhaustiveLSManipulator(PrinsExhaustiveLSManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void Manipulate(IRandom random, PrinsEncoding individual) {
+      List<Tour> tours = individual.GetTours();
+      bool improvement = false;
+      int iterations = 0;
+
+      do {
+        int u = depot;
+        improvement = false;
+        double originalQuality = GetQuality(individual);
+        PrinsEncoding child = null;
+
+        while (!improvement && u < ProblemInstance.Cities.Value) {
+          int v = depot;
+          while (!improvement && v < ProblemInstance.Cities.Value) {
+            if (u != v) {
+              child = Manipulate(individual,
+                originalQuality, u, v);
+
+              improvement = child != null;
+            }
+            v++;
+          }
+          u++;
+        }
+
+        if (improvement) {
+          for (int i = 0; i < child.Length; i++) {
+            individual[i] = child[i];
+          }
+        }
+
+        iterations++;
+      } while (improvement &&
+        iterations < Iterations.Value.Value);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/Manipulators/PrinsLSManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/Manipulators/PrinsLSManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/Manipulators/PrinsLSManipulator.cs	(revision 14416)
@@ -0,0 +1,459 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Prins {
+  [Item("PrinsLSManipulator", "An operator which manipulates a VRP representation by using the Prins local search.  It is implemented as described in Prins, C. (2004). A simple and effective evolutionary algorithm for the vehicle routing problem. Computers & Operations Research, 12:1985-2002.")]
+  [StorableClass]
+  public abstract class PrinsLSManipulator : PrinsManipulator, IVRPLocalSearchManipulator {
+    public IValueParameter<IntValue> Iterations {
+      get { return (IValueParameter<IntValue>)Parameters["Iterations"]; }
+    }
+
+    [StorableConstructor]
+    protected PrinsLSManipulator(bool deserializing) : base(deserializing) { }
+
+    public PrinsLSManipulator()
+      : base() {
+      Parameters.Add(new ValueParameter<IntValue>("Iterations", "The number of max iterations.", new IntValue(5)));
+    }
+
+    protected PrinsLSManipulator(PrinsLSManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected double GetQuality(PrinsEncoding individual) {
+      return ProblemInstance.Evaluate(individual).Quality;
+    }
+
+    private int FindCity(PrinsEncoding individual, int city) {
+      int index = -1;
+
+      int i = 0;
+      while (i < individual.Length && index == -1) {
+        if (individual[i] == city)
+          index = i;
+
+        i++;
+      }
+
+      return index;
+    }
+
+    protected const int depot = -1;
+
+    private Tour FindTour(PrinsEncoding individual, int city) {
+      Tour found = null;
+
+      List<Tour> tours = individual.GetTours();
+      int i = 0;
+
+      while (found == null && i < tours.Count) {
+        if (tours[i].Stops.Contains(city))
+          found = tours[i];
+
+        i++;
+      }
+
+      return found;
+    }
+
+    //inserts u after v in the child
+    private void InsertAfter(int u, int v, PrinsEncoding parent, PrinsEncoding child) {
+      int pi = 0;
+      int ci = 0;
+
+      while (ci != child.Length) {
+        if (parent[pi] != u) {
+          child[ci] = parent[pi];
+          ci++;
+        }
+        if (parent[pi] == v) {
+          child[ci] = u;
+          ci++;
+        }
+
+        pi++;
+      }
+    }
+
+    //inserts (u, x) after v in the child
+    private void InsertAfter(int u, int x, int v, PrinsEncoding parent, PrinsEncoding child) {
+      int pi = 0;
+      int ci = 0;
+
+      while (ci != child.Length) {
+        if (parent[pi] != u && parent[pi] != x) {
+          child[ci] = parent[pi];
+          ci++;
+        }
+        if (parent[pi] == v) {
+          child[ci] = u;
+          ci++;
+
+          child[ci] = x;
+          ci++;
+        }
+
+        pi++;
+      }
+    }
+
+    //inserts u before v in the child
+    private void InsertBefore(int u, int v, PrinsEncoding parent, PrinsEncoding child) {
+      int pi = 0;
+      int ci = 0;
+
+      while (ci != child.Length) {
+        if (parent[pi] == v) {
+          child[ci] = u;
+          ci++;
+        }
+        if (parent[pi] != u) {
+          child[ci] = parent[pi];
+          ci++;
+        }
+
+        pi++;
+      }
+    }
+
+    //inserts (u, x) before v in the child
+    private void InsertBefore(int u, int x, int v, PrinsEncoding parent, PrinsEncoding child) {
+      int pi = 0;
+      int ci = 0;
+
+      while (ci != child.Length) {
+        if (parent[pi] == v) {
+          child[ci] = u;
+          ci++;
+
+          child[ci] = x;
+          ci++;
+        }
+        if (parent[pi] != u && parent[pi] != x) {
+          child[ci] = parent[pi];
+          ci++;
+        }
+
+        pi++;
+      }
+    }
+
+    //swaps u and v
+    private void Swap(int u, int v, PrinsEncoding parent, PrinsEncoding child) {
+      for (int i = 0; i < child.Length; i++) {
+        if (parent[i] == u)
+          child[i] = v;
+        else if (parent[i] == v)
+          child[i] = u;
+        else
+          child[i] = parent[i];
+      }
+    }
+
+    //swaps (u, x) and v
+    private void Swap(int u, int x, int v, PrinsEncoding parent, PrinsEncoding child) {
+      int childIndex = 0;
+      int parentIndex = 0;
+
+      while (childIndex < child.Length) {
+        if (parent[parentIndex] == u) {
+          child[childIndex] = v;
+          parentIndex++;
+        } else if (parent[parentIndex] == v) {
+          child[childIndex] = u;
+          childIndex++;
+          child[childIndex] = x;
+        } else {
+          child[childIndex] = parent[parentIndex];
+        }
+
+        childIndex++;
+        parentIndex++;
+      }
+    }
+
+    //swaps (u, x) and (v, y)
+    private void Swap(int u, int x, int v, int y, PrinsEncoding parent, PrinsEncoding child) {
+      int i = 0;
+
+      while (i < child.Length) {
+        if (child[i] == u) {
+          child[i] = v;
+          i++;
+          child[i] = y;
+        } else if (child[i] == v) {
+          child[i] = u;
+          i++;
+          child[i] = x;
+        } else {
+          child[i] = parent[i];
+        }
+
+        i++;
+      }
+    }
+
+    //swaps (u, x) and (v, y) by (u, y) and (x, v)
+    private void Swap2(int u, int x, int v, int y, PrinsEncoding parent, PrinsEncoding child) {
+      int i = 0;
+
+      while (i < child.Length) {
+        if (parent[i] == x) {
+          child[i] = y;
+        } else if (parent[i] == v) {
+          child[i] = x;
+        } else if (parent[i] == y) {
+          child[i] = v;
+        } else {
+          child[i] = parent[i];
+        }
+
+        i++;
+      }
+    }
+
+    private void M1(PrinsEncoding parent, PrinsEncoding child, int u, int v) {
+      if (u != depot) {
+        if (v == depot) {
+          Tour tour = FindTour(child, u + 1);
+          v = tour.Stops[0] - 1;
+          InsertBefore(u, v, parent, child);
+        } else {
+          InsertAfter(u, v, parent, child);
+        }
+      }
+    }
+
+    private void M2(PrinsEncoding parent, PrinsEncoding child, int u, int v) {
+      if (u != depot) {
+        Tour tour = FindTour(child, u + 1);
+        int iu = tour.Stops.IndexOf(u + 1);
+        if (iu < tour.Stops.Count - 1) {
+          int x = tour.Stops[iu + 1] - 1;
+
+          if (v == depot) {
+            tour = FindTour(child, u + 1);
+            v = tour.Stops[0] - 1;
+            InsertBefore(u, x, v, parent, child);
+          } else {
+            InsertAfter(u, x, v, parent, child);
+          }
+        }
+      }
+    }
+
+    private void M3(PrinsEncoding parent, PrinsEncoding child, int u, int v) {
+      if (u != depot) {
+        Tour tour = FindTour(child, u + 1);
+        int iu = tour.Stops.IndexOf(u + 1);
+        if (iu < tour.Stops.Count - 1) {
+          int x = tour.Stops[iu + 1] - 1;
+
+          if (v == depot) {
+            tour = FindTour(child, u + 1);
+            v = tour.Stops[0] - 1;
+            InsertBefore(x, u, v, parent, child);
+          } else {
+            InsertAfter(x, u, v, parent, child);
+          }
+        }
+      }
+    }
+
+    private void M4(PrinsEncoding parent, PrinsEncoding child, int u, int v) {
+      if (u != depot && v != depot) {
+        Swap(u, v, parent, child);
+      }
+    }
+
+    private void M5(PrinsEncoding parent, PrinsEncoding child, int u, int v) {
+      if (u != depot && v != depot) {
+        Tour tour = FindTour(child, u + 1);
+        int iu = tour.Stops.IndexOf(u + 1);
+        if (iu < tour.Stops.Count - 1) {
+          int x = tour.Stops[iu + 1] - 1;
+
+          if (x != v)
+            Swap(u, x, v, parent, child);
+        }
+      }
+    }
+
+    private void M6(PrinsEncoding parent, PrinsEncoding child, int u, int v) {
+      if (u != depot && v != depot) {
+        Tour tour = FindTour(child, u + 1);
+        int iu = tour.Stops.IndexOf(u + 1);
+        if (iu < tour.Stops.Count - 1) {
+          int x = tour.Stops[iu + 1] - 1;
+
+          tour = FindTour(child, v + 1);
+          int iv = tour.Stops.IndexOf(v + 1);
+          if (iv < tour.Stops.Count - 1) {
+            int y = tour.Stops[iv + 1] - 1;
+
+            if (x != v && y != u)
+              Swap(u, x, v, y, parent, child);
+          }
+        }
+      }
+    }
+
+    private void M7(PrinsEncoding parent, PrinsEncoding child, int u, int v) {
+      if (u != depot && v != depot) {
+        Tour tu = FindTour(child, u + 1);
+        Tour tv = FindTour(child, v + 1);
+
+        if (tu.Stops[0] == tv.Stops[0]) {
+          int iu = tu.Stops.IndexOf(u + 1);
+          if (iu < tu.Stops.Count - 1) {
+            int x = tu.Stops[iu + 1] - 1;
+
+            int iv = tv.Stops.IndexOf(v + 1);
+            if (iv < tv.Stops.Count - 1) {
+              int y = tv.Stops[iv + 1] - 1;
+
+              if (x != v && y != u)
+                Swap(x, v, parent, child);
+            }
+          }
+        }
+      }
+    }
+
+    private void M8(PrinsEncoding parent, PrinsEncoding child, int u, int v) {
+      if (u != depot && v != depot) {
+        Tour tu = FindTour(child, u + 1);
+        Tour tv = FindTour(child, v + 1);
+
+        if (tu.Stops[0] != tv.Stops[0]) {
+          int iu = tu.Stops.IndexOf(u + 1);
+          if (iu < tu.Stops.Count - 1) {
+            int x = tu.Stops[iu + 1] - 1;
+
+            int iv = tv.Stops.IndexOf(v + 1);
+            if (iv < tv.Stops.Count - 1) {
+              int y = tv.Stops[iv + 1] - 1;
+
+              if (x != v && y != u)
+                Swap(x, v, parent, child);
+            }
+          }
+        }
+      }
+    }
+
+    private void M9(PrinsEncoding parent, PrinsEncoding child, int u, int v) {
+      if (u != depot && v != depot) {
+        Tour tu = FindTour(child, u + 1);
+        Tour tv = FindTour(child, v + 1);
+
+        if (tu.Stops[0] != tv.Stops[0]) {
+          int iu = tu.Stops.IndexOf(u + 1);
+          if (iu < tu.Stops.Count - 1) {
+            int x = tu.Stops[iu + 1] - 1;
+
+            int iv = tv.Stops.IndexOf(v + 1);
+            if (iv < tv.Stops.Count - 1) {
+              int y = tv.Stops[iv + 1] - 1;
+
+              if (x != v && y != u)
+                Swap2(u, x, v, y, parent, child);
+            }
+          }
+        }
+      }
+    }
+
+    protected PrinsEncoding Manipulate(PrinsEncoding individual,
+      double originalQuality, int u, int v) {
+      PrinsEncoding child = null;
+      bool improvement = false;
+
+      if (u != v) {
+        child = individual.Clone() as PrinsEncoding;
+        M1(individual, child, u, v);
+        improvement = GetQuality(child) < originalQuality;
+
+        if (!improvement) {
+          child = individual.Clone() as PrinsEncoding;
+          M2(individual, child, u, v);
+          improvement = GetQuality(child) < originalQuality;
+        }
+
+        if (!improvement) {
+          child = individual.Clone() as PrinsEncoding;
+          M3(individual, child, u, v);
+          improvement = GetQuality(child) < originalQuality;
+        }
+
+        if (!improvement) {
+          child = individual.Clone() as PrinsEncoding;
+          M4(individual, child, u, v);
+          improvement = GetQuality(child) < originalQuality;
+        }
+
+        if (!improvement) {
+          child = individual.Clone() as PrinsEncoding;
+          M5(individual, child, u, v);
+          improvement = GetQuality(child) < originalQuality;
+        }
+
+        if (!improvement) {
+          child = individual.Clone() as PrinsEncoding;
+          M6(individual, child, u, v);
+          improvement = GetQuality(child) < originalQuality;
+        }
+
+        if (!improvement) {
+          child = individual.Clone() as PrinsEncoding;
+          M7(individual, child, u, v);
+          improvement = GetQuality(child) < originalQuality;
+        }
+
+        if (!improvement) {
+          child = individual.Clone() as PrinsEncoding;
+          M8(individual, child, u, v);
+          improvement = GetQuality(child) < originalQuality;
+        }
+
+        if (!improvement) {
+          child = individual.Clone() as PrinsEncoding;
+          M9(individual, child, u, v);
+          improvement = GetQuality(child) < originalQuality;
+        }
+      }
+
+      if (improvement)
+        return child;
+      else
+        return null;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/Manipulators/PrinsManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/Manipulators/PrinsManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/Manipulators/PrinsManipulator.cs	(revision 14416)
@@ -0,0 +1,63 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Prins {
+  [Item("PrinsManipulator", "An operator which manipulates a VRP representation.")]
+  [StorableClass]
+  public abstract class PrinsManipulator : VRPManipulator, IStochasticOperator, IPrinsOperator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    [StorableConstructor]
+    protected PrinsManipulator(bool deserializing) : base(deserializing) { }
+
+    public PrinsManipulator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator which should be used for stochastic manipulation operators."));
+    }
+
+    protected PrinsManipulator(PrinsManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected abstract void Manipulate(IRandom random, PrinsEncoding individual);
+
+    public override IOperation InstrumentedApply() {
+      IVRPEncoding solution = VRPToursParameter.ActualValue;
+      if (!(solution is PrinsEncoding)) {
+        VRPToursParameter.ActualValue = PrinsEncoding.ConvertFrom(solution, ProblemInstance);
+      }
+
+      Manipulate(RandomParameter.ActualValue, VRPToursParameter.ActualValue as PrinsEncoding);
+
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/Manipulators/PrinsPermutationManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/Manipulators/PrinsPermutationManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/Manipulators/PrinsPermutationManipulator.cs	(revision 14416)
@@ -0,0 +1,60 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Encodings.PermutationEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Prins {
+  [Item("PrinsPermutationManipulator", "An operator which manipulates a VRP representation by using a standard permutation manipulator. It is implemented as described in Prins, C. (2004). A simple and effective evolutionary algorithm for the vehicle routing problem. Computers & Operations Research, 12:1985-2002.")]
+  [StorableClass]
+  public sealed class PrinsPermutationManipulator : PrinsManipulator {
+    public IValueLookupParameter<IPermutationManipulator> InnerManipulatorParameter {
+      get { return (IValueLookupParameter<IPermutationManipulator>)Parameters["InnerManipulator"]; }
+    }
+
+    [StorableConstructor]
+    private PrinsPermutationManipulator(bool deserializing) : base(deserializing) { }
+
+    public PrinsPermutationManipulator()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<IPermutationManipulator>("InnerManipulator", "The permutation manipulator.", new TranslocationManipulator()));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PrinsPermutationManipulator(this, cloner);
+    }
+
+    private PrinsPermutationManipulator(PrinsPermutationManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void Manipulate(IRandom random, PrinsEncoding individual) {
+      InnerManipulatorParameter.ActualValue.PermutationParameter.ActualName = VRPToursParameter.ActualName;
+
+      IAtomicOperation op = this.ExecutionContext.CreateOperation(
+        InnerManipulatorParameter.ActualValue, this.ExecutionContext.Scope);
+      op.Operator.Execute((IExecutionContext)op, CancellationToken);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/Manipulators/PrinsStochasticLSManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/Manipulators/PrinsStochasticLSManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/Manipulators/PrinsStochasticLSManipulator.cs	(revision 14416)
@@ -0,0 +1,88 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Prins {
+  [Item("PrinsStochasticLSManipulator", "An operator which manipulates a VRP representation by using the stochastic version of the Prins local search.  It is implemented as described in Prins, C. (2004). A simple and effective evolutionary algorithm for the vehicle routing problem. Computers & Operations Research, 12:1985-2002.")]
+  [StorableClass]
+  public sealed class PrinsStochasticLSManipulator : PrinsLSManipulator {
+    public IValueParameter<IntValue> SampleSize {
+      get { return (IValueParameter<IntValue>)Parameters["SampleSize"]; }
+    }
+
+    [StorableConstructor]
+    private PrinsStochasticLSManipulator(bool deserializing) : base(deserializing) { }
+
+    public PrinsStochasticLSManipulator()
+      : base() {
+      Parameters.Add(new ValueParameter<IntValue>("SampleSize", "The sample size.", new IntValue(200)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PrinsStochasticLSManipulator(this, cloner);
+    }
+
+    private PrinsStochasticLSManipulator(PrinsStochasticLSManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void Manipulate(IRandom random, PrinsEncoding individual) {
+      List<Tour> tours = individual.GetTours();
+      bool improvement = false;
+      int iterations = 0;
+
+      do {
+        improvement = false;
+        double originalQuality = GetQuality(individual);
+        PrinsEncoding child = null;
+
+        int samples = 0;
+        while (!improvement &&
+          samples < SampleSize.Value.Value) {
+          int u = random.Next(ProblemInstance.Cities.Value);
+          int v = random.Next(ProblemInstance.Cities.Value);
+
+          child = Manipulate(individual,
+                originalQuality, u, v);
+
+          improvement = child != null;
+
+          samples++;
+        }
+
+        if (improvement) {
+          for (int i = 0; i < child.Length; i++) {
+            individual[i] = child[i];
+          }
+        }
+
+        iterations++;
+      } while (improvement &&
+        iterations < Iterations.Value.Value);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/PrinsEncoding.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/PrinsEncoding.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Prins/PrinsEncoding.cs	(revision 14416)
@@ -0,0 +1,178 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Prins {
+  [Item("PrinsEncoding", "Represents an Prins encoding of VRP solutions. It is implemented as described in Prins, C. (2004). A simple and effective evolutionary algorithm for the vehicle routing problem. Computers & Operations Research, 12:1985-2002.")]
+  [StorableClass]
+  public class PrinsEncoding : General.PermutationEncoding {
+    #region IVRPEncoding Members
+    public override int GetTourIndex(Tour tour) {
+      return 0;
+    }
+
+    public override List<Tour> GetTours() {
+      List<Tour> result = new List<Tour>();
+
+      int cities = ProblemInstance.Cities.Value;
+
+      //Split permutation into vector P
+      int[] P = new int[cities + 1];
+      for (int i = 0; i <= cities; i++)
+        P[i] = -1;
+
+      double[] V = new double[cities + 1];
+      V[0] = 0;
+      for (int i = 1; i <= cities; i++) {
+        V[i] = double.MaxValue;
+      }
+
+      for (int i = 1; i <= cities; i++) {
+        int j = i;
+        Tour tour = new Tour();
+        bool feasible = true;
+
+        do {
+          tour.Stops.Add(this[j - 1] + 1);
+
+          VRPEvaluation eval =
+            ProblemInstance.EvaluateTour(tour, this);
+
+          double cost = eval.Quality;
+          feasible = ProblemInstance.Feasible(eval);
+
+          if (feasible || j == i) {
+            if (V[i - 1] + cost < V[j]) {
+              V[j] = V[i - 1] + cost;
+              P[j] = i - 1;
+            }
+            j++;
+          }
+
+        } while (j <= cities && feasible);
+      }
+
+      //extract VRP solution from vector P
+      int index = 0;
+      int index2 = cities;
+      Tour trip = null;
+      do {
+        index = P[index2];
+        trip = new Tour();
+
+        for (int k = index + 1; k <= index2; k++) {
+          trip.Stops.Add(this[k - 1] + 1);
+        }
+
+        if (trip.Stops.Count > 0)
+          result.Add(trip);
+
+        index2 = index;
+      } while (index != 0);
+
+      //if there are too many vehicles - repair
+      while (result.Count > ProblemInstance.Vehicles.Value) {
+        Tour tour = result[result.Count - 1];
+
+        //find predecessor / successor in permutation
+        int predecessorIndex = Array.IndexOf(this.array, tour.Stops[0] - 1) - 1;
+        if (predecessorIndex >= 0) {
+          int predecessor = this[predecessorIndex] + 1;
+
+          foreach (Tour t in result) {
+            int insertPosition = t.Stops.IndexOf(predecessor) + 1;
+            if (insertPosition != -1) {
+              t.Stops.InsertRange(insertPosition, tour.Stops);
+              break;
+            }
+          }
+        } else {
+          int successorIndex = Array.IndexOf(this.array,
+            tour.Stops[tour.Stops.Count - 1] - 1) + 1;
+          int successor = this[successorIndex] + 1;
+
+          foreach (Tour t in result) {
+            int insertPosition = t.Stops.IndexOf(successor);
+            if (insertPosition != -1) {
+              t.Stops.InsertRange(insertPosition, tour.Stops);
+              break;
+            }
+          }
+        }
+
+        result.Remove(tour);
+      }
+
+      return result;
+    }
+    #endregion
+    public PrinsEncoding(Permutation permutation, IVRPProblemInstance problemInstance)
+      : base(permutation, problemInstance) {
+    }
+
+    [StorableConstructor]
+    protected PrinsEncoding(bool serializing)
+      : base(serializing) {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PrinsEncoding(this, cloner);
+    }
+
+    protected PrinsEncoding(PrinsEncoding original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public static PrinsEncoding ConvertFrom(IVRPEncoding encoding, IVRPProblemInstance problemInstance) {
+      List<Tour> tours = encoding.GetTours();
+      List<int> route = new List<int>();
+
+      foreach (Tour tour in tours) {
+        foreach (int city in tour.Stops)
+          route.Add(city - 1);
+      }
+
+      return new PrinsEncoding(
+        new Permutation(PermutationTypes.RelativeUndirected, route.ToArray()), problemInstance);
+    }
+
+    public static PrinsEncoding ConvertFrom(List<int> routeParam, IVRPProblemInstance problemInstance) {
+      List<int> route = new List<int>(routeParam);
+
+      while (route.Remove(0)) { //remove all delimiters (0)
+      }
+
+      for (int i = 0; i < route.Count; i++)
+        route[i]--;
+
+      return new PrinsEncoding(
+        new Permutation(PermutationTypes.RelativeUndirected, route.ToArray()), problemInstance);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Tour.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Tour.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Tour.cs	(revision 14416)
@@ -0,0 +1,81 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  [StorableClass]
+  public class Tour : Item {
+    [Storable]
+    public List<int> Stops { get; private set; }
+
+    public Tour() {
+      Stops = new List<int>();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Tour(this, cloner);
+    }
+
+    protected Tour(Tour original, Cloner cloner)
+      : base(original, cloner) {
+      this.Stops = new List<int>(original.Stops);
+    }
+
+    [StorableConstructor]
+    protected Tour(bool deserializing) : base(deserializing) { }
+
+    public double GetTourLength(IVRPProblemInstance instance, IVRPEncoding solution) {
+      double length = 0;
+
+      if (Stops.Count > 0) {
+        List<int> cities = new List<int>();
+        cities.Add(0);
+        foreach (int city in Stops) {
+          cities.Add(city);
+        }
+        cities.Add(0);
+
+        for (int i = 1; i < cities.Count; i++) {
+          length += instance.GetDistance(cities[i - 1], cities[i], solution);
+        }
+      }
+
+      return length;
+    }
+
+    public bool IsEqual(Tour tour) {
+      bool equal = (tour != null) && (tour.Stops.Count == Stops.Count);
+      int index = 0;
+
+      while (equal && index < Stops.Count) {
+        equal = equal && tour.Stops[index] == Stops[index];
+        index++;
+      }
+
+      return equal;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/VRPOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/VRPOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/VRPOperator.cs	(revision 14416)
@@ -0,0 +1,53 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings {
+  [Item("VRPOperator", "Represents a VRP operator.")]
+  [StorableClass]
+  public abstract class VRPOperator : InstrumentedOperator, IVRPOperator {
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (LookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+
+    public IVRPProblemInstance ProblemInstance {
+      get { return ProblemInstanceParameter.ActualValue; }
+    }
+
+    [StorableConstructor]
+    protected VRPOperator(bool deserializing) : base(deserializing) { }
+
+    public VRPOperator()
+      : base() {
+      Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The VRP problem instance"));
+    }
+
+    protected VRPOperator(VRPOperator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Crossovers/ZhuCrossover.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Crossovers/ZhuCrossover.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Crossovers/ZhuCrossover.cs	(revision 14416)
@@ -0,0 +1,71 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Zhu {
+  [Item("ZhuCrossover", "An operator which crosses two VRP representations.")]
+  [StorableClass]
+  public abstract class ZhuCrossover : VRPCrossover, IStochasticOperator, IZhuOperator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    [StorableConstructor]
+    protected ZhuCrossover(bool deserializing) : base(deserializing) { }
+
+    public ZhuCrossover()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator which should be used for stochastic manipulation operators."));
+    }
+
+    protected ZhuCrossover(ZhuCrossover original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected abstract ZhuEncoding Crossover(IRandom random, ZhuEncoding parent1, ZhuEncoding parent2);
+
+    public override IOperation InstrumentedApply() {
+      ItemArray<IVRPEncoding> parents = new ItemArray<IVRPEncoding>(ParentsParameter.ActualValue.Length);
+      for (int i = 0; i < ParentsParameter.ActualValue.Length; i++) {
+        IVRPEncoding solution = ParentsParameter.ActualValue[i];
+
+        if (!(solution is ZhuEncoding)) {
+          parents[i] = ZhuEncoding.ConvertFrom(solution, ProblemInstance);
+        } else {
+          parents[i] = solution;
+        }
+      }
+      ParentsParameter.ActualValue = parents;
+
+      ChildParameter.ActualValue =
+        Crossover(RandomParameter.ActualValue, parents[0] as ZhuEncoding, parents[1] as ZhuEncoding);
+
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Crossovers/ZhuHeuristicCrossover1.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Crossovers/ZhuHeuristicCrossover1.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Crossovers/ZhuHeuristicCrossover1.cs	(revision 14416)
@@ -0,0 +1,93 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Zhu {
+  [Item("ZhuHeuristicCrossover1", "The Zhu Heuristic Crossover (Version 1). It is implemented as described in Zhu, K.Q. (2000). A New Genetic Algorithm For VRPTW. Proceedings of the International Conference on Artificial Intelligence.")]
+  [StorableClass]
+  public sealed class ZhuHeuristicCrossover1 : ZhuCrossover {
+    [StorableConstructor]
+    private ZhuHeuristicCrossover1(bool deserializing) : base(deserializing) { }
+
+    public ZhuHeuristicCrossover1()
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ZhuHeuristicCrossover1(this, cloner);
+    }
+
+    private ZhuHeuristicCrossover1(ZhuHeuristicCrossover1 original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    private void Swap(ZhuEncoding individual, int city1, int city2) {
+      int index1 = individual.IndexOf(city1);
+      int index2 = individual.IndexOf(city2);
+
+      int temp = individual[index1];
+      individual[index1] = individual[index2];
+      individual[index2] = temp;
+    }
+
+    protected override ZhuEncoding Crossover(IRandom random, ZhuEncoding parent1, ZhuEncoding parent2) {
+      parent1 = parent1.Clone() as ZhuEncoding;
+      parent2 = parent2.Clone() as ZhuEncoding;
+
+      ZhuEncoding child = parent2.Clone() as ZhuEncoding;
+
+      if (parent1.Length != parent2.Length)
+        return child;
+
+      int breakPoint = random.Next(child.Length);
+      int i = breakPoint;
+      int predecessor = breakPoint - 1;
+      if (predecessor < 0)
+        predecessor = predecessor + child.Length;
+
+      while (i != predecessor) {
+        if (i == breakPoint) {
+          child[i] = parent1[i];
+          Swap(parent2, parent2[i], parent1[i]);
+        }
+
+        if (ProblemInstance.GetDistance(
+          child[i] + 1, parent1[(i + 1) % child.Length] + 1, child)
+          <
+          ProblemInstance.GetDistance(
+          child[i] + 1, parent2[(i + 1) % child.Length] + 1, child)) {
+          child[(i + 1) % child.Length] = parent1[(i + 1) % child.Length];
+          Swap(parent2, parent2[(i + 1) % child.Length], parent1[(i + 1) % child.Length]);
+        } else {
+          child[(i + 1) % child.Length] = parent2[(i + 1) % child.Length];
+          Swap(parent1, parent1[(i + 1) % child.Length], parent2[(i + 1) % child.Length]);
+        }
+
+        i = (i + 1) % child.Length;
+      }
+
+      return child;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Crossovers/ZhuHeuristicCrossover2.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Crossovers/ZhuHeuristicCrossover2.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Crossovers/ZhuHeuristicCrossover2.cs	(revision 14416)
@@ -0,0 +1,101 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Zhu {
+  [Item("ZhuHeuristicCrossover2", "The Zhu Heuristic Crossover (Version 2). It is implemented as described in Zhu, K.Q. (2000). A New Genetic Algorithm For VRPTW. Proceedings of the International Conference on Artificial Intelligence.")]
+  [StorableClass]
+  public sealed class ZhuHeuristicCrossover2 : ZhuCrossover {
+    [StorableConstructor]
+    private ZhuHeuristicCrossover2(bool deserializing) : base(deserializing) { }
+
+    public ZhuHeuristicCrossover2()
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ZhuHeuristicCrossover2(this, cloner);
+    }
+
+    private ZhuHeuristicCrossover2(ZhuHeuristicCrossover2 original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override ZhuEncoding Crossover(IRandom random, ZhuEncoding parent1, ZhuEncoding parent2) {
+      List<int> p1 = new List<int>(parent1);
+      List<int> p2 = new List<int>(parent2);
+
+      ZhuEncoding child = parent2.Clone() as ZhuEncoding;
+
+      if (parent1.Length != parent2.Length)
+        return child;
+
+      int breakPoint = random.Next(child.Length);
+      int i = breakPoint;
+      int predecessor = breakPoint - 1;
+      if (predecessor < 0)
+        predecessor = predecessor + child.Length;
+
+      int parent1Index = i;
+      int parent2Index = i;
+
+      while (i != predecessor) {
+        if (i == breakPoint) {
+          child[i] = p1[parent1Index];
+
+          p1.Remove(child[i]);
+          if (parent1Index >= p1.Count)
+            parent1Index = 0;
+
+          p2.Remove(child[i]);
+          if (parent2Index >= p2.Count)
+            parent2Index = 0;
+        }
+
+        if (ProblemInstance.GetDistance(
+         child[i] + 1, p1[parent1Index] + 1, child)
+         <
+         ProblemInstance.GetDistance(
+         child[i] + 1, p2[parent2Index] + 1, child)) {
+          child[(i + 1) % child.Length] = p1[parent1Index];
+        } else {
+          child[(i + 1) % child.Length] = p2[parent2Index];
+        }
+
+        p1.Remove(child[(i + 1) % child.Length]);
+        if (parent1Index >= p1.Count)
+          parent1Index = 0;
+
+        p2.Remove(child[(i + 1) % child.Length]);
+        if (parent2Index >= p2.Count)
+          parent2Index = 0;
+
+        i = (i + 1) % child.Length;
+      }
+
+      return child;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Crossovers/ZhuMergeCrossover1.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Crossovers/ZhuMergeCrossover1.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Crossovers/ZhuMergeCrossover1.cs	(revision 14416)
@@ -0,0 +1,96 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Zhu {
+  [Item("ZhuMergeCrossover1", "The Zhu Merge Crossover (Version 1). It is implemented as described in Zhu, K.Q. (2000). A New Genetic Algorithm For VRPTW. Proceedings of the International Conference on Artificial Intelligence.")]
+  [StorableClass]
+  public sealed class ZhuMergeCrossover1 : ZhuCrossover {
+    [StorableConstructor]
+    private ZhuMergeCrossover1(bool deserializing) : base(deserializing) { }
+
+    public ZhuMergeCrossover1()
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ZhuMergeCrossover1(this, cloner);
+    }
+
+    private ZhuMergeCrossover1(ZhuMergeCrossover1 original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    private void Swap(ZhuEncoding individual, int city1, int city2) {
+      int index1 = individual.IndexOf(city1);
+      int index2 = individual.IndexOf(city2);
+
+      int temp = individual[index1];
+      individual[index1] = individual[index2];
+      individual[index2] = temp;
+    }
+
+    protected override ZhuEncoding Crossover(IRandom random, ZhuEncoding parent1, ZhuEncoding parent2) {
+      parent1 = parent1.Clone() as ZhuEncoding;
+      parent2 = parent2.Clone() as ZhuEncoding;
+
+      ZhuEncoding child = parent2.Clone() as ZhuEncoding;
+
+      if (parent1.Length != parent2.Length)
+        return child;
+
+      int breakPoint = random.Next(child.Length);
+      int i = breakPoint;
+
+      DoubleArray dueTime = null;
+      if (ProblemInstance is ITimeWindowedProblemInstance) {
+        dueTime = (ProblemInstance as ITimeWindowedProblemInstance).DueTime;
+      }
+
+      do {
+        if (i == breakPoint) {
+          child[i] = parent1[i];
+          Swap(parent2, parent2[i], parent1[i]);
+        } else {
+          if (
+            (dueTime != null) &&
+            (dueTime[parent1[i] + 1] <
+             dueTime[parent2[i] + 1])) {
+            child[i] = parent1[i];
+            Swap(parent2, parent2[i], parent1[i]);
+          } else {
+            child[i] = parent2[i];
+            Swap(parent1, parent1[i], parent2[i]);
+          }
+        }
+
+        i = (i + 1) % child.Length;
+      } while (i != breakPoint);
+
+      return child;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Crossovers/ZhuMergeCrossover2.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Crossovers/ZhuMergeCrossover2.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Crossovers/ZhuMergeCrossover2.cs	(revision 14416)
@@ -0,0 +1,95 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Zhu {
+  [Item("ZhuMergeCrossover2", "The Zhu Merge Crossover (Version 2).  It is implemented as described in Zhu, K.Q. (2000). A New Genetic Algorithm For VRPTW. Proceedings of the International Conference on Artificial Intelligence.")]
+  [StorableClass]
+  public sealed class ZhuMergeCrossover2 : ZhuCrossover {
+    [StorableConstructor]
+    private ZhuMergeCrossover2(bool deserializing) : base(deserializing) { }
+
+    public ZhuMergeCrossover2()
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ZhuMergeCrossover2(this, cloner);
+    }
+
+    private ZhuMergeCrossover2(ZhuMergeCrossover2 original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override ZhuEncoding Crossover(IRandom random, ZhuEncoding parent1, ZhuEncoding parent2) {
+      List<int> p1 = new List<int>(parent1);
+      List<int> p2 = new List<int>(parent2);
+
+      ZhuEncoding child = parent2.Clone() as ZhuEncoding;
+
+      if (parent1.Length != parent2.Length)
+        return child;
+
+      int breakPoint = random.Next(child.Length);
+      int i = breakPoint;
+
+      int parent1Index = i;
+      int parent2Index = i;
+
+      DoubleArray dueTime = null;
+      if (ProblemInstance is ITimeWindowedProblemInstance) {
+        dueTime = (ProblemInstance as ITimeWindowedProblemInstance).DueTime;
+      }
+
+      do {
+        if (i == breakPoint) {
+          child[i] = p1[parent1Index];
+        } else {
+          if (dueTime != null &&
+            (dueTime[p1[parent1Index] + 1] <
+            dueTime[p2[parent2Index] + 1])) {
+            child[i] = p1[parent1Index];
+          } else {
+            child[i] = p2[parent2Index];
+          }
+        }
+
+        p1.Remove(child[i]);
+        if (parent1Index >= p1.Count)
+          parent1Index = 0;
+
+        p2.Remove(child[i]);
+        if (parent2Index >= p2.Count)
+          parent2Index = 0;
+
+        i = (i + 1) % child.Length;
+      } while (i != breakPoint);
+
+      return child;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Crossovers/ZhuPermutationCrossover.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Crossovers/ZhuPermutationCrossover.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Crossovers/ZhuPermutationCrossover.cs	(revision 14416)
@@ -0,0 +1,73 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Encodings.PermutationEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Zhu {
+  [Item("ZhuPermutationCrossover", "An operator which crosses two VRP representations using a standard permutation operator. It is implemented as described in Zhu, K.Q. (2000). A New Genetic Algorithm For VRPTW. Proceedings of the International Conference on Artificial Intelligence.")]
+  [StorableClass]
+  public sealed class PrinsPermutationCrossover : ZhuCrossover {
+    public IValueLookupParameter<IPermutationCrossover> InnerCrossoverParameter {
+      get { return (IValueLookupParameter<IPermutationCrossover>)Parameters["InnerCrossover"]; }
+    }
+
+    [StorableConstructor]
+    private PrinsPermutationCrossover(bool deserializing) : base(deserializing) { }
+
+    public PrinsPermutationCrossover()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<IPermutationCrossover>("InnerCrossover", "The permutation crossover.", new PartiallyMatchedCrossover()));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PrinsPermutationCrossover(this, cloner);
+    }
+
+    private PrinsPermutationCrossover(PrinsPermutationCrossover original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override ZhuEncoding Crossover(IRandom random, ZhuEncoding parent1, ZhuEncoding parent2) {
+      //note - the inner crossover is called here and the result is converted to a prins representation
+      //some refactoring should be done here in the future - the crossover operation should be called directly
+      if (parent1.Length != parent2.Length)
+        return parent1.Clone() as ZhuEncoding;
+
+      InnerCrossoverParameter.ActualValue.ParentsParameter.ActualName = ParentsParameter.ActualName;
+      IAtomicOperation op = this.ExecutionContext.CreateOperation(
+        InnerCrossoverParameter.ActualValue, this.ExecutionContext.Scope);
+      op.Operator.Execute((IExecutionContext)op, CancellationToken);
+
+      string childName = InnerCrossoverParameter.ActualValue.ChildParameter.ActualName;
+      if (ExecutionContext.Scope.Variables.ContainsKey(childName)) {
+        Permutation permutation = ExecutionContext.Scope.Variables[childName].Value as Permutation;
+        ExecutionContext.Scope.Variables.Remove(childName);
+
+        return new ZhuEncoding(permutation, ProblemInstance);
+      } else
+        return null;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/IZhuOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/IZhuOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/IZhuOperator.cs	(revision 14416)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Zhu {
+  public interface IZhuOperator :
+    ISingleDepotOperator, IHomogenousCapacitatedOperator, ITimeWindowedOperator {
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Manipulators/ZhuManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Manipulators/ZhuManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Manipulators/ZhuManipulator.cs	(revision 14416)
@@ -0,0 +1,63 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Zhu {
+  [Item("ZhuManipulator", "An operator which manipulates a VRP representation.")]
+  [StorableClass]
+  public abstract class ZhuManipulator : VRPManipulator, IStochasticOperator, IZhuOperator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    [StorableConstructor]
+    protected ZhuManipulator(bool deserializing) : base(deserializing) { }
+
+    public ZhuManipulator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator which should be used for stochastic manipulation operators."));
+    }
+
+    protected ZhuManipulator(ZhuManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected abstract void Manipulate(IRandom random, ZhuEncoding individual);
+
+    public override IOperation InstrumentedApply() {
+      IVRPEncoding solution = VRPToursParameter.ActualValue;
+      if (!(solution is ZhuEncoding)) {
+        VRPToursParameter.ActualValue = ZhuEncoding.ConvertFrom(solution, ProblemInstance);
+      }
+
+      Manipulate(RandomParameter.ActualValue, VRPToursParameter.ActualValue as ZhuEncoding);
+
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Manipulators/ZhuPermutationManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Manipulators/ZhuPermutationManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/Manipulators/ZhuPermutationManipulator.cs	(revision 14416)
@@ -0,0 +1,60 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Encodings.PermutationEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Zhu {
+  [Item("ZhuPermutationManipulator", "An operator which manipulates a VRP representation by using a standard permutation manipulator. It is implemented as described in Zhu, K.Q. (2000). A New Genetic Algorithm For VRPTW. Proceedings of the International Conference on Artificial Intelligence.")]
+  [StorableClass]
+  public sealed class ZhuPermutationManipulator : ZhuManipulator {
+    public IValueLookupParameter<IPermutationManipulator> InnerManipulatorParameter {
+      get { return (IValueLookupParameter<IPermutationManipulator>)Parameters["InnerManipulator"]; }
+    }
+
+    [StorableConstructor]
+    private ZhuPermutationManipulator(bool deserializing) : base(deserializing) { }
+
+    public ZhuPermutationManipulator()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<IPermutationManipulator>("InnerManipulator", "The permutation manipulator.", new TranslocationManipulator()));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ZhuPermutationManipulator(this, cloner);
+    }
+
+    private ZhuPermutationManipulator(ZhuPermutationManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected override void Manipulate(IRandom random, ZhuEncoding individual) {
+      InnerManipulatorParameter.ActualValue.PermutationParameter.ActualName = VRPToursParameter.ActualName;
+
+      IAtomicOperation op = this.ExecutionContext.CreateOperation(
+        InnerManipulatorParameter.ActualValue, this.ExecutionContext.Scope);
+      op.Operator.Execute((IExecutionContext)op, CancellationToken);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/ZhuEncoding.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/ZhuEncoding.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Zhu/ZhuEncoding.cs	(revision 14416)
@@ -0,0 +1,140 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Zhu {
+  [Item("ZhuEncoding", "Represents a Zhu encoding of VRP solutions. It is implemented as described in Zhu, K.Q. (2000). A New Genetic Algorithm For VRPTW. Proceedings of the International Conference on Artificial Intelligence.")]
+  [StorableClass]
+  public class ZhuEncoding : General.PermutationEncoding {
+    #region IVRPEncoding Members
+    public override int GetTourIndex(Tour tour) {
+      return 0;
+    }
+
+    public override List<Tour> GetTours() {
+      List<Tour> result = new List<Tour>();
+
+      Tour newTour = new Tour();
+
+      for (int i = 0; i < this.Length; i++) {
+        int city = this[i] + 1;
+        newTour.Stops.Add(city);
+        if (!ProblemInstance.TourFeasible(newTour, this)) {
+          newTour.Stops.Remove(city);
+          if (newTour.Stops.Count > 0)
+            result.Add(newTour);
+
+          newTour = new Tour();
+          newTour.Stops.Add(city);
+        }
+      }
+
+      if (newTour.Stops.Count > 0)
+        result.Add(newTour);
+
+      //if there are too many vehicles - repair
+      while (result.Count > ProblemInstance.Vehicles.Value) {
+        Tour tour = result[result.Count - 1];
+
+        //find predecessor / successor in permutation
+        int predecessorIndex = Array.IndexOf(this.array, tour.Stops[0] - 1) - 1;
+        if (predecessorIndex >= 0) {
+          int predecessor = this[predecessorIndex] + 1;
+
+          foreach (Tour t in result) {
+            int insertPosition = t.Stops.IndexOf(predecessor) + 1;
+            if (insertPosition != -1) {
+              t.Stops.InsertRange(insertPosition, tour.Stops);
+              break;
+            }
+          }
+        } else {
+          int successorIndex = Array.IndexOf(this.array,
+            tour.Stops[tour.Stops.Count - 1] - 1) + 1;
+          int successor = this[successorIndex] + 1;
+
+          foreach (Tour t in result) {
+            int insertPosition = t.Stops.IndexOf(successor);
+            if (insertPosition != -1) {
+              t.Stops.InsertRange(insertPosition, tour.Stops);
+              break;
+            }
+          }
+        }
+
+        result.Remove(tour);
+      }
+
+      return result;
+    }
+    #endregion
+
+    public ZhuEncoding(Permutation permutation, IVRPProblemInstance problemInstance)
+      : base(permutation, problemInstance) {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ZhuEncoding(this, cloner);
+    }
+
+    protected ZhuEncoding(ZhuEncoding original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    [StorableConstructor]
+    protected ZhuEncoding(bool serializing)
+      : base(serializing) {
+    }
+
+    public static ZhuEncoding ConvertFrom(IVRPEncoding encoding, IVRPProblemInstance problemInstance) {
+      List<Tour> tours = encoding.GetTours();
+      List<int> route = new List<int>();
+
+      foreach (Tour tour in tours) {
+        foreach (int city in tour.Stops)
+          route.Add(city - 1);
+      }
+
+      return new ZhuEncoding(
+        new Permutation(PermutationTypes.RelativeUndirected, route.ToArray()), problemInstance);
+    }
+
+    public static ZhuEncoding ConvertFrom(List<int> routeParam, IVRPProblemInstance problemInstance) {
+      List<int> route = new List<int>(routeParam);
+
+      while (route.Remove(0)) { //remove all delimiters (0)
+      }
+
+      for (int i = 0; i < route.Count; i++)
+        route[i]--;
+
+      return new ZhuEncoding(
+        new Permutation(PermutationTypes.RelativeUndirected, route.ToArray()), problemInstance);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/HeuristicLab.Problems.VehicleRouting-3.4.csproj
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/HeuristicLab.Problems.VehicleRouting-3.4.csproj	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/HeuristicLab.Problems.VehicleRouting-3.4.csproj	(revision 14416)
@@ -0,0 +1,504 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{B94FFB82-43D4-40AB-9980-B03470ADF221}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.Problems.VehicleRouting</RootNamespace>
+    <AssemblyName>HeuristicLab.Problems.VehicleRouting-3.4</AssemblyName>
+    <SignAssembly>true</SignAssembly>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <OldToolsVersion>3.5</OldToolsVersion>
+    <UpgradeBackupLocation>
+    </UpgradeBackupLocation>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\..\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>
+    </DocumentationFile>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>..\..\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>
+    </DocumentationFile>
+    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+    <OutputPath>..\..\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <DocumentationFile>
+    </DocumentationFile>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+    <OutputPath>..\..\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <DocumentationFile>bin\x64\Release\HeuristicLab.Routing.TSP-3.3.XML</DocumentationFile>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Analyzer\BestAverageWorstTours\BestAverageWorstVRPToursAnalyzer.cs" />
+    <Compile Include="Analyzer\BestAverageWorstTours\BestAverageWorstVRPToursCalculator.cs" />
+    <Compile Include="Analyzer\BestAverageWorstTours\BestVRPToursMemorizer.cs" />
+    <Compile Include="Analyzer\BestAverageWorstTours\Capacitated\BestAverageWorstCapacitatedVRPToursAnalyzer.cs" />
+    <Compile Include="Analyzer\BestAverageWorstTours\Capacitated\BestAverageWorstCapacitatedVRPToursCalculator.cs" />
+    <Compile Include="Analyzer\BestAverageWorstTours\Capacitated\BestCapacitatedVRPToursMemorizer.cs" />
+    <Compile Include="Analyzer\BestAverageWorstTours\PickupAndDelivery\BestAverageWorstPickupAndDeliveryVRPToursAnalyzer.cs" />
+    <Compile Include="Analyzer\BestAverageWorstTours\PickupAndDelivery\BestAverageWorstPickupAndDeliveryVRPToursCalculator.cs" />
+    <Compile Include="Analyzer\BestAverageWorstTours\PickupAndDelivery\BestPickupAndDeliveryVRPToursMemorizer.cs" />
+    <Compile Include="Analyzer\BestAverageWorstTours\TimeWindowed\BestAverageWorstTimeWindowedVRPToursAnalyzer.cs" />
+    <Compile Include="Analyzer\BestAverageWorstTours\TimeWindowed\BestAverageWorstTimeWindowedVRPToursCalculator.cs" />
+    <Compile Include="Analyzer\BestAverageWorstTours\TimeWindowed\BestTimeWindowedVRPToursMemorizer.cs" />
+    <Compile Include="Analyzer\BestSolution\BestVRPSolutionAnalyzer.cs" />
+    <Compile Include="Analyzer\BestSolution\Capacitated\BestCapacitatedVRPSolutionAnalyzer.cs" />
+    <Compile Include="Analyzer\BestSolution\PickupAndDelivery\BestPickupAndDeliveryVRPSolutionAnalyzer.cs" />
+    <Compile Include="Analyzer\BestSolution\TimeWindowed\BestTimeWindowedVRPSolutionAnalyzer.cs" />
+    <Compile Include="Analyzer\ConstraintRelaxation\Capacitated\CapacityRelaxationVRPAnalyzer.cs" />
+    <Compile Include="Analyzer\ConstraintRelaxation\PickupAndDelivery\PickupViolationsRelaxationVRPAnalyzer.cs" />
+    <Compile Include="Analyzer\ConstraintRelaxation\TimeWindowed\TimeWindowRelaxationVRPAnalyzer.cs" />
+    <Compile Include="Analyzer\VRPSolution.cs" />
+    <Compile Include="Encodings\Potvin\Moves\TwoOptStar\IPotvinTwoOptStarMoveOperator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\TwoOptStar\PotvinTwoOptStarExhaustiveMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\TwoOptStar\PotvinTwoOptStarMove.cs" />
+    <Compile Include="Encodings\Potvin\Moves\TwoOptStar\PotvinTwoOptStarMoveAttribute.cs" />
+    <Compile Include="Encodings\Potvin\Moves\TwoOptStar\PotvinTwoOptStarMoveEvaluator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\TwoOptStar\PotvinTwoOptStarMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\TwoOptStar\PotvinTwoOptStarMoveMaker.cs" />
+    <Compile Include="Encodings\Potvin\Moves\TwoOptStar\PotvinTwoOptStarMoveTabuCriterion.cs" />
+    <Compile Include="Encodings\Potvin\Moves\TwoOptStar\PotvinTwoOptStarMoveTabuMaker.cs" />
+    <Compile Include="Encodings\Potvin\Moves\TwoOptStar\PotvinTwoOptStarMultiMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\TwoOptStar\PotvinTwoOptStarSingleMoveGenerator.cs" />
+    <Compile Include="Improver\VRPImprovementOperator.cs" />
+    <Compile Include="Improver\VRPIntraRouteImprovementOperator.cs" />
+    <Compile Include="Interfaces\IVRPLocalSearchManipulator.cs" />
+    <Compile Include="Interpreters\MDCVRPInterpreter.cs" />
+    <Compile Include="Interpreters\VRPInterpreter.cs" />
+    <Compile Include="Interpreters\MDCVRPTWInterpreter.cs" />
+    <Compile Include="Interpreters\PDPTWInterpreter.cs" />
+    <Compile Include="Interpreters\CVRPTWInterpreter.cs" />
+    <Compile Include="Interpreters\CVRPInterpreter.cs" />
+    <Compile Include="Interpreters\IVRPDataInterpreter.cs" />
+    <Compile Include="PathRelinkers\VRPPathRelinker.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Encodings\Alba\AlbaEncoding.cs" />
+    <Compile Include="Encodings\Alba\Creators\RandomCreator.cs" />
+    <Compile Include="Encodings\Alba\Creators\AlbaCreator.cs" />
+    <Compile Include="Encodings\Alba\IAlbaOperator.cs" />
+    <Compile Include="Encodings\Alba\Crossovers\AlbaCrossover.cs" />
+    <Compile Include="Encodings\Alba\Crossovers\AlbaPermutationCrossover.cs" />
+    <Compile Include="Encodings\Alba\LocalImprovement\AlbaLambdaInterchangeLocalImprovementOperator.cs" />
+    <Compile Include="Encodings\Alba\Manipulators\AlbaCustomerInsertionManipulator.cs" />
+    <Compile Include="Encodings\Alba\Manipulators\AlbaCustomerInversionManipulator.cs" />
+    <Compile Include="Encodings\Alba\Manipulators\AlbaCustomerSwapManipulator.cs" />
+    <Compile Include="Encodings\Alba\Manipulators\AlbaIntraRouteInversionManipulator.cs" />
+    <Compile Include="Encodings\Alba\Manipulators\AlbaLambdaInterchangeManipulator.cs" />
+    <Compile Include="Encodings\Alba\Manipulators\AlbaManipulator.cs" />
+    <Compile Include="Encodings\Alba\Manipulators\AlbaPermutationManipulator.cs" />
+    <Compile Include="Encodings\Alba\Moves\AlbaMoveEvaluator.cs" />
+    <Compile Include="Encodings\Alba\Moves\AlbaMoveMaker.cs" />
+    <Compile Include="Encodings\Alba\Moves\AlbaMoveGenerator.cs" />
+    <Compile Include="Encodings\Alba\Moves\IntraRouteInversion\AlbaExhaustiveIntraRouteInversionMoveGenerator.cs" />
+    <Compile Include="Encodings\Alba\Moves\IntraRouteInversion\AlbaIntraRouteInversionEvaluator.cs" />
+    <Compile Include="Encodings\Alba\Moves\IntraRouteInversion\AlbaIntraRouteInversionMove.cs" />
+    <Compile Include="Encodings\Alba\Moves\IntraRouteInversion\AlbaIntraRouteInversionMoveGenerator.cs" />
+    <Compile Include="Encodings\Alba\Moves\IntraRouteInversion\AlbaIntraRouteInversionMoveMaker.cs" />
+    <Compile Include="Encodings\Alba\Moves\IntraRouteInversion\AlbaStochasticIntraRouteInversionMutliMoveGenerator.cs" />
+    <Compile Include="Encodings\Alba\Moves\IntraRouteInversion\AlbaStochasticIntraRouteInversionSingleMoveGenerator.cs" />
+    <Compile Include="Encodings\Alba\Moves\IntraRouteInversion\IAlbaIntraRouteInversionMoveOperator.cs" />
+    <Compile Include="Encodings\Alba\Moves\LambdaInterchange\AlbaExhaustiveLambdaInterchangeMoveGenerator.cs" />
+    <Compile Include="Encodings\Alba\Moves\LambdaInterchange\AlbaLambdaInterchangeMove.cs" />
+    <Compile Include="Encodings\Alba\Moves\LambdaInterchange\AlbaLambdaInterchangeMoveEvaluator.cs" />
+    <Compile Include="Encodings\Alba\Moves\LambdaInterchange\AlbaLambdaInterchangeMoveGenerator.cs" />
+    <Compile Include="Encodings\Alba\Moves\LambdaInterchange\AlbaLambdaInterchangeMoveMaker.cs" />
+    <Compile Include="Encodings\Alba\Moves\LambdaInterchange\AlbaStochasticLambdaInterchangeMutliMoveGenerator.cs" />
+    <Compile Include="Encodings\Alba\Moves\LambdaInterchange\AlbaStochasticLambdaInterchangeSingleMoveGenerator.cs" />
+    <Compile Include="Encodings\Alba\Moves\LambdaInterchange\IAlbaLambdaInterchangeMoveOperator.cs" />
+    <Compile Include="Encodings\Alba\Moves\ThreeOpt\AlbaTranslocationMove.cs" />
+    <Compile Include="Encodings\Alba\Moves\ThreeOpt\AlbaTranslocationMoveEvaluator.cs" />
+    <Compile Include="Encodings\Alba\Moves\ThreeOpt\AlbaTranslocationMoveGenerator.cs" />
+    <Compile Include="Encodings\Alba\Moves\ThreeOpt\AlbaTranslocationMoveHardTabuCriterion.cs" />
+    <Compile Include="Encodings\Alba\Moves\ThreeOpt\AlbaTranslocationMoveMaker.cs" />
+    <Compile Include="Encodings\Alba\Moves\ThreeOpt\AlbaTranslocationMoveSoftTabuCriterion.cs" />
+    <Compile Include="Encodings\Alba\Moves\ThreeOpt\AlbaTranslocationMoveTabuMaker.cs" />
+    <Compile Include="Encodings\Alba\Moves\ThreeOpt\AlbaStochasticTranslocationSingleMoveGenerator.cs" />
+    <Compile Include="Encodings\Alba\Moves\ThreeOpt\IAlbaTranslocationMoveOperator.cs" />
+    <Compile Include="Encodings\Potvin\Creators\IterativeInsertionCreator.cs" />
+    <Compile Include="Encodings\Potvin\Creators\PushForwardInsertionCreator.cs" />
+    <Compile Include="Encodings\General\Creators\MultiVRPSolutionCreator.cs" />
+    <Compile Include="Encodings\General\Creators\VRPCreator.cs" />
+    <Compile Include="Encodings\General\Crossovers\BiasedMultiVRPSolutionCrossover.cs" />
+    <Compile Include="Encodings\General\Crossovers\MultiVRPSolutionCrossover.cs" />
+    <Compile Include="Encodings\General\Crossovers\RandomParentCloneCrossover.cs" />
+    <Compile Include="Encodings\General\Crossovers\VRPCrossover.cs" />
+    <Compile Include="Encodings\General\Manipulators\BiasedMultiVRPSolutionManipulator.cs" />
+    <Compile Include="Encodings\General\Manipulators\MultiVRPSolutionManipulator.cs" />
+    <Compile Include="Encodings\General\Manipulators\VRPManipulator.cs" />
+    <Compile Include="Encodings\General\Moves\Interfaces\IMultiVRPMoveGenerator.cs" />
+    <Compile Include="Encodings\General\Moves\Interfaces\IMultiVRPMoveOperator.cs" />
+    <Compile Include="Encodings\General\Moves\Interfaces\IVRPMove.cs" />
+    <Compile Include="Encodings\General\Moves\MultiVRPMoveOperator\MultiVRPMoveTabuMaker.cs" />
+    <Compile Include="Encodings\General\Moves\MultiVRPMoveOperator\MultiVRPMoveTabuChecker.cs" />
+    <Compile Include="Encodings\General\Moves\MultiVRPMoveOperator\MultiVRPMoveEvaluator.cs" />
+    <Compile Include="Encodings\General\Moves\MultiVRPMoveOperator\MultiVRPMoveGenerator.cs" />
+    <Compile Include="Encodings\General\Moves\MultiVRPMoveOperator\MultiVRPMoveMaker.cs" />
+    <Compile Include="Encodings\General\Moves\VRPMoveGenerator.cs" />
+    <Compile Include="Encodings\General\Moves\VRPMoveOperator.cs" />
+    <Compile Include="Encodings\General\Moves\VRPMoveMaker.cs" />
+    <Compile Include="Encodings\General\Moves\VRPMoveEvaluator.cs" />
+    <Compile Include="Encodings\General\PermutationEncoding.cs" />
+    <Compile Include="Encodings\General\ShakingOperators\VehicleRoutingShakingOperator.cs" />
+    <Compile Include="Encodings\General\TourEncoding.cs" />
+    <Compile Include="Encodings\GVR\Crossovers\GVRCrossover.cs" />
+    <Compile Include="Encodings\GVR\GVREncoding.cs" />
+    <Compile Include="Encodings\GVR\IGVROperator.cs" />
+    <Compile Include="Encodings\GVR\Manipulators\GVRDisplacementManipulator.cs" />
+    <Compile Include="Encodings\GVR\Manipulators\GVRInsertionManipulator.cs" />
+    <Compile Include="Encodings\GVR\Manipulators\GVRInversionManipulator.cs" />
+    <Compile Include="Encodings\GVR\Manipulators\GVRManipulator.cs" />
+    <Compile Include="Encodings\GVR\Manipulators\GVRSwapManipulator.cs" />
+    <Compile Include="Encodings\Potvin\Creators\PotvinCreator.cs" />
+    <Compile Include="Encodings\Potvin\Crossovers\PotvinCrossover.cs" />
+    <Compile Include="Encodings\Potvin\Crossovers\PotvinInsertionBasedCrossover.cs" />
+    <Compile Include="Encodings\Potvin\Crossovers\PotvinRouteBasedCrossover.cs" />
+    <Compile Include="Encodings\Potvin\Crossovers\PotvinSequenceBasedCrossover.cs" />
+    <Compile Include="Encodings\Potvin\IPotvinOperator.cs" />
+    <Compile Include="Encodings\Potvin\Manipulators\PotvinPairwiseTwoLevelExchangeManipulator.cs" />
+    <Compile Include="Encodings\Potvin\Manipulators\PotvinPairwiseOneLevelExchangeManipulator.cs" />
+    <Compile Include="Encodings\Potvin\Manipulators\PotvinVehicleAssignmentManipulator.cs" />
+    <Compile Include="Encodings\Potvin\Manipulators\PotvinLocalSearchManipulator.cs" />
+    <Compile Include="Encodings\Potvin\Manipulators\PotvinManipulator.cs" />
+    <Compile Include="Encodings\Potvin\Manipulators\PotvinOneLevelExchangeManipulator.cs" />
+    <Compile Include="Encodings\Potvin\Manipulators\PotvinTwoLevelExchangeManipulator.cs" />
+    <Compile Include="Encodings\General\Moves\VRPMoveAttribute.cs" />
+    <Compile Include="Encodings\Potvin\Moves\CustomerRelocation\PotvinCustomerRelocationMoveTabuMaker.cs" />
+    <Compile Include="Encodings\Potvin\Moves\CustomerRelocation\PotvinCustomerRelocationSingleMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\CustomerRelocation\PotvinCustomerRelocationMultiMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\CustomerRelocation\PotvinCustomerRelocationExhaustiveMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\CustomerRelocation\PotvinCustomerRelocationMoveEvaluator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\CustomerRelocation\PotvinCustomerRelocationMoveMaker.cs" />
+    <Compile Include="Encodings\Potvin\Moves\CustomerRelocation\IPotvinCustomerRelocationMoveOperator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\CustomerRelocation\PotvinCustomerRelocationMoveAttribute.cs" />
+    <Compile Include="Encodings\Potvin\Moves\CustomerRelocation\PotvinCustomerRelocationMoveTabuCriterion.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PotvinPDRelocateMoveAttribute.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDExchange\IPotvinPDExchangeMoveOperator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDExchange\PotvinPDExchangeExhaustiveMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDExchange\PotvinPDExchangeMove.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDExchange\PotvinPDExchangeMoveEvaluator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDExchange\PotvinPDExchangeMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDExchange\PotvinPDExchangeMoveMaker.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDExchange\PotvinPDExchangeMoveTabuCriterion.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDExchange\PotvinPDExchangeMoveTabuMaker.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDExchange\PotvinPDExchangeMultiMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDExchange\PotvinPDExchangeSingleMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDRearrange\IPotvinPDRearrangeMoveOperator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDRearrange\PotvinPDRearrangeExhaustiveMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDRearrange\PotvinPDRearrangeMove.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDRearrange\PotvinPDRearrangeMoveEvaluator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDRearrange\PotvinPDRearrangeMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDRearrange\PotvinPDRearrangeMoveMaker.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDRearrange\PotvinPDRearrangeMoveTabuCriterion.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDRearrange\PotvinPDRearrangeMoveTabuMaker.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDRearrange\PotvinPDRearrangeMultiMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDRearrange\PotvinPDRearrangeSingleMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDShift\IPotvinPDShiftMoveOperator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDShift\PotvinPDShiftMoveTabuCriterion.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDShift\PotvinPDShiftMoveTabuMaker.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDShift\PotvinPDShiftMultiMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDShift\PotvinPDShiftSingleMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDShift\PotvinPDShiftExhaustiveMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDShift\PotvinPDShiftMoveMaker.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDShift\PotvinPDShiftMoveEvaluator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDShift\PotvinPDShiftMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PickupDelivery\PDShift\PotvinPDShiftMove.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PotvinMoveEvaluator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PotvinMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\PotvinMoveMaker.cs" />
+    <Compile Include="Encodings\Potvin\Moves\CustomerRelocation\PotvinCustomerRelocationMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\CustomerRelocation\PotvinCustomerRelocationMove.cs" />
+    <Compile Include="Encodings\Potvin\Moves\VehicleAssignment\IPotvinVehicleAssignmentMoveOperator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\VehicleAssignment\PotvinVehicleAssignmentMoveTabuCriterion.cs" />
+    <Compile Include="Encodings\Potvin\Moves\VehicleAssignment\PotvinVehicleAssignmentMoveTabuMaker.cs" />
+    <Compile Include="Encodings\Potvin\Moves\VehicleAssignment\PotvinVehicleAssignmentExhaustiveMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\VehicleAssignment\PotvinVehicleAssignmentMove.cs" />
+    <Compile Include="Encodings\Potvin\Moves\VehicleAssignment\PotvinVehicleAssignmentMoveAttribute.cs" />
+    <Compile Include="Encodings\Potvin\Moves\VehicleAssignment\PotvinVehicleAssignmentMoveEvaluator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\VehicleAssignment\PotvinVehicleAssignmentMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\VehicleAssignment\PotvinVehicleAssignmentMoveMaker.cs" />
+    <Compile Include="Encodings\Potvin\Moves\VehicleAssignment\PotvinVehicleAssignmentMultiMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\Moves\VehicleAssignment\PotvinVehicleAssignmentSingleMoveGenerator.cs" />
+    <Compile Include="Encodings\Potvin\PotvinEncoding.cs" />
+    <Compile Include="Encodings\Prins\Crossovers\PrinsCrossover.cs" />
+    <Compile Include="Encodings\Prins\Crossovers\PrinsPermutationCrossover.cs" />
+    <Compile Include="Encodings\Prins\IPrinsOperator.cs" />
+    <Compile Include="Encodings\Prins\Manipulators\PrinsExhaustiveLSManipulator.cs" />
+    <Compile Include="Encodings\Prins\Manipulators\PrinsLSManipulator.cs" />
+    <Compile Include="Encodings\Prins\Manipulators\PrinsManipulator.cs" />
+    <Compile Include="Encodings\Prins\Manipulators\PrinsPermutationManipulator.cs" />
+    <Compile Include="Encodings\Prins\Manipulators\PrinsStochasticLSManipulator.cs" />
+    <Compile Include="Encodings\Prins\PrinsEncoding.cs" />
+    <Compile Include="Encodings\VRPOperator.cs" />
+    <Compile Include="Encodings\Zhu\Crossovers\ZhuCrossover.cs" />
+    <Compile Include="Encodings\Zhu\Crossovers\ZhuHeuristicCrossover1.cs" />
+    <Compile Include="Encodings\Zhu\Crossovers\ZhuHeuristicCrossover2.cs" />
+    <Compile Include="Encodings\Zhu\Crossovers\ZhuMergeCrossover1.cs" />
+    <Compile Include="Encodings\Zhu\Crossovers\ZhuMergeCrossover2.cs" />
+    <Compile Include="Encodings\Zhu\Crossovers\ZhuPermutationCrossover.cs" />
+    <Compile Include="Encodings\Zhu\IZhuOperator.cs" />
+    <Compile Include="Encodings\Zhu\Manipulators\ZhuManipulator.cs" />
+    <Compile Include="Encodings\Zhu\Manipulators\ZhuPermutationManipulator.cs" />
+    <Compile Include="Encodings\Zhu\ZhuEncoding.cs" />
+    <Compile Include="Interfaces\IMultiVRPOperator.cs" />
+    <Compile Include="Interfaces\IVRPManipulator.cs" />
+    <Compile Include="Interfaces\IVRPCrossover.cs" />
+    <Compile Include="Interfaces\IVRPEvaluator.cs" />
+    <Compile Include="Interfaces\IVRPCreator.cs" />
+    <Compile Include="Interfaces\IVRPMoveOperator.cs" />
+    <Compile Include="Interfaces\IVRPMultiNeighborhoodShakingOperator.cs" />
+    <Compile Include="Interfaces\IVRPOperator.cs" />
+    <Compile Include="Interfaces\IVRPEncoding.cs" />
+    <Compile Include="Interfaces\IVRPProblemInstance.cs" />
+    <Compile Include="Plugin.cs" />
+    <Compile Include="ProblemInstances\MultiDepotVRP\MDCVRP\MDCVRPEvaluator.cs" />
+    <Compile Include="ProblemInstances\MultiDepotVRP\MDCVRP\MDCVRPProblemInstance.cs" />
+    <Compile Include="ProblemInstances\MultiDepotVRP\MDCVRP\MDCVRPTW\MDCVRPPDTW\MDCVRPPDTWEvaluator.cs" />
+    <Compile Include="ProblemInstances\MultiDepotVRP\MDCVRP\MDCVRPTW\MDCVRPPDTW\MDCVRPPDTWProblemInstance.cs" />
+    <Compile Include="ProblemInstances\MultiDepotVRP\MDCVRP\MDCVRPTW\MDCVRPTWEvaluator.cs" />
+    <Compile Include="ProblemInstances\MultiDepotVRP\MDCVRP\MDCVRPTW\MDCVRPTWProblemInstance.cs" />
+    <Compile Include="ProblemInstances\MultiDepotVRP\MultiDepotVRPProblemInstance.cs" />
+    <Compile Include="ProblemInstances\MultiDepotVRP\MultiDepotVRPEvaluator.cs" />
+    <Compile Include="ProblemInstances\SingleDepotVRP\CVRP\CVRPTW\CVRPPDTW\CVRPPDTWProblemInstance.cs" />
+    <Compile Include="ProblemInstances\SingleDepotVRP\CVRP\CVRPTW\CVRPPDTW\CVRPPDTWEvaluation.cs" />
+    <Compile Include="ProblemInstances\SingleDepotVRP\CVRP\CVRPTW\CVRPPDTW\CVRPPDTWEvaluator.cs" />
+    <Compile Include="ProblemInstances\SingleDepotVRP\SingleDepotVRPEvaluator.cs" />
+    <Compile Include="SimilarityCalculators\VRPSimilarityCalculator.cs" />
+    <Compile Include="SolutionParser.cs" />
+    <Compile Include="Variants\Capacitated\Heterogenous\IHeterogenousCapacitatedProblemInstance.cs" />
+    <Compile Include="Variants\Capacitated\Heterogenous\IHeterogenousCapacitatedOperator.cs" />
+    <Compile Include="Variants\Capacitated\Homogenous\IHomogenousCapacitatedOperator.cs" />
+    <Compile Include="Variants\Capacitated\Homogenous\IHomogenousCapacitatedProblemInstance.cs" />
+    <Compile Include="Variants\Capacitated\ICapacitatedProblemInstance.cs" />
+    <Compile Include="Variants\Capacitated\ICapacitatedOperator.cs" />
+    <Compile Include="Variants\General\IGeneralVRPOperator.cs" />
+    <Compile Include="Variants\MultiDepot\IMultiDepotOperator.cs" />
+    <Compile Include="Variants\MultiDepot\IMultiDepotProblemInstance.cs" />
+    <Compile Include="Variants\PickupAndDelivery\IPickupAndDeliveryOperator.cs" />
+    <Compile Include="Variants\PickupAndDelivery\IPickupAndDeliveryProblemInstance.cs" />
+    <Compile Include="Variants\SingleDepot\ISingleDepotOperator.cs" />
+    <Compile Include="Variants\SingleDepot\ISingleDepotProblemInstance.cs" />
+    <Compile Include="Variants\TimeWindowed\ITimeWindowedProblemInstance.cs" />
+    <Compile Include="Variants\TimeWindowed\ITimeWindowedOperator.cs" />
+    <Compile Include="ProblemInstances\SingleDepotVRP\CVRP\CVRPTW\CVRPTWProblemInstance.cs" />
+    <Compile Include="ProblemInstances\SingleDepotVRP\CVRP\CVRPProblemInstance.cs" />
+    <Compile Include="ProblemInstances\SingleDepotVRP\CVRP\CVRPTW\CVRPTWEvaluation.cs" />
+    <Compile Include="ProblemInstances\SingleDepotVRP\CVRP\CVRPEvaluation.cs" />
+    <Compile Include="ProblemInstances\SingleDepotVRP\CVRP\CVRPTW\CVRPTWEvaluator.cs" />
+    <Compile Include="ProblemInstances\SingleDepotVRP\CVRP\CVRPEvaluator.cs" />
+    <Compile Include="ProblemInstances\VRPEvaluator.cs" />
+    <Compile Include="ProblemInstances\VRPEvaluation.cs" />
+    <Compile Include="ProblemInstances\SingleDepotVRP\SingleDepotVRPProblemInstance.cs" />
+    <Compile Include="ProblemInstances\VRPProblemInstance.cs" />
+    <Compile Include="Encodings\Tour.cs" />
+    <Compile Include="VehicleRoutingProblem.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Properties\AssemblyInfo.cs.frame" />
+    <None Include="HeuristicLab.snk" />
+    <None Include="Plugin.cs.frame" />
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+      <Visible>False</Visible>
+      <ProductName>Windows Installer 3.1</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Analysis\3.3\HeuristicLab.Analysis-3.3.csproj">
+      <Project>{887425B4-4348-49ED-A457-B7D2C26DDBF9}</Project>
+      <Name>HeuristicLab.Analysis-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Collections\3.3\HeuristicLab.Collections-3.3.csproj">
+      <Project>{958B43BC-CC5C-4FA2-8628-2B3B01D890B6}</Project>
+      <Name>HeuristicLab.Collections-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Common.Resources\3.3\HeuristicLab.Common.Resources-3.3.csproj">
+      <Project>{0E27A536-1C4A-4624-A65E-DC4F4F23E3E1}</Project>
+      <Name>HeuristicLab.Common.Resources-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Common\3.3\HeuristicLab.Common-3.3.csproj">
+      <Project>{A9AD58B9-3EF9-4CC1-97E5-8D909039FF5C}</Project>
+      <Name>HeuristicLab.Common-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Core\3.3\HeuristicLab.Core-3.3.csproj">
+      <Project>{C36BD924-A541-4A00-AFA8-41701378DDC5}</Project>
+      <Name>HeuristicLab.Core-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Data\3.3\HeuristicLab.Data-3.3.csproj">
+      <Project>{BBAB9DF5-5EF3-4BA8-ADE9-B36E82114937}</Project>
+      <Name>HeuristicLab.Data-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Encodings.PermutationEncoding\3.3\HeuristicLab.Encodings.PermutationEncoding-3.3.csproj">
+      <Project>{DBECB8B0-B166-4133-BAF1-ED67C3FD7FCA}</Project>
+      <Name>HeuristicLab.Encodings.PermutationEncoding-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Operators\3.3\HeuristicLab.Operators-3.3.csproj">
+      <Project>{23DA7FF4-D5B8-41B6-AA96-F0561D24F3EE}</Project>
+      <Name>HeuristicLab.Operators-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Optimization.Operators\3.3\HeuristicLab.Optimization.Operators-3.3.csproj">
+      <Project>{25087811-F74C-4128-BC86-8324271DA13E}</Project>
+      <Name>HeuristicLab.Optimization.Operators-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Optimization\3.3\HeuristicLab.Optimization-3.3.csproj">
+      <Project>{14AB8D24-25BC-400C-A846-4627AA945192}</Project>
+      <Name>HeuristicLab.Optimization-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Parameters\3.3\HeuristicLab.Parameters-3.3.csproj">
+      <Project>{56F9106A-079F-4C61-92F6-86A84C2D84B7}</Project>
+      <Name>HeuristicLab.Parameters-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Persistence\3.3\HeuristicLab.Persistence-3.3.csproj">
+      <Project>{102BC7D3-0EF9-439C-8F6D-96FF0FDB8E1B}</Project>
+      <Name>HeuristicLab.Persistence-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.PluginInfrastructure\3.3\HeuristicLab.PluginInfrastructure-3.3.csproj">
+      <Project>{94186A6A-5176-4402-AE83-886557B53CCA}</Project>
+      <Name>HeuristicLab.PluginInfrastructure-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Problems.Instances\3.3\HeuristicLab.Problems.Instances-3.3.csproj">
+      <Project>{3540E29E-4793-49E7-8EE2-FEA7F61C3994}</Project>
+      <Name>HeuristicLab.Problems.Instances-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Random\3.3\HeuristicLab.Random-3.3.csproj">
+      <Project>{F4539FB6-4708-40C9-BE64-0A1390AEA197}</Project>
+      <Name>HeuristicLab.Random-3.3</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- 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>
+  -->
+  <PropertyGroup>
+    <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+set ProjectDir=$(ProjectDir)
+set SolutionDir=$(SolutionDir)
+set Outdir=$(Outdir)
+
+call PreBuildEvent.cmd</PreBuildEvent>
+    <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
+export ProjectDir=$(ProjectDir)
+export SolutionDir=$(SolutionDir)
+
+$SolutionDir/PreBuildEvent.sh
+</PreBuildEvent>
+  </PropertyGroup>
+  <PropertyGroup>
+    <PostBuildEvent>
+    </PostBuildEvent>
+  </PropertyGroup>
+</Project>
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Improver/VRPImprovementOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Improver/VRPImprovementOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Improver/VRPImprovementOperator.cs	(revision 14416)
@@ -0,0 +1,94 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  /// <summary>
+  /// A base class for operators which improve VRP solutions.
+  /// </summary>
+  [Item("VRPImprovementOperator", "A base class for operators which improve VRP solutions.")]
+  [StorableClass]
+  public abstract class VRPImprovementOperator : VRPOperator, IGeneralVRPOperator, ISingleObjectiveImprovementOperator {
+    #region Parameter properties
+    public ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+    public IValueParameter<IntValue> ImprovementAttemptsParameter {
+      get { return (IValueParameter<IntValue>)Parameters["ImprovementAttempts"]; }
+    }
+    public IValueLookupParameter<IntValue> LocalEvaluatedSolutions {
+      get { return (IValueLookupParameter<IntValue>)Parameters["LocalEvaluatedSolutions"]; }
+    }
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    public IValueParameter<IntValue> SampleSizeParameter {
+      get { return (IValueParameter<IntValue>)Parameters["SampleSize"]; }
+    }
+    public IValueLookupParameter<IItem> SolutionParameter {
+      get { return (IValueLookupParameter<IItem>)Parameters["Solution"]; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected VRPImprovementOperator(bool deserializing) : base(deserializing) { }
+    protected VRPImprovementOperator(VRPImprovementOperator original, Cloner cloner) : base(original, cloner) { }
+    protected VRPImprovementOperator()
+      : base() {
+      #region Create parameters
+      Parameters.Add(new ScopeParameter("CurrentScope", "The current scope that contains the solution to be improved."));
+      Parameters.Add(new ValueParameter<IntValue>("ImprovementAttempts", "The number of improvement attempts the operator should perform.", new IntValue(100)));
+      Parameters.Add(new ValueLookupParameter<IntValue>("LocalEvaluatedSolutions", "The number of evaluated solutions."));
+      Parameters.Add(new LookupParameter<IRandom>("Random", "A pseudo random number generator."));
+      Parameters.Add(new ValueParameter<IntValue>("SampleSize", "The number of moves that should be executed.", new IntValue(25)));
+      Parameters.Add(new ValueLookupParameter<IItem>("Solution", "The solution to be improved. This parameter is used for name translation only."));
+      #endregion
+    }
+
+    public override IOperation InstrumentedApply() {
+      var solution = SolutionParameter.ActualValue as IVRPEncoding;
+      var potvinSolution = solution is PotvinEncoding ? solution as PotvinEncoding : PotvinEncoding.ConvertFrom(solution, ProblemInstance);
+
+      if (solution == null)
+        throw new ArgumentException("Cannot improve solution because it has the wrong type.");
+
+      int evaluatedSolutions = Improve(potvinSolution);
+
+      SolutionParameter.ActualValue = solution;
+      LocalEvaluatedSolutions.ActualValue = new IntValue(evaluatedSolutions);
+
+      return base.InstrumentedApply();
+    }
+
+    protected abstract int Improve(PotvinEncoding solution);
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Improver/VRPIntraRouteImprovementOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Improver/VRPIntraRouteImprovementOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Improver/VRPIntraRouteImprovementOperator.cs	(revision 14416)
@@ -0,0 +1,98 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  /// <summary>
+  /// An operator which improves VRP solutions.
+  /// </summary>
+  [Item("VRPIntraRouteImprovementOperator", "An operator which improves VRP solutions.")]
+  [StorableClass]
+  public sealed class VRPIntraRouteImprovementOperator : VRPImprovementOperator {
+    [StorableConstructor]
+    private VRPIntraRouteImprovementOperator(bool deserializing) : base(deserializing) { }
+    private VRPIntraRouteImprovementOperator(VRPIntraRouteImprovementOperator original, Cloner cloner) : base(original, cloner) { }
+    public VRPIntraRouteImprovementOperator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new VRPIntraRouteImprovementOperator(this, cloner);
+    }
+
+    protected override int Improve(PotvinEncoding solution) {
+      int evaluatedSolutions = 0;
+
+      var rand = RandomParameter.ActualValue;
+      var instance = ProblemInstance;
+      int sampleSize = SampleSizeParameter.Value.Value;
+      int attempts = ImprovementAttemptsParameter.Value.Value;
+      int customers = instance.Cities.Value;
+
+      // store city-to-tour assignment and position of the city within the tour
+      var tours = new Dictionary<int, Tour>();
+      var position = new Dictionary<int, int>();
+      foreach (Tour tour in solution.Tours) {
+        for (int stop = 0; stop < tour.Stops.Count; stop++) {
+          int city = tour.Stops[stop];
+          tours[city] = tour;
+          position[city] = stop;
+        }
+      }
+
+      for (int attempt = 0; attempt < attempts; attempt++) {
+        for (int sample = 0; sample < sampleSize; sample++) {
+          int chosenCust = 1 + rand.Next(customers);
+          var custTour = tours[chosenCust];
+
+          double beforeQuality = instance.EvaluateTour(custTour, solution).Quality;
+          evaluatedSolutions++;
+
+          custTour.Stops.RemoveAt(position[chosenCust]);
+          int place = solution.FindBestInsertionPlace(custTour, chosenCust);
+          evaluatedSolutions += custTour.Stops.Count;
+          custTour.Stops.Insert(place, chosenCust);
+
+          if (place != position[chosenCust]) {
+            double afterQuality = instance.EvaluateTour(custTour, solution).Quality;
+            if (afterQuality > beforeQuality) {
+              // revert move
+              custTour.Stops.RemoveAt(place);
+              custTour.Stops.Insert(position[chosenCust], chosenCust);
+            } else {
+              // accept move and update positions of the cities within the tour
+              for (int stop = 0; stop < custTour.Stops.Count; stop++) {
+                int city = custTour.Stops[stop];
+                position[city] = stop;
+              }
+              break;
+            }
+          }
+        }
+      }
+
+      return evaluatedSolutions;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IMultiVRPOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IMultiVRPOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IMultiVRPOperator.cs	(revision 14416)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Problems.VehicleRouting.Interfaces {
+  interface IMultiVRPOperator : IVRPOperator {
+    void SetOperators(IEnumerable<IOperator> operators);
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPCreator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPCreator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPCreator.cs	(revision 14416)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Optimization;
+
+namespace HeuristicLab.Problems.VehicleRouting.Interfaces {
+  public interface IVRPCreator : IVRPOperator, ISolutionCreator {
+    ILookupParameter<IVRPEncoding> VRPToursParameter { get; }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPCrossover.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPCrossover.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPCrossover.cs	(revision 14416)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Optimization;
+
+namespace HeuristicLab.Problems.VehicleRouting.Interfaces {
+  public interface IVRPCrossover : IVRPOperator, ICrossover {
+    ILookupParameter<ItemArray<IVRPEncoding>> ParentsParameter { get; }
+    ILookupParameter<IVRPEncoding> ChildParameter { get; }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPEncoding.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPEncoding.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPEncoding.cs	(revision 14416)
@@ -0,0 +1,31 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Problems.VehicleRouting.Interfaces {
+  public interface IVRPEncoding : IItem {
+    List<Tour> GetTours();
+    int GetTourIndex(Tour tour);
+    int GetVehicleAssignment(int tour);
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPEvaluator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPEvaluator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPEvaluator.cs	(revision 14416)
@@ -0,0 +1,35 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Optimization;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+
+namespace HeuristicLab.Problems.VehicleRouting.Interfaces {
+  public interface IVRPEvaluator : IVRPOperator, ISingleObjectiveEvaluator {
+    ILookupParameter<IVRPEncoding> VRPToursParameter { get; }
+
+    VRPEvaluation Evaluate(IVRPProblemInstance instance, IVRPEncoding solution);
+    VRPEvaluation EvaluateTour(IVRPProblemInstance instance, Tour tour, IVRPEncoding solution);
+    bool Feasible(VRPEvaluation evaluation);
+    double GetInsertionCosts(IVRPProblemInstance instance, IVRPEncoding solution, VRPEvaluation eval, int customer, int tour, int index, out bool feasible);
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPLocalSearchManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPLocalSearchManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPLocalSearchManipulator.cs	(revision 14416)
@@ -0,0 +1,26 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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
+
+
+namespace HeuristicLab.Problems.VehicleRouting.Interfaces {
+  public interface IVRPLocalSearchManipulator : IVRPManipulator {
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPManipulator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPManipulator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPManipulator.cs	(revision 14416)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Optimization;
+
+namespace HeuristicLab.Problems.VehicleRouting.Interfaces {
+  public interface IVRPManipulator : IVRPOperator, IManipulator {
+    ILookupParameter<IVRPEncoding> VRPToursParameter { get; }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPMoveOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPMoveOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPMoveOperator.cs	(revision 14416)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Optimization;
+
+namespace HeuristicLab.Problems.VehicleRouting.Interfaces {
+  public interface IVRPMoveOperator : IVRPOperator, IMoveOperator {
+    ILookupParameter<IVRPEncoding> VRPToursParameter { get; }
+    ILookupParameter VRPMoveParameter { get; }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPMultiNeighborhoodShakingOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPMultiNeighborhoodShakingOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPMultiNeighborhoodShakingOperator.cs	(revision 14416)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Optimization;
+
+namespace HeuristicLab.Problems.VehicleRouting.Interfaces {
+  public interface IVRPMultiNeighborhoodShakingOperator : IMultiNeighborhoodShakingOperator, IVRPOperator {
+    ILookupParameter<IVRPEncoding> VRPToursParameter { get; }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPOperator.cs	(revision 14416)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Problems.VehicleRouting.Interfaces {
+  public interface IVRPOperator : IItem {
+    ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter { get; }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPProblemInstance.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPProblemInstance.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPProblemInstance.cs	(revision 14416)
@@ -0,0 +1,57 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.ProblemInstances;
+
+namespace HeuristicLab.Problems.VehicleRouting.Interfaces {
+  public interface IVRPProblemInstance : IParameterizedNamedItem {
+    IVRPEvaluator SolutionEvaluator { get; set; }
+    IVRPEvaluator MoveEvaluator { get; }
+    IEnumerable<IOperator> Operators { get; }
+
+    event EventHandler EvaluationChanged;
+
+    DoubleMatrix Coordinates { get; }
+    DoubleMatrix DistanceMatrix { get; }
+    BoolValue UseDistanceMatrix { get; }
+    IntValue Vehicles { get; }
+    DoubleArray Demand { get; }
+    IntValue Cities { get; }
+
+    DoubleValue FleetUsageFactor { get; }
+    DoubleValue DistanceFactor { get; }
+
+    double[] GetCoordinates(int city);
+    double GetDemand(int city);
+    double GetDistance(int start, int end, IVRPEncoding solution);
+    double GetInsertionDistance(int start, int customer, int end, IVRPEncoding solution, out double startDistance, out double endDistance);
+    bool Feasible(IVRPEncoding solution);
+    bool TourFeasible(Tour tour, IVRPEncoding solution);
+    VRPEvaluation Evaluate(IVRPEncoding solution);
+    VRPEvaluation EvaluateTour(Tour tour, IVRPEncoding solution);
+    bool Feasible(VRPEvaluation eval);
+    double GetInsertionCosts(VRPEvaluation eval, IVRPEncoding solution, int customer, int tour, int index, out bool feasible);
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/CVRPInterpreter.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/CVRPInterpreter.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/CVRPInterpreter.cs	(revision 14416)
@@ -0,0 +1,53 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Data;
+using HeuristicLab.Problems.Instances;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using System;
+
+namespace HeuristicLab.Problems.VehicleRouting.Interpreters {
+  public class CVRPInterpreter : VRPInterpreter, IVRPDataInterpreter<CVRPData> {   
+    protected override IVRPProblemInstance CreateProblemInstance() {
+      return new CVRPProblemInstance();
+    }
+
+    protected override void Interpret(IVRPData data, IVRPProblemInstance problemInstance) {
+      CVRPData cvrpData = (CVRPData)data;
+      CVRPProblemInstance problem = (CVRPProblemInstance)problemInstance;
+      
+      if (cvrpData.Coordinates != null)
+        problem.Coordinates = new DoubleMatrix(cvrpData.Coordinates);
+      if (cvrpData.MaximumVehicles != null)
+        problem.Vehicles.Value = (int)cvrpData.MaximumVehicles;
+      else
+        problem.Vehicles.Value = cvrpData.Dimension - 1;
+      problem.Capacity.Value = cvrpData.Capacity;
+      problem.Demand = new DoubleArray(cvrpData.Demands);
+      if (cvrpData.DistanceMeasure != DistanceMeasure.Euclidean) {
+        problem.UseDistanceMatrix.Value = true;
+        problem.DistanceMatrix = new DoubleMatrix(cvrpData.GetDistanceMatrix());
+      }
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/CVRPTWInterpreter.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/CVRPTWInterpreter.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/CVRPTWInterpreter.cs	(revision 14416)
@@ -0,0 +1,46 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Data;
+using HeuristicLab.Problems.Instances;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using System;
+
+namespace HeuristicLab.Problems.VehicleRouting.Interpreters {
+  public class CVRPTWInterpreter: CVRPInterpreter, IVRPDataInterpreter<CVRPTWData> {    
+    protected override IVRPProblemInstance CreateProblemInstance() {
+      return new CVRPTWProblemInstance();
+    }
+
+    protected override void Interpret(IVRPData data, IVRPProblemInstance problemInstance) {
+      base.Interpret(data, problemInstance);
+
+      CVRPTWData cvrptwData = (CVRPTWData)data;
+      CVRPTWProblemInstance problem = (CVRPTWProblemInstance)problemInstance;
+
+      problem.ReadyTime = new DoubleArray(cvrptwData.ReadyTimes);
+      problem.ServiceTime = new DoubleArray(cvrptwData.ServiceTimes);
+      problem.DueTime = new DoubleArray(cvrptwData.DueTimes);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/IVRPDataInterpreter.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/IVRPDataInterpreter.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/IVRPDataInterpreter.cs	(revision 14416)
@@ -0,0 +1,41 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.Instances;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using System;
+
+namespace HeuristicLab.Problems.VehicleRouting.Interpreters {
+  public struct VRPInstanceDescription {
+    public string Name { get; set; }
+    public string Description { get; set; }
+    public IVRPProblemInstance ProblemInstance { get; set; }
+    public double? BestKnownQuality { get; set; }
+    public IVRPEncoding BestKnownSolution { get; set; }
+  }
+
+  public interface IVRPDataInterpreter {
+    VRPInstanceDescription Interpret(IVRPData data);
+  }
+
+  public interface IVRPDataInterpreter<T> : IVRPDataInterpreter where T : IVRPData {
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/MDCVRPInterpreter.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/MDCVRPInterpreter.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/MDCVRPInterpreter.cs	(revision 14416)
@@ -0,0 +1,56 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Data;
+using HeuristicLab.Problems.Instances;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using System;
+
+namespace HeuristicLab.Problems.VehicleRouting.Interpreters {
+  public class MDCVRPInterpreter : VRPInterpreter, IVRPDataInterpreter<MDCVRPData> {   
+    protected override IVRPProblemInstance CreateProblemInstance() {
+      return new MDCVRPProblemInstance();
+    }
+
+    protected override void Interpret(IVRPData data, IVRPProblemInstance problemInstance) {
+      MDCVRPData cvrpData = (MDCVRPData)data;
+      MDCVRPProblemInstance problem = (MDCVRPProblemInstance)problemInstance;
+
+      if (cvrpData.Coordinates != null)
+        problem.Coordinates = new DoubleMatrix(cvrpData.Coordinates);
+      if (cvrpData.MaximumVehicles != null)
+        problem.Vehicles.Value = (int)cvrpData.MaximumVehicles;
+      else
+        problem.Vehicles.Value = cvrpData.Dimension - 1;
+      problem.Capacity = new DoubleArray(cvrpData.Capacity);
+      problem.Demand = new DoubleArray(cvrpData.Demands);
+      if (cvrpData.DistanceMeasure != DistanceMeasure.Euclidean) {
+        problem.UseDistanceMatrix.Value = true;
+        problem.DistanceMatrix = new DoubleMatrix(cvrpData.GetDistanceMatrix());
+      }
+
+      problem.Depots.Value = cvrpData.Depots;
+      problem.VehicleDepotAssignment = new IntArray(cvrpData.VehicleDepotAssignment);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/MDCVRPTWInterpreter.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/MDCVRPTWInterpreter.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/MDCVRPTWInterpreter.cs	(revision 14416)
@@ -0,0 +1,46 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Data;
+using HeuristicLab.Problems.Instances;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using System;
+
+namespace HeuristicLab.Problems.VehicleRouting.Interpreters {
+  public class MDCVRPTWInterpreter : MDCVRPInterpreter, IVRPDataInterpreter<MDCVRPTWData> {    
+    protected override IVRPProblemInstance CreateProblemInstance() {
+      return new MDCVRPTWProblemInstance();
+    }
+
+    protected override void Interpret(IVRPData data, IVRPProblemInstance problemInstance) {
+      base.Interpret(data, problemInstance);
+
+      MDCVRPTWData cvrptwData = (MDCVRPTWData)data;
+      MDCVRPTWProblemInstance problem = (MDCVRPTWProblemInstance)problemInstance;
+
+      problem.ReadyTime = new DoubleArray(cvrptwData.ReadyTimes);
+      problem.ServiceTime = new DoubleArray(cvrptwData.ServiceTimes);
+      problem.DueTime = new DoubleArray(cvrptwData.DueTimes);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/PDPTWInterpreter.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/PDPTWInterpreter.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/PDPTWInterpreter.cs	(revision 14416)
@@ -0,0 +1,44 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Data;
+using HeuristicLab.Problems.Instances;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using System;
+
+namespace HeuristicLab.Problems.VehicleRouting.Interpreters {
+  public class PDPTWInterpreter : CVRPTWInterpreter, IVRPDataInterpreter<PDPTWData> {    
+    protected override IVRPProblemInstance CreateProblemInstance() {
+      return new CVRPPDTWProblemInstance();
+    }
+
+    protected override void Interpret(IVRPData data, IVRPProblemInstance problemInstance) {
+      base.Interpret(data, problemInstance);
+
+      PDPTWData pdpData = (PDPTWData)data;
+      CVRPPDTWProblemInstance problem = (CVRPPDTWProblemInstance)problemInstance;
+
+      problem.PickupDeliveryLocation = new IntArray(pdpData.PickupDeliveryLocations);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/VRPInterpreter.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/VRPInterpreter.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/VRPInterpreter.cs	(revision 14416)
@@ -0,0 +1,77 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.IO;
+using HeuristicLab.Data;
+using HeuristicLab.Problems.Instances;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using System;
+
+namespace HeuristicLab.Problems.VehicleRouting.Interpreters {
+  public abstract class VRPInterpreter : IVRPDataInterpreter<IVRPData> {
+    protected abstract void Interpret(IVRPData data, IVRPProblemInstance problemInstance);
+
+    protected virtual IVRPEncoding GetBestKnowTour(IVRPData data, IVRPProblemInstance problemInstance) {
+      if (data.BestKnownTour != null) {
+        PotvinEncoding solution = new PotvinEncoding(problemInstance);
+
+        for (int i = 0; i < data.BestKnownTour.GetLength(0); i++) {
+          Tour tour = new Tour();
+          solution.Tours.Add(tour);
+
+          foreach (int stop in data.BestKnownTour[i]) {
+            tour.Stops.Add(stop + 1);
+          }
+        }
+
+        if (data.BestKnownTourVehicleAssignment != null) {
+          if (data.BestKnownTourVehicleAssignment.Length != solution.VehicleAssignment.Length)
+            throw new InvalidDataException("Number of vehicles of the best known tour does not match the number vehicles of the instance.");
+          for (int i = 0; i < data.BestKnownTourVehicleAssignment.Length; i++)
+            solution.VehicleAssignment[i] = data.BestKnownTourVehicleAssignment[i];
+        }
+
+        return solution;
+      } else {
+        return null;
+      }
+    }
+
+    protected abstract IVRPProblemInstance CreateProblemInstance();
+
+    public VRPInstanceDescription Interpret(IVRPData data) {
+      VRPInstanceDescription result = new VRPInstanceDescription();
+      result.Name = data.Name;
+      result.Description = data.Description;
+
+      IVRPProblemInstance problem = CreateProblemInstance();
+      Interpret(data, problem);
+      result.ProblemInstance = problem;
+
+      result.BestKnownQuality = data.BestKnownQuality;
+      result.BestKnownSolution = GetBestKnowTour(data, problem);
+
+      return result;
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/PathRelinkers/VRPPathRelinker.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/PathRelinkers/VRPPathRelinker.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/PathRelinkers/VRPPathRelinker.cs	(revision 14416)
@@ -0,0 +1,324 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  /// <summary>
+  /// An operator which relinks paths between VRP solutions.
+  /// </summary>
+  [Item("VRPPathRelinker", "An operator which relinks paths between VRP solutions.")]
+  [StorableClass]
+  public sealed class VRPPathRelinker : SingleObjectivePathRelinker, IGeneralVRPOperator, IStochasticOperator {
+    #region Parameter properties
+    public IValueParameter<IntValue> IterationsParameter {
+      get { return (IValueParameter<IntValue>)Parameters["Iterations"]; }
+    }
+    public ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (ILookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    public IValueParameter<IntValue> SampleSizeParameter {
+      get { return (IValueParameter<IntValue>)Parameters["SampleSize"]; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private VRPPathRelinker(bool deserializing) : base(deserializing) { }
+    private VRPPathRelinker(VRPPathRelinker original, Cloner cloner) : base(original, cloner) { }
+    public VRPPathRelinker()
+      : base() {
+      Parameters.Add(new ValueParameter<IntValue>("Iterations", "The number of iterations the operator should perform.", new IntValue(50)));
+      Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The VRP problem instance"));
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator which should be used for stochastic manipulation operators."));
+      Parameters.Add(new ValueParameter<IntValue>("SampleSize", "The number of moves that should be executed.", new IntValue(10)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new VRPPathRelinker(this, cloner);
+    }
+
+    public static ItemArray<IItem> Apply(PotvinEncoding initiator, PotvinEncoding guide, PercentValue n, int sampleSize, int iterations, IRandom rand, IVRPProblemInstance problemInstance) {
+      if (initiator == null || guide == null)
+        throw new ArgumentException("Cannot relink path because one of the provided solutions or both are null.");
+
+      double sigma = 1.5;
+      double minPenalty = 0.001;
+      double maxPenalty = 1000000000;
+
+      var originalOverloadPenalty = new DoubleValue();
+      if (problemInstance is IHomogenousCapacitatedProblemInstance)
+        originalOverloadPenalty.Value = (problemInstance as IHomogenousCapacitatedProblemInstance).OverloadPenalty.Value;
+      var originalTardinessPenalty = new DoubleValue();
+      if (problemInstance is ITimeWindowedProblemInstance)
+        originalTardinessPenalty.Value = (problemInstance as ITimeWindowedProblemInstance).TardinessPenalty.Value;
+
+      PotvinEncoding current = MatchTours(initiator, guide, problemInstance);
+      double currentSimilarity = VRPSimilarityCalculator.CalculateSimilarity(current, guide);
+
+      IList<PotvinEncoding> solutions = new List<PotvinEncoding>();
+      int i = 0;
+      while (i < iterations && !currentSimilarity.IsAlmost(1.0)) {
+        var currentEval = problemInstance.Evaluate(current);
+        currentSimilarity = VRPSimilarityCalculator.CalculateSimilarity(current, guide);
+
+        if (currentSimilarity < 1.0) {
+          for (int sample = 0; sample < sampleSize; sample++) {
+            var next = current.Clone() as PotvinEncoding;
+
+            int neighborhood = rand.Next(3);
+            switch (neighborhood) {
+              case 0: next = RouteBasedXOver(next, guide, rand,
+                problemInstance);
+                break;
+              case 1: next = SequenceBasedXOver(next, guide, rand,
+                problemInstance);
+                break;
+              case 2: GuidedRelocateMove(next, guide, rand);
+                break;
+            }
+
+            next = MatchTours(next, guide, problemInstance);
+
+            var nextEval = problemInstance.Evaluate(next);
+            if ((nextEval.Quality < currentEval.Quality)) {
+              current = next;
+              solutions.Add(current);
+              break;
+            }
+          }
+
+          if (problemInstance is IHomogenousCapacitatedProblemInstance) {
+            if (((CVRPEvaluation)currentEval).Overload > 0) {
+              (problemInstance as IHomogenousCapacitatedProblemInstance).OverloadPenalty.Value =
+                Math.Min(maxPenalty,
+                (problemInstance as IHomogenousCapacitatedProblemInstance).OverloadPenalty.Value * sigma);
+            } else {
+              (problemInstance as IHomogenousCapacitatedProblemInstance).OverloadPenalty.Value =
+                Math.Max(minPenalty,
+                (problemInstance as IHomogenousCapacitatedProblemInstance).OverloadPenalty.Value * sigma);
+            }
+          }
+
+
+          if (problemInstance is ITimeWindowedProblemInstance) {
+            if (((CVRPTWEvaluation)currentEval).Tardiness > 0) {
+              (problemInstance as ITimeWindowedProblemInstance).TardinessPenalty.Value =
+                Math.Min(maxPenalty,
+              (problemInstance as ITimeWindowedProblemInstance).TardinessPenalty.Value * sigma);
+            } else {
+              (problemInstance as ITimeWindowedProblemInstance).TardinessPenalty.Value =
+                Math.Max(minPenalty,
+                (problemInstance as ITimeWindowedProblemInstance).TardinessPenalty.Value / sigma);
+            }
+          }
+
+          i++;
+        }
+      }
+
+      if (problemInstance is IHomogenousCapacitatedProblemInstance)
+        (problemInstance as IHomogenousCapacitatedProblemInstance).OverloadPenalty.Value = originalOverloadPenalty.Value;
+      if (problemInstance is ITimeWindowedProblemInstance)
+        (problemInstance as ITimeWindowedProblemInstance).TardinessPenalty.Value = originalTardinessPenalty.Value;
+
+      return new ItemArray<IItem>(ChooseSelection(solutions, n));
+    }
+
+    private static IList<IItem> ChooseSelection(IList<PotvinEncoding> solutions, PercentValue n) {
+      IList<IItem> selection = new List<IItem>();
+      if (solutions.Count > 0) {
+        int noSol = (int)(solutions.Count * n.Value);
+        if (noSol <= 0) noSol++;
+        double stepSize = (double)solutions.Count / (double)noSol;
+        for (int i = 0; i < noSol; i++)
+          selection.Add(solutions.ElementAt((int)((i + 1) * stepSize - stepSize * 0.5)));
+      }
+
+      return selection;
+    }
+
+    protected override ItemArray<IItem> Relink(ItemArray<IItem> parents, PercentValue n) {
+      if (parents.Length != 2)
+        throw new ArgumentException("The number of parents is not equal to 2.");
+
+      if (!(parents[0] is PotvinEncoding))
+        parents[0] = PotvinEncoding.ConvertFrom(parents[0] as IVRPEncoding, ProblemInstanceParameter.ActualValue);
+      if (!(parents[1] is PotvinEncoding))
+        parents[1] = PotvinEncoding.ConvertFrom(parents[1] as IVRPEncoding, ProblemInstanceParameter.ActualValue);
+
+      return Apply(parents[0] as PotvinEncoding, parents[1] as PotvinEncoding, n,
+        SampleSizeParameter.Value.Value, IterationsParameter.Value.Value, RandomParameter.ActualValue, ProblemInstanceParameter.ActualValue);
+    }
+
+    private static int MatchingCities(Tour tour1, Tour tour2) {
+      return tour1.Stops.Intersect(tour2.Stops).Count();
+    }
+
+    private static PotvinEncoding MatchTours(PotvinEncoding initiator, PotvinEncoding guide, IVRPProblemInstance problemInstance) {
+      var result = new PotvinEncoding(problemInstance);
+
+      var used = new List<bool>();
+      for (int i = 0; i < initiator.Tours.Count; i++) {
+        used.Add(false);
+      }
+
+      for (int i = 0; i < guide.Tours.Count; i++) {
+        int bestMatch = -1;
+        int bestTour = -1;
+
+        for (int j = 0; j < initiator.Tours.Count; j++) {
+          if (!used[j]) {
+            int match = MatchingCities(guide.Tours[i], initiator.Tours[j]);
+            if (match > bestMatch) {
+              bestMatch = match;
+              bestTour = j;
+            }
+          }
+        }
+
+        if (bestTour != -1) {
+          result.Tours.Add(initiator.Tours[bestTour]);
+          used[bestTour] = true;
+        }
+      }
+
+      for (int i = 0; i < initiator.Tours.Count; i++) {
+        if (!used[i])
+          result.Tours.Add(initiator.Tours[i]);
+      }
+
+      return result;
+    }
+
+    #region moves
+    public static PotvinEncoding RouteBasedXOver(PotvinEncoding initiator, PotvinEncoding guide, IRandom random, IVRPProblemInstance problemInstance) {
+      return PotvinRouteBasedCrossover.Apply(random, initiator, guide, problemInstance, false);
+    }
+
+    public static PotvinEncoding SequenceBasedXOver(PotvinEncoding initiator, PotvinEncoding guide, IRandom random, IVRPProblemInstance problemInstance) {
+      return PotvinSequenceBasedCrossover.Apply(random, initiator, guide, problemInstance, false);
+    }
+
+    public static void GuidedRelocateMove(PotvinEncoding initiator, PotvinEncoding guide, IRandom random) {
+      List<int> cities = new List<int>();
+      foreach (Tour tour in initiator.Tours) {
+        foreach (int city in tour.Stops) {
+          Tour guideTour = guide.Tours.First(t => t.Stops.Contains(city));
+          if (guide.Tours.IndexOf(guideTour) != initiator.Tours.IndexOf(tour)) {
+            cities.Add(city);
+          }
+        }
+      }
+
+      if (cities.Count == 0) {
+        RelocateMove(initiator, random);
+      } else {
+        int city = cities[random.Next(cities.Count)];
+        Tour tour = initiator.Tours.First(t => t.Stops.Contains(city));
+        tour.Stops.Remove(city);
+
+        Tour guideTour = guide.Tours.First(t => t.Stops.Contains(city));
+        int guideTourIndex = guide.Tours.IndexOf(guideTour);
+
+        if (guideTourIndex < initiator.Tours.Count) {
+          Tour tour2 = initiator.Tours[guideTourIndex];
+
+          int guideIndex = guideTour.Stops.IndexOf(city);
+          if (guideIndex == 0) {
+            tour2.Stops.Insert(0, city);
+          } else {
+            int predecessor = guideTour.Stops[guideIndex - 1];
+            int initIndex = tour2.Stops.IndexOf(predecessor);
+            if (initIndex != -1) {
+              tour2.Stops.Insert(initIndex + 1, city);
+            } else {
+              if (guideIndex == guideTour.Stops.Count - 1) {
+                tour2.Stops.Insert(tour2.Stops.Count, city);
+              } else {
+                int sucessor = guideTour.Stops[guideIndex + 1];
+                initIndex = tour2.Stops.IndexOf(sucessor);
+                if (initIndex != -1) {
+                  tour2.Stops.Insert(initIndex, city);
+                } else {
+                  tour2.Stops.Insert(random.Next(tour2.Stops.Count + 1), city);
+                }
+              }
+            }
+          }
+        } else {
+          Tour tour2 = new Tour();
+          tour2.Stops.Add(city);
+          initiator.Tours.Add(tour2);
+        }
+
+        if (tour.Stops.Count == 0)
+          initiator.Tours.Remove(tour);
+      }
+    }
+
+    public static void RelocateMove(PotvinEncoding individual, IRandom random) {
+      int cities = individual.Cities;
+      int city = 1 + random.Next(cities);
+      Tour originalTour = individual.Tours.Find(t => t.Stops.Contains(city));
+      //consider creating new route
+      individual.Tours.Add(new Tour());
+
+      int position = 1 + random.Next(cities + individual.Tours.Count - 1);
+      if (position >= city) {
+        position++;
+      }
+
+      int originalPosition = originalTour.Stops.IndexOf(city);
+      originalTour.Stops.RemoveAt(originalPosition);
+
+      Tour insertionTour;
+      int insertionPosition;
+      if (position <= cities) {
+        insertionTour = individual.Tours.Find(t => t.Stops.Contains(position));
+        insertionPosition = insertionTour.Stops.IndexOf(position) + 1;
+      } else {
+        insertionTour = individual.Tours[position - cities - 1];
+        insertionPosition = 0;
+      }
+
+      insertionTour.Stops.Insert(insertionPosition, city);
+
+      individual.Tours.RemoveAll(t => t.Stops.Count == 0);
+    }
+    #endregion
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Plugin.cs.frame
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Plugin.cs.frame	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Plugin.cs.frame	(revision 14416)
@@ -0,0 +1,46 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.PluginInfrastructure;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  /// <summary>
+  /// Plugin class for HeuristicLab.Problems.VehicleRouting plugin
+  /// </summary>
+  [Plugin("HeuristicLab.Problems.VehicleRouting", "3.4.7.$WCREV$")]
+  [PluginFile("HeuristicLab.Problems.VehicleRouting-3.4.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.Instances", "3.3")]
+  [PluginDependency("HeuristicLab.Random", "3.3")]
+  public class HeuristicLabProblemsVehicleRoutingPlugin : PluginBase {
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPEvaluator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPEvaluator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPEvaluator.cs	(revision 14416)
@@ -0,0 +1,151 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  [Item("MDCVRPEvaluator", "Represents a multi depot CVRP evaluator.")]
+  [StorableClass]
+  public class MDCVRPEvaluator : VRPEvaluator {
+    public ILookupParameter<DoubleValue> OverloadParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Overload"]; }
+    }
+
+    protected override VRPEvaluation CreateTourEvaluation() {
+      return new CVRPEvaluation();
+    }
+
+    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;
+
+      double delivered = 0.0;
+      double overweight = 0.0;
+      double distance = 0.0;
+
+      int tourIndex = solution.GetTourIndex(tour);
+      int vehicle = solution.GetVehicleAssignment(tourIndex);
+
+      double capacity = cvrpInstance.Capacity[vehicle];
+      for (int i = 0; i < tour.Stops.Count; i++) {
+        delivered += instance.GetDemand(tour.Stops[i]);
+      }
+
+      double spareCapacity = capacity - delivered;
+
+      //simulate a tour, start and end at depot
+      for (int i = 0; i <= tour.Stops.Count; i++) {
+        int start = 0;
+        if (i > 0)
+          start = tour.Stops[i - 1];
+        int end = 0;
+        if (i < tour.Stops.Count)
+          end = tour.Stops[i];
+
+        //drive there
+        double currentDistace = instance.GetDistance(start, end, solution);
+        distance += currentDistace;
+
+        CVRPInsertionInfo stopInfo = new CVRPInsertionInfo(start, end, spareCapacity);
+        tourInfo.AddStopInsertionInfo(stopInfo);
+      }
+
+      eval.Quality += instance.FleetUsageFactor.Value;
+      eval.Quality += instance.DistanceFactor.Value * distance;
+
+      eval.Distance += distance;
+      eval.VehicleUtilization += 1;
+
+      if (delivered > capacity) {
+        overweight = delivered - capacity;
+      }
+
+      (eval as CVRPEvaluation).Overload += overweight;
+      double penalty = overweight * cvrpInstance.OverloadPenalty.Value;
+      eval.Penalty += penalty;
+      eval.Quality += penalty;
+      tourInfo.Penalty = penalty;
+      tourInfo.Quality = eval.Quality - originalQuality;
+    }
+
+    protected override double GetTourInsertionCosts(IVRPProblemInstance instance, IVRPEncoding solution, TourInsertionInfo tourInsertionInfo, int index, int customer,
+      out bool feasible) {
+      CVRPInsertionInfo insertionInfo = tourInsertionInfo.GetStopInsertionInfo(index) as CVRPInsertionInfo;
+
+      double costs = 0;
+      feasible = tourInsertionInfo.Penalty < double.Epsilon;
+
+      IHeterogenousCapacitatedProblemInstance cvrp = instance as IHeterogenousCapacitatedProblemInstance;
+      double overloadPenalty = cvrp.OverloadPenalty.Value;
+
+      double startDistance, endDistance;
+      costs += instance.GetInsertionDistance(insertionInfo.Start, customer, insertionInfo.End, solution, out startDistance, out endDistance);
+
+      double demand = instance.GetDemand(customer);
+      if (demand > insertionInfo.SpareCapacity) {
+        feasible = false;
+
+        if (insertionInfo.SpareCapacity >= 0)
+          costs += (demand - insertionInfo.SpareCapacity) * overloadPenalty;
+        else
+          costs += demand * overloadPenalty;
+      }
+
+      return costs;
+    }
+
+    protected override void InitResultParameters() {
+      base.InitResultParameters();
+
+      OverloadParameter.ActualValue = new DoubleValue(0);
+    }
+
+    protected override void SetResultParameters(VRPEvaluation tourEvaluation) {
+      base.SetResultParameters(tourEvaluation);
+
+      OverloadParameter.ActualValue.Value = (tourEvaluation as CVRPEvaluation).Overload;
+    }
+
+    [StorableConstructor]
+    protected MDCVRPEvaluator(bool deserializing) : base(deserializing) { }
+
+    public MDCVRPEvaluator() {
+      Parameters.Add(new LookupParameter<DoubleValue>("Overload", "The overload."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MDCVRPEvaluator(this, cloner);
+    }
+
+    protected MDCVRPEvaluator(MDCVRPEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPProblemInstance.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPProblemInstance.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPProblemInstance.cs	(revision 14416)
@@ -0,0 +1,136 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  [Item("MDCVRPProblemInstance", "Represents a multi depot CVRP instance.")]
+  [StorableClass]
+  public class MDCVRPProblemInstance : MultiDepotVRPProblemInstance, IHeterogenousCapacitatedProblemInstance {
+    protected IValueParameter<DoubleArray> CapacityParameter {
+      get { return (IValueParameter<DoubleArray>)Parameters["Capacity"]; }
+    }
+    protected IValueParameter<DoubleValue> OverloadPenaltyParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["EvalOverloadPenalty"]; }
+    }
+
+    public DoubleArray Capacity {
+      get { return CapacityParameter.Value; }
+      set { CapacityParameter.Value = value; }
+    }
+
+    protected IValueParameter<DoubleValue> CurrentOverloadPenaltyParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["CurrentOverloadPenalty"]; }
+    }
+
+    public DoubleValue OverloadPenalty {
+      get {
+        DoubleValue currentOverloadPenalty = CurrentOverloadPenaltyParameter.Value;
+        if (currentOverloadPenalty != null)
+          return currentOverloadPenalty;
+        else
+          return OverloadPenaltyParameter.Value;
+      }
+    }
+    DoubleValue ICapacitatedProblemInstance.CurrentOverloadPenalty {
+      get { return CurrentOverloadPenaltyParameter.Value; }
+      set { CurrentOverloadPenaltyParameter.Value = value; }
+    }
+
+    protected override IEnumerable<IOperator> GetOperators() {
+      return base.GetOperators()
+        .Where(o => o is IHeterogenousCapacitatedOperator).Cast<IOperator>();
+    }
+
+    protected override IEnumerable<IOperator> GetAnalyzers() {
+      return ApplicationManager.Manager.GetInstances<ICapacitatedOperator>()
+        .Where(o => o is IAnalyzer)
+        .Cast<IOperator>().Union(base.GetAnalyzers());
+    }
+
+    protected override IVRPEvaluator Evaluator {
+      get {
+        return new MDCVRPEvaluator();
+      }
+    }
+
+    [StorableConstructor]
+    protected MDCVRPProblemInstance(bool deserializing) : base(deserializing) { }
+
+    public MDCVRPProblemInstance() {
+      Parameters.Add(new ValueParameter<DoubleArray>("Capacity", "The capacity of each vehicle.", new DoubleArray()));
+      Parameters.Add(new ValueParameter<DoubleValue>("EvalOverloadPenalty", "The overload penalty considered in the evaluation.", new DoubleValue(100)));
+      Parameters.Add(new OptionalValueParameter<DoubleValue>("CurrentOverloadPenalty", "The current overload penalty considered in the evaluation.") { Hidden = true });
+
+      AttachEventHandlers();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MDCVRPProblemInstance(this, cloner);
+    }
+
+    protected MDCVRPProblemInstance(MDCVRPProblemInstance original, Cloner cloner)
+      : base(original, cloner) {
+      AttachEventHandlers();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      AttachEventHandlers();
+    }
+
+    private void AttachEventHandlers() {
+      CapacityParameter.ValueChanged += new EventHandler(CapacityParameter_ValueChanged);
+      OverloadPenaltyParameter.ValueChanged += new EventHandler(OverloadPenaltyParameter_ValueChanged);
+      OverloadPenaltyParameter.Value.ValueChanged += new EventHandler(OverloadPenalty_ValueChanged);
+    }
+
+    public override void InitializeState() {
+      base.InitializeState();
+
+      CurrentOverloadPenaltyParameter.Value = null;
+    }
+
+    #region Event handlers
+    void CapacityParameter_ValueChanged(object sender, EventArgs e) {
+      EvalBestKnownSolution();
+    }
+    void OverloadPenaltyParameter_ValueChanged(object sender, EventArgs e) {
+      OverloadPenaltyParameter.Value.ValueChanged += new EventHandler(OverloadPenalty_ValueChanged);
+      EvalBestKnownSolution();
+    }
+    void OverloadPenalty_ValueChanged(object sender, EventArgs e) {
+      EvalBestKnownSolution();
+    }
+    #endregion
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPTW/MDCVRPPDTW/MDCVRPPDTWEvaluator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPTW/MDCVRPPDTW/MDCVRPPDTWEvaluator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPTW/MDCVRPPDTW/MDCVRPPDTWEvaluator.cs	(revision 14416)
@@ -0,0 +1,340 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  [Item("MDCVRPPDTWEvaluator", "Represents a multi depot CVRPPDTW evaluator.")]
+  [StorableClass]
+  public class MDCVRPPDTWEvaluator : MDCVRPTWEvaluator {
+    public ILookupParameter<IntValue> PickupViolationsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["PickupViolations"]; }
+    }
+
+    protected override VRPEvaluation CreateTourEvaluation() {
+      return new CVRPPDTWEvaluation();
+    }
+
+    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[0];
+      time = tourStartTime;
+
+      //simulate a tour, start and end at depot
+      for (int i = 0; i <= tour.Stops.Count; i++) {
+        int start = 0;
+        if (i > 0)
+          start = tour.Stops[i - 1];
+        int end = 0;
+        if (i < tour.Stops.Count)
+          end = tour.Stops[i];
+
+        //drive there
+        double currentDistace = vrptw.GetDistance(start, end, solution);
+        time += currentDistace;
+        distance += currentDistace;
+
+        double arrivalTime = time;
+
+        int endIndex;
+        if (end == 0)
+          endIndex = depot;
+        else
+          endIndex = end + depots - 1;
+
+        //check if it was serviced on time
+        if (time > dueTime[endIndex])
+          tardiness += time - dueTime[endIndex];
+
+        //wait
+        double currentWaitingTime = 0.0;
+        if (time < readyTime[endIndex])
+          currentWaitingTime = readyTime[endIndex] - time;
+
+        double waitTime = readyTime[endIndex] - time;
+
+        waitingTime += currentWaitingTime;
+        time += currentWaitingTime;
+
+        double spareTime = dueTime[endIndex] - time;
+        double arrivalSpareCapacity = capacity - currentLoad;
+
+        if (end > 0) {
+          //service
+          double currentServiceTime = serviceTimes[end - 1];
+          serviceTime += currentServiceTime;
+          time += currentServiceTime;
+
+          //Pickup / deliver
+          bool validPickupDelivery =
+            validPickupDelivery =
+            ((demand[end - 1] >= 0) ||
+             (stops.ContainsKey(pickupDeliveryLocation[end - 1])));
+
+          if (validPickupDelivery) {
+            currentLoad += demand[end - 1];
+          } else {
+            pickupViolations++;
+          }
+
+          if (currentLoad > capacity)
+            overweight += currentLoad - capacity;
+        }
+
+        double spareCapacity = capacity - currentLoad;
+        CVRPPDTWInsertionInfo stopInfo = new CVRPPDTWInsertionInfo(start, end, spareCapacity, tourStartTime,
+          arrivalTime, time, spareTime, waitTime, new List<int>(stops.Keys), arrivalSpareCapacity);
+        tourInfo.AddStopInsertionInfo(stopInfo);
+
+        stops.Add(end, true);
+      }
+
+      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) {
+      CVRPPDTWInsertionInfo insertionInfo = tourInsertionInfo.GetStopInsertionInfo(index) as CVRPPDTWInsertionInfo;
+
+      double costs = 0;
+      feasible = tourInsertionInfo.Penalty < double.Epsilon;
+      bool tourFeasible = true;
+
+      ICapacitatedProblemInstance cvrp = instance as ICapacitatedProblemInstance;
+      double overloadPenalty = cvrp.OverloadPenalty.Value;
+
+      ITimeWindowedProblemInstance vrptw = instance as ITimeWindowedProblemInstance;
+      DoubleArray dueTime = vrptw.DueTime;
+      DoubleArray readyTime = vrptw.ReadyTime;
+      DoubleArray serviceTimes = vrptw.ServiceTime;
+      double tardinessPenalty = vrptw.TardinessPenalty.Value;
+
+      IMultiDepotProblemInstance mdp = instance as IMultiDepotProblemInstance;
+      int depots = mdp.Depots.Value;
+
+      IPickupAndDeliveryProblemInstance pdp = instance as IPickupAndDeliveryProblemInstance;
+      IntArray pickupDeliveryLocation = pdp.PickupDeliveryLocation;
+      double pickupPenalty = pdp.PickupViolationPenalty.Value;
+
+      double startDistance, endDistance;
+      costs += instance.GetInsertionDistance(insertionInfo.Start, customer, insertionInfo.End, solution, out startDistance, out endDistance);
+
+      double demand = instance.GetDemand(customer);
+      if (demand > insertionInfo.ArrivalSpareCapacity) {
+        tourFeasible = feasible = false;
+        if (insertionInfo.ArrivalSpareCapacity >= 0)
+          costs += (demand - insertionInfo.ArrivalSpareCapacity) * overloadPenalty;
+        else
+          costs += demand * overloadPenalty;
+      }
+      int destination = pickupDeliveryLocation[customer - 1];
+
+      bool validPickup = true;
+      if (demand < 0 && !insertionInfo.Visited.Contains(destination)) {
+        tourFeasible = feasible = false;
+        validPickup = false;
+        costs += pickupPenalty;
+      }
+
+      double time = 0;
+      double tardiness = 0;
+
+      if (index > 0)
+        time = (tourInsertionInfo.GetStopInsertionInfo(index - 1) as CVRPTWInsertionInfo).LeaveTime;
+      else
+        time = insertionInfo.TourStartTime;
+
+      time += startDistance;
+
+      int customerIndex = customer + depots - 1;
+
+      if (time > dueTime[customerIndex]) {
+        tardiness += time - dueTime[customerIndex];
+      }
+      if (time < readyTime[customerIndex])
+        time += readyTime[customerIndex] - time;
+      time += serviceTimes[customer - 1];
+      time += endDistance;
+
+      double additionalTime = time - (tourInsertionInfo.GetStopInsertionInfo(index) as CVRPTWInsertionInfo).ArrivalTime;
+      for (int i = index; i < tourInsertionInfo.GetStopCount(); i++) {
+        CVRPTWInsertionInfo nextStop = tourInsertionInfo.GetStopInsertionInfo(i) as CVRPTWInsertionInfo;
+
+        if (demand >= 0) {
+          if (nextStop.End == destination) {
+            demand = 0;
+            costs -= pickupPenalty;
+            if (tourInsertionInfo.Penalty == pickupPenalty && tourFeasible)
+              feasible = true;
+          } else if (nextStop.SpareCapacity < 0) {
+            costs += demand * overloadPenalty;
+          } else if (nextStop.SpareCapacity < demand) {
+            tourFeasible = feasible = false;
+            costs += (demand - nextStop.SpareCapacity) * overloadPenalty;
+          }
+        } else if (validPickup) {
+          if (nextStop.SpareCapacity < 0) {
+            costs += Math.Max(demand, nextStop.SpareCapacity) * overloadPenalty;
+          }
+        }
+
+        if (additionalTime < 0) {
+          //arrive earlier than before
+          //wait probably
+          if (nextStop.WaitingTime < 0) {
+            double wait = nextStop.WaitingTime - additionalTime;
+            if (wait > 0)
+              additionalTime += wait;
+          } else {
+            additionalTime = 0;
+          }
+
+          //check due date, decrease tardiness
+          if (nextStop.SpareTime < 0) {
+            costs += Math.Max(nextStop.SpareTime, additionalTime) * tardinessPenalty;
+          }
+        } else {
+          //arrive later than before, probably don't have to wait
+          if (nextStop.WaitingTime > 0) {
+            additionalTime -= Math.Min(additionalTime, nextStop.WaitingTime);
+          }
+
+          //check due date
+          if (nextStop.SpareTime > 0) {
+            double spare = nextStop.SpareTime - additionalTime;
+            if (spare < 0)
+              tardiness += -spare;
+          } else {
+            tardiness += additionalTime;
+          }
+        }
+      }
+
+      costs += additionalTime * vrptw.TimeFactor.Value;
+
+      if (tardiness > 0) {
+        tourFeasible = feasible = false;
+      }
+
+      costs += tardiness * tardinessPenalty;
+
+      return costs;
+    }
+
+    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 MDCVRPPDTWEvaluator(bool deserializing) : base(deserializing) { }
+
+    public MDCVRPPDTWEvaluator() {
+      Parameters.Add(new LookupParameter<IntValue>("PickupViolations", "The number of pickup violations."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MDCVRPPDTWEvaluator(this, cloner);
+    }
+
+    protected MDCVRPPDTWEvaluator(MDCVRPPDTWEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPTW/MDCVRPPDTW/MDCVRPPDTWProblemInstance.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPTW/MDCVRPPDTW/MDCVRPPDTWProblemInstance.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPTW/MDCVRPPDTW/MDCVRPPDTWProblemInstance.cs	(revision 14416)
@@ -0,0 +1,139 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  [Item("MDCVRPPDTWProblemInstance", "Represents a multi depot CVRPPDTW instance.")]
+  [StorableClass]
+  public class MDCVRPPDTWProblemInstance : MDCVRPTWProblemInstance, IPickupAndDeliveryProblemInstance {
+    protected IValueParameter<IntArray> PickupDeliveryLocationParameter {
+      get { return (IValueParameter<IntArray>)Parameters["PickupDeliveryLocation"]; }
+    }
+    protected IValueParameter<DoubleValue> PickupViolationPenaltyParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["EvalPickupViolationPenalty"]; }
+    }
+
+    public IntArray PickupDeliveryLocation {
+      get { return PickupDeliveryLocationParameter.Value; }
+      set { PickupDeliveryLocationParameter.Value = value; }
+    }
+
+    protected IValueParameter<DoubleValue> CurrentPickupViolationPenaltyParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["CurrentPickupViolationPenalty"]; }
+    }
+
+    public DoubleValue PickupViolationPenalty {
+      get {
+        DoubleValue currentPickupViolationPenalty = CurrentPickupViolationPenaltyParameter.Value;
+        if (currentPickupViolationPenalty != null)
+          return currentPickupViolationPenalty;
+        else
+          return PickupViolationPenaltyParameter.Value;
+      }
+    }
+    DoubleValue IPickupAndDeliveryProblemInstance.CurrentPickupViolationPenalty {
+      get { return CurrentPickupViolationPenaltyParameter.Value; }
+      set { CurrentPickupViolationPenaltyParameter.Value = value; }
+    }
+
+    protected override IEnumerable<IOperator> GetOperators() {
+      return
+        ApplicationManager.Manager.GetInstances<IPickupAndDeliveryOperator>()
+        .Where(o => !(o is IAnalyzer))
+        .Cast<IOperator>().Union(base.GetOperators());
+    }
+
+    protected override IEnumerable<IOperator> GetAnalyzers() {
+      return ApplicationManager.Manager.GetInstances<IPickupAndDeliveryOperator>()
+        .Where(o => o is IAnalyzer)
+        .Cast<IOperator>().Union(base.GetAnalyzers());
+    }
+
+    protected override IVRPEvaluator Evaluator {
+      get {
+        return new MDCVRPPDTWEvaluator();
+      }
+    }
+
+    public int GetPickupDeliveryLocation(int city) {
+      return PickupDeliveryLocation[city - 1];
+    }
+
+    [StorableConstructor]
+    protected MDCVRPPDTWProblemInstance(bool deserializing) : base(deserializing) { }
+
+    public MDCVRPPDTWProblemInstance() {
+      Parameters.Add(new ValueParameter<IntArray>("PickupDeliveryLocation", "The pickup and delivery location for each customer.", new IntArray()));
+
+      Parameters.Add(new ValueParameter<DoubleValue>("EvalPickupViolationPenalty", "The pickup violation penalty considered in the evaluation.", new DoubleValue(100)));
+      Parameters.Add(new OptionalValueParameter<DoubleValue>("CurrentPickupViolationPenalty", "The current pickup violation penalty considered in the evaluation.") { Hidden = true });
+
+      AttachEventHandlers();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MDCVRPPDTWProblemInstance(this, cloner);
+    }
+
+    protected MDCVRPPDTWProblemInstance(MDCVRPPDTWProblemInstance original, Cloner cloner)
+      : base(original, cloner) {
+      AttachEventHandlers();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      AttachEventHandlers();
+    }
+
+    private void AttachEventHandlers() {
+      PickupDeliveryLocationParameter.ValueChanged += new EventHandler(PickupDeliveryLocationParameter_ValueChanged);
+    }
+
+    public override void InitializeState() {
+      base.InitializeState();
+
+      CurrentPickupViolationPenaltyParameter.Value = null;
+    }
+
+    #region Event handlers
+    void PickupDeliveryLocationParameter_ValueChanged(object sender, EventArgs e) {
+      PickupDeliveryLocationParameter.Value.ItemChanged += new EventHandler<EventArgs<int>>(Value_ItemChanged);
+      EvalBestKnownSolution();
+    }
+
+    void Value_ItemChanged(object sender, EventArgs<int> e) {
+      EvalBestKnownSolution();
+    }
+    #endregion
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPTW/MDCVRPTWEvaluator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPTW/MDCVRPTWEvaluator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPTW/MDCVRPTWEvaluator.cs	(revision 14416)
@@ -0,0 +1,292 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  [Item("MDCVRPTWEvaluator", "Represents a multi depot CVRPTW evaluator.")]
+  [StorableClass]
+  public class MDCVRPTWEvaluator : MDCVRPEvaluator {
+    public ILookupParameter<DoubleValue> TardinessParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Tardiness"]; }
+    }
+
+    public ILookupParameter<DoubleValue> TravelTimeParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["TravelTime"]; }
+    }
+
+    protected override VRPEvaluation CreateTourEvaluation() {
+      return new CVRPTWEvaluation();
+    }
+
+    protected override void EvaluateTour(VRPEvaluation eval, IVRPProblemInstance instance, Tour tour, IVRPEncoding solution) {
+      TourInsertionInfo tourInfo = new TourInsertionInfo(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;
+
+      IMultiDepotProblemInstance mdp = instance as IMultiDepotProblemInstance;
+      IntArray vehicleAssignment = mdp.VehicleDepotAssignment;
+      int depots = mdp.Depots.Value;
+
+      double time = 0.0;
+      double waitingTime = 0.0;
+      double serviceTime = 0.0;
+      double tardiness = 0.0;
+      double delivered = 0.0;
+      double overweight = 0.0;
+      double distance = 0.0;
+
+      int tourIndex = solution.GetTourIndex(tour);
+      int vehicle = solution.GetVehicleAssignment(tourIndex);
+      int depot = vehicleAssignment[vehicle];
+
+      double capacity = cvrpInstance.Capacity[vehicle];
+      for (int i = 0; i < tour.Stops.Count; i++) {
+        delivered += instance.GetDemand(tour.Stops[i]);
+      }
+
+      double spareCapacity = capacity - delivered;
+
+      double tourStartTime = vrptw.ReadyTime[depot];
+      time = tourStartTime;
+
+      //simulate a tour, start and end at depot
+      for (int i = 0; i <= tour.Stops.Count; i++) {
+        int start = 0;
+        if (i > 0)
+          start = tour.Stops[i - 1];
+        int end = 0;
+        if (i < tour.Stops.Count)
+          end = tour.Stops[i];
+
+        //drive there
+        double currentDistace = vrptw.GetDistance(start, end, solution);
+        time += currentDistace;
+        distance += currentDistace;
+
+        double arrivalTime = time;
+
+        int endIndex;
+        if (end == 0)
+          endIndex = depot;
+        else
+          endIndex = end + depots - 1;
+
+        //check if it was serviced on time
+        if (time > dueTime[endIndex])
+          tardiness += time - dueTime[endIndex];
+
+        //wait
+        double currentWaitingTime = 0.0;
+        if (time < readyTime[endIndex])
+          currentWaitingTime = readyTime[endIndex] - time;
+
+        double waitTime = readyTime[endIndex] - time;
+
+        waitingTime += currentWaitingTime;
+        time += currentWaitingTime;
+
+        double spareTime = dueTime[endIndex] - time;
+
+        //service
+        double currentServiceTime = 0;
+        if (end > 0)
+          currentServiceTime = serviceTimes[end - 1];
+        serviceTime += currentServiceTime;
+        time += currentServiceTime;
+
+        CVRPTWInsertionInfo stopInfo = new CVRPTWInsertionInfo(start, end, spareCapacity, tourStartTime, arrivalTime, time, spareTime, waitTime);
+        tourInfo.AddStopInsertionInfo(stopInfo);
+      }
+
+      eval.Quality += instance.FleetUsageFactor.Value;
+      eval.Quality += instance.DistanceFactor.Value * distance;
+      eval.Distance += distance;
+      eval.VehicleUtilization += 1;
+
+      if (delivered > capacity) {
+        overweight = delivered - capacity;
+      }
+
+      (eval as CVRPEvaluation).Overload += overweight;
+      double tourPenalty = 0;
+      double penalty = overweight * cvrpInstance.OverloadPenalty.Value;
+      eval.Penalty += penalty;
+      eval.Quality += penalty;
+      tourPenalty += penalty;
+
+      (eval as CVRPTWEvaluation).Tardiness += tardiness;
+      (eval as CVRPTWEvaluation).TravelTime += time;
+
+      penalty = tardiness * vrptw.TardinessPenalty.Value;
+      eval.Penalty += penalty;
+      eval.Quality += penalty;
+      tourPenalty += penalty;
+      eval.Quality += time * vrptw.TimeFactor.Value;
+      tourInfo.Penalty = tourPenalty;
+      tourInfo.Quality = eval.Quality - originalQuality;
+    }
+
+    protected override double GetTourInsertionCosts(IVRPProblemInstance instance, IVRPEncoding solution, TourInsertionInfo tourInsertionInfo, int index, int customer,
+      out bool feasible) {
+      CVRPTWInsertionInfo insertionInfo = tourInsertionInfo.GetStopInsertionInfo(index) as CVRPTWInsertionInfo;
+
+      double costs = 0;
+      feasible = tourInsertionInfo.Penalty < double.Epsilon;
+
+      ICapacitatedProblemInstance cvrp = instance as ICapacitatedProblemInstance;
+      double overloadPenalty = cvrp.OverloadPenalty.Value;
+
+      ITimeWindowedProblemInstance vrptw = instance as ITimeWindowedProblemInstance;
+      DoubleArray dueTime = vrptw.DueTime;
+      DoubleArray readyTime = vrptw.ReadyTime;
+      DoubleArray serviceTimes = vrptw.ServiceTime;
+      double tardinessPenalty = vrptw.TardinessPenalty.Value;
+
+      IMultiDepotProblemInstance mdp = instance as IMultiDepotProblemInstance;
+      int depots = mdp.Depots.Value;
+
+      double startDistance, endDistance;
+      costs += instance.GetInsertionDistance(insertionInfo.Start, customer, insertionInfo.End, solution, out startDistance, out endDistance);
+
+      double demand = instance.GetDemand(customer);
+      if (demand > insertionInfo.SpareCapacity) {
+        feasible = false;
+
+        if (insertionInfo.SpareCapacity >= 0)
+          costs += (demand - insertionInfo.SpareCapacity) * overloadPenalty;
+        else
+          costs += demand * overloadPenalty;
+      }
+
+      double time = 0;
+      double tardiness = 0;
+
+      if (index > 0)
+        time = (tourInsertionInfo.GetStopInsertionInfo(index - 1) as CVRPTWInsertionInfo).LeaveTime;
+      else
+        time = insertionInfo.TourStartTime;
+
+      time += startDistance;
+
+      int customerIndex = customer + depots - 1;
+
+      if (time > dueTime[customerIndex]) {
+        tardiness += time - dueTime[customerIndex];
+      }
+      if (time < readyTime[customerIndex])
+        time += readyTime[customerIndex] - time;
+      time += serviceTimes[customer - 1];
+      time += endDistance;
+
+      double additionalTime = time - (tourInsertionInfo.GetStopInsertionInfo(index) as CVRPTWInsertionInfo).ArrivalTime;
+      for (int i = index; i < tourInsertionInfo.GetStopCount(); i++) {
+        CVRPTWInsertionInfo nextStop = tourInsertionInfo.GetStopInsertionInfo(i) as CVRPTWInsertionInfo;
+
+        if (additionalTime < 0) {
+          //arrive earlier than before
+          //wait probably
+          if (nextStop.WaitingTime < 0) {
+            double wait = nextStop.WaitingTime - additionalTime;
+            if (wait > 0)
+              additionalTime += wait;
+          } else {
+            additionalTime = 0;
+          }
+
+          //check due date, decrease tardiness
+          if (nextStop.SpareTime < 0) {
+            costs += Math.Max(nextStop.SpareTime, additionalTime) * tardinessPenalty;
+          }
+        } else {
+          //arrive later than before, probably don't have to wait
+          if (nextStop.WaitingTime > 0) {
+            additionalTime -= Math.Min(additionalTime, nextStop.WaitingTime);
+          }
+
+          //check due date
+          if (nextStop.SpareTime > 0) {
+            double spare = nextStop.SpareTime - additionalTime;
+            if (spare < 0)
+              tardiness += -spare;
+          } else {
+            tardiness += additionalTime;
+          }
+        }
+      }
+
+      costs += additionalTime * vrptw.TimeFactor.Value;
+
+      if (tardiness > 0) {
+        feasible = false;
+      }
+
+      costs += tardiness * tardinessPenalty;
+
+      return costs;
+    }
+
+    protected override void InitResultParameters() {
+      base.InitResultParameters();
+
+      TardinessParameter.ActualValue = new DoubleValue(0);
+      TravelTimeParameter.ActualValue = new DoubleValue(0);
+    }
+
+    protected override void SetResultParameters(VRPEvaluation tourEvaluation) {
+      base.SetResultParameters(tourEvaluation);
+
+      TardinessParameter.ActualValue.Value = (tourEvaluation as CVRPTWEvaluation).Tardiness;
+      TravelTimeParameter.ActualValue.Value = (tourEvaluation as CVRPTWEvaluation).TravelTime;
+    }
+
+    [StorableConstructor]
+    protected MDCVRPTWEvaluator(bool deserializing) : base(deserializing) { }
+
+    public MDCVRPTWEvaluator() {
+      Parameters.Add(new LookupParameter<DoubleValue>("Tardiness", "The tardiness."));
+      Parameters.Add(new LookupParameter<DoubleValue>("TravelTime", "The travel time."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MDCVRPTWEvaluator(this, cloner);
+    }
+
+    protected MDCVRPTWEvaluator(MDCVRPTWEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPTW/MDCVRPTWProblemInstance.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPTW/MDCVRPTWProblemInstance.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MDCVRP/MDCVRPTW/MDCVRPTWProblemInstance.cs	(revision 14416)
@@ -0,0 +1,167 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  [Item("MDCVRPTWProblemInstance", "Represents a multi depot CVRPTW instance.")]
+  [StorableClass]
+  public class MDCVRPTWProblemInstance : MDCVRPProblemInstance, ITimeWindowedProblemInstance {
+    protected IValueParameter<DoubleArray> ReadyTimeParameter {
+      get { return (IValueParameter<DoubleArray>)Parameters["ReadyTime"]; }
+    }
+    protected IValueParameter<DoubleArray> DueTimeParameter {
+      get { return (IValueParameter<DoubleArray>)Parameters["DueTime"]; }
+    }
+    protected IValueParameter<DoubleArray> ServiceTimeParameter {
+      get { return (IValueParameter<DoubleArray>)Parameters["ServiceTime"]; }
+    }
+
+    protected IValueParameter<DoubleValue> TimeFactorParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["EvalTimeFactor"]; }
+    }
+    protected IValueParameter<DoubleValue> TardinessPenaltyParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["EvalTardinessPenalty"]; }
+    }
+
+    public DoubleArray ReadyTime {
+      get { return ReadyTimeParameter.Value; }
+      set { ReadyTimeParameter.Value = value; }
+    }
+    public DoubleArray DueTime {
+      get { return DueTimeParameter.Value; }
+      set { DueTimeParameter.Value = value; }
+    }
+    public DoubleArray ServiceTime {
+      get { return ServiceTimeParameter.Value; }
+      set { ServiceTimeParameter.Value = value; }
+    }
+    public DoubleValue TimeFactor {
+      get { return TimeFactorParameter.Value; }
+      set { TimeFactorParameter.Value = value; }
+    }
+
+    protected IValueParameter<DoubleValue> CurrentTardinessPenaltyParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["CurrentTardinessPenalty"]; }
+    }
+
+    public DoubleValue TardinessPenalty {
+      get {
+        DoubleValue currentTardinessPenalty = CurrentTardinessPenaltyParameter.Value;
+        if (currentTardinessPenalty != null)
+          return currentTardinessPenalty;
+        else
+          return TardinessPenaltyParameter.Value;
+      }
+    }
+    DoubleValue ITimeWindowedProblemInstance.CurrentTardinessPenalty {
+      get { return CurrentTardinessPenaltyParameter.Value; }
+      set { CurrentTardinessPenaltyParameter.Value = value; }
+    }
+
+    protected override IEnumerable<IOperator> GetOperators() {
+      return base.GetOperators()
+        .Where(o => o is ITimeWindowedOperator).Cast<IOperator>();
+    }
+
+    protected override IEnumerable<IOperator> GetAnalyzers() {
+      return ApplicationManager.Manager.GetInstances<ITimeWindowedOperator>()
+        .Where(o => o is IAnalyzer)
+        .Cast<IOperator>().Union(base.GetAnalyzers());
+    }
+
+    protected override IVRPEvaluator Evaluator {
+      get {
+        return new MDCVRPTWEvaluator();
+      }
+    }
+
+    [StorableConstructor]
+    protected MDCVRPTWProblemInstance(bool deserializing) : base(deserializing) { }
+
+    public MDCVRPTWProblemInstance() {
+      Parameters.Add(new ValueParameter<DoubleArray>("ReadyTime", "The ready time of each customer.", new DoubleArray()));
+      Parameters.Add(new ValueParameter<DoubleArray>("DueTime", "The due time of each customer.", new DoubleArray()));
+      Parameters.Add(new ValueParameter<DoubleArray>("ServiceTime", "The service time of each customer.", new DoubleArray()));
+
+      Parameters.Add(new ValueParameter<DoubleValue>("EvalTimeFactor", "The time factor considered in the evaluation.", new DoubleValue(0)));
+      Parameters.Add(new ValueParameter<DoubleValue>("EvalTardinessPenalty", "The tardiness penalty considered in the evaluation.", new DoubleValue(100)));
+      Parameters.Add(new OptionalValueParameter<DoubleValue>("CurrentTardinessPenalty", "The current tardiness penalty considered in the evaluation.") { Hidden = true });
+
+      AttachEventHandlers();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MDCVRPTWProblemInstance(this, cloner);
+    }
+
+    protected MDCVRPTWProblemInstance(MDCVRPTWProblemInstance original, Cloner cloner)
+      : base(original, cloner) {
+      AttachEventHandlers();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      AttachEventHandlers();
+    }
+
+    private void AttachEventHandlers() {
+      TardinessPenaltyParameter.ValueChanged += new EventHandler(TardinessPenaltyParameter_ValueChanged);
+      TardinessPenaltyParameter.Value.ValueChanged += new EventHandler(TardinessPenalty_ValueChanged);
+      TimeFactorParameter.ValueChanged += new EventHandler(TimeFactorParameter_ValueChanged);
+      TimeFactorParameter.Value.ValueChanged += new EventHandler(TimeFactor_ValueChanged);
+    }
+
+    public override void InitializeState() {
+      base.InitializeState();
+
+      CurrentTardinessPenaltyParameter.Value = null;
+    }
+
+    #region Event handlers
+    void TardinessPenaltyParameter_ValueChanged(object sender, EventArgs e) {
+      TardinessPenaltyParameter.Value.ValueChanged += new EventHandler(TardinessPenalty_ValueChanged);
+      EvalBestKnownSolution();
+    }
+    void TardinessPenalty_ValueChanged(object sender, EventArgs e) {
+      EvalBestKnownSolution();
+    }
+    void TimeFactorParameter_ValueChanged(object sender, EventArgs e) {
+      TimeFactorParameter.Value.ValueChanged += new EventHandler(TimeFactor_ValueChanged);
+      EvalBestKnownSolution();
+    }
+    void TimeFactor_ValueChanged(object sender, EventArgs e) {
+      EvalBestKnownSolution();
+    }
+    #endregion
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MultiDepotVRPEvaluator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MultiDepotVRPEvaluator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MultiDepotVRPEvaluator.cs	(revision 14416)
@@ -0,0 +1,95 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Interfaces;
+
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  [Item("SingleDepotVRPEvaluator", "Represents a single depot VRP evaluator.")]
+  [StorableClass]
+  public class MultiDepotVRPEvaluator : VRPEvaluator {
+    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 distance = 0.0;
+      double quality = 0.0;
+
+      //simulate a tour, start and end at depot
+      for (int i = 0; i <= tour.Stops.Count; i++) {
+        int start = 0;
+        if (i > 0)
+          start = tour.Stops[i - 1];
+        int end = 0;
+        if (i < tour.Stops.Count)
+          end = tour.Stops[i];
+
+        //drive there
+        double currentDistace = instance.GetDistance(start, end, solution);
+        distance += currentDistace;
+
+        StopInsertionInfo stopInfo = new StopInsertionInfo(start, end);
+        tourInfo.AddStopInsertionInfo(stopInfo);
+      }
+
+      //Fleet usage
+      quality += instance.FleetUsageFactor.Value;
+      //Distance
+      quality += instance.DistanceFactor.Value * distance;
+
+      eval.Distance += distance;
+      eval.VehicleUtilization += 1;
+
+      eval.Quality += quality;
+      tourInfo.Quality = quality;
+    }
+
+    protected override double GetTourInsertionCosts(IVRPProblemInstance instance, IVRPEncoding solution, TourInsertionInfo tourInsertionInfo, int index, int customer,
+      out bool feasible) {
+      StopInsertionInfo insertionInfo = tourInsertionInfo.GetStopInsertionInfo(index);
+
+      double costs = 0;
+      feasible = true;
+      double startDistance, endDistance;
+
+      costs += instance.GetInsertionDistance(insertionInfo.Start, customer, insertionInfo.End, solution, out startDistance, out endDistance);
+
+      return costs;
+    }
+
+    [StorableConstructor]
+    protected MultiDepotVRPEvaluator(bool deserializing) : base(deserializing) { }
+
+    public MultiDepotVRPEvaluator() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MultiDepotVRPEvaluator(this, cloner);
+    }
+
+    protected MultiDepotVRPEvaluator(MultiDepotVRPEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MultiDepotVRPProblemInstance.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MultiDepotVRPProblemInstance.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/MultiDepotVRP/MultiDepotVRPProblemInstance.cs	(revision 14416)
@@ -0,0 +1,190 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  [Item("MultiDepotVRPProblemInstance", "Represents a multi depot VRP instance.")]
+  [StorableClass]
+  public class MultiDepotVRPProblemInstance : VRPProblemInstance, IMultiDepotProblemInstance {
+    protected IValueParameter<IntValue> DepotsParameter {
+      get { return (IValueParameter<IntValue>)Parameters["Depots"]; }
+    }
+
+    protected IValueParameter<IntArray> VehicleDepotAssignmentParameter {
+      get { return (IValueParameter<IntArray>)Parameters["VehicleDepotAssignment"]; }
+    }
+
+    public IntValue Depots {
+      get {
+        return DepotsParameter.Value;
+      }
+    }
+
+    public IntArray VehicleDepotAssignment {
+      get {
+        return VehicleDepotAssignmentParameter.Value;
+      }
+      set {
+        VehicleDepotAssignmentParameter.Value = value;
+      }
+    }
+
+    protected override IEnumerable<IOperator> GetOperators() {
+      return ApplicationManager.Manager.GetInstances<IMultiDepotOperator>().Cast<IOperator>();
+    }
+
+    protected override IEnumerable<IOperator> GetAnalyzers() {
+      return ApplicationManager.Manager.GetInstances<IMultiDepotOperator>()
+        .Where(o => o is IAnalyzer)
+        .Cast<IOperator>();
+    }
+
+    public override IntValue Cities {
+      get {
+        return new IntValue(Demand.Length);
+      }
+    }
+
+    protected override IVRPEvaluator Evaluator {
+      get {
+        return new MultiDepotVRPEvaluator();
+      }
+    }
+
+    protected override IVRPCreator Creator {
+      get {
+        return new HeuristicLab.Problems.VehicleRouting.Encodings.Alba.RandomCreator();
+      }
+    }
+
+    public override double GetDemand(int city) {
+      return base.GetDemand(city - 1);
+    }
+
+    public override double[] GetCoordinates(int city) {
+      double[] coordinates;
+
+      if (city == 0) {
+        //calculate centroid
+        coordinates = new double[Coordinates.Columns];
+
+        for (int i = 0; i < Depots.Value; i++) {
+          for (int j = 0; j < coordinates.Length; j++) {
+            coordinates[j] += Coordinates[i, j];
+          }
+        }
+
+        for (int j = 0; j < coordinates.Length; j++) {
+          coordinates[j] /= (double)Depots.Value;
+        }
+      } else {
+        city += Depots.Value - 1;
+        coordinates = base.GetCoordinates(city);
+      }
+
+      return coordinates;
+    }
+
+    public int GetDepot(int customer, IVRPEncoding solution) {
+      int depot = -1;
+
+      Tour tour =
+          solution.GetTours().FirstOrDefault(t => t.Stops.Contains(customer));
+
+      if (tour != null) {
+        int tourIndex = solution.GetTourIndex(tour);
+        int vehicle = solution.GetVehicleAssignment(tourIndex);
+        depot = VehicleDepotAssignment[vehicle];
+      }
+
+      return depot;
+    }
+
+    public override double GetDistance(int start, int end, IVRPEncoding solution) {
+      if (start == 0 && end == 0)
+        return 0;
+
+      if (start == 0) {
+        start = GetDepot(end, solution);
+        end += Depots.Value - 1;
+      } else if (end == 0) {
+        end = GetDepot(start, solution);
+        start += Depots.Value - 1;
+      } else {
+        start += Depots.Value - 1;
+        end += Depots.Value - 1;
+      }
+
+      return base.GetDistance(start, end, solution);
+    }
+
+    public override double GetInsertionDistance(int start, int customer, int end, IVRPEncoding solution,
+      out double startDistance, out double endDistance) {
+      if (start == 0) {
+        start = GetDepot(end, solution);
+        end += Depots.Value - 1;
+      } else if (end == 0) {
+        end = GetDepot(start, solution);
+        start += Depots.Value - 1;
+      } else {
+        start += Depots.Value - 1;
+        end += Depots.Value - 1;
+      }
+      customer += Depots.Value - 1;
+
+      double distance = base.GetDistance(start, end, solution);
+
+      startDistance = base.GetDistance(start, customer, solution);
+      endDistance = base.GetDistance(customer, end, solution);
+
+      double newDistance = startDistance + endDistance;
+
+      return newDistance - distance;
+    }
+
+    [StorableConstructor]
+    protected MultiDepotVRPProblemInstance(bool deserializing) : base(deserializing) { }
+
+    public MultiDepotVRPProblemInstance() {
+      Parameters.Add(new ValueParameter<IntValue>("Depots", "The number of depots", new IntValue(0)));
+      Parameters.Add(new ValueParameter<IntArray>("VehicleDepotAssignment", "The assignment of vehicles to depots", new IntArray()));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MultiDepotVRPProblemInstance(this, cloner);
+    }
+
+    protected MultiDepotVRPProblemInstance(MultiDepotVRPProblemInstance original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPEvaluation.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPEvaluation.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPEvaluation.cs	(revision 14416)
@@ -0,0 +1,40 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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
+
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  public class CVRPInsertionInfo : StopInsertionInfo {
+    private double spareCapacity;
+
+    public double SpareCapacity {
+      get { return spareCapacity; }
+    }
+
+    public CVRPInsertionInfo(int start, int end, double spareCapacity)
+      : base(start, end) {
+      this.spareCapacity = spareCapacity;
+    }
+  }
+
+  public class CVRPEvaluation : VRPEvaluation {
+    public double Overload { get; set; }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPEvaluator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPEvaluator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPEvaluator.cs	(revision 14416)
@@ -0,0 +1,156 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  [Item("CVRPEvaluator", "Represents a single depot CVRP evaluator.")]
+  [StorableClass]
+  public class CVRPEvaluator : VRPEvaluator {
+    public ILookupParameter<DoubleValue> OverloadParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Overload"]; }
+    }
+
+    protected override VRPEvaluation CreateTourEvaluation() {
+      return new CVRPEvaluation();
+    }
+
+    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;
+
+      IHomogenousCapacitatedProblemInstance cvrpInstance = instance as IHomogenousCapacitatedProblemInstance;
+      DoubleArray demand = instance.Demand;
+
+      double delivered = 0.0;
+      double overweight = 0.0;
+      double distance = 0.0;
+
+      double capacity = cvrpInstance.Capacity.Value;
+      for (int i = 0; i <= tour.Stops.Count; i++) {
+        int end = 0;
+        if (i < tour.Stops.Count)
+          end = tour.Stops[i];
+
+        delivered += demand[end];
+      }
+
+      double spareCapacity = capacity - delivered;
+
+      //simulate a tour, start and end at depot
+      for (int i = 0; i <= tour.Stops.Count; i++) {
+        int start = 0;
+        if (i > 0)
+          start = tour.Stops[i - 1];
+        int end = 0;
+        if (i < tour.Stops.Count)
+          end = tour.Stops[i];
+
+        //drive there
+        double currentDistace = instance.GetDistance(start, end, solution);
+        distance += currentDistace;
+
+        CVRPInsertionInfo stopInfo = new CVRPInsertionInfo(start, end, spareCapacity);
+        tourInfo.AddStopInsertionInfo(stopInfo);
+      }
+
+      eval.Quality += instance.FleetUsageFactor.Value;
+      eval.Quality += instance.DistanceFactor.Value * distance;
+
+      eval.Distance += distance;
+      eval.VehicleUtilization += 1;
+
+      if (delivered > capacity) {
+        overweight = delivered - capacity;
+      }
+
+      (eval as CVRPEvaluation).Overload += overweight;
+      double penalty = overweight * cvrpInstance.OverloadPenalty.Value;
+      eval.Penalty += penalty;
+      eval.Quality += penalty;
+      tourInfo.Penalty = penalty;
+      tourInfo.Quality = eval.Quality - originalQuality;
+    }
+
+    protected override double GetTourInsertionCosts(IVRPProblemInstance instance, IVRPEncoding solution, TourInsertionInfo tourInsertionInfo, int index, int customer,
+      out bool feasible) {
+      CVRPInsertionInfo insertionInfo = tourInsertionInfo.GetStopInsertionInfo(index) as CVRPInsertionInfo;
+
+      double costs = 0;
+      feasible = tourInsertionInfo.Penalty < double.Epsilon;
+
+      ICapacitatedProblemInstance cvrp = instance as ICapacitatedProblemInstance;
+      double overloadPenalty = cvrp.OverloadPenalty.Value;
+
+      double distance = instance.GetDistance(insertionInfo.Start, insertionInfo.End, solution);
+      double newDistance =
+        instance.GetDistance(insertionInfo.Start, customer, solution) +
+        instance.GetDistance(customer, insertionInfo.End, solution);
+      costs += instance.DistanceFactor.Value * (newDistance - distance);
+
+      double demand = instance.Demand[customer];
+      if (demand > insertionInfo.SpareCapacity) {
+        feasible = false;
+
+        if (insertionInfo.SpareCapacity >= 0)
+          costs += (demand - insertionInfo.SpareCapacity) * overloadPenalty;
+        else
+          costs += demand * overloadPenalty;
+      }
+
+      return costs;
+    }
+
+    protected override void InitResultParameters() {
+      base.InitResultParameters();
+
+      OverloadParameter.ActualValue = new DoubleValue(0);
+    }
+
+    protected override void SetResultParameters(VRPEvaluation tourEvaluation) {
+      base.SetResultParameters(tourEvaluation);
+
+      OverloadParameter.ActualValue.Value = (tourEvaluation as CVRPEvaluation).Overload;
+    }
+
+    [StorableConstructor]
+    protected CVRPEvaluator(bool deserializing) : base(deserializing) { }
+
+    public CVRPEvaluator() {
+      Parameters.Add(new LookupParameter<DoubleValue>("Overload", "The overload."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new CVRPEvaluator(this, cloner);
+    }
+
+    protected CVRPEvaluator(CVRPEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPProblemInstance.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPProblemInstance.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPProblemInstance.cs	(revision 14416)
@@ -0,0 +1,141 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  [Item("CVRPProblemInstance", "Represents a single depot CVRP instance.")]
+  [StorableClass]
+  public class CVRPProblemInstance : SingleDepotVRPProblemInstance, IHomogenousCapacitatedProblemInstance {
+    protected IValueParameter<DoubleValue> CapacityParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["Capacity"]; }
+    }
+    protected IValueParameter<DoubleValue> OverloadPenaltyParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["EvalOverloadPenalty"]; }
+    }
+
+    public DoubleValue Capacity {
+      get { return CapacityParameter.Value; }
+      set { CapacityParameter.Value = value; }
+    }
+
+    protected IValueParameter<DoubleValue> CurrentOverloadPenaltyParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["CurrentOverloadPenalty"]; }
+    }
+
+    public DoubleValue OverloadPenalty {
+      get {
+        DoubleValue currentOverloadPenalty = CurrentOverloadPenaltyParameter.Value;
+        if (currentOverloadPenalty != null)
+          return currentOverloadPenalty;
+        else
+          return OverloadPenaltyParameter.Value;
+      }
+    }
+    DoubleValue ICapacitatedProblemInstance.CurrentOverloadPenalty {
+      get { return CurrentOverloadPenaltyParameter.Value; }
+      set { CurrentOverloadPenaltyParameter.Value = value; }
+    }
+
+    protected override IEnumerable<IOperator> GetOperators() {
+      return base.GetOperators()
+        .Where(o => o is IHomogenousCapacitatedOperator).Cast<IOperator>();
+    }
+
+    protected override IEnumerable<IOperator> GetAnalyzers() {
+      return ApplicationManager.Manager.GetInstances<ICapacitatedOperator>()
+        .Where(o => o is IAnalyzer)
+        .Cast<IOperator>().Union(base.GetAnalyzers());
+    }
+
+    protected override IVRPEvaluator Evaluator {
+      get {
+        return new CVRPEvaluator();
+      }
+    }
+
+    [StorableConstructor]
+    protected CVRPProblemInstance(bool deserializing) : base(deserializing) { }
+
+    public CVRPProblemInstance() {
+      Parameters.Add(new ValueParameter<DoubleValue>("Capacity", "The capacity of each vehicle.", new DoubleValue(0)));
+      Parameters.Add(new ValueParameter<DoubleValue>("EvalOverloadPenalty", "The overload penalty considered in the evaluation.", new DoubleValue(100)));
+      Parameters.Add(new OptionalValueParameter<DoubleValue>("CurrentOverloadPenalty", "The current overload penalty considered in the evaluation.") { Hidden = true });
+
+      AttachEventHandlers();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new CVRPProblemInstance(this, cloner);
+    }
+
+    protected CVRPProblemInstance(CVRPProblemInstance original, Cloner cloner)
+      : base(original, cloner) {
+      AttachEventHandlers();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      AttachEventHandlers();
+    }
+
+    private void AttachEventHandlers() {
+      CapacityParameter.ValueChanged += new EventHandler(CapacityParameter_ValueChanged);
+      CapacityParameter.Value.ValueChanged += new EventHandler(Capacity_ValueChanged);
+      OverloadPenaltyParameter.ValueChanged += new EventHandler(OverloadPenaltyParameter_ValueChanged);
+      OverloadPenaltyParameter.Value.ValueChanged += new EventHandler(OverloadPenalty_ValueChanged);
+    }
+
+    public override void InitializeState() {
+      base.InitializeState();
+
+      CurrentOverloadPenaltyParameter.Value = null;
+    }
+
+    #region Event handlers
+    void CapacityParameter_ValueChanged(object sender, EventArgs e) {
+      CapacityParameter.Value.ValueChanged += new EventHandler(Capacity_ValueChanged);
+      EvalBestKnownSolution();
+    }
+    void Capacity_ValueChanged(object sender, EventArgs e) {
+      EvalBestKnownSolution();
+    }
+    void OverloadPenaltyParameter_ValueChanged(object sender, EventArgs e) {
+      OverloadPenaltyParameter.Value.ValueChanged += new EventHandler(OverloadPenalty_ValueChanged);
+      EvalBestKnownSolution();
+    }
+    void OverloadPenalty_ValueChanged(object sender, EventArgs e) {
+      EvalBestKnownSolution();
+    }
+    #endregion
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPTW/CVRPPDTW/CVRPPDTWEvaluation.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPTW/CVRPPDTW/CVRPPDTWEvaluation.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPTW/CVRPPDTW/CVRPPDTWEvaluation.cs	(revision 14416)
@@ -0,0 +1,49 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  public class CVRPPDTWInsertionInfo : CVRPTWInsertionInfo {
+    private List<int> visited;
+
+    public List<int> Visited {
+      get { return visited; }
+    }
+
+    private double arrivalSpareCapacity;
+
+    public double ArrivalSpareCapacity {
+      get { return arrivalSpareCapacity; }
+    }
+
+    public CVRPPDTWInsertionInfo(int start, int end, double spareCapacity, double tourStartTime,
+      double arrivalTime, double leaveTime, double spareTime, double waitingTime, List<int> visited, double arrivalSpareCapacity)
+      : base(start, end, spareCapacity, tourStartTime, arrivalTime, leaveTime, spareTime, waitingTime) {
+      this.visited = visited;
+      this.arrivalSpareCapacity = arrivalSpareCapacity;
+    }
+  }
+
+  public class CVRPPDTWEvaluation : CVRPTWEvaluation {
+    public int PickupViolations { get; set; }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPTW/CVRPPDTW/CVRPPDTWEvaluator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPTW/CVRPPDTW/CVRPPDTWEvaluator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPTW/CVRPPDTW/CVRPPDTWEvaluator.cs	(revision 14416)
@@ -0,0 +1,322 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  [Item("CVRPPDTWEvaluator", "Represents a single depot CVRPPDTW evaluator.")]
+  [StorableClass]
+  public class CVRPPDTWEvaluator : CVRPTWEvaluator {
+    public ILookupParameter<IntValue> PickupViolationsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["PickupViolations"]; }
+    }
+
+    protected override VRPEvaluation CreateTourEvaluation() {
+      return new CVRPPDTWEvaluation();
+    }
+
+    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;
+
+      IHomogenousCapacitatedProblemInstance cvrpInstance = instance as IHomogenousCapacitatedProblemInstance;
+      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;
+
+      double capacity = cvrpInstance.Capacity.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;
+
+      double currentLoad = 0.0;
+      Dictionary<int, bool> stops = new Dictionary<int, bool>();
+      int pickupViolations = 0;
+
+      double tourStartTime = readyTime[0];
+      time = tourStartTime;
+
+      //simulate a tour, start and end at depot
+      for (int i = 0; i <= tour.Stops.Count; i++) {
+        int start = 0;
+        if (i > 0)
+          start = tour.Stops[i - 1];
+        int end = 0;
+        if (i < tour.Stops.Count)
+          end = tour.Stops[i];
+
+        //drive there
+        double currentDistace = vrptw.GetDistance(start, end, solution);
+        time += currentDistace;
+        distance += currentDistace;
+
+        double arrivalTime = time;
+
+        //check if it was serviced on time
+        if (time > dueTime[end])
+          tardiness += time - dueTime[end];
+
+        //wait
+        double currentWaitingTime = 0.0;
+        if (time < readyTime[end])
+          currentWaitingTime = readyTime[end] - time;
+
+        double waitTime = readyTime[end] - time;
+
+        waitingTime += currentWaitingTime;
+        time += currentWaitingTime;
+
+        double spareTime = dueTime[end] - time;
+
+        //service
+        double currentServiceTime = serviceTimes[end];
+        serviceTime += currentServiceTime;
+        time += currentServiceTime;
+
+        //Pickup / deliver
+        double arrivalSpareCapacity = capacity - currentLoad;
+
+        bool validPickupDelivery =
+          validPickupDelivery =
+          ((demand[end] >= 0) ||
+           (stops.ContainsKey(pickupDeliveryLocation[end])));
+
+        if (validPickupDelivery) {
+          currentLoad += demand[end];
+        } else {
+          pickupViolations++;
+        }
+
+        if (currentLoad > capacity)
+          overweight += currentLoad - capacity;
+
+        double spareCapacity = capacity - currentLoad;
+        CVRPPDTWInsertionInfo stopInfo = new CVRPPDTWInsertionInfo(start, end, spareCapacity, tourStartTime,
+          arrivalTime, time, spareTime, waitTime, new List<int>(stops.Keys), arrivalSpareCapacity);
+        tourInfo.AddStopInsertionInfo(stopInfo);
+
+        stops.Add(end, true);
+      }
+
+      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) {
+      CVRPPDTWInsertionInfo insertionInfo = tourInsertionInfo.GetStopInsertionInfo(index) as CVRPPDTWInsertionInfo;
+
+      double costs = 0;
+      feasible = tourInsertionInfo.Penalty < double.Epsilon;
+      bool tourFeasible = true;
+
+      ICapacitatedProblemInstance cvrp = instance as ICapacitatedProblemInstance;
+      double overloadPenalty = cvrp.OverloadPenalty.Value;
+
+      ITimeWindowedProblemInstance vrptw = instance as ITimeWindowedProblemInstance;
+      DoubleArray dueTime = vrptw.DueTime;
+      DoubleArray readyTime = vrptw.ReadyTime;
+      DoubleArray serviceTimes = vrptw.ServiceTime;
+      double tardinessPenalty = vrptw.TardinessPenalty.Value;
+
+      IPickupAndDeliveryProblemInstance pdp = instance as IPickupAndDeliveryProblemInstance;
+      IntArray pickupDeliveryLocation = pdp.PickupDeliveryLocation;
+      double pickupPenalty = pdp.PickupViolationPenalty.Value;
+
+      double distance = instance.GetDistance(insertionInfo.Start, insertionInfo.End, solution);
+      double newDistance =
+        instance.GetDistance(insertionInfo.Start, customer, solution) +
+        instance.GetDistance(customer, insertionInfo.End, solution);
+      costs += instance.DistanceFactor.Value * (newDistance - distance);
+
+      double demand = instance.Demand[customer];
+      if (demand > insertionInfo.ArrivalSpareCapacity) {
+        tourFeasible = feasible = false;
+        if (insertionInfo.ArrivalSpareCapacity >= 0)
+          costs += (demand - insertionInfo.ArrivalSpareCapacity) * overloadPenalty;
+        else
+          costs += demand * overloadPenalty;
+      }
+      int destination = pickupDeliveryLocation[customer];
+
+      bool validPickup = true;
+      if (demand < 0 && !insertionInfo.Visited.Contains(destination)) {
+        tourFeasible = feasible = false;
+        validPickup = false;
+        costs += pickupPenalty;
+      }
+
+      double time = 0;
+      double tardiness = 0;
+
+      if (index > 0)
+        time = (tourInsertionInfo.GetStopInsertionInfo(index - 1) as CVRPTWInsertionInfo).LeaveTime;
+      else
+        time = insertionInfo.TourStartTime;
+
+      time += instance.GetDistance(insertionInfo.Start, customer, solution);
+      if (time > dueTime[customer]) {
+        tardiness += time - dueTime[customer];
+      }
+      if (time < readyTime[customer])
+        time += readyTime[customer] - time;
+      time += serviceTimes[customer];
+      time += instance.GetDistance(customer, insertionInfo.End, solution);
+
+      double additionalTime = time - (tourInsertionInfo.GetStopInsertionInfo(index) as CVRPTWInsertionInfo).ArrivalTime;
+      for (int i = index; i < tourInsertionInfo.GetStopCount(); i++) {
+        CVRPTWInsertionInfo nextStop = tourInsertionInfo.GetStopInsertionInfo(i) as CVRPTWInsertionInfo;
+
+        if (demand >= 0) {
+          if (nextStop.End == destination) {
+            demand = 0;
+            costs -= pickupPenalty;
+            if (tourInsertionInfo.Penalty == pickupPenalty && tourFeasible)
+              feasible = true;
+          } else if (nextStop.SpareCapacity < 0) {
+            costs += demand * overloadPenalty;
+          } else if (nextStop.SpareCapacity < demand) {
+            tourFeasible = feasible = false;
+            costs += (demand - nextStop.SpareCapacity) * overloadPenalty;
+          }
+        } else if (validPickup) {
+          if (nextStop.SpareCapacity < 0) {
+            costs += Math.Max(demand, nextStop.SpareCapacity) * overloadPenalty;
+          }
+        }
+
+        if (additionalTime < 0) {
+          //arrive earlier than before
+          //wait probably
+          if (nextStop.WaitingTime < 0) {
+            double wait = nextStop.WaitingTime - additionalTime;
+            if (wait > 0)
+              additionalTime += wait;
+          } else {
+            additionalTime = 0;
+          }
+
+          //check due date, decrease tardiness
+          if (nextStop.SpareTime < 0) {
+            costs += Math.Max(nextStop.SpareTime, additionalTime) * tardinessPenalty;
+          }
+        } else {
+          //arrive later than before, probably don't have to wait
+          if (nextStop.WaitingTime > 0) {
+            additionalTime -= Math.Min(additionalTime, nextStop.WaitingTime);
+          }
+
+          //check due date
+          if (nextStop.SpareTime > 0) {
+            double spare = nextStop.SpareTime - additionalTime;
+            if (spare < 0)
+              tardiness += -spare;
+          } else {
+            tardiness += additionalTime;
+          }
+        }
+      }
+
+      costs += additionalTime * vrptw.TimeFactor.Value;
+
+      if (tardiness > 0) {
+        tourFeasible = feasible = false;
+      }
+
+      costs += tardiness * tardinessPenalty;
+
+      return costs;
+    }
+
+    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 CVRPPDTWEvaluator(bool deserializing) : base(deserializing) { }
+
+    public CVRPPDTWEvaluator() {
+      Parameters.Add(new LookupParameter<IntValue>("PickupViolations", "The number of pickup violations."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new CVRPPDTWEvaluator(this, cloner);
+    }
+
+    protected CVRPPDTWEvaluator(CVRPPDTWEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPTW/CVRPPDTW/CVRPPDTWProblemInstance.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPTW/CVRPPDTW/CVRPPDTWProblemInstance.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPTW/CVRPPDTW/CVRPPDTWProblemInstance.cs	(revision 14416)
@@ -0,0 +1,139 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  [Item("CVRPPDTWProblemInstance", "Represents a single depot CVRPPDTW instance.")]
+  [StorableClass]
+  public class CVRPPDTWProblemInstance : CVRPTWProblemInstance, IPickupAndDeliveryProblemInstance {
+    protected IValueParameter<IntArray> PickupDeliveryLocationParameter {
+      get { return (IValueParameter<IntArray>)Parameters["PickupDeliveryLocation"]; }
+    }
+    protected IValueParameter<DoubleValue> PickupViolationPenaltyParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["EvalPickupViolationPenalty"]; }
+    }
+
+    public IntArray PickupDeliveryLocation {
+      get { return PickupDeliveryLocationParameter.Value; }
+      set { PickupDeliveryLocationParameter.Value = value; }
+    }
+
+    protected IValueParameter<DoubleValue> CurrentPickupViolationPenaltyParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["CurrentPickupViolationPenalty"]; }
+    }
+
+    public DoubleValue PickupViolationPenalty {
+      get {
+        DoubleValue currentPickupViolationPenalty = CurrentPickupViolationPenaltyParameter.Value;
+        if (currentPickupViolationPenalty != null)
+          return currentPickupViolationPenalty;
+        else
+          return PickupViolationPenaltyParameter.Value;
+      }
+    }
+    DoubleValue IPickupAndDeliveryProblemInstance.CurrentPickupViolationPenalty {
+      get { return CurrentOverloadPenaltyParameter.Value; }
+      set { CurrentPickupViolationPenaltyParameter.Value = value; }
+    }
+
+    protected override IEnumerable<IOperator> GetOperators() {
+      return
+        ApplicationManager.Manager.GetInstances<IPickupAndDeliveryOperator>()
+        .Where(o => !(o is IAnalyzer))
+        .Cast<IOperator>().Union(base.GetOperators());
+    }
+
+    protected override IEnumerable<IOperator> GetAnalyzers() {
+      return ApplicationManager.Manager.GetInstances<IPickupAndDeliveryOperator>()
+        .Where(o => o is IAnalyzer)
+        .Cast<IOperator>().Union(base.GetAnalyzers());
+    }
+
+    protected override IVRPEvaluator Evaluator {
+      get {
+        return new CVRPPDTWEvaluator();
+      }
+    }
+
+    public int GetPickupDeliveryLocation(int city) {
+      return PickupDeliveryLocation[city];
+    }
+
+    [StorableConstructor]
+    protected CVRPPDTWProblemInstance(bool deserializing) : base(deserializing) { }
+
+    public CVRPPDTWProblemInstance() {
+      Parameters.Add(new ValueParameter<IntArray>("PickupDeliveryLocation", "The pickup and delivery location for each customer.", new IntArray()));
+
+      Parameters.Add(new ValueParameter<DoubleValue>("EvalPickupViolationPenalty", "The pickup violation penalty considered in the evaluation.", new DoubleValue(100)));
+      Parameters.Add(new OptionalValueParameter<DoubleValue>("CurrentPickupViolationPenalty", "The current pickup violation penalty considered in the evaluation.") { Hidden = true });
+
+      AttachEventHandlers();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new CVRPPDTWProblemInstance(this, cloner);
+    }
+
+    protected CVRPPDTWProblemInstance(CVRPPDTWProblemInstance original, Cloner cloner)
+      : base(original, cloner) {
+      AttachEventHandlers();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      AttachEventHandlers();
+    }
+
+    private void AttachEventHandlers() {
+      PickupDeliveryLocationParameter.ValueChanged += new EventHandler(PickupDeliveryLocationParameter_ValueChanged);
+    }
+
+    public override void InitializeState() {
+      base.InitializeState();
+
+      CurrentPickupViolationPenaltyParameter.Value = null;
+    }
+
+    #region Event handlers
+    void PickupDeliveryLocationParameter_ValueChanged(object sender, EventArgs e) {
+      PickupDeliveryLocationParameter.Value.ItemChanged += new EventHandler<EventArgs<int>>(Value_ItemChanged);
+      EvalBestKnownSolution();
+    }
+
+    void Value_ItemChanged(object sender, EventArgs<int> e) {
+      EvalBestKnownSolution();
+    }
+    #endregion
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPTW/CVRPTWEvaluation.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPTW/CVRPTWEvaluation.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPTW/CVRPTWEvaluation.cs	(revision 14416)
@@ -0,0 +1,69 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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
+
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  public class CVRPTWInsertionInfo : CVRPInsertionInfo {
+    private double tourStartTime;
+
+    public double TourStartTime {
+      get { return tourStartTime; }
+    }
+
+    private double arrivalTime;
+
+    public double ArrivalTime {
+      get { return arrivalTime; }
+    }
+
+    private double leaveTime;
+
+    public double LeaveTime {
+      get { return leaveTime; }
+    }
+
+    private double spareTime;
+
+    public double SpareTime {
+      get { return spareTime; }
+    }
+
+    private double waitingTime;
+
+    public double WaitingTime {
+      get { return waitingTime; }
+    }
+
+    public CVRPTWInsertionInfo(int start, int end, double spareCapacity, double tourStartTime, double arrivalTime, double leaveTime, double spareTime, double waitingTime)
+      : base(start, end, spareCapacity) {
+      this.tourStartTime = tourStartTime;
+      this.arrivalTime = arrivalTime;
+      this.leaveTime = leaveTime;
+      this.spareTime = spareTime;
+      this.waitingTime = waitingTime;
+    }
+  }
+
+  public class CVRPTWEvaluation : CVRPEvaluation {
+    public double Tardiness { get; set; }
+    public double TravelTime { get; set; }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPTW/CVRPTWEvaluator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPTW/CVRPTWEvaluator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPTW/CVRPTWEvaluator.cs	(revision 14416)
@@ -0,0 +1,276 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  [Item("CVRPTWEvaluator", "Represents a single depot CVRPTW evaluator.")]
+  [StorableClass]
+  public class CVRPTWEvaluator : CVRPEvaluator {
+    public ILookupParameter<DoubleValue> TardinessParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Tardiness"]; }
+    }
+
+    public ILookupParameter<DoubleValue> TravelTimeParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["TravelTime"]; }
+    }
+
+    protected override VRPEvaluation CreateTourEvaluation() {
+      return new CVRPTWEvaluation();
+    }
+
+    protected override void EvaluateTour(VRPEvaluation eval, IVRPProblemInstance instance, Tour tour, IVRPEncoding solution) {
+      TourInsertionInfo tourInfo = new TourInsertionInfo(solution.GetVehicleAssignment(solution.GetTourIndex(tour)));
+      eval.InsertionInfo.AddTourInsertionInfo(tourInfo);
+      double originalQuality = eval.Quality;
+
+      IHomogenousCapacitatedProblemInstance cvrpInstance = instance as IHomogenousCapacitatedProblemInstance;
+      DoubleArray demand = instance.Demand;
+
+      ITimeWindowedProblemInstance vrptw = instance as ITimeWindowedProblemInstance;
+      DoubleArray dueTime = vrptw.DueTime;
+      DoubleArray readyTime = vrptw.ReadyTime;
+      DoubleArray serviceTimes = vrptw.ServiceTime;
+
+      double time = 0.0;
+      double waitingTime = 0.0;
+      double serviceTime = 0.0;
+      double tardiness = 0.0;
+      double delivered = 0.0;
+      double overweight = 0.0;
+      double distance = 0.0;
+
+      double capacity = cvrpInstance.Capacity.Value;
+      for (int i = 0; i <= tour.Stops.Count; i++) {
+        int end = 0;
+        if (i < tour.Stops.Count)
+          end = tour.Stops[i];
+
+        delivered += demand[end];
+      }
+
+      double spareCapacity = capacity - delivered;
+
+      double tourStartTime = readyTime[0];
+      time = tourStartTime;
+
+      //simulate a tour, start and end at depot
+      for (int i = 0; i <= tour.Stops.Count; i++) {
+        int start = 0;
+        if (i > 0)
+          start = tour.Stops[i - 1];
+        int end = 0;
+        if (i < tour.Stops.Count)
+          end = tour.Stops[i];
+
+        //drive there
+        double currentDistace = vrptw.GetDistance(start, end, solution);
+        time += currentDistace;
+        distance += currentDistace;
+
+        double arrivalTime = time;
+
+        //check if it was serviced on time
+        if (time > dueTime[end])
+          tardiness += time - dueTime[end];
+
+        //wait
+        double currentWaitingTime = 0.0;
+        if (time < readyTime[end])
+          currentWaitingTime = readyTime[end] - time;
+
+        double waitTime = readyTime[end] - time;
+
+        waitingTime += currentWaitingTime;
+        time += currentWaitingTime;
+
+        double spareTime = dueTime[end] - time;
+
+        //service
+        double currentServiceTime = serviceTimes[end];
+        serviceTime += currentServiceTime;
+        time += currentServiceTime;
+
+        CVRPTWInsertionInfo stopInfo = new CVRPTWInsertionInfo(start, end, spareCapacity, tourStartTime, arrivalTime, time, spareTime, waitTime);
+        tourInfo.AddStopInsertionInfo(stopInfo);
+      }
+
+      eval.Quality += instance.FleetUsageFactor.Value;
+      eval.Quality += instance.DistanceFactor.Value * distance;
+      eval.Distance += distance;
+      eval.VehicleUtilization += 1;
+
+      if (delivered > capacity) {
+        overweight = delivered - capacity;
+      }
+
+      (eval as CVRPEvaluation).Overload += overweight;
+      double tourPenalty = 0;
+      double penalty = overweight * cvrpInstance.OverloadPenalty.Value;
+      eval.Penalty += penalty;
+      eval.Quality += penalty;
+      tourPenalty += penalty;
+
+      (eval as CVRPTWEvaluation).Tardiness += tardiness;
+      (eval as CVRPTWEvaluation).TravelTime += time;
+
+      penalty = tardiness * vrptw.TardinessPenalty.Value;
+      eval.Penalty += penalty;
+      eval.Quality += penalty;
+      tourPenalty += penalty;
+      eval.Quality += time * vrptw.TimeFactor.Value;
+      tourInfo.Penalty = tourPenalty;
+      tourInfo.Quality = eval.Quality - originalQuality;
+    }
+
+    protected override double GetTourInsertionCosts(IVRPProblemInstance instance, IVRPEncoding solution, TourInsertionInfo tourInsertionInfo, int index, int customer,
+      out bool feasible) {
+      CVRPTWInsertionInfo insertionInfo = tourInsertionInfo.GetStopInsertionInfo(index) as CVRPTWInsertionInfo;
+
+      double costs = 0;
+      feasible = tourInsertionInfo.Penalty < double.Epsilon;
+
+      ICapacitatedProblemInstance cvrp = instance as ICapacitatedProblemInstance;
+      double overloadPenalty = cvrp.OverloadPenalty.Value;
+
+      ITimeWindowedProblemInstance vrptw = instance as ITimeWindowedProblemInstance;
+      DoubleArray dueTime = vrptw.DueTime;
+      DoubleArray readyTime = vrptw.ReadyTime;
+      DoubleArray serviceTimes = vrptw.ServiceTime;
+      double tardinessPenalty = vrptw.TardinessPenalty.Value;
+
+      double distance = instance.GetDistance(insertionInfo.Start, insertionInfo.End, solution);
+      double newDistance =
+        instance.GetDistance(insertionInfo.Start, customer, solution) +
+        instance.GetDistance(customer, insertionInfo.End, solution);
+      costs += instance.DistanceFactor.Value * (newDistance - distance);
+
+      double demand = instance.Demand[customer];
+      if (demand > insertionInfo.SpareCapacity) {
+        feasible = false;
+        if (insertionInfo.SpareCapacity >= 0)
+          costs += (demand - insertionInfo.SpareCapacity) * overloadPenalty;
+        else
+          costs += demand * overloadPenalty;
+      }
+
+      double time = 0;
+      double tardiness = 0;
+
+      if (index > 0)
+        time = (tourInsertionInfo.GetStopInsertionInfo(index - 1) as CVRPTWInsertionInfo).LeaveTime;
+      else
+        time = insertionInfo.TourStartTime;
+
+      time += instance.GetDistance(insertionInfo.Start, customer, solution);
+      if (time > dueTime[customer]) {
+        tardiness += time - dueTime[customer];
+      }
+      if (time < readyTime[customer])
+        time += readyTime[customer] - time;
+      time += serviceTimes[customer];
+      time += instance.GetDistance(customer, insertionInfo.End, solution);
+
+      double additionalTime = time - (tourInsertionInfo.GetStopInsertionInfo(index) as CVRPTWInsertionInfo).ArrivalTime;
+      for (int i = index; i < tourInsertionInfo.GetStopCount(); i++) {
+        CVRPTWInsertionInfo nextStop = tourInsertionInfo.GetStopInsertionInfo(i) as CVRPTWInsertionInfo;
+
+        if (additionalTime < 0) {
+          //arrive earlier than before
+          //wait probably
+          if (nextStop.WaitingTime < 0) {
+            double wait = nextStop.WaitingTime - additionalTime;
+            if (wait > 0)
+              additionalTime += wait;
+          } else {
+            additionalTime = 0;
+          }
+
+          //check due date, decrease tardiness
+          if (nextStop.SpareTime < 0) {
+            costs += Math.Max(nextStop.SpareTime, additionalTime) * tardinessPenalty;
+          }
+        } else {
+          //arrive later than before, probably don't have to wait
+          if (nextStop.WaitingTime > 0) {
+            additionalTime -= Math.Min(additionalTime, nextStop.WaitingTime);
+          }
+
+          //check due date
+          if (nextStop.SpareTime > 0) {
+            double spare = nextStop.SpareTime - additionalTime;
+            if (spare < 0)
+              tardiness += -spare;
+          } else {
+            tardiness += additionalTime;
+          }
+        }
+      }
+
+      costs += additionalTime * vrptw.TimeFactor.Value;
+
+      if (tardiness > 0) {
+        feasible = false;
+      }
+
+      costs += tardiness * tardinessPenalty;
+
+      return costs;
+    }
+
+    protected override void InitResultParameters() {
+      base.InitResultParameters();
+
+      TardinessParameter.ActualValue = new DoubleValue(0);
+      TravelTimeParameter.ActualValue = new DoubleValue(0);
+    }
+
+    protected override void SetResultParameters(VRPEvaluation tourEvaluation) {
+      base.SetResultParameters(tourEvaluation);
+
+      TardinessParameter.ActualValue.Value = (tourEvaluation as CVRPTWEvaluation).Tardiness;
+      TravelTimeParameter.ActualValue.Value = (tourEvaluation as CVRPTWEvaluation).TravelTime;
+    }
+
+    [StorableConstructor]
+    protected CVRPTWEvaluator(bool deserializing) : base(deserializing) { }
+
+    public CVRPTWEvaluator() {
+      Parameters.Add(new LookupParameter<DoubleValue>("Tardiness", "The tardiness."));
+      Parameters.Add(new LookupParameter<DoubleValue>("TravelTime", "The travel time."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new CVRPTWEvaluator(this, cloner);
+    }
+
+    protected CVRPTWEvaluator(CVRPTWEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPTW/CVRPTWProblemInstance.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPTW/CVRPTWProblemInstance.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPTW/CVRPTWProblemInstance.cs	(revision 14416)
@@ -0,0 +1,167 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  [Item("CVRPTWProblemInstance", "Represents a single depot CVRPTW instance.")]
+  [StorableClass]
+  public class CVRPTWProblemInstance : CVRPProblemInstance, ITimeWindowedProblemInstance {
+    protected IValueParameter<DoubleArray> ReadyTimeParameter {
+      get { return (IValueParameter<DoubleArray>)Parameters["ReadyTime"]; }
+    }
+    protected IValueParameter<DoubleArray> DueTimeParameter {
+      get { return (IValueParameter<DoubleArray>)Parameters["DueTime"]; }
+    }
+    protected IValueParameter<DoubleArray> ServiceTimeParameter {
+      get { return (IValueParameter<DoubleArray>)Parameters["ServiceTime"]; }
+    }
+
+    protected IValueParameter<DoubleValue> TimeFactorParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["EvalTimeFactor"]; }
+    }
+    protected IValueParameter<DoubleValue> TardinessPenaltyParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["EvalTardinessPenalty"]; }
+    }
+
+    public DoubleArray ReadyTime {
+      get { return ReadyTimeParameter.Value; }
+      set { ReadyTimeParameter.Value = value; }
+    }
+    public DoubleArray DueTime {
+      get { return DueTimeParameter.Value; }
+      set { DueTimeParameter.Value = value; }
+    }
+    public DoubleArray ServiceTime {
+      get { return ServiceTimeParameter.Value; }
+      set { ServiceTimeParameter.Value = value; }
+    }
+    public DoubleValue TimeFactor {
+      get { return TimeFactorParameter.Value; }
+      set { TimeFactorParameter.Value = value; }
+    }
+
+    protected IValueParameter<DoubleValue> CurrentTardinessPenaltyParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["CurrentTardinessPenalty"]; }
+    }
+
+    public DoubleValue TardinessPenalty {
+      get {
+        DoubleValue currentTardinessPenalty = CurrentTardinessPenaltyParameter.Value;
+        if (currentTardinessPenalty != null)
+          return currentTardinessPenalty;
+        else
+          return TardinessPenaltyParameter.Value;
+      }
+    }
+    DoubleValue ITimeWindowedProblemInstance.CurrentTardinessPenalty {
+      get { return CurrentTardinessPenaltyParameter.Value; }
+      set { CurrentTardinessPenaltyParameter.Value = value; }
+    }
+
+    protected override IEnumerable<IOperator> GetOperators() {
+      return base.GetOperators()
+        .Where(o => o is ITimeWindowedOperator).Cast<IOperator>();
+    }
+
+    protected override IEnumerable<IOperator> GetAnalyzers() {
+      return ApplicationManager.Manager.GetInstances<ITimeWindowedOperator>()
+        .Where(o => o is IAnalyzer)
+        .Cast<IOperator>().Union(base.GetAnalyzers());
+    }
+
+    protected override IVRPEvaluator Evaluator {
+      get {
+        return new CVRPTWEvaluator();
+      }
+    }
+
+    [StorableConstructor]
+    protected CVRPTWProblemInstance(bool deserializing) : base(deserializing) { }
+
+    public CVRPTWProblemInstance() {
+      Parameters.Add(new ValueParameter<DoubleArray>("ReadyTime", "The ready time of each customer.", new DoubleArray()));
+      Parameters.Add(new ValueParameter<DoubleArray>("DueTime", "The due time of each customer.", new DoubleArray()));
+      Parameters.Add(new ValueParameter<DoubleArray>("ServiceTime", "The service time of each customer.", new DoubleArray()));
+
+      Parameters.Add(new ValueParameter<DoubleValue>("EvalTimeFactor", "The time factor considered in the evaluation.", new DoubleValue(0)));
+      Parameters.Add(new ValueParameter<DoubleValue>("EvalTardinessPenalty", "The tardiness penalty considered in the evaluation.", new DoubleValue(100)));
+      Parameters.Add(new OptionalValueParameter<DoubleValue>("CurrentTardinessPenalty", "The current tardiness penalty considered in the evaluation.") { Hidden = true });
+
+      AttachEventHandlers();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new CVRPTWProblemInstance(this, cloner);
+    }
+
+    protected CVRPTWProblemInstance(CVRPTWProblemInstance original, Cloner cloner)
+      : base(original, cloner) {
+      AttachEventHandlers();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      AttachEventHandlers();
+    }
+
+    private void AttachEventHandlers() {
+      TardinessPenaltyParameter.ValueChanged += new EventHandler(TardinessPenaltyParameter_ValueChanged);
+      TardinessPenaltyParameter.Value.ValueChanged += new EventHandler(TardinessPenalty_ValueChanged);
+      TimeFactorParameter.ValueChanged += new EventHandler(TimeFactorParameter_ValueChanged);
+      TimeFactorParameter.Value.ValueChanged += new EventHandler(TimeFactor_ValueChanged);
+    }
+
+    public override void InitializeState() {
+      base.InitializeState();
+
+      CurrentTardinessPenaltyParameter.Value = null;
+    }
+
+    #region Event handlers
+    void TardinessPenaltyParameter_ValueChanged(object sender, EventArgs e) {
+      TardinessPenaltyParameter.Value.ValueChanged += new EventHandler(TardinessPenalty_ValueChanged);
+      EvalBestKnownSolution();
+    }
+    void TardinessPenalty_ValueChanged(object sender, EventArgs e) {
+      EvalBestKnownSolution();
+    }
+    void TimeFactorParameter_ValueChanged(object sender, EventArgs e) {
+      TimeFactorParameter.Value.ValueChanged += new EventHandler(TimeFactor_ValueChanged);
+      EvalBestKnownSolution();
+    }
+    void TimeFactor_ValueChanged(object sender, EventArgs e) {
+      EvalBestKnownSolution();
+    }
+    #endregion
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/SingleDepotVRPEvaluator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/SingleDepotVRPEvaluator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/SingleDepotVRPEvaluator.cs	(revision 14416)
@@ -0,0 +1,99 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Interfaces;
+
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  [Item("SingleDepotVRPEvaluator", "Represents a single depot VRP evaluator.")]
+  [StorableClass]
+  public class SingleDepotVRPEvaluator : VRPEvaluator {
+    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 distance = 0.0;
+      double quality = 0.0;
+
+      //simulate a tour, start and end at depot
+      for (int i = 0; i <= tour.Stops.Count; i++) {
+        int start = 0;
+        if (i > 0)
+          start = tour.Stops[i - 1];
+        int end = 0;
+        if (i < tour.Stops.Count)
+          end = tour.Stops[i];
+
+        //drive there
+        double currentDistace = instance.GetDistance(start, end, solution);
+        distance += currentDistace;
+
+        StopInsertionInfo stopInfo = new StopInsertionInfo(start, end);
+        tourInfo.AddStopInsertionInfo(stopInfo);
+      }
+
+      //Fleet usage
+      quality += instance.FleetUsageFactor.Value;
+      //Distance
+      quality += instance.DistanceFactor.Value * distance;
+
+      eval.Distance += distance;
+      eval.VehicleUtilization += 1;
+
+      tourInfo.Quality = quality;
+      eval.Quality += quality;
+    }
+
+    protected override double GetTourInsertionCosts(IVRPProblemInstance instance, IVRPEncoding solution, TourInsertionInfo tourInsertionInfo, int index, int customer,
+      out bool feasible) {
+      StopInsertionInfo insertionInfo = tourInsertionInfo.GetStopInsertionInfo(index);
+
+      double costs = 0;
+      feasible = true;
+
+      double distance = instance.GetDistance(insertionInfo.Start, insertionInfo.End, solution);
+      double newDistance =
+        instance.GetDistance(insertionInfo.Start, customer, solution) +
+        instance.GetDistance(customer, insertionInfo.End, solution);
+
+      costs += instance.DistanceFactor.Value * (newDistance - distance);
+
+      return costs;
+    }
+
+    [StorableConstructor]
+    protected SingleDepotVRPEvaluator(bool deserializing) : base(deserializing) { }
+
+    public SingleDepotVRPEvaluator() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SingleDepotVRPEvaluator(this, cloner);
+    }
+
+    protected SingleDepotVRPEvaluator(SingleDepotVRPEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/SingleDepotVRPProblemInstance.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/SingleDepotVRPProblemInstance.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/SingleDepotVRPProblemInstance.cs	(revision 14416)
@@ -0,0 +1,79 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  [Item("SingleDepotVRPProblemInstance", "Represents a single depot VRP instance.")]
+  [StorableClass]
+  public class SingleDepotVRPProblemInstance : VRPProblemInstance, ISingleDepotProblemInstance {
+    protected override IEnumerable<IOperator> GetOperators() {
+      return ApplicationManager.Manager.GetInstances<ISingleDepotOperator>().Cast<IOperator>();
+    }
+
+    protected override IEnumerable<IOperator> GetAnalyzers() {
+      return ApplicationManager.Manager.GetInstances<ISingleDepotOperator>()
+        .Where(o => o is IAnalyzer)
+        .Cast<IOperator>();
+    }
+
+    public override IntValue Cities {
+      get {
+        return new IntValue(Demand.Length - 1);
+      }
+    }
+
+    protected override IVRPEvaluator Evaluator {
+      get {
+        return new SingleDepotVRPEvaluator();
+      }
+    }
+
+    protected override IVRPCreator Creator {
+      get {
+        return new HeuristicLab.Problems.VehicleRouting.Encodings.Alba.RandomCreator();
+      }
+    }
+
+    [StorableConstructor]
+    protected SingleDepotVRPProblemInstance(bool deserializing) : base(deserializing) { }
+
+    public SingleDepotVRPProblemInstance() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SingleDepotVRPProblemInstance(this, cloner);
+    }
+
+    protected SingleDepotVRPProblemInstance(SingleDepotVRPProblemInstance original, Cloner cloner)
+      : base(original, cloner) {
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/VRPEvaluation.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/VRPEvaluation.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/VRPEvaluation.cs	(revision 14416)
@@ -0,0 +1,101 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  public class StopInsertionInfo {
+    private int start;
+
+    public int Start {
+      get { return start; }
+    }
+
+    private int end;
+
+    public int End {
+      get { return end; }
+    }
+
+    public StopInsertionInfo(int start, int end)
+      : base() {
+      this.start = start;
+      this.end = end;
+    }
+  }
+
+  public class TourInsertionInfo {
+    public double Penalty { get; set; }
+    public double Quality { get; set; }
+
+    public int Vehicle { get; set; }
+
+    private List<StopInsertionInfo> stopInsertionInfos;
+
+    public TourInsertionInfo(int vehicle)
+      : base() {
+      stopInsertionInfos = new List<StopInsertionInfo>();
+      Vehicle = vehicle;
+    }
+
+    public void AddStopInsertionInfo(StopInsertionInfo info) {
+      stopInsertionInfos.Add(info);
+    }
+
+    public StopInsertionInfo GetStopInsertionInfo(int stop) {
+      return stopInsertionInfos[stop];
+    }
+
+    public int GetStopCount() {
+      return stopInsertionInfos.Count;
+    }
+  }
+
+  public class InsertionInfo {
+    private List<TourInsertionInfo> tourInsertionInfos;
+
+    public InsertionInfo()
+      : base() {
+      tourInsertionInfos = new List<TourInsertionInfo>();
+    }
+
+    public void AddTourInsertionInfo(TourInsertionInfo info) {
+      tourInsertionInfos.Add(info);
+    }
+
+    public TourInsertionInfo GetTourInsertionInfo(int tour) {
+      return tourInsertionInfos[tour];
+    }
+  }
+
+  public class VRPEvaluation {
+    public double Quality { get; set; }
+    public double Distance { get; set; }
+    public int VehicleUtilization { get; set; }
+    public InsertionInfo InsertionInfo { get; set; }
+
+    public double Penalty { get; set; }
+
+    public VRPEvaluation() {
+      InsertionInfo = new InsertionInfo();
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/VRPEvaluator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/VRPEvaluator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/VRPEvaluator.cs	(revision 14416)
@@ -0,0 +1,147 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  [Item("VRPEvaluator", "Represents a VRP evaluator.")]
+  [StorableClass]
+  public abstract class VRPEvaluator : VRPOperator, IVRPEvaluator {
+    public ILookupParameter<IVRPEncoding> VRPToursParameter {
+      get { return (ILookupParameter<IVRPEncoding>)Parameters["VRPTours"]; }
+    }
+
+    #region ISingleObjectiveEvaluator Members
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    #endregion
+
+    public ILookupParameter<DoubleValue> DistanceParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Distance"]; }
+    }
+    public ILookupParameter<DoubleValue> VehcilesUtilizedParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["VehiclesUtilized"]; }
+    }
+
+    public ILookupParameter<DoubleValue> PenaltyParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Penalty"]; }
+    }
+
+    [StorableConstructor]
+    protected VRPEvaluator(bool deserializing) : base(deserializing) { }
+
+    public VRPEvaluator() {
+      Parameters.Add(new LookupParameter<IVRPEncoding>("VRPTours", "The VRP tours which should be evaluated."));
+
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The evaluated quality of the VRP solution."));
+      Parameters.Add(new LookupParameter<DoubleValue>("Distance", "The distance."));
+      Parameters.Add(new LookupParameter<DoubleValue>("VehiclesUtilized", "The number of vehicles utilized."));
+
+      Parameters.Add(new LookupParameter<DoubleValue>("Penalty", "The applied penalty."));
+    }
+
+    protected VRPEvaluator(VRPEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected virtual VRPEvaluation CreateTourEvaluation() {
+      return new VRPEvaluation();
+    }
+
+    protected abstract void EvaluateTour(VRPEvaluation eval, IVRPProblemInstance instance, Tour tour, IVRPEncoding solution);
+
+    protected virtual void InitResultParameters() {
+      QualityParameter.ActualValue = new DoubleValue(0);
+      VehcilesUtilizedParameter.ActualValue = new DoubleValue(0);
+      DistanceParameter.ActualValue = new DoubleValue(0);
+      PenaltyParameter.ActualValue = new DoubleValue(0);
+    }
+
+    protected virtual void SetResultParameters(VRPEvaluation tourEvaluation) {
+      QualityParameter.ActualValue.Value = tourEvaluation.Quality;
+      VehcilesUtilizedParameter.ActualValue.Value = tourEvaluation.VehicleUtilization;
+      DistanceParameter.ActualValue.Value = tourEvaluation.Distance;
+      PenaltyParameter.ActualValue.Value = tourEvaluation.Penalty;
+    }
+
+    #region IVRPEvaluator Members
+
+    public bool Feasible(VRPEvaluation evaluation) {
+      return evaluation.Penalty < double.Epsilon;
+    }
+
+    protected abstract double GetTourInsertionCosts(IVRPProblemInstance instance, IVRPEncoding solution, TourInsertionInfo tourInsertionInfo, int index, int customer, out bool feasible);
+
+    public double GetInsertionCosts(IVRPProblemInstance instance, IVRPEncoding solution, VRPEvaluation eval, int customer, int tour, int index, out bool feasible) {
+      bool tourFeasible;
+      double costs = GetTourInsertionCosts(
+        instance,
+        solution,
+        eval.InsertionInfo.GetTourInsertionInfo(tour),
+        index,
+        customer, out tourFeasible);
+
+      feasible = tourFeasible;
+
+      return costs;
+    }
+
+    public VRPEvaluation EvaluateTour(IVRPProblemInstance instance, Tour tour, IVRPEncoding solution) {
+      VRPEvaluation evaluation = CreateTourEvaluation();
+      EvaluateTour(evaluation, instance, tour, solution);
+      return evaluation;
+    }
+
+    public virtual VRPEvaluation Evaluate(IVRPProblemInstance instance, IVRPEncoding solution) {
+      VRPEvaluation evaluation = CreateTourEvaluation();
+
+      foreach (Tour tour in solution.GetTours()) {
+        EvaluateTour(evaluation, instance, tour, solution);
+      }
+
+      return evaluation;
+    }
+
+    public override IOperation InstrumentedApply() {
+      InitResultParameters();
+
+      VRPEvaluation evaluation = CreateTourEvaluation();
+      IVRPEncoding solution = VRPToursParameter.ActualValue;
+      foreach (Tour tour in solution.GetTours()) {
+        EvaluateTour(evaluation, ProblemInstance, tour, solution);
+      }
+      SetResultParameters(evaluation);
+
+      QualityParameter.ActualValue = new DoubleValue(evaluation.Quality);
+
+      return base.InstrumentedApply();
+    }
+
+    #endregion
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/VRPProblemInstance.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/VRPProblemInstance.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/VRPProblemInstance.cs	(revision 14416)
@@ -0,0 +1,345 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.ProblemInstances {
+  [Item("VRPProblemInstance", "Represents a VRP instance.")]
+  [StorableClass]
+  public abstract class VRPProblemInstance : ParameterizedNamedItem, IVRPProblemInstance, IStatefulItem {
+    IVRPEvaluator moveEvaluator;
+
+    private object locker = new object();
+
+    public IVRPEvaluator MoveEvaluator {
+      get {
+        lock (locker) {
+          if (evaluator == null)
+            return null;
+          else {
+            if (moveEvaluator == null) {
+              moveEvaluator = evaluator.Clone() as IVRPEvaluator;
+
+              foreach (IParameter parameter in moveEvaluator.Parameters) {
+                if (parameter is ILookupParameter
+                  && parameter != moveEvaluator.ProblemInstanceParameter
+                  && parameter != moveEvaluator.VRPToursParameter) {
+                  (parameter as ILookupParameter).ActualName =
+                    VRPMoveEvaluator.MovePrefix +
+                    (parameter as ILookupParameter).ActualName;
+                }
+              }
+            }
+
+            return moveEvaluator;
+          }
+        }
+      }
+    }
+
+    protected abstract IEnumerable<IOperator> GetOperators();
+    protected abstract IEnumerable<IOperator> GetAnalyzers();
+
+    public IEnumerable<IOperator> Operators {
+      get {
+        return GetOperators().Union(GetAnalyzers());
+      }
+    }
+
+    protected ValueParameter<DoubleMatrix> CoordinatesParameter {
+      get { return (ValueParameter<DoubleMatrix>)Parameters["Coordinates"]; }
+    }
+    protected OptionalValueParameter<DoubleMatrix> DistanceMatrixParameter {
+      get { return (OptionalValueParameter<DoubleMatrix>)Parameters["DistanceMatrix"]; }
+    }
+    protected ValueParameter<BoolValue> UseDistanceMatrixParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["UseDistanceMatrix"]; }
+    }
+    protected ValueParameter<IntValue> VehiclesParameter {
+      get { return (ValueParameter<IntValue>)Parameters["Vehicles"]; }
+    }
+    protected ValueParameter<DoubleArray> DemandParameter {
+      get { return (ValueParameter<DoubleArray>)Parameters["Demand"]; }
+    }
+
+    protected IValueParameter<DoubleValue> FleetUsageFactorParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["EvalFleetUsageFactor"]; }
+    }
+    protected IValueParameter<DoubleValue> DistanceFactorParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["EvalDistanceFactor"]; }
+    }
+
+    public DoubleMatrix Coordinates {
+      get { return CoordinatesParameter.Value; }
+      set { CoordinatesParameter.Value = value; }
+    }
+
+    public DoubleMatrix DistanceMatrix {
+      get { return DistanceMatrixParameter.Value; }
+      set { DistanceMatrixParameter.Value = value; }
+    }
+    public BoolValue UseDistanceMatrix {
+      get { return UseDistanceMatrixParameter.Value; }
+      set { UseDistanceMatrixParameter.Value = value; }
+    }
+    public IntValue Vehicles {
+      get { return VehiclesParameter.Value; }
+      set { VehiclesParameter.Value = value; }
+    }
+    public DoubleArray Demand {
+      get { return DemandParameter.Value; }
+      set { DemandParameter.Value = value; }
+    }
+    public virtual IntValue Cities {
+      get { return new IntValue(Demand.Length); }
+    }
+
+    public DoubleValue FleetUsageFactor {
+      get { return FleetUsageFactorParameter.Value; }
+      set { FleetUsageFactorParameter.Value = value; }
+    }
+    public DoubleValue DistanceFactor {
+      get { return DistanceFactorParameter.Value; }
+      set { DistanceFactorParameter.Value = value; }
+    }
+
+    protected virtual double CalculateDistance(int start, int end) {
+      double distance = 0.0;
+
+      distance =
+          Math.Sqrt(
+            Math.Pow(Coordinates[start, 0] - Coordinates[end, 0], 2) +
+            Math.Pow(Coordinates[start, 1] - Coordinates[end, 1], 2));
+
+      return distance;
+    }
+
+    private DoubleMatrix CreateDistanceMatrix() {
+      DoubleMatrix distanceMatrix = new DoubleMatrix(Coordinates.Rows, Coordinates.Rows);
+
+      for (int i = 0; i < distanceMatrix.Rows; i++) {
+        for (int j = 0; j < distanceMatrix.Columns; j++) {
+          double distance = CalculateDistance(i, j);
+
+          distanceMatrix[i, j] = distance;
+        }
+      }
+
+      return distanceMatrix;
+    }
+
+    public virtual double[] GetCoordinates(int city) {
+      double[] coordinates = new double[Coordinates.Columns];
+
+      for (int i = 0; i < Coordinates.Columns; i++) {
+        coordinates[i] = Coordinates[city, i];
+      }
+
+      return coordinates;
+    }
+
+    public virtual double GetDemand(int city) {
+      return Demand[city];
+    }
+
+    //cache for performance improvement
+    private DoubleMatrix distanceMatrix = null;
+    private IVRPEvaluator evaluator = null;
+
+    public IVRPEvaluator SolutionEvaluator {
+      get {
+        return evaluator;
+      }
+
+      set {
+        lock (locker) {
+          moveEvaluator = null;
+          evaluator = value;
+          EvalBestKnownSolution();
+        }
+      }
+    }
+
+    public virtual double GetDistance(int start, int end, IVRPEncoding solution) {
+      if (distanceMatrix == null && UseDistanceMatrix.Value) {
+        if (DistanceMatrix == null) DistanceMatrix = CreateDistanceMatrix();
+        distanceMatrix = DistanceMatrix;
+      }
+
+      if (distanceMatrix != null) return distanceMatrix[start, end];
+      return CalculateDistance(start, end);
+    }
+
+    public virtual double GetInsertionDistance(int start, int customer, int end, IVRPEncoding solution,
+      out double startDistance, out double endDistance) {
+      double distance = GetDistance(start, end, solution);
+
+      startDistance = GetDistance(start, customer, solution);
+      endDistance = GetDistance(customer, end, solution);
+
+      double newDistance = startDistance + endDistance;
+
+      return newDistance - distance;
+    }
+
+    public bool Feasible(IVRPEncoding solution) {
+      return evaluator.Feasible(
+        evaluator.Evaluate(
+          this, solution));
+    }
+
+    public bool TourFeasible(Tour tour, IVRPEncoding solution) {
+      return evaluator.Feasible(
+        evaluator.EvaluateTour(
+        this, tour, solution));
+    }
+
+    public VRPEvaluation Evaluate(IVRPEncoding solution) {
+      return evaluator.Evaluate(this, solution);
+    }
+
+    public VRPEvaluation EvaluateTour(Tour tour, IVRPEncoding solution) {
+      return evaluator.EvaluateTour(this, tour, solution);
+    }
+
+    public bool Feasible(VRPEvaluation eval) {
+      return evaluator.Feasible(eval);
+    }
+
+    public double GetInsertionCosts(VRPEvaluation eval, IVRPEncoding solution, int customer, int tour, int index, out bool feasible) {
+      return evaluator.GetInsertionCosts(this, solution, eval, customer, tour, index, out feasible);
+    }
+
+
+    public event EventHandler EvaluationChanged;
+
+    protected void EvalBestKnownSolution() {
+      EventHandler tmp = EvaluationChanged;
+      if (tmp != null)
+        tmp(this, null);
+    }
+
+    protected abstract IVRPEvaluator Evaluator { get; }
+    protected abstract IVRPCreator Creator { get; }
+
+    [StorableConstructor]
+    protected VRPProblemInstance(bool deserializing) : base(deserializing) { }
+
+    public VRPProblemInstance()
+      : base() {
+      Parameters.Add(new ValueParameter<DoubleMatrix>("Coordinates", "The x- and y-Coordinates of the cities.", new DoubleMatrix()));
+      Parameters.Add(new OptionalValueParameter<DoubleMatrix>("DistanceMatrix", "The matrix which contains the distances between the cities."));
+      Parameters.Add(new ValueParameter<BoolValue>("UseDistanceMatrix", "True if a distance matrix should be calculated and used for evaluation, otherwise false.", new BoolValue(true)));
+      Parameters.Add(new ValueParameter<IntValue>("Vehicles", "The number of vehicles.", new IntValue(0)));
+      Parameters.Add(new ValueParameter<DoubleArray>("Demand", "The demand of each customer.", new DoubleArray()));
+
+      Parameters.Add(new ValueParameter<DoubleValue>("EvalFleetUsageFactor", "The fleet usage factor considered in the evaluation.", new DoubleValue(0)));
+      Parameters.Add(new ValueParameter<DoubleValue>("EvalDistanceFactor", "The distance factor considered in the evaluation.", new DoubleValue(1)));
+
+      evaluator = Evaluator;
+      AttachEventHandlers();
+    }
+
+    protected VRPProblemInstance(VRPProblemInstance original, Cloner cloner)
+      : base(original, cloner) {
+      evaluator = Evaluator;
+      AttachEventHandlers();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      evaluator = Evaluator;
+      AttachEventHandlers();
+    }
+
+    private void AttachEventHandlers() {
+      DistanceFactorParameter.ValueChanged += new EventHandler(DistanceFactorParameter_ValueChanged);
+      DistanceFactorParameter.Value.ValueChanged += new EventHandler(DistanceFactor_ValueChanged);
+      FleetUsageFactorParameter.ValueChanged += new EventHandler(FleetUsageFactorParameter_ValueChanged);
+      FleetUsageFactorParameter.Value.ValueChanged += new EventHandler(FleetUsageFactor_ValueChanged);
+      DistanceMatrixParameter.ValueChanged += new EventHandler(DistanceMatrixParameter_ValueChanged);
+      if (DistanceMatrix != null) {
+        DistanceMatrix.ItemChanged += new EventHandler<EventArgs<int, int>>(DistanceMatrix_ItemChanged);
+        DistanceMatrix.Reset += new EventHandler(DistanceMatrix_Reset);
+      }
+      UseDistanceMatrixParameter.ValueChanged += new EventHandler(UseDistanceMatrixParameter_ValueChanged);
+      UseDistanceMatrix.ValueChanged += new EventHandler(UseDistanceMatrix_ValueChanged);
+    }
+
+    public virtual void InitializeState() {
+    }
+
+    public virtual void ClearState() {
+    }
+
+    #region Event handlers
+    void DistanceFactorParameter_ValueChanged(object sender, EventArgs e) {
+      DistanceFactorParameter.Value.ValueChanged += new EventHandler(DistanceFactor_ValueChanged);
+      EvalBestKnownSolution();
+    }
+    void DistanceFactor_ValueChanged(object sender, EventArgs e) {
+      EvalBestKnownSolution();
+    }
+    void FleetUsageFactorParameter_ValueChanged(object sender, EventArgs e) {
+      FleetUsageFactorParameter.Value.ValueChanged += new EventHandler(FleetUsageFactor_ValueChanged);
+      EvalBestKnownSolution();
+    }
+    void FleetUsageFactor_ValueChanged(object sender, EventArgs e) {
+      EvalBestKnownSolution();
+    }
+    void DistanceMatrixParameter_ValueChanged(object sender, EventArgs e) {
+      if (DistanceMatrix != null) {
+        DistanceMatrix.ItemChanged += new EventHandler<EventArgs<int, int>>(DistanceMatrix_ItemChanged);
+        DistanceMatrix.Reset += new EventHandler(DistanceMatrix_Reset);
+      }
+      distanceMatrix = DistanceMatrix;
+      EvalBestKnownSolution();
+    }
+    void DistanceMatrix_Reset(object sender, EventArgs e) {
+      EvalBestKnownSolution();
+    }
+    void DistanceMatrix_ItemChanged(object sender, EventArgs<int, int> e) {
+      distanceMatrix = DistanceMatrix;
+      EvalBestKnownSolution();
+    }
+    void UseDistanceMatrixParameter_ValueChanged(object sender, EventArgs e) {
+      UseDistanceMatrix.ValueChanged += new EventHandler(UseDistanceMatrix_ValueChanged);
+      if (!UseDistanceMatrix.Value)
+        distanceMatrix = null;
+      EvalBestKnownSolution();
+    }
+    void UseDistanceMatrix_ValueChanged(object sender, EventArgs e) {
+      if (!UseDistanceMatrix.Value)
+        distanceMatrix = null;
+      EvalBestKnownSolution();
+    }
+    #endregion
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Properties/AssemblyInfo.cs.frame
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Properties/AssemblyInfo.cs.frame	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Properties/AssemblyInfo.cs.frame	(revision 14416)
@@ -0,0 +1,55 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.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.Problems.VehicleRouting")]
+[assembly: AssemblyDescription("HeuristicLab Vehicle Routing Problem classes")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("HeuristicLab")]
+[assembly: AssemblyCopyright("(c) 2002-2016 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("10E4FF40-80AF-4C6F-93EE-B30E818BBFA2")]
+
+// 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 Revision and Build Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("3.4.0.0")]
+[assembly: AssemblyFileVersion("3.4.7.$WCREV$")]
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/SimilarityCalculators/VRPSimilarityCalculator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/SimilarityCalculators/VRPSimilarityCalculator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/SimilarityCalculators/VRPSimilarityCalculator.cs	(revision 14416)
@@ -0,0 +1,103 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  /// <summary>
+  /// An operator which performs similarity calculation between two VRP solutions.
+  /// </summary>
+  /// <remarks>
+  /// The operator calculates the similarity based on the number of edges the two solutions have in common.
+  /// </remarks>
+  [Item("VRPSimilarityCalculator", "An operator which performs similarity calculation between two VRP solutions.")]
+  [StorableClass]
+  public sealed class VRPSimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator {
+    protected override bool IsCommutative { get { return true; } }
+
+    [Storable]
+    public IVRPProblemInstance ProblemInstance { get; set; }
+
+    private VRPSimilarityCalculator(bool deserializing) : base(deserializing) { }
+    private VRPSimilarityCalculator(VRPSimilarityCalculator original, Cloner cloner)
+      : base(original, cloner) {
+      this.ProblemInstance = cloner.Clone(original.ProblemInstance);
+    }
+    public VRPSimilarityCalculator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new VRPSimilarityCalculator(this, cloner);
+    }
+
+    public static double CalculateSimilarity(PotvinEncoding left, PotvinEncoding right) {
+      if (left == null || right == null)
+        throw new ArgumentException("Cannot calculate similarity because one of the provided solutions or both are null.");
+      if (left == right) return 1.0;
+
+      // extract edges from first solution
+      var edges1 = new List<Tuple<int, int>>();
+      foreach (Tour tour in left.Tours) {
+        edges1.Add(new Tuple<int, int>(0, tour.Stops[0]));
+        for (int i = 0; i < tour.Stops.Count - 1; i++)
+          edges1.Add(new Tuple<int, int>(tour.Stops[i], tour.Stops[i + 1]));
+        edges1.Add(new Tuple<int, int>(tour.Stops[tour.Stops.Count - 1], 0));
+      }
+
+      // extract edges from second solution
+      var edges2 = new List<Tuple<int, int>>();
+      foreach (Tour tour in right.Tours) {
+        edges2.Add(new Tuple<int, int>(0, tour.Stops[0]));
+        for (int i = 0; i < tour.Stops.Count - 1; i++)
+          edges2.Add(new Tuple<int, int>(tour.Stops[i], tour.Stops[i + 1]));
+        edges2.Add(new Tuple<int, int>(tour.Stops[tour.Stops.Count - 1], 0));
+      }
+
+      if (edges1.Count + edges2.Count == 0)
+        throw new ArgumentException("Cannot calculate diversity because no tours exist.");
+
+      int identicalEdges = 0;
+      foreach (var edge in edges1) {
+        if (edges2.Any(x => x.Equals(edge)))
+          identicalEdges++;
+      }
+
+      return identicalEdges * 2.0 / (edges1.Count + edges2.Count);
+    }
+
+    public override double CalculateSolutionSimilarity(IScope leftSolution, IScope rightSolution) {
+      var sol1 = leftSolution.Variables[SolutionVariableName].Value as IVRPEncoding;
+      var sol2 = rightSolution.Variables[SolutionVariableName].Value as IVRPEncoding;
+
+      var potvinSol1 = sol1 is PotvinEncoding ? sol1 as PotvinEncoding : PotvinEncoding.ConvertFrom(sol1, ProblemInstance);
+      var potvinSol2 = sol2 is PotvinEncoding ? sol2 as PotvinEncoding : PotvinEncoding.ConvertFrom(sol2, ProblemInstance);
+
+      return CalculateSimilarity(potvinSol1, potvinSol2);
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/SolutionParser.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/SolutionParser.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/SolutionParser.cs	(revision 14416)
@@ -0,0 +1,63 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  class SolutionParser {
+    private string file;
+
+    private List<List<int>> routes;
+
+    public List<List<int>> Routes {
+      get {
+        return routes;
+      }
+    }
+
+    public SolutionParser(string file) {
+      this.file = file;
+      this.routes = new List<List<int>>();
+    }
+
+    public void Parse() {
+      this.routes.Clear();
+      using (StreamReader reader = new StreamReader(file)) {
+        String line;
+        while ((line = reader.ReadLine()) != null) {
+          string[] token = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
+
+          if (token.Length > 2) {
+            List<int> route = new List<int>();
+
+            for (int i = 2; i < token.Length; i++) {
+              route.Add(int.Parse(token[i]));
+            }
+
+            routes.Add(route);
+          }
+        }
+      }
+    }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/Capacitated/Heterogenous/IHeterogenousCapacitatedOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/Capacitated/Heterogenous/IHeterogenousCapacitatedOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/Capacitated/Heterogenous/IHeterogenousCapacitatedOperator.cs	(revision 14416)
@@ -0,0 +1,26 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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
+
+
+namespace HeuristicLab.Problems.VehicleRouting.Variants {
+  public interface IHeterogenousCapacitatedOperator : IHomogenousCapacitatedOperator {
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/Capacitated/Heterogenous/IHeterogenousCapacitatedProblemInstance.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/Capacitated/Heterogenous/IHeterogenousCapacitatedProblemInstance.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/Capacitated/Heterogenous/IHeterogenousCapacitatedProblemInstance.cs	(revision 14416)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Data;
+
+namespace HeuristicLab.Problems.VehicleRouting.Variants {
+  public interface IHeterogenousCapacitatedProblemInstance : ICapacitatedProblemInstance {
+    DoubleArray Capacity { get; }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/Capacitated/Homogenous/IHomogenousCapacitatedOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/Capacitated/Homogenous/IHomogenousCapacitatedOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/Capacitated/Homogenous/IHomogenousCapacitatedOperator.cs	(revision 14416)
@@ -0,0 +1,26 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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
+
+
+namespace HeuristicLab.Problems.VehicleRouting.Variants {
+  public interface IHomogenousCapacitatedOperator : ICapacitatedOperator {
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/Capacitated/Homogenous/IHomogenousCapacitatedProblemInstance.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/Capacitated/Homogenous/IHomogenousCapacitatedProblemInstance.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/Capacitated/Homogenous/IHomogenousCapacitatedProblemInstance.cs	(revision 14416)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Data;
+
+namespace HeuristicLab.Problems.VehicleRouting.Variants {
+  public interface IHomogenousCapacitatedProblemInstance : ICapacitatedProblemInstance {
+    DoubleValue Capacity { get; }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/Capacitated/ICapacitatedOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/Capacitated/ICapacitatedOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/Capacitated/ICapacitatedOperator.cs	(revision 14416)
@@ -0,0 +1,27 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Variants {
+  public interface ICapacitatedOperator : IVRPOperator {
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/Capacitated/ICapacitatedProblemInstance.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/Capacitated/ICapacitatedProblemInstance.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/Capacitated/ICapacitatedProblemInstance.cs	(revision 14416)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Data;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Variants {
+  public interface ICapacitatedProblemInstance : IVRPProblemInstance {
+    DoubleValue OverloadPenalty { get; }
+    DoubleValue CurrentOverloadPenalty { get; set; }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/General/IGeneralVRPOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/General/IGeneralVRPOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/General/IGeneralVRPOperator.cs	(revision 14416)
@@ -0,0 +1,27 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Variants {
+  public interface IGeneralVRPOperator : IVRPOperator {
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/MultiDepot/IMultiDepotOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/MultiDepot/IMultiDepotOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/MultiDepot/IMultiDepotOperator.cs	(revision 14416)
@@ -0,0 +1,27 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Variants {
+  public interface IMultiDepotOperator : IVRPOperator {
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/MultiDepot/IMultiDepotProblemInstance.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/MultiDepot/IMultiDepotProblemInstance.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/MultiDepot/IMultiDepotProblemInstance.cs	(revision 14416)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Data;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Variants {
+  public interface IMultiDepotProblemInstance : IVRPProblemInstance {
+    IntValue Depots { get; }
+    IntArray VehicleDepotAssignment { get; }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/PickupAndDelivery/IPickupAndDeliveryOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/PickupAndDelivery/IPickupAndDeliveryOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/PickupAndDelivery/IPickupAndDeliveryOperator.cs	(revision 14416)
@@ -0,0 +1,27 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Variants {
+  public interface IPickupAndDeliveryOperator : IVRPOperator {
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/PickupAndDelivery/IPickupAndDeliveryProblemInstance.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/PickupAndDelivery/IPickupAndDeliveryProblemInstance.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/PickupAndDelivery/IPickupAndDeliveryProblemInstance.cs	(revision 14416)
@@ -0,0 +1,33 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Data;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Variants {
+  public interface IPickupAndDeliveryProblemInstance : IVRPProblemInstance {
+    IntArray PickupDeliveryLocation { get; }
+    DoubleValue PickupViolationPenalty { get; }
+    DoubleValue CurrentPickupViolationPenalty { get; set; }
+
+    int GetPickupDeliveryLocation(int city);
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/SingleDepot/ISingleDepotOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/SingleDepot/ISingleDepotOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/SingleDepot/ISingleDepotOperator.cs	(revision 14416)
@@ -0,0 +1,27 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Variants {
+  public interface ISingleDepotOperator : IVRPOperator {
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/SingleDepot/ISingleDepotProblemInstance.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/SingleDepot/ISingleDepotProblemInstance.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/SingleDepot/ISingleDepotProblemInstance.cs	(revision 14416)
@@ -0,0 +1,27 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Variants {
+  public interface ISingleDepotProblemInstance : IVRPProblemInstance {
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/TimeWindowed/ITimeWindowedOperator.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/TimeWindowed/ITimeWindowedOperator.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/TimeWindowed/ITimeWindowedOperator.cs	(revision 14416)
@@ -0,0 +1,27 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Variants {
+  public interface ITimeWindowedOperator : IVRPOperator {
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/TimeWindowed/ITimeWindowedProblemInstance.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/TimeWindowed/ITimeWindowedProblemInstance.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Variants/TimeWindowed/ITimeWindowedProblemInstance.cs	(revision 14416)
@@ -0,0 +1,34 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Data;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Variants {
+  public interface ITimeWindowedProblemInstance : IVRPProblemInstance {
+    DoubleArray ReadyTime { get; }
+    DoubleArray DueTime { get; }
+    DoubleArray ServiceTime { get; }
+    DoubleValue TimeFactor { get; }
+    DoubleValue TardinessPenalty { get; }
+    DoubleValue CurrentTardinessPenalty { get; set; }
+  }
+}
Index: /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/VehicleRoutingProblem.cs
===================================================================
--- /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/VehicleRoutingProblem.cs	(revision 14416)
+++ /branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/VehicleRoutingProblem.cs	(revision 14416)
@@ -0,0 +1,410 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Drawing;
+using System.Linq;
+using HeuristicLab.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+using HeuristicLab.Problems.Instances;
+using HeuristicLab.Problems.VehicleRouting.Encodings.Alba;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Interpreters;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  [Item("Vehicle Routing Problem (VRP)", "Represents a Vehicle Routing Problem.")]
+  [Creatable(CreatableAttribute.Categories.CombinatorialProblems, Priority = 110)]
+  [StorableClass]
+  public sealed class VehicleRoutingProblem : Problem, ISingleObjectiveHeuristicOptimizationProblem, IStorableContent, IProblemInstanceConsumer<IVRPData> {
+    public string Filename { get; set; }
+
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Type; }
+    }
+
+    #region Parameter Properties
+    public ValueParameter<BoolValue> MaximizationParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    IParameter ISingleObjectiveHeuristicOptimizationProblem.MaximizationParameter {
+      get { return MaximizationParameter; }
+    }
+    public ValueParameter<IVRPProblemInstance> ProblemInstanceParameter {
+      get { return (ValueParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
+    }
+    public OptionalValueParameter<DoubleValue> BestKnownQualityParameter {
+      get { return (OptionalValueParameter<DoubleValue>)Parameters["BestKnownQuality"]; }
+    }
+    IParameter ISingleObjectiveHeuristicOptimizationProblem.BestKnownQualityParameter {
+      get { return BestKnownQualityParameter; }
+    }
+    public OptionalValueParameter<VRPSolution> BestKnownSolutionParameter {
+      get { return (OptionalValueParameter<VRPSolution>)Parameters["BestKnownSolution"]; }
+    }
+    public IConstrainedValueParameter<IVRPCreator> SolutionCreatorParameter {
+      get { return (IConstrainedValueParameter<IVRPCreator>)Parameters["SolutionCreator"]; }
+    }
+    IParameter IHeuristicOptimizationProblem.SolutionCreatorParameter {
+      get { return SolutionCreatorParameter; }
+    }
+    public IValueParameter<IVRPEvaluator> EvaluatorParameter {
+      get { return (IValueParameter<IVRPEvaluator>)Parameters["Evaluator"]; }
+    }
+    IParameter IHeuristicOptimizationProblem.EvaluatorParameter {
+      get { return EvaluatorParameter; }
+    }
+    #endregion
+
+    #region Properties
+    public IVRPProblemInstance ProblemInstance {
+      get { return ProblemInstanceParameter.Value; }
+      set { ProblemInstanceParameter.Value = value; }
+    }
+
+    public VRPSolution BestKnownSolution {
+      get { return BestKnownSolutionParameter.Value; }
+      set { BestKnownSolutionParameter.Value = value; }
+    }
+
+    public DoubleValue BestKnownQuality {
+      get { return BestKnownQualityParameter.Value; }
+      set { BestKnownQualityParameter.Value = value; }
+    }
+
+    public ISingleObjectiveEvaluator Evaluator {
+      get { return EvaluatorParameter.Value; }
+    }
+
+    IEvaluator IHeuristicOptimizationProblem.Evaluator {
+      get { return this.Evaluator; }
+    }
+
+    ISolutionCreator IHeuristicOptimizationProblem.SolutionCreator {
+      get { return SolutionCreatorParameter.Value; }
+    }
+    public IVRPCreator SolutionCreator {
+      get { return SolutionCreatorParameter.Value; }
+      set { SolutionCreatorParameter.Value = value; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private VehicleRoutingProblem(bool deserializing) : base(deserializing) { }
+    public VehicleRoutingProblem()
+      : base() {
+      Parameters.Add(new ValueParameter<BoolValue>("Maximization", "Set to false as the Vehicle Routing Problem is a minimization problem.", new BoolValue(false)));
+      Parameters.Add(new ValueParameter<IVRPProblemInstance>("ProblemInstance", "The VRP problem instance"));
+      Parameters.Add(new OptionalValueParameter<DoubleValue>("BestKnownQuality", "The quality of the best known solution of this VRP instance."));
+      Parameters.Add(new OptionalValueParameter<VRPSolution>("BestKnownSolution", "The best known solution of this VRP instance."));
+
+      Parameters.Add(new ConstrainedValueParameter<IVRPCreator>("SolutionCreator", "The operator which should be used to create new VRP solutions."));
+      Parameters.Add(new ValueParameter<IVRPEvaluator>("Evaluator", "The operator which should be used to evaluate VRP solutions."));
+
+      EvaluatorParameter.Hidden = true;
+
+      InitializeRandomVRPInstance();
+      InitializeOperators();
+
+      AttachEventHandlers();
+      AttachProblemInstanceEventHandlers();
+
+      EvaluatorParameter.Value = ProblemInstance.SolutionEvaluator;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      cloner.Clone(ProblemInstance);
+      return new VehicleRoutingProblem(this, cloner);
+    }
+
+    private VehicleRoutingProblem(VehicleRoutingProblem original, Cloner cloner)
+      : base(original, cloner) {
+      this.AttachEventHandlers();
+      this.AttachProblemInstanceEventHandlers();
+
+      ProblemInstance.SolutionEvaluator = EvaluatorParameter.Value;
+    }
+
+    #region Events
+    public event EventHandler SolutionCreatorChanged;
+    private void OnSolutionCreatorChanged() {
+      EventHandler handler = SolutionCreatorChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler EvaluatorChanged;
+    private void OnEvaluatorChanged() {
+      EventHandler handler = EvaluatorChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    #endregion
+
+    #region Helpers
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      AttachEventHandlers();
+      AttachProblemInstanceEventHandlers();
+
+      ProblemInstance.SolutionEvaluator = EvaluatorParameter.Value;
+    }
+
+    [Storable(Name = "operators", AllowOneWay = true)]
+    private List<IOperator> StorableOperators {
+      set { Operators.AddRange(value); }
+    }
+
+    private void AttachEventHandlers() {
+      ProblemInstanceParameter.ValueChanged += new EventHandler(ProblemInstanceParameter_ValueChanged);
+      BestKnownSolutionParameter.ValueChanged += new EventHandler(BestKnownSolutionParameter_ValueChanged);
+      EvaluatorParameter.ValueChanged += new EventHandler(EvaluatorParameter_ValueChanged);
+      SolutionCreatorParameter.ValueChanged += new EventHandler(SolutionCreatorParameter_ValueChanged);
+    }
+
+    private void AttachProblemInstanceEventHandlers() {
+      if (ProblemInstance != null) {
+        ProblemInstance.EvaluationChanged += new EventHandler(ProblemInstance_EvaluationChanged);
+      }
+    }
+
+    private void EvalBestKnownSolution() {
+      if (BestKnownSolution != null) {
+        //call evaluator
+        BestKnownQuality = new DoubleValue(ProblemInstance.Evaluate(BestKnownSolution.Solution).Quality);
+        BestKnownSolution.Quality = BestKnownQuality;
+      } else {
+        BestKnownQuality = null;
+      }
+    }
+
+    void BestKnownSolutionParameter_ValueChanged(object sender, EventArgs e) {
+      EvalBestKnownSolution();
+    }
+
+    void ProblemInstance_EvaluationChanged(object sender, EventArgs e) {
+      EvalBestKnownSolution();
+    }
+
+    void ProblemInstanceParameter_ValueChanged(object sender, EventArgs e) {
+      InitializeOperators();
+      AttachProblemInstanceEventHandlers();
+
+      EvaluatorParameter.Value = ProblemInstance.SolutionEvaluator;
+
+      OnSolutionCreatorChanged();
+      OnEvaluatorChanged();
+      OnOperatorsChanged();
+    }
+
+    public void SetProblemInstance(IVRPProblemInstance instance) {
+      ProblemInstanceParameter.ValueChanged -= new EventHandler(ProblemInstanceParameter_ValueChanged);
+
+      ProblemInstance = instance;
+      AttachProblemInstanceEventHandlers();
+
+      OnSolutionCreatorChanged();
+      OnEvaluatorChanged();
+
+      ProblemInstanceParameter.ValueChanged += new EventHandler(ProblemInstanceParameter_ValueChanged);
+    }
+
+    private void SolutionCreatorParameter_ValueChanged(object sender, EventArgs e) {
+      OnSolutionCreatorChanged();
+    }
+    private void EvaluatorParameter_ValueChanged(object sender, EventArgs e) {
+      if (ProblemInstance != null)
+        ProblemInstance.SolutionEvaluator = EvaluatorParameter.Value;
+      OnEvaluatorChanged();
+    }
+
+    private void InitializeOperators() {
+      var solutionCreatorParameter = SolutionCreatorParameter as ConstrainedValueParameter<IVRPCreator>;
+      solutionCreatorParameter.ValidValues.Clear();
+
+      Operators.Clear();
+
+      if (ProblemInstance != null) {
+        Operators.AddRange(
+        ProblemInstance.Operators.Concat(
+          ApplicationManager.Manager.GetInstances<IGeneralVRPOperator>().Cast<IOperator>()).OrderBy(op => op.Name));
+        Operators.Add(new VRPSimilarityCalculator());
+        Operators.Add(new QualitySimilarityCalculator());
+        Operators.Add(new NoSimilarityCalculator());
+        Operators.Add(new PopulationSimilarityAnalyzer(Operators.OfType<ISolutionSimilarityCalculator>()));
+
+        IVRPCreator defaultCreator = null;
+        foreach (IVRPCreator creator in Operators.Where(o => o is IVRPCreator)) {
+          solutionCreatorParameter.ValidValues.Add(creator);
+          if (creator is Encodings.Alba.RandomCreator)
+            defaultCreator = creator;
+        }
+        Operators.Add(new AlbaLambdaInterchangeLocalImprovementOperator());
+        if (defaultCreator != null)
+          solutionCreatorParameter.Value = defaultCreator;
+      }
+
+      ParameterizeOperators();
+    }
+
+    private void ParameterizeOperators() {
+      foreach (IOperator op in Operators.OfType<IOperator>()) {
+        if (op is IMultiVRPOperator) {
+          (op as IMultiVRPOperator).SetOperators(Operators.OfType<IOperator>());
+        }
+      }
+      if (ProblemInstance != null) {
+        foreach (ISingleObjectiveImprovementOperator op in Operators.OfType<ISingleObjectiveImprovementOperator>()) {
+          op.SolutionParameter.ActualName = SolutionCreator.VRPToursParameter.ActualName;
+          op.SolutionParameter.Hidden = true;
+        }
+        foreach (ISingleObjectivePathRelinker op in Operators.OfType<ISingleObjectivePathRelinker>()) {
+          op.ParentsParameter.ActualName = SolutionCreator.VRPToursParameter.ActualName;
+          op.ParentsParameter.Hidden = true;
+        }
+        foreach (ISolutionSimilarityCalculator op in Operators.OfType<ISolutionSimilarityCalculator>()) {
+          op.SolutionVariableName = SolutionCreator.VRPToursParameter.ActualName;
+          op.QualityVariableName = ProblemInstance.SolutionEvaluator.QualityParameter.ActualName;
+          var calc = op as VRPSimilarityCalculator;
+          if (calc != null) calc.ProblemInstance = ProblemInstance;
+        }
+      }
+    }
+
+    #endregion
+
+    private void InitializeRandomVRPInstance() {
+      System.Random rand = new System.Random();
+
+      CVRPTWProblemInstance problem = new CVRPTWProblemInstance();
+      int cities = 100;
+
+      problem.Coordinates = new DoubleMatrix(cities + 1, 2);
+      problem.Demand = new DoubleArray(cities + 1);
+      problem.DueTime = new DoubleArray(cities + 1);
+      problem.ReadyTime = new DoubleArray(cities + 1);
+      problem.ServiceTime = new DoubleArray(cities + 1);
+
+      problem.Vehicles.Value = 100;
+      problem.Capacity.Value = 200;
+
+      for (int i = 0; i <= cities; i++) {
+        problem.Coordinates[i, 0] = rand.Next(0, 100);
+        problem.Coordinates[i, 1] = rand.Next(0, 100);
+
+        if (i == 0) {
+          problem.Demand[i] = 0;
+          problem.DueTime[i] = Int16.MaxValue;
+          problem.ReadyTime[i] = 0;
+          problem.ServiceTime[i] = 0;
+        } else {
+          problem.Demand[i] = rand.Next(10, 50);
+          problem.DueTime[i] = rand.Next((int)Math.Ceiling(problem.GetDistance(0, i, null)), 1200);
+          problem.ReadyTime[i] = problem.DueTime[i] - rand.Next(0, 100);
+          problem.ServiceTime[i] = 90;
+        }
+      }
+
+      this.ProblemInstance = problem;
+    }
+
+    public void ImportSolution(string solutionFileName) {
+      SolutionParser parser = new SolutionParser(solutionFileName);
+      parser.Parse();
+
+      HeuristicLab.Problems.VehicleRouting.Encodings.Potvin.PotvinEncoding encoding = new Encodings.Potvin.PotvinEncoding(ProblemInstance);
+
+      int cities = 0;
+      foreach (List<int> route in parser.Routes) {
+        Tour tour = new Tour();
+        tour.Stops.AddRange(route);
+        cities += tour.Stops.Count;
+
+        encoding.Tours.Add(tour);
+      }
+
+      if (cities != ProblemInstance.Coordinates.Rows - 1)
+        ErrorHandling.ShowErrorDialog(new Exception("The optimal solution does not seem to correspond with the problem data"));
+      else {
+        VRPSolution solution = new VRPSolution(ProblemInstance, encoding, new DoubleValue(0));
+        BestKnownSolutionParameter.Value = solution;
+      }
+    }
+
+    #region Instance Consuming
+    public void Load(IVRPData data, IVRPDataInterpreter interpreter) {
+      VRPInstanceDescription instance = interpreter.Interpret(data);
+
+      Name = instance.Name;
+      Description = instance.Description;
+
+      BestKnownQuality = null;
+      BestKnownSolution = null;
+
+      if (ProblemInstance != null && instance.ProblemInstance != null &&
+        instance.ProblemInstance.GetType() == ProblemInstance.GetType())
+        SetProblemInstance(instance.ProblemInstance);
+      else
+        ProblemInstance = instance.ProblemInstance;
+
+      OnReset();
+
+      if (instance.BestKnownQuality != null) {
+        BestKnownQuality = new DoubleValue((double)instance.BestKnownQuality);
+      }
+
+      if (instance.BestKnownSolution != null) {
+        VRPSolution solution = new VRPSolution(ProblemInstance, instance.BestKnownSolution, new DoubleValue(0));
+        BestKnownSolution = solution;
+      }
+    }
+    #endregion
+
+    #region IProblemInstanceConsumer<VRPData> Members
+
+    public void Load(IVRPData data) {
+      var interpreterDataType = data.GetType();
+      var interpreterType = typeof(IVRPDataInterpreter<>).MakeGenericType(interpreterDataType);
+
+      var interpreters = ApplicationManager.Manager.GetTypes(interpreterType);
+
+      var concreteInterpreter = interpreters.Single(t => GetInterpreterDataType(t) == interpreterDataType);
+
+      Load(data, (IVRPDataInterpreter)Activator.CreateInstance(concreteInterpreter));
+    }
+
+    private Type GetInterpreterDataType(Type type) {
+      var parentInterfaces = type.BaseType.GetInterfaces();
+      var interfaces = type.GetInterfaces().Except(parentInterfaces);
+
+      var interpreterInterface = interfaces.Single(i => typeof(IVRPDataInterpreter).IsAssignableFrom(i));
+      return interpreterInterface.GetGenericArguments()[0];
+    }
+
+    #endregion
+  }
+}
