Index: /trunk/sources/HeuristicLab.Problems.VehicleRouting/3.4/HeuristicLab.Problems.VehicleRouting-3.4.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Problems.VehicleRouting/3.4/HeuristicLab.Problems.VehicleRouting-3.4.csproj	(revision 8893)
+++ /trunk/sources/HeuristicLab.Problems.VehicleRouting/3.4/HeuristicLab.Problems.VehicleRouting-3.4.csproj	(revision 8894)
@@ -141,4 +141,5 @@
     <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" />
@@ -474,5 +475,5 @@
   -->
   <PropertyGroup>
-   <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+    <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
 set ProjectDir=$(ProjectDir)
 set SolutionDir=$(SolutionDir)
@@ -480,5 +481,5 @@
 
 call PreBuildEvent.cmd</PreBuildEvent>
-<PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
+    <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
 export ProjectDir=$(ProjectDir)
 export SolutionDir=$(SolutionDir)
Index: /trunk/sources/HeuristicLab.Problems.VehicleRouting/3.4/Improver/VRPImprovementOperator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.VehicleRouting/3.4/Improver/VRPImprovementOperator.cs	(revision 8893)
+++ /trunk/sources/HeuristicLab.Problems.VehicleRouting/3.4/Improver/VRPImprovementOperator.cs	(revision 8894)
@@ -28,5 +28,4 @@
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 using HeuristicLab.Problems.VehicleRouting.Encodings;
-using HeuristicLab.Problems.VehicleRouting.Encodings.Alba;
 using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
 using HeuristicLab.Problems.VehicleRouting.Interfaces;
@@ -35,9 +34,9 @@
 namespace HeuristicLab.Problems.VehicleRouting {
   /// <summary>
-  /// An operator that improves vehicle routing solutions.
+  /// A base class for operators which improve VRP solutions.
   /// </summary>
-  [Item("VRPImprovementOperator", "An operator that improves vehicle routing solutions.")]
+  [Item("VRPImprovementOperator", "A base class for operators which improve VRP solutions.")]
   [StorableClass]
-  public sealed class VRPImprovementOperator : VRPOperator, IGeneralVRPOperator, ISingleObjectiveImprovementOperator {
+  public abstract class VRPImprovementOperator : VRPOperator, IGeneralVRPOperator, ISingleObjectiveImprovementOperator {
     #region Parameter properties
     public ScopeParameter CurrentScopeParameter {
@@ -47,6 +46,6 @@
       get { return (IValueParameter<IntValue>)Parameters["ImprovementAttempts"]; }
     }
-    public IValueParameter<IntValue> LambdaParameter {
-      get { return (IValueParameter<IntValue>)Parameters["Lambda"]; }
+    public IValueLookupParameter<IntValue> LocalEvaluatedSolutions {
+      get { return (IValueLookupParameter<IntValue>)Parameters["LocalEvaluatedSolutions"]; }
     }
     public ILookupParameter<IRandom> RandomParameter {
@@ -62,43 +61,34 @@
 
     [StorableConstructor]
-    private VRPImprovementOperator(bool deserializing) : base(deserializing) { }
-    private VRPImprovementOperator(VRPImprovementOperator original, Cloner cloner) : base(original, cloner) { }
-    public VRPImprovementOperator()
+    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 ValueParameter<IntValue>("Lambda", "The number of neighbors that should be exchanged.", new IntValue(1)));
+      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(100)));
+      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 IDeepCloneable Clone(Cloner cloner) {
-      return new VRPImprovementOperator(this, cloner);
-    }
-
     public override IOperation Apply() {
-      AlbaEncoding solution = SolutionParameter.ActualValue is AlbaEncoding
-                                ? SolutionParameter.ActualValue as AlbaEncoding
-                                : AlbaEncoding.ConvertFrom(SolutionParameter.ActualValue as IVRPEncoding, ProblemInstance);
+      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.");
 
-      double quality = -1;
-      int evaluatedSolutions;
+      int evaluatedSolutions = Improve(potvinSolution);
 
-      AlbaLambdaInterchangeLocalImprovementOperator.Apply(solution, ImprovementAttemptsParameter.Value.Value,
-                                                          LambdaParameter.Value.Value, SampleSizeParameter.Value.Value,
-                                                          RandomParameter.ActualValue, ProblemInstance, ref quality,
-                                                          out evaluatedSolutions);
-
-      SolutionParameter.ActualValue = PotvinEncoding.ConvertFrom(solution, ProblemInstance);
-      CurrentScopeParameter.ActualValue.Variables.Add(new Variable("LocalEvaluatedSolutions", new IntValue(evaluatedSolutions)));
+      SolutionParameter.ActualValue = solution;
+      LocalEvaluatedSolutions.ActualValue = new IntValue(evaluatedSolutions);
 
       return base.Apply();
     }
+
+    protected abstract int Improve(PotvinEncoding solution);
   }
 }
Index: /trunk/sources/HeuristicLab.Problems.VehicleRouting/3.4/Improver/VRPIntraRouteImprovementOperator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.VehicleRouting/3.4/Improver/VRPIntraRouteImprovementOperator.cs	(revision 8894)
+++ /trunk/sources/HeuristicLab.Problems.VehicleRouting/3.4/Improver/VRPIntraRouteImprovementOperator.cs	(revision 8894)
@@ -0,0 +1,98 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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(VRPImprovementOperator 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: /trunk/sources/HeuristicLab.Problems.VehicleRouting/3.4/PathRelinkers/VRPPathRelinker.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.VehicleRouting/3.4/PathRelinkers/VRPPathRelinker.cs	(revision 8893)
+++ /trunk/sources/HeuristicLab.Problems.VehicleRouting/3.4/PathRelinkers/VRPPathRelinker.cs	(revision 8894)
@@ -37,21 +37,21 @@
 namespace HeuristicLab.Problems.VehicleRouting {
   /// <summary>
-  /// An operator that relinks paths between vehicle routing solutions.
+  /// An operator which relinks paths between VRP solutions.
   /// </summary>
-  [Item("VRPPathRelinker", "An operator that relinks paths between vehicle routing solutions.")]
+  [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 ILookupParameter<IVRPProblemInstance> ProblemInstanceParameter {
-      get { return (ILookupParameter<IVRPProblemInstance>)Parameters["ProblemInstance"]; }
-    }
     public IValueParameter<IntValue> SampleSizeParameter {
       get { return (IValueParameter<IntValue>)Parameters["SampleSize"]; }
-    }
-    public IValueParameter<IntValue> IterationsParameter {
-      get { return (IValueParameter<IntValue>)Parameters["Iterations"]; }
     }
     #endregion
@@ -62,8 +62,8 @@
     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 LookupParameter<IVRPProblemInstance>("ProblemInstance", "The VRP problem instance"));
       Parameters.Add(new ValueParameter<IntValue>("SampleSize", "The number of moves that should be executed.", new IntValue(10)));
-      Parameters.Add(new ValueParameter<IntValue>("Iterations", "The number of iterations the operator should perform.", new IntValue(50)));
     }
 
@@ -72,4 +72,117 @@
     }
 
+    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();
@@ -77,7 +190,7 @@
 
     private static PotvinEncoding MatchTours(PotvinEncoding initiator, PotvinEncoding guide, IVRPProblemInstance problemInstance) {
-      PotvinEncoding result = new PotvinEncoding(problemInstance);
-
-      List<bool> used = new List<bool>();
+      var result = new PotvinEncoding(problemInstance);
+
+      var used = new List<bool>();
       for (int i = 0; i < initiator.Tours.Count; i++) {
         used.Add(false);
@@ -120,5 +233,4 @@
       return PotvinSequenceBasedCrossover.Apply(random, initiator, guide, problemInstance, false);
     }
-
 
     public static void GuidedRelocateMove(PotvinEncoding initiator, PotvinEncoding guide, IRandom random) {
@@ -208,242 +320,5 @@
       individual.Tours.RemoveAll(t => t.Stops.Count == 0);
     }
-
-    public static void ExchangeMove(PotvinEncoding individual, IRandom random) {
-      if (individual.Tours.Count > 1) {
-        int tour1Idx = random.Next(individual.Tours.Count);
-        int tour2Idx = random.Next(individual.Tours.Count - 1);
-        if (tour2Idx >= tour1Idx)
-          tour2Idx++;
-
-        Tour tour1 = individual.Tours[tour1Idx];
-        Tour tour2 = individual.Tours[tour2Idx];
-
-        int index1 = random.Next(tour1.Stops.Count);
-        int city1 = tour1.Stops[index1];
-
-        int index2 = random.Next(tour2.Stops.Count);
-        int city2 = tour2.Stops[index2];
-
-        tour1.Stops.RemoveAt(index1);
-        tour1.Stops.Insert(index1, city2);
-
-        tour2.Stops.RemoveAt(index2);
-        tour2.Stops.Insert(index2, city1);
-      }
-    }
-
-    public static void TwoOptMove(PotvinEncoding individual, IRandom random) {
-      List<Tour> tours = individual.Tours.FindAll(t => t.Stops.Count >= 4);
-
-      if (tours.Count > 0) {
-        int tourIdx = random.Next(tours.Count);
-        Tour tour = tours[tourIdx];
-
-        int a;
-        if (tour.Stops.Count == 4) {
-          a = 0;
-        } else if (tour.Stops.Count == 5) {
-          int idx = random.Next(4);
-          if (idx >= 2)
-            idx++;
-          a = idx;
-        } else {
-          a = random.Next(tour.Stops.Count);
-        }
-
-        int b;
-        List<int> indices = new List<int>();
-        for (int i = 0; i < tour.Stops.Count; i++) {
-          if (Math.Abs(i - a) > 2) {
-            indices.Add(i);
-          }
-        }
-        b = indices[random.Next(indices.Count)];
-
-        if (b < a) {
-          int tmp = a;
-          a = b;
-          b = tmp;
-        }
-
-        int index = a + 1;
-        int count = b - a - 1;
-        List<int> segment = tour.Stops.GetRange(index, count);
-        tour.Stops.RemoveRange(index, count);
-        segment.Reverse();
-        tour.Stops.InsertRange(index, segment);
-      }
-    }
-
-    public static void TwoOptStarMove(PotvinEncoding individual, IRandom random) {
-      //consider creating new tour
-      individual.Tours.Add(new Tour());
-
-      int route1Idx = random.Next(individual.Tours.Count);
-      int route2Idx = random.Next(individual.Tours.Count - 1);
-      if (route2Idx >= route1Idx)
-        route2Idx++;
-
-      Tour route1 = individual.Tours[route1Idx];
-      Tour route2 = individual.Tours[route2Idx];
-
-      int x1 = random.Next(route1.Stops.Count + 1);
-      int x2 = random.Next(route2.Stops.Count + 1);
-
-      int count = route1.Stops.Count - x1;
-      List<int> segmentX1 = new List<int>();
-      if (count > 0) {
-        segmentX1 = route1.Stops.GetRange(x1, count);
-        route1.Stops.RemoveRange(x1, count);
-      }
-
-      count = route2.Stops.Count - x2;
-      List<int> segmentX2 = new List<int>();
-      if (count > 0) {
-        segmentX2 = route2.Stops.GetRange(x2, count);
-        route2.Stops.RemoveRange(x2, count);
-      }
-
-      route1.Stops.AddRange(segmentX2);
-      route2.Stops.AddRange(segmentX1);
-
-      individual.Tours.RemoveAll(t => t.Stops.Count == 0);
-    }
-
-    public static void OrOptMove(PotvinEncoding individual, IRandom random) {
-      List<Tour> tours = individual.Tours.FindAll(t => t.Stops.Count >= 2);
-
-      if (tours.Count > 0) {
-        int tourIdx = random.Next(tours.Count);
-        Tour tour = tours[tourIdx];
-
-        int segmentStart = random.Next(tour.Stops.Count);
-        int segmentLength;
-        if (segmentStart == 0) {
-          segmentLength = 1 + random.Next(tour.Stops.Count - 1);
-        } else {
-          segmentLength = 1 + random.Next(tour.Stops.Count - segmentStart);
-        }
-
-        List<int> segment = tour.Stops.GetRange(segmentStart, segmentLength);
-        tour.Stops.RemoveRange(segmentStart, segmentLength);
-        int newPos;
-        if (tour.Stops.Count == 1)
-          newPos = 0;
-        else
-          newPos = random.Next(tour.Stops.Count - 1);
-
-        if (newPos >= segmentStart)
-          newPos++;
-        tour.Stops.InsertRange(newPos, segment);
-      }
-    }
     #endregion
-
-    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;
-    }
-
-    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;
-
-      DoubleValue originalOverloadPenalty = new DoubleValue();
-      if (problemInstance is IHomogenousCapacitatedProblemInstance)
-        originalOverloadPenalty.Value = (problemInstance as IHomogenousCapacitatedProblemInstance).OverloadPenalty.Value;
-      DoubleValue 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 != 1.0) {
-        VRPEvaluation currentEval = problemInstance.Evaluate(current);
-        currentSimilarity = VRPSimilarityCalculator.CalculateSimilarity(current, guide);
-
-        if (currentSimilarity < 1.0) {
-          for (int sample = 0; sample < sampleSize; sample++) {
-            PotvinEncoding next = current.Clone() as PotvinEncoding;
-
-            int neighborhood = rand.Next(4);
-            switch (neighborhood) {
-              case 0: next = RouteBasedXOver(next, guide, rand,
-                problemInstance);
-                break;
-              case 1: next = SequenceBasedXOver(next, guide, rand,
-                problemInstance);
-                break;
-              case 2: TwoOptMove(next, rand);
-                break;
-              case 3: GuidedRelocateMove(next, guide, rand);
-                break;
-            }
-
-            next = MatchTours(next, guide, problemInstance);
-
-            VRPEvaluation nextEval = problemInstance.Evaluate(next);
-            double nextSimilarity = VRPSimilarityCalculator.CalculateSimilarity(next, guide);
-
-            if (nextSimilarity > currentSimilarity && nextEval.Quality <= currentEval.Quality) {
-              current = next;
-              solutions.Add(current);
-              break;
-            }
-          }
-
-          if (problemInstance is IHomogenousCapacitatedProblemInstance) {
-            if (((CVRPEvaluation)currentEval).Overload > 0)
-              (problemInstance as IHomogenousCapacitatedProblemInstance).OverloadPenalty.Value *= sigma;
-            else
-              (problemInstance as IHomogenousCapacitatedProblemInstance).OverloadPenalty.Value /= sigma;
-          }
-
-
-          if (problemInstance is ITimeWindowedProblemInstance) {
-            if (((CVRPTWEvaluation)currentEval).Tardiness > 0)
-              (problemInstance as ITimeWindowedProblemInstance).TardinessPenalty.Value *= sigma;
-            else
-              (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));
-    }
-
-    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);
-    }
   }
 }
Index: /trunk/sources/HeuristicLab.Problems.VehicleRouting/3.4/SimilarityCalculators/VRPSimilarityCalculator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.VehicleRouting/3.4/SimilarityCalculators/VRPSimilarityCalculator.cs	(revision 8893)
+++ /trunk/sources/HeuristicLab.Problems.VehicleRouting/3.4/SimilarityCalculators/VRPSimilarityCalculator.cs	(revision 8894)
@@ -32,10 +32,10 @@
 namespace HeuristicLab.Problems.VehicleRouting {
   /// <summary>
-  /// An operator that performs similarity calculation between two vehicle routing solutions.
+  /// 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 that performs similarity calculation between two vehicle routing solutions.")]
+  [Item("VRPSimilarityCalculator", "An operator which performs similarity calculation between two VRP solutions.")]
   [StorableClass]
   public sealed class VRPSimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator {
Index: /trunk/sources/HeuristicLab.Tests/HeuristicLab-3.3/SamplesTest.cs
===================================================================
--- /trunk/sources/HeuristicLab.Tests/HeuristicLab-3.3/SamplesTest.cs	(revision 8893)
+++ /trunk/sources/HeuristicLab.Tests/HeuristicLab-3.3/SamplesTest.cs	(revision 8894)
@@ -968,14 +968,14 @@
       ss.SetSeedRandomly.Value = false;
       RunAlgorithm(ss);
-      Assert.AreEqual(749, GetDoubleResult(ss, "BestQuality"));
-      Assert.AreEqual(766.95, GetDoubleResult(ss, "CurrentAverageQuality"));
-      Assert.AreEqual(789, GetDoubleResult(ss, "CurrentWorstQuality"));
-      Assert.AreEqual(27400, GetIntResult(ss, "EvaluatedSolutions"));
+      Assert.AreEqual(828.93686694283383, GetDoubleResult(ss, "BestQuality"));
+      Assert.AreEqual(868.63623986983077, GetDoubleResult(ss, "CurrentAverageQuality"));
+      Assert.AreEqual(1048.8333559209832, GetDoubleResult(ss, "CurrentWorstQuality"));
+      Assert.AreEqual(262622, GetIntResult(ss, "EvaluatedSolutions"));
     }
 
     private ScatterSearch CreateScatterSearchVRPSample() {
       #region Problem Configuration
-      var provider = new AugeratInstanceProvider();
-      var instance = provider.GetDataDescriptors().Where(x => x.Name == "A-n38-k5").Single();
+      var provider = new SolomonInstanceProvider();
+      var instance = provider.GetDataDescriptors().Single(x => x.Name == "C101");
       VehicleRoutingProblem vrpProblem = new VehicleRoutingProblem();
       vrpProblem.Load(provider.LoadData(instance));
@@ -986,20 +986,22 @@
       ss.Engine = new SequentialEngine();
       ss.Name = "Scatter Search - VRP";
-      ss.Description = "A Scatter Search algorithm which solves the \"A-n38-k5\" vehicle routing problem (imported from Augerat)";
+      ss.Description = "A scatter search algorithm which solves the \"C101\" vehicle routing problem (imported from Solomon)";
       ss.Problem = vrpProblem;
 
-      var improver = ss.Problem.Operators.OfType<VRPImprovementOperator>().First();
-      improver.ImprovementAttemptsParameter.Value.Value = 5;
-      improver.SampleSizeParameter.Value.Value = 5;
+      var improver = ss.Problem.Operators.OfType<VRPIntraRouteImprovementOperator>().First();
+      improver.ImprovementAttemptsParameter.Value.Value = 15;
+      improver.SampleSizeParameter.Value.Value = 10;
       ss.Improver = improver;
 
       var pathRelinker = ss.Problem.Operators.OfType<VRPPathRelinker>().First();
-      pathRelinker.IterationsParameter.Value.Value = 15;
+      pathRelinker.IterationsParameter.Value.Value = 25;
       ss.PathRelinker = pathRelinker;
 
-      var qualitySimCalc = ss.SimilarityCalculatorParameter.ValidValues.OfType<QualitySimilarityCalculator>().First();
-      ss.SimilarityCalculator = qualitySimCalc;
-
-      ss.MaximumIterations.Value = 5;
+      var similarityCalculator = ss.SimilarityCalculatorParameter.ValidValues.OfType<VRPSimilarityCalculator>().First();
+      ss.SimilarityCalculator = similarityCalculator;
+
+      ss.MaximumIterations.Value = 2;
+      ss.PopulationSize.Value = 20;
+      ss.ReferenceSetSize.Value = 10;
       ss.Seed.Value = 0;
       return ss;
