Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/DiversityCalculator.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/DiversityCalculator.cs	(revision 7774)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/DiversityCalculator.cs	(revision 7775)
@@ -42,12 +42,15 @@
     }
 
-    public int ExecuteCalculation(IItem left, IItem right) {
-      if (left == null || right == null) throw new ArgumentException("Cannot calculate diversity because one of the provided objects is null.");
-      if (left.GetType() != right.GetType()) throw new ArgumentException("Cannot calculate diversity because the provided objects differ in type.");
+    public double ExecuteCalculation(IItem left, IItem right) {
+      if (left == null || right == null)
+        throw new ArgumentException("Cannot calculate diversity because one of the provided objects is null.");
+      if (left.GetType() != right.GetType())
+        throw new ArgumentException("Cannot calculate diversity because the provided objects differ in type.");
+
       if (left == right) return 0;
       else return CalculateDiversity(left, right);
     }
 
-    protected abstract int CalculateDiversity(IItem left, IItem right);
+    protected abstract double CalculateDiversity(IItem left, IItem right);
   }
 }
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/HeuristicLab.Algorithms.ScatterSearch-3.3.csproj
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/HeuristicLab.Algorithms.ScatterSearch-3.3.csproj	(revision 7774)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/HeuristicLab.Algorithms.ScatterSearch-3.3.csproj	(revision 7775)
@@ -39,5 +39,4 @@
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="HeuristicLab.Algorithms.LocalSearch-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL" />
     <Reference Include="HeuristicLab.Analysis-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL" />
     <Reference Include="HeuristicLab.Collections-3.3">
@@ -55,4 +54,5 @@
     <Reference Include="HeuristicLab.Encodings.BinaryVectorEncoding-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL" />
     <Reference Include="HeuristicLab.Encodings.PermutationEncoding-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL" />
+    <Reference Include="HeuristicLab.Encodings.RealVectorEncoding-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL" />
     <Reference Include="HeuristicLab.Operators-3.3">
       <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Operators-3.3.dll</HintPath>
@@ -72,4 +72,5 @@
     <Reference Include="HeuristicLab.PluginInfrastructure-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL" />
     <Reference Include="HeuristicLab.Problems.Knapsack-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL" />
+    <Reference Include="HeuristicLab.Problems.TestFunctions-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL" />
     <Reference Include="HeuristicLab.Problems.TravelingSalesman-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL" />
     <Reference Include="HeuristicLab.Random-3.3">
@@ -86,8 +87,26 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="SolutionPool2TierUpdateMethod.cs" />
     <Compile Include="DiversityCalculator.cs" />
     <Compile Include="IPathRelinker.cs" />
     <Compile Include="Knapsack\BinaryVectorDiversityCalculator.cs" />
+    <Compile Include="Knapsack\KnapsackMultipleGuidesPathRelinker.cs" />
+    <Compile Include="Knapsack\KnapsackSimultaneousPathRelinker.cs" />
     <Compile Include="Knapsack\KnapsackPathRelinker.cs" />
+    <Compile Include="TestFunctions\TestFunctionsZakharovImprovementOperator.cs" />
+    <Compile Include="TestFunctions\TestFunctionsSumSquaresImprovementOperator.cs" />
+    <Compile Include="TestFunctions\TestFunctionsSchwefelImprovementOperator.cs" />
+    <Compile Include="TestFunctions\TestFunctionsRosenbrockImprovementOperator.cs" />
+    <Compile Include="TestFunctions\TestFunctionsMatyasImprovementOperator.cs" />
+    <Compile Include="TestFunctions\TestFunctionsLevyImprovementOperator.cs" />
+    <Compile Include="TestFunctions\TestFunctionsGriewankImprovementOperator.cs" />
+    <Compile Include="TestFunctions\TestFunctionsBoothImprovementOperator.cs" />
+    <Compile Include="TestFunctions\TestFunctionsBealeImprovementOperator.cs" />
+    <Compile Include="TestFunctions\TestFunctionsAckleyImprovementOperator.cs" />
+    <Compile Include="TestFunctions\TestFunctionsPathRelinker.cs" />
+    <Compile Include="TestFunctions\RealVectorDiversityCalculator.cs" />
+    <Compile Include="TestFunctions\TestFunctionsImprovementOperator.cs" />
+    <Compile Include="TravelingSalesman\TravelingSalesmanMultipleGuidesPathRelinker.cs" />
+    <Compile Include="TravelingSalesman\TravelingSalesmanSimultaneousPathRelinker.cs" />
     <Compile Include="TravelingSalesman\TravelingSalesmanPathRelinker.cs" />
     <Compile Include="PathRelinker.cs" />
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/IScatterSearchTargetProcessor.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/IScatterSearchTargetProcessor.cs	(revision 7774)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/IScatterSearchTargetProcessor.cs	(revision 7775)
@@ -23,4 +23,7 @@
 
 namespace HeuristicLab.Algorithms.ScatterSearch {
+  /// <summary>
+  /// An interface which represents an operator that uses a target parameter.
+  /// </summary>
   public interface IScatterSearchTargetProcessor {
     IValueLookupParameter<IItem> TargetParameter { get; }
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Knapsack/BinaryVectorDiversityCalculator.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Knapsack/BinaryVectorDiversityCalculator.cs	(revision 7774)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Knapsack/BinaryVectorDiversityCalculator.cs	(revision 7775)
@@ -20,4 +20,5 @@
 #endregion
 
+using System;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -41,11 +42,13 @@
     }
 
-    protected override int CalculateDiversity(IItem left, IItem right) {
+    protected override double CalculateDiversity(IItem left, IItem right) {
+      if (!(left is BinaryVector) || !(right is BinaryVector))
+        throw new ArgumentException("Cannot calculate diversity because one of the provided objects or both have the wrong type.");
+
       var v1 = left as BinaryVector;
       var v2 = right as BinaryVector;
-      int diversity = 0;
-      if (v1 != null && v2 != null)
-        for (int i = 0; i < v1.Length; i++)
-          if (v1[i] != v2[i]) diversity++;
+      double diversity = 0;
+      for (int i = 0; i < v1.Length; i++)
+        if (v1[i] != v2[i]) diversity++;
       return diversity;
     }
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Knapsack/KnapsackImprovementOperator.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Knapsack/KnapsackImprovementOperator.cs	(revision 7774)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Knapsack/KnapsackImprovementOperator.cs	(revision 7775)
@@ -67,4 +67,7 @@
       get { return (IValueLookupParameter<IItem>)Parameters["Target"]; }
     }
+    public IValueLookupParameter<DoubleValue> PenaltyParameter {
+      get { return (IValueLookupParameter<DoubleValue>)Parameters["Penalty"]; }
+    }
     #region ILocalImprovementOperator Parameters
     public IValueLookupParameter<IntValue> MaximumIterationsParameter {
@@ -99,4 +102,8 @@
       get { return TargetParameter.ActualValue; }
     }
+    private DoubleValue Penalty {
+      get { return PenaltyParameter.ActualValue; }
+      set { PenaltyParameter.ActualValue = value; }
+    }
     #endregion
 
@@ -115,4 +122,5 @@
       Parameters.Add(new ValueLookupParameter<IntValue>("KnapsackCapacity"));
       Parameters.Add(new ValueLookupParameter<IItem>("Target"));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("Penalty"));
       #endregion
       TargetParameter.ActualName = "KnapsackSolution"; // temporary solution for the knapsack problem
@@ -128,7 +136,7 @@
       // calculate value-to-weight ratio
       double[] ratio = new double[Values.Length];
-      for (int i = 0; i < ratio.Length; i++) {
+      for (int i = 0; i < ratio.Length; i++)
         ratio[i] = (double)Values[i] / (double)Weights[i];
-      }
+
 
       // calculate order for ratio
@@ -140,13 +148,12 @@
 
       int j = sol.Length - 1;
-      while (KnapsackEvaluator.Apply(sol, KnapsackCapacity, new DoubleValue(1.0), Weights, Values).SumWeights.Value > KnapsackCapacity.Value && j >= 0) {
+      while (KnapsackEvaluator.Apply(sol, KnapsackCapacity, Penalty, Weights, Values)
+                              .SumWeights.Value > KnapsackCapacity.Value && j >= 0)
         sol[order[j--]] = false;
-      }
 
       // calculate weight
-      int lhs = 0;
-      for (int i = 0; i < sol.Length; i++) {
-        if (sol[i]) lhs += Weights[i];
-      }
+      int weight = 0;
+      for (int i = 0; i < sol.Length; i++)
+        if (sol[i]) weight += Weights[i];
 
       // improve solution
@@ -154,10 +161,8 @@
       while (feasible && j < sol.Length) {
         while (sol[order[j]]) j++;
-        if (lhs + Weights[order[j]] <= KnapsackCapacity.Value) {
+        if (weight + Weights[order[j]] <= KnapsackCapacity.Value) {
           sol[order[j]] = true;
-          lhs += Weights[order[j]];
-        } else {
-          feasible = false;
-        }
+          weight += Weights[order[j]];
+        } else feasible = false;
       }
 
@@ -166,11 +171,4 @@
       return base.Apply();
     }
-
-    private bool IsFeasiblse(BinaryVector sol) {
-      int sum = 0;
-      for (int i = 0; i < sol.Length; i++)
-        if (sol[i]) sum += Weights[i];
-      return sum <= KnapsackCapacity.Value;
-    }
   }
 }
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Knapsack/KnapsackMultipleGuidesPathRelinker.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Knapsack/KnapsackMultipleGuidesPathRelinker.cs	(revision 7775)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Knapsack/KnapsackMultipleGuidesPathRelinker.cs	(revision 7775)
@@ -0,0 +1,86 @@
+﻿#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;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.BinaryVectorEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Algorithms.ScatterSearch.Knapsack {
+  /// <summary>
+  /// An operator that relinks paths between knapsack solutions using a multiple guiding strategy.
+  /// </summary>
+  [Item("KnapsackMultipleGuidesPathRelinker", "An operator that relinks paths between knapsack solutions using a multiple guiding strategy.")]
+  [StorableClass]
+  public sealed class KnapsackMultipleGuidesPathRelinker : PathRelinker {
+    [StorableConstructor]
+    private KnapsackMultipleGuidesPathRelinker(bool deserializing) : base(deserializing) { }
+    private KnapsackMultipleGuidesPathRelinker(KnapsackMultipleGuidesPathRelinker original, Cloner cloner) : base(original, cloner) { }
+    public KnapsackMultipleGuidesPathRelinker()
+      : base() {
+      ParentsParameter.ActualName = "KnapsackSolution";
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new KnapsackMultipleGuidesPathRelinker(this, cloner);
+    }
+
+    public static ItemArray<IItem> Apply(IItem initiator, IItem[] guides, PercentValue n) {
+      if (!(initiator is BinaryVector) || guides.Any(x => !(x is BinaryVector)))
+        throw new ArgumentException("Cannot relink path because some of the provided solutions have the wrong type.");
+      if (n.Value <= 0.0)
+        throw new ArgumentException("RelinkingAccuracy must be greater than 0.");
+
+      var v1 = initiator.Clone() as BinaryVector;
+      var targets = new BinaryVector[guides.Length];
+      Array.Copy(guides, targets, guides.Length);
+
+      if (targets.Any(x => x.Length != v1.Length))
+        throw new ArgumentException("At least one solution is of different length.");
+
+      var solutions = new List<BinaryVector>();
+      for (int i = 0; i < v1.Length; i++) {
+        // TODO: path relinking
+      }
+
+      var selection = new List<IItem>();
+      if (solutions.Count > 0) {
+        var noSol = (int)Math.Round(solutions.Count * n.Value);
+        if (noSol <= 0) noSol++;
+        var stepSize = (double)solutions.Count / (double)noSol;
+        for (int i = 0; i < noSol; i++)
+          selection.Add(solutions.ElementAt((int)Math.Round((i + 1) * stepSize - stepSize * 0.5)));
+      }
+
+      return new ItemArray<IItem>(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.");
+      return Apply(parents[0], parents.Skip(1).ToArray(), n);
+    }
+  }
+}
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Knapsack/KnapsackPathRelinker.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Knapsack/KnapsackPathRelinker.cs	(revision 7774)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Knapsack/KnapsackPathRelinker.cs	(revision 7775)
@@ -49,24 +49,29 @@
 
     public static ItemArray<IItem> Apply(IItem initiator, IItem guide, PercentValue n) {
+      if (!(initiator is BinaryVector) || !(guide is BinaryVector))
+        throw new ArgumentException("Cannot relink path because one of the provided solutions or both have the wrong type.");
+      if (n.Value <= 0.0)
+        throw new ArgumentException("RelinkingAccuracy must be greater than 0.");
+
       var v1 = initiator.Clone() as BinaryVector;
       var v2 = guide as BinaryVector;
 
       if (v1.Length != v2.Length)
-        throw new ArgumentException("KnapsackPathRelinker: The solutions are of different length.");
-      if (n.Value == 0.0)
-        throw new ArgumentException("KnapsackPathRelinker: RelinkingAccuracy is 0.");
+        throw new ArgumentException("The solutions are of different length.");
 
       var solutions = new List<BinaryVector>();
-      for (int i = 0; i < v1.Length; i++) {
+      for (int i = 0; i < v1.Length; i++)
         if (v1[i] != v2[i]) {
           v1[i] = v2[i];
-          solutions.Add((BinaryVector)v1.Clone());
+          solutions.Add(v1.Clone() as BinaryVector);
         }
-      }
 
-      var stepSize = 1 / n.Value;
       var selection = new List<IItem>();
-      for (int i = 0; i < solutions.Count; i = (int)Math.Round(i + stepSize)) {
-        selection.Add(solutions.ElementAt(i));
+      if (solutions.Count > 0) {
+        var noSol = (int)Math.Round(solutions.Count * n.Value);
+        if (noSol <= 0) noSol++;
+        var stepSize = (double)solutions.Count / (double)noSol;
+        for (int i = 0; i < noSol; i++)
+          selection.Add(solutions.ElementAt((int)Math.Round((i + 1) * stepSize - stepSize * 0.5)));
       }
 
@@ -75,5 +80,6 @@
 
     protected override ItemArray<IItem> Relink(ItemArray<IItem> parents, PercentValue n) {
-      if (parents.Length != 2) throw new ArgumentException("KnapsackPathRelinker: The number of parents is not equal to 2.");
+      if (parents.Length != 2)
+        throw new ArgumentException("The number of parents is not equal to 2.");
       return Apply(parents[0], parents[1], n);
     }
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Knapsack/KnapsackSimultaneousPathRelinker.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Knapsack/KnapsackSimultaneousPathRelinker.cs	(revision 7775)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Knapsack/KnapsackSimultaneousPathRelinker.cs	(revision 7775)
@@ -0,0 +1,95 @@
+﻿#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;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.BinaryVectorEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Algorithms.ScatterSearch.Knapsack {
+  /// <summary>
+  /// An operator that relinks paths between knapsack solutions starting from both ends.
+  /// </summary>
+  [Item("KnapsackSimultaneousPathRelinker", "An operator that relinks paths between knapsack solutions starting from both ends.")]
+  [StorableClass]
+  public sealed class KnapsackSimultaneousPathRelinker : PathRelinker {
+    [StorableConstructor]
+    private KnapsackSimultaneousPathRelinker(bool deserializing) : base(deserializing) { }
+    private KnapsackSimultaneousPathRelinker(KnapsackSimultaneousPathRelinker original, Cloner cloner) : base(original, cloner) { }
+    public KnapsackSimultaneousPathRelinker()
+      : base() {
+      ParentsParameter.ActualName = "KnapsackSolution";
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new KnapsackSimultaneousPathRelinker(this, cloner);
+    }
+
+    public static ItemArray<IItem> Apply(IItem initiator, IItem guide, PercentValue n) {
+      if (!(initiator is BinaryVector) || !(guide is BinaryVector))
+        throw new ArgumentException("Cannot relink path because one of the provided solutions or both have the wrong type.");
+      if (n.Value <= 0.0)
+        throw new ArgumentException("RelinkingAccuracy must be greater than 0.");
+
+      var firstInitiator = initiator.Clone() as BinaryVector;
+      var firstGuide = guide.Clone() as BinaryVector;
+      var secondInitiator = firstGuide.Clone() as BinaryVector;
+      var secondGuide = firstInitiator.Clone() as BinaryVector;
+
+      if (firstInitiator.Length != firstGuide.Length)
+        throw new ArgumentException("The solutions are of different length.");
+
+      var solutions = new List<BinaryVector>();
+      for (int i = 0; i < firstInitiator.Length / 2; i++) {
+        if (firstInitiator[i] != firstGuide[i]) {
+          firstInitiator[i] = firstGuide[i];
+          solutions.Add(firstInitiator.Clone() as BinaryVector);
+        }
+        var j = secondInitiator.Length - 1 - i;
+        if (secondInitiator[j] != secondGuide[j]) {
+          secondInitiator[j] = secondGuide[j];
+          solutions.Add(secondInitiator.Clone() as BinaryVector);
+        }
+      }
+
+      var selection = new List<IItem>();
+      if (solutions.Count > 0) {
+        var noSol = (int)Math.Round(solutions.Count * n.Value);
+        if (noSol <= 0) noSol++;
+        var stepSize = (double)solutions.Count / (double)noSol;
+        for (int i = 0; i < noSol; i++)
+          selection.Add(solutions.ElementAt((int)Math.Round((i + 1) * stepSize - stepSize * 0.5)));
+      }
+
+      return new ItemArray<IItem>(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.");
+      return Apply(parents[0], parents[1], n);
+    }
+  }
+}
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Knapsack/NBinaryVectorCrossover.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Knapsack/NBinaryVectorCrossover.cs	(revision 7774)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Knapsack/NBinaryVectorCrossover.cs	(revision 7775)
@@ -72,7 +72,6 @@
     public sealed override IOperation Apply() {
       var offspringSolutions = Cross(RandomParameter.ActualValue, ParentsParameter.ActualValue);
-      for (int i = 0; i < offspringSolutions.Length; i++) {
+      for (int i = 0; i < offspringSolutions.Length; i++)
         CurrentScope.Variables.Add(new Variable(string.Format("Child {0}", i), offspringSolutions[i]));
-      }
       return base.Apply();
     }
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Knapsack/NChildCrossover.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Knapsack/NChildCrossover.cs	(revision 7774)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Knapsack/NChildCrossover.cs	(revision 7775)
@@ -58,8 +58,6 @@
       if (parent1.Length != parent2.Length)
         throw new ArgumentException("NChildCrossover: The parents are of different length.");
-
       if (n.Value > Math.Pow(2, parent1.Length) - 2)
         throw new ArgumentException("NChildCrossover: There cannot be more children than 2^size of parents - 2.");
-
       if (n.Value < 1)
         throw new ArgumentException("NChildCrossover: N cannot be < 1.");
@@ -68,7 +66,6 @@
       for (int i = 0; i < n.Value; i++) {
         var solution = new BinaryVector(parent1.Length);
-        for (int j = 0; j < solution.Length; j++) {
+        for (int j = 0; j < solution.Length; j++)
           solution[j] = random.Next(2) % 2 == 0 ? parent1[j] : parent2[j];
-        }
         solutions[i] = solution;
       }
@@ -78,8 +75,8 @@
 
     protected override ItemArray<BinaryVector> Cross(IRandom random, ItemArray<BinaryVector> parents) {
-      if (parents.Length != 2) throw new ArgumentException("NChildCrossover: The number of parents is not equal to 2.");
-
-      if (NParameter.ActualValue == null) throw new InvalidOperationException("NChildCrossover: Parameter " + NParameter.ActualName + " could not be found.");
-
+      if (parents.Length != 2)
+        throw new ArgumentException("NChildCrossover: The number of parents is not equal to 2.");
+      if (NParameter.ActualValue == null)
+        throw new InvalidOperationException("NChildCrossover: Parameter " + NParameter.ActualName + " could not be found.");
       return Apply(random, parents[0], parents[1], NParameter.Value);
     }
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/PathRelinker.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/PathRelinker.cs	(revision 7774)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/PathRelinker.cs	(revision 7775)
@@ -31,5 +31,5 @@
   /// A base class for operators that perform path relinking.
   /// </summary>
-  [Item("PathRelinker", "A base class for operators that perform a crossover of bool-valued vectors.")]
+  [Item("PathRelinker", "A base class for operators that perform path relinking.")]
   [StorableClass]
   public abstract class PathRelinker : SingleSuccessorOperator, IPathRelinker {
@@ -38,6 +38,6 @@
       get { return (ScopeParameter)Parameters["CurrentScope"]; }
     }
-    public IValueLookupParameter<PercentValue> RelinkingAccuracyParameter {
-      get { return (IValueLookupParameter<PercentValue>)Parameters["RelinkingAccuracy"]; }
+    public IValueParameter<PercentValue> RelinkingAccuracyParameter {
+      get { return (IValueParameter<PercentValue>)Parameters["RelinkingAccuracy"]; }
     }
     public ILookupParameter<ItemArray<IItem>> ParentsParameter {
@@ -50,4 +50,10 @@
       get { return CurrentScopeParameter.ActualValue; }
     }
+    private PercentValue RelinkingAccuracy {
+      get { return RelinkingAccuracyParameter.Value; }
+    }
+    private ItemArray<IItem> Parents {
+      get { return ParentsParameter.ActualValue; }
+    }
     #endregion
 
@@ -59,5 +65,5 @@
       #region Create parameters
       Parameters.Add(new ScopeParameter("CurrentScope"));
-      Parameters.Add(new ValueLookupParameter<PercentValue>("RelinkingAccuracy", new PercentValue(0.25)));
+      Parameters.Add(new ValueParameter<PercentValue>("RelinkingAccuracy", new PercentValue(0.25)));
       Parameters.Add(new ScopeTreeLookupParameter<IItem>("Parents"));
       #endregion
@@ -65,8 +71,7 @@
 
     public sealed override IOperation Apply() {
-      var relinkedSolutions = Relink(ParentsParameter.ActualValue, RelinkingAccuracyParameter.ActualValue);
-      for (int i = 0; i < relinkedSolutions.Length; i++) {
+      var relinkedSolutions = Relink(Parents, RelinkingAccuracy);
+      for (int i = 0; i < relinkedSolutions.Length; i++)
         CurrentScope.Variables.Add(new Variable(string.Format("Child {0}", i), relinkedSolutions[i]));
-      }
       return base.Apply();
     }
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Plugin.cs.frame
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Plugin.cs.frame	(revision 7774)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/Plugin.cs.frame	(revision 7775)
@@ -26,5 +26,5 @@
   /// Plugin class for HeuristicLab.Algorithms.ScatterSearch plugin.
   /// </summary>
-  [Plugin("HeuristicLab.Algorithms.ScatterSearch", "3.3.6.$WCREV$")]
+  [Plugin("HeuristicLab.Algorithms.ScatterSearch", "3.3.6.7756")]
   [PluginFile("HeuristicLab.Algorithms.ScatterSearch-3.3.dll", PluginFileType.Assembly)]
   [PluginDependency("HeuristicLab.Analysis", "3.3")]
@@ -33,4 +33,7 @@
   [PluginDependency("HeuristicLab.Core", "3.3")]
   [PluginDependency("HeuristicLab.Data", "3.3")]
+  [PluginDependency("HeuristicLab.Encodings.BinaryVectorEncoding", "3.3")]
+  [PluginDependency("HeuristicLab.Encodings.PermutationEncoding", "3.3")]
+  [PluginDependency("HeuristicLab.Encodings.RealVectorEncoding", "3.3")]
   [PluginDependency("HeuristicLab.Operators", "3.3")]
   [PluginDependency("HeuristicLab.Optimization", "3.3")]
@@ -38,4 +41,7 @@
   [PluginDependency("HeuristicLab.Parameters", "3.3")]
   [PluginDependency("HeuristicLab.Persistence", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.Knapsack", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.TestFunctions", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.TravelingSalesman", "3.3")]
   [PluginDependency("HeuristicLab.Random", "3.3")]
   [PluginDependency("HeuristicLab.Selection", "3.3")]
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/ReferenceSetUpdateMethod.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/ReferenceSetUpdateMethod.cs	(revision 7774)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/ReferenceSetUpdateMethod.cs	(revision 7775)
@@ -95,5 +95,5 @@
       var population = new Dictionary<IScope, double>();
       foreach (var pScope in CurrentScope.SubScopes[0].SubScopes) {
-        int diversity = 0;
+        double diversity = 0;
         var pSol = pScope.Variables[TargetParameter.ActualName].Value;
         foreach (var rScope in CurrentScope.SubScopes[1].SubScopes) {
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/ScatterSearch.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/ScatterSearch.cs	(revision 7774)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/ScatterSearch.cs	(revision 7775)
@@ -306,6 +306,10 @@
       ICrossover defaultCrossover = Problem.Operators.OfType<ICrossover>().FirstOrDefault();
 
+      CrossoverParameter.ValidValues.Add(new Knapsack.KnapsackPathRelinker());
+      CrossoverParameter.ValidValues.Add(new Knapsack.KnapsackSimultaneousPathRelinker());
+      CrossoverParameter.ValidValues.Add(new TestFunctions.TestFunctionsPathRelinker());
       CrossoverParameter.ValidValues.Add(new TravelingSalesman.TravelingSalesmanPathRelinker());
-      CrossoverParameter.ValidValues.Add(new Knapsack.KnapsackPathRelinker());
+      CrossoverParameter.ValidValues.Add(new TravelingSalesman.TravelingSalesmanSimultaneousPathRelinker());
+      CrossoverParameter.ValidValues.Add(new TravelingSalesman.TravelingSalesmanMultipleGuidesPathRelinker());
 
       foreach (ICrossover crossover in Problem.Operators.OfType<ICrossover>().OrderBy(x => x.Name))
@@ -329,4 +333,5 @@
 
       DiversityCalculatorParameter.ValidValues.Add(new Knapsack.BinaryVectorDiversityCalculator());
+      DiversityCalculatorParameter.ValidValues.Add(new TestFunctions.RealVectorDiversityCalculator());
       DiversityCalculatorParameter.ValidValues.Add(new TravelingSalesman.PermutationDiversityCalculator());
 
@@ -348,4 +353,14 @@
 
       ImproverParameter.ValidValues.Add(new Knapsack.KnapsackImprovementOperator());
+      ImproverParameter.ValidValues.Add(new TestFunctions.TestFunctionsAckleyImprovementOperator());
+      ImproverParameter.ValidValues.Add(new TestFunctions.TestFunctionsBealeImprovementOperator());
+      ImproverParameter.ValidValues.Add(new TestFunctions.TestFunctionsBoothImprovementOperator());
+      ImproverParameter.ValidValues.Add(new TestFunctions.TestFunctionsGriewankImprovementOperator());
+      ImproverParameter.ValidValues.Add(new TestFunctions.TestFunctionsLevyImprovementOperator());
+      ImproverParameter.ValidValues.Add(new TestFunctions.TestFunctionsMatyasImprovementOperator());
+      ImproverParameter.ValidValues.Add(new TestFunctions.TestFunctionsRosenbrockImprovementOperator());
+      ImproverParameter.ValidValues.Add(new TestFunctions.TestFunctionsSchwefelImprovementOperator());
+      ImproverParameter.ValidValues.Add(new TestFunctions.TestFunctionsSumSquaresImprovementOperator());
+      ImproverParameter.ValidValues.Add(new TestFunctions.TestFunctionsZakharovImprovementOperator());
       ImproverParameter.ValidValues.Add(new TravelingSalesman.TravelingSalesmanImprovementOperator());
 
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/ScatterSearchMainLoop.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/ScatterSearchMainLoop.cs	(revision 7774)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/ScatterSearchMainLoop.cs	(revision 7775)
@@ -33,5 +33,5 @@
   /// An operator which represents a scatter search.
   /// </summary>
-  [Item("ScatterSearchMainLoop", "An operator which represents the main loop of a scatter search.")]
+  [Item("ScatterSearchMainLoop", "An operator which represents a scatter search.")]
   [StorableClass]
   public sealed class ScatterSearchMainLoop : AlgorithmOperator {
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/SolutionPool2TierUpdateMethod.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/SolutionPool2TierUpdateMethod.cs	(revision 7775)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/SolutionPool2TierUpdateMethod.cs	(revision 7775)
@@ -0,0 +1,206 @@
+﻿#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;
+using System.Collections.Generic;
+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.Algorithms.ScatterSearch {
+  /// <summary>
+  /// An operator that updates the solution pool using a 2-tier strategy.
+  /// </summary>
+  [Item("SolutionPool2TierUpdateMethod", "An operator that updates the solution pool using a 2-tier strategy.")]
+  [StorableClass]
+  public sealed class SolutionPool2TierUpdateMethod : SingleSuccessorOperator, IScatterSearchTargetProcessor {
+    #region Parameter properties
+    public ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+    public IValueLookupParameter<DiversityCalculator> DiversityCalculatorParameter {
+      get { return (IValueLookupParameter<DiversityCalculator>)Parameters["DiversityCalculator"]; }
+    }
+    public IValueLookupParameter<BoolValue> MaximizationParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    public IValueLookupParameter<BoolValue> NewSolutionsParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters["NewSolutions"]; }
+    }
+    public IValueLookupParameter<IntValue> NumberOfHighQualitySolutionsParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["NumberOfHighQualitySolutions"]; }
+    }
+    public IValueLookupParameter<IntValue> ReferenceSetSizeParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["ReferenceSetSize"]; }
+    }
+    public IValueLookupParameter<IItem> QualityParameter {
+      get { return (IValueLookupParameter<IItem>)Parameters["Quality"]; }
+    }
+    public IValueLookupParameter<IItem> TargetParameter {
+      get { return (IValueLookupParameter<IItem>)Parameters["Target"]; }
+    }
+    #endregion
+
+    #region Properties
+    private IScope CurrentScope {
+      get { return CurrentScopeParameter.ActualValue; }
+    }
+    private DiversityCalculator DiversityCalculator {
+      get { return DiversityCalculatorParameter.ActualValue; }
+    }
+    private BoolValue Maximization {
+      get { return MaximizationParameter.ActualValue; }
+      set { MaximizationParameter.ActualValue = value; }
+    }
+    private BoolValue NewSolutions {
+      get { return NewSolutionsParameter.ActualValue; }
+    }
+    private IntValue NumberOfHighQualitySolutions {
+      get { return NumberOfHighQualitySolutionsParameter.ActualValue; }
+    }
+    private IntValue ReferenceSetSize {
+      get { return ReferenceSetSizeParameter.ActualValue; }
+      set { ReferenceSetSizeParameter.ActualValue = value; }
+    }
+    private IItem Quality {
+      get { return QualityParameter.ActualValue; }
+    }
+    private IItem Target {
+      get { return TargetParameter.ActualValue; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private SolutionPool2TierUpdateMethod(bool deserializing) : base(deserializing) { }
+    private SolutionPool2TierUpdateMethod(SolutionPool2TierUpdateMethod original, Cloner cloner) : base(original, cloner) { }
+    public SolutionPool2TierUpdateMethod() : base() { Initialize(); }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SolutionPool2TierUpdateMethod(this, cloner);
+    }
+
+    private void Initialize() {
+      #region Create parameters
+      Parameters.Add(new ScopeParameter("CurrentScope"));
+      Parameters.Add(new ValueLookupParameter<DiversityCalculator>("DiversityCalculator"));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("Maximization"));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("NewSolutions"));
+      Parameters.Add(new ValueLookupParameter<IntValue>("NumberOfHighQualitySolutions"));
+      Parameters.Add(new ValueLookupParameter<IntValue>("ReferenceSetSize"));
+      Parameters.Add(new ValueLookupParameter<IItem>("Quality"));
+      Parameters.Add(new ValueLookupParameter<IItem>("Target"));
+      #endregion
+      TargetParameter.ActualName = "KnapsackSolution"; // temporary solution for the knapsack problem
+    }
+
+    public override IOperation Apply() {
+      var parentsScope = new Scope("Parents");
+      var offspringScope = new Scope("Offspring");
+
+      // split parents and offspring
+      foreach (var scope in CurrentScope.SubScopes) {
+        parentsScope.SubScopes.AddRange(scope.SubScopes.Take(scope.SubScopes.Count - 1));
+        offspringScope.SubScopes.AddRange(scope.SubScopes.Last().SubScopes);
+      }
+
+      var orderedParents = Maximization.Value ? parentsScope.SubScopes.OrderByDescending(x => x.Variables[QualityParameter.ActualName].Value) :
+                                                parentsScope.SubScopes.OrderBy(x => x.Variables[QualityParameter.ActualName].Value);
+      var orderedOffspring = Maximization.Value ? offspringScope.SubScopes.OrderByDescending(x => x.Variables[QualityParameter.ActualName].Value) :
+                                                  offspringScope.SubScopes.OrderBy(x => x.Variables[QualityParameter.ActualName].Value);
+
+      var highQualityParents = orderedParents.Take(NumberOfHighQualitySolutions.Value).ToList();
+      var highDiversityParents = new List<Tuple<IScope, double>>();
+      foreach (var oScope in orderedParents.Skip(NumberOfHighQualitySolutions.Value)) {
+        double diversity = 0.0;
+        var oSol = oScope.Variables[TargetParameter.ActualName].Value;
+        foreach (var hScope in highQualityParents) {
+          var hSol = hScope.Variables[TargetParameter.ActualName].Value;
+          diversity += DiversityCalculator.ExecuteCalculation(oSol, hSol);
+        }
+        highDiversityParents.Add(new Tuple<IScope, double>(oScope, diversity));
+      }
+
+      var offspring = new List<Tuple<IScope, double>>();
+      foreach (var oScope in orderedOffspring) {
+        double diversity = 0.0;
+        var oSol = oScope.Variables[TargetParameter.ActualName].Value;
+        foreach (var hScope in highQualityParents) {
+          var hSol = hScope.Variables[TargetParameter.ActualName].Value;
+          diversity += DiversityCalculator.ExecuteCalculation(oSol, hSol);
+        }
+        offspring.Add(new Tuple<IScope, double>(oScope, diversity));
+      }
+
+      // update high quality part of the reference set
+      var hasBetterQuality = Maximization.Value ? (Func<Tuple<IScope, double>, bool>)(x => { return (x.Item1.Variables[QualityParameter.ActualName].Value as DoubleValue).Value > (highQualityParents.OrderBy(y => y.Variables[QualityParameter.ActualName].Value).First().Variables[QualityParameter.ActualName].Value as DoubleValue).Value; }) :
+                                                  (Func<Tuple<IScope, double>, bool>)(x => { return (x.Item1.Variables[QualityParameter.ActualName].Value as DoubleValue).Value < (highQualityParents.OrderByDescending(y => y.Variables[QualityParameter.ActualName].Value).First().Variables[QualityParameter.ActualName].Value as DoubleValue).Value; });
+      if (offspring.Any(hasBetterQuality)) NewSolutions.Value = true;
+      while (offspring.Any(hasBetterQuality)) { // better offspring available
+        // select best offspring
+        var bestChild = Maximization.Value ? offspring.OrderByDescending(x => x.Item1.Variables[QualityParameter.ActualName].Value).First() :
+                                             offspring.OrderBy(x => x.Item1.Variables[QualityParameter.ActualName].Value).First();
+        // select worst parent
+        var worstParent = Maximization.Value ? highQualityParents.OrderByDescending(x => x.Variables[QualityParameter.ActualName].Value).Last() :
+                                               highQualityParents.OrderBy(x => x.Variables[QualityParameter.ActualName].Value).Last();
+        highQualityParents.Remove(worstParent);
+        highQualityParents.Add(bestChild.Item1);
+        offspring.Remove(bestChild);
+      }
+
+      // update diversity part of the reference set
+      var hasBetterDiversity = (Func<Tuple<IScope, double>, bool>)(x => { return x.Item2 > highDiversityParents.OrderBy(y => y.Item2).First().Item2; });
+      if (offspring.Any(hasBetterDiversity)) NewSolutions.Value = true;
+      while (offspring.Any(hasBetterDiversity)) { // better offspring available
+        // select best offspring
+        var bestChild = offspring.OrderByDescending(x => x.Item2).First();
+        // select worst parent
+        var worstParent = highDiversityParents.OrderBy(x => x.Item2).First();
+        highDiversityParents.Remove(worstParent);
+        highDiversityParents.Add(bestChild);
+        offspring.Remove(bestChild);
+      }
+
+      CurrentScope.SubScopes.Replace(highQualityParents.Concat(highDiversityParents.Select(x => x.Item1)).ToList());
+
+      return base.Apply();
+    }
+
+    private class KeyEqualityComparer<T> : IEqualityComparer<T> {
+      private readonly Func<T, object> keyExtractor;
+
+      public KeyEqualityComparer(Func<T, object> keyExtractor) {
+        this.keyExtractor = keyExtractor;
+      }
+
+      public bool Equals(T x, T y) {
+        return keyExtractor(x).Equals(keyExtractor(y));
+      }
+
+      public int GetHashCode(T obj) {
+        return keyExtractor(obj).GetHashCode();
+      }
+    }
+  }
+}
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/SolutionPoolUpdateMethod.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/SolutionPoolUpdateMethod.cs	(revision 7774)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/SolutionPoolUpdateMethod.cs	(revision 7775)
@@ -123,13 +123,13 @@
       var worstParentQuality = (orderedParents.Last().Variables[QualityParameter.ActualName].Value as DoubleValue).Value;
 
-      var Constraint = Maximization.Value ? (Func<IScope, bool>)(x => { return (x.Variables[QualityParameter.ActualName].Value as DoubleValue).Value > worstParentQuality; }) :
+      var hasBetterQuality = Maximization.Value ? (Func<IScope, bool>)(x => { return (x.Variables[QualityParameter.ActualName].Value as DoubleValue).Value > worstParentQuality; }) :
                                             (Func<IScope, bool>)(x => { return (x.Variables[QualityParameter.ActualName].Value as DoubleValue).Value < worstParentQuality; });
 
       // is there any offspring better than the worst parent?
-      if (orderedOffspring.Any(Constraint)) {
+      if (orderedOffspring.Any(hasBetterQuality)) {
         // produce the set union
         // attention: distinction might cause a too small reference set! (e.g. reference set = {1, 2, 2, 2, ..., 2} -> union = {1, 2}
-        var union = orderedParents.Union(orderedOffspring.Where(Constraint), new KeyEqualityComparer<IScope>(x => x.Variables[TargetParameter.ActualName].Value.ToString()));
-        if (union.Count() > orderedParents./*Distinct(new KeyEqualityComparer<IScope>(x => x.Variables[TargetParameter.ActualName].Value.ToString())).*/Count()) {
+        var union = orderedParents.Union(orderedOffspring.Where(hasBetterQuality), new KeyEqualityComparer<IScope>(x => x.Variables[TargetParameter.ActualName].Value.ToString()));
+        if (union.Count() > orderedParents/*.Distinct(new KeyEqualityComparer<IScope>(x => x.Variables[TargetParameter.ActualName].Value.ToString()))*/.Count()) {
           var orderedUnion = Maximization.Value ? union.OrderByDescending(x => x.Variables[QualityParameter.ActualName].Value) :
                                                   union.OrderBy(x => x.Variables[QualityParameter.ActualName].Value);
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/RealVectorDiversityCalculator.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/RealVectorDiversityCalculator.cs	(revision 7775)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/RealVectorDiversityCalculator.cs	(revision 7775)
@@ -0,0 +1,56 @@
+﻿#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;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.RealVectorEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Algorithms.ScatterSearch.TestFunctions {
+  /// <summary>
+  /// An operator that performs diversity calculation between real vectors.
+  /// </summary>
+  [Item("RealVectorDiversityCalculator", "An operator that performs diversity calculation between real vectors.")]
+  [StorableClass]
+  public sealed class RealVectorDiversityCalculator : DiversityCalculator {
+    [StorableConstructor]
+    private RealVectorDiversityCalculator(bool deserializing) : base(deserializing) { }
+    private RealVectorDiversityCalculator(RealVectorDiversityCalculator original, Cloner cloner) : base(original, cloner) { }
+    public RealVectorDiversityCalculator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RealVectorDiversityCalculator(this, cloner);
+    }
+
+    protected override double CalculateDiversity(IItem left, IItem right) {
+      if (!(left is RealVector) || !(right is RealVector))
+        throw new ArgumentException("Cannot calculate diversity because one of the provided objects or both have the wrong type.");
+
+      var v1 = left as RealVector;
+      var v2 = right as RealVector;
+      double sum = 0.0;
+      for (int i = 0; i < v1.Length; i++)
+        sum += Math.Pow(v1[i] - v2[i], 2);
+      return Math.Sqrt(sum);
+    }
+  }
+}
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsAckleyImprovementOperator.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsAckleyImprovementOperator.cs	(revision 7775)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsAckleyImprovementOperator.cs	(revision 7775)
@@ -0,0 +1,48 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.TestFunctions;
+
+namespace HeuristicLab.Algorithms.ScatterSearch.TestFunctions {
+  /// <summary>
+  /// An operator that improves Ackley test function solutions.
+  /// </summary>
+  [Item("TestFunctionsAckleyImprovementOperator", "An operator that improves Ackley test function solutions.")]
+  [StorableClass]
+  public sealed class TestFunctionsAckleyImprovementOperator : TestFunctionsImprovementOperator {
+    [StorableConstructor]
+    private TestFunctionsAckleyImprovementOperator(bool deserializing) : base(deserializing) { }
+    private TestFunctionsAckleyImprovementOperator(TestFunctionsAckleyImprovementOperator original, Cloner cloner) : base(original, cloner) { }
+    public TestFunctionsAckleyImprovementOperator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new TestFunctionsAckleyImprovementOperator(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      FunctionEvaluator = x => { return AckleyEvaluator.Apply(x); };
+      return base.Apply();
+    }
+  }
+}
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsBealeImprovementOperator.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsBealeImprovementOperator.cs	(revision 7775)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsBealeImprovementOperator.cs	(revision 7775)
@@ -0,0 +1,48 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.TestFunctions;
+
+namespace HeuristicLab.Algorithms.ScatterSearch.TestFunctions {
+  /// <summary>
+  /// An operator that improves Beale test function solutions.
+  /// </summary>
+  [Item("TestFunctionsBealeImprovementOperator", "An operator that improves Beale test function solutions.")]
+  [StorableClass]
+  public sealed class TestFunctionsBealeImprovementOperator : TestFunctionsImprovementOperator {
+    [StorableConstructor]
+    private TestFunctionsBealeImprovementOperator(bool deserializing) : base(deserializing) { }
+    private TestFunctionsBealeImprovementOperator(TestFunctionsBealeImprovementOperator original, Cloner cloner) : base(original, cloner) { }
+    public TestFunctionsBealeImprovementOperator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new TestFunctionsBealeImprovementOperator(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      FunctionEvaluator = x => { return BealeEvaluator.Apply(x); };
+      return base.Apply();
+    }
+  }
+}
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsBoothImprovementOperator.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsBoothImprovementOperator.cs	(revision 7775)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsBoothImprovementOperator.cs	(revision 7775)
@@ -0,0 +1,48 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.TestFunctions;
+
+namespace HeuristicLab.Algorithms.ScatterSearch.TestFunctions {
+  /// <summary>
+  /// An operator that improves Booth test function solutions.
+  /// </summary>
+  [Item("TestFunctionsBoothImprovementOperator", "An operator that improves Booth test function solutions.")]
+  [StorableClass]
+  public sealed class TestFunctionsBoothImprovementOperator : TestFunctionsImprovementOperator {
+    [StorableConstructor]
+    private TestFunctionsBoothImprovementOperator(bool deserializing) : base(deserializing) { }
+    private TestFunctionsBoothImprovementOperator(TestFunctionsBoothImprovementOperator original, Cloner cloner) : base(original, cloner) { }
+    public TestFunctionsBoothImprovementOperator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new TestFunctionsBoothImprovementOperator(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      FunctionEvaluator = x => { return BoothEvaluator.Apply(x); };
+      return base.Apply();
+    }
+  }
+}
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsGriewankImprovementOperator.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsGriewankImprovementOperator.cs	(revision 7775)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsGriewankImprovementOperator.cs	(revision 7775)
@@ -0,0 +1,48 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.TestFunctions;
+
+namespace HeuristicLab.Algorithms.ScatterSearch.TestFunctions {
+  /// <summary>
+  /// An operator that improves Griewank test function solutions.
+  /// </summary>
+  [Item("TestFunctionsGriewankImprovementOperator", "An operator that improves Griewank test function solutions.")]
+  [StorableClass]
+  public sealed class TestFunctionsGriewankImprovementOperator : TestFunctionsImprovementOperator {
+    [StorableConstructor]
+    private TestFunctionsGriewankImprovementOperator(bool deserializing) : base(deserializing) { }
+    private TestFunctionsGriewankImprovementOperator(TestFunctionsGriewankImprovementOperator original, Cloner cloner) : base(original, cloner) { }
+    public TestFunctionsGriewankImprovementOperator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new TestFunctionsGriewankImprovementOperator(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      FunctionEvaluator = x => { return GriewankEvaluator.Apply(x); };
+      return base.Apply();
+    }
+  }
+}
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsImprovementOperator.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsImprovementOperator.cs	(revision 7775)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsImprovementOperator.cs	(revision 7775)
@@ -0,0 +1,234 @@
+﻿#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;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.RealVectorEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.Knapsack;
+using HeuristicLab.Problems.TestFunctions;
+
+namespace HeuristicLab.Algorithms.ScatterSearch.TestFunctions {
+  /// <summary>
+  /// An operator that improves test functions solutions.
+  /// </summary>
+  [Item("TestFunctionsImprovementOperator", "An operator that improves test functions solutions.")]
+  [StorableClass]
+  public abstract class TestFunctionsImprovementOperator : SingleSuccessorOperator, ILocalImprovementOperator, IScatterSearchTargetProcessor {
+    #region Problem properties
+    public Type ProblemType {
+      get { return typeof(KnapsackProblem); }
+    }
+    [Storable]
+    private KnapsackProblem problem;
+    public IProblem Problem {
+      get { return problem; }
+      set { problem = (KnapsackProblem)value; }
+    }
+    #endregion
+
+    #region Parameter properties
+    public ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+    public IValueLookupParameter<DoubleMatrix> CoordinatesParameter {
+      get { return (IValueLookupParameter<DoubleMatrix>)Parameters["Coordinates"]; }
+    }
+    public IValueLookupParameter<ISingleObjectiveTestFunctionProblemEvaluator> EvaluatorParameter {
+      get { return (IValueLookupParameter<ISingleObjectiveTestFunctionProblemEvaluator>)Parameters["Evaluator"]; }
+    }
+    public IValueLookupParameter<IntValue> ImprovementAttemptsParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["ImprovementAttempts"]; }
+    }
+    public IValueLookupParameter<IRandom> RandomParameter {
+      get { return (IValueLookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    public IValueLookupParameter<IItem> TargetParameter {
+      get { return (IValueLookupParameter<IItem>)Parameters["Target"]; }
+    }
+    public IValueParameter<DoubleValue> AlphaParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["Alpha"]; }
+    }
+    public IValueParameter<DoubleValue> BetaParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["Beta"]; }
+    }
+    public IValueParameter<DoubleValue> GammaParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["Gamma"]; }
+    }
+    public IValueParameter<DoubleValue> DeltaParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["Delta"]; }
+    }
+    #region ILocalImprovementOperator Parameters
+    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"]; }
+    }
+    #endregion
+    #endregion
+
+    #region Properties
+    private IItem Target {
+      get { return TargetParameter.ActualValue; }
+    }
+    private DoubleValue Alpha {
+      get { return AlphaParameter.Value; }
+    }
+    private DoubleValue Beta {
+      get { return BetaParameter.Value; }
+    }
+    private DoubleValue Gamma {
+      get { return GammaParameter.Value; }
+    }
+    private DoubleValue Delta {
+      get { return DeltaParameter.Value; }
+    }
+    protected Func<RealVector, double> FunctionEvaluator { get; set; }
+    public IScope CurrentScope {
+      get { return CurrentScopeParameter.ActualValue; }
+    }
+    public DoubleMatrix Coordinates {
+      get { return CoordinatesParameter.ActualValue; }
+      set { CoordinatesParameter.ActualValue = value; }
+    }
+    public ISingleObjectiveTestFunctionProblemEvaluator Evaluator {
+      get { return EvaluatorParameter.ActualValue; }
+      set { EvaluatorParameter.ActualValue = value; }
+    }
+    public IntValue ImprovementAttempts {
+      get { return ImprovementAttemptsParameter.ActualValue; }
+      set { ImprovementAttemptsParameter.ActualValue = value; }
+    }
+    public IRandom Random {
+      get { return RandomParameter.ActualValue; }
+      set { RandomParameter.ActualValue = value; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected TestFunctionsImprovementOperator(bool deserializing) : base(deserializing) { }
+    protected TestFunctionsImprovementOperator(TestFunctionsImprovementOperator original, Cloner cloner)
+      : base(original, cloner) {
+      this.problem = cloner.Clone(original.problem);
+    }
+    public TestFunctionsImprovementOperator()
+      : base() {
+      #region Create parameters
+      Parameters.Add(new ScopeParameter("CurrentScope"));
+      Parameters.Add(new ValueLookupParameter<DoubleMatrix>("Coordinates"));
+      Parameters.Add(new ValueLookupParameter<ISingleObjectiveTestFunctionProblemEvaluator>("Evaluator"));
+      Parameters.Add(new ValueLookupParameter<IntValue>("ImprovementAttempts", new IntValue(100)));
+      Parameters.Add(new ValueLookupParameter<IRandom>("Random"));
+      Parameters.Add(new ValueLookupParameter<IItem>("Target"));
+      Parameters.Add(new ValueParameter<DoubleValue>("Alpha", new DoubleValue(1.0)));
+      Parameters.Add(new ValueParameter<DoubleValue>("Beta", new DoubleValue(2.0)));
+      Parameters.Add(new ValueParameter<DoubleValue>("Gamma", new DoubleValue(0.5)));
+      Parameters.Add(new ValueParameter<DoubleValue>("Delta", new DoubleValue(0.5)));
+      #endregion
+      TargetParameter.ActualName = "Point"; // temporary solution for the test functions problem
+    }
+
+    public override IOperation Apply() {
+      var bestSol = CurrentScope.Variables[TargetParameter.ActualName].Value as RealVector;
+      var bestSolQuality = FunctionEvaluator(bestSol);
+
+      // create perturbed solutions
+      var simplex = new RealVector[bestSol.Length];
+      for (int i = 0; i < simplex.Length; i++) {
+        simplex[i] = bestSol.Clone() as RealVector;
+        simplex[i][i] += 0.1 * (Evaluator.Bounds[0, 1] - Evaluator.Bounds[0, 0]);
+        if (simplex[i][i] > Evaluator.Bounds[0, 1]) simplex[i][i] = Evaluator.Bounds[0, 1];
+        if (simplex[i][i] < Evaluator.Bounds[0, 0]) simplex[i][i] = Evaluator.Bounds[0, 0];
+      }
+
+      // improve solutions
+      for (int i = 0; i < ImprovementAttempts.Value; i++) {
+        // order according to their objective function value
+        Array.Sort(simplex, (x, y) => FunctionEvaluator(x).CompareTo(FunctionEvaluator(y)));
+
+        // calculate centroid
+        var centroid = new RealVector(bestSol.Length);
+        foreach (var vector in simplex)
+          for (int j = 0; j < centroid.Length; j++)
+            centroid[j] += vector[j];
+        for (int j = 0; j < centroid.Length; j++)
+          centroid[j] /= simplex.Length;
+
+        // reflection
+        var reflectionPoint = new RealVector(bestSol.Length);
+        for (int j = 0; j < reflectionPoint.Length; j++)
+          reflectionPoint[j] = centroid[j] + Alpha.Value * (centroid[j] - simplex[simplex.Length - 1][j]);
+        double reflectionPointQuality = FunctionEvaluator(reflectionPoint);
+        if (FunctionEvaluator(simplex[0]) <= reflectionPointQuality
+            && reflectionPointQuality < FunctionEvaluator(simplex[simplex.Length - 2]))
+          simplex[simplex.Length - 1] = reflectionPoint;
+
+        // expansion
+        if (reflectionPointQuality < FunctionEvaluator(simplex[0])) {
+          var expansionPoint = new RealVector(bestSol.Length);
+          for (int j = 0; j < expansionPoint.Length; j++)
+            expansionPoint[j] = centroid[j] + Beta.Value * (reflectionPoint[j] - centroid[j]);
+          simplex[simplex.Length - 1] = FunctionEvaluator(expansionPoint) < reflectionPointQuality ? expansionPoint : reflectionPoint;
+        }
+
+        // contraction
+        if (FunctionEvaluator(simplex[simplex.Length - 2]) <= reflectionPointQuality
+            && reflectionPointQuality < FunctionEvaluator(simplex[simplex.Length - 1])) {
+          var outsideContractionPoint = new RealVector(bestSol.Length);
+          for (int j = 0; j < outsideContractionPoint.Length; j++)
+            outsideContractionPoint[j] = centroid[j] + Gamma.Value * (reflectionPoint[j] - centroid[j]);
+          if (FunctionEvaluator(outsideContractionPoint) <= reflectionPointQuality) {
+            simplex[simplex.Length - 1] = outsideContractionPoint;
+            if (FunctionEvaluator(reflectionPoint) >= FunctionEvaluator(simplex[simplex.Length - 1])) {
+              var insideContractionPoint = new RealVector(bestSol.Length);
+              for (int j = 0; j < insideContractionPoint.Length; j++)
+                insideContractionPoint[j] = centroid[j] - Gamma.Value * (reflectionPoint[j] - centroid[j]);
+              if (FunctionEvaluator(insideContractionPoint) < FunctionEvaluator(simplex[simplex.Length - 1])) simplex[simplex.Length - 1] = insideContractionPoint;
+            }
+          }
+        }
+
+        // reduction
+        for (int j = 1; j < simplex.Length; j++)
+          for (int k = 0; k < simplex[j].Length; k++)
+            simplex[j][k] = simplex[0][k] + Delta.Value * (simplex[j][k] - simplex[0][k]);
+      }
+
+      for (int i = 0; i < simplex[0].Length; i++) {
+        if (simplex[0][i] > Evaluator.Bounds[0, 1]) simplex[0][i] = Evaluator.Bounds[0, 1];
+        if (simplex[0][i] < Evaluator.Bounds[0, 0]) simplex[0][i] = Evaluator.Bounds[0, 0];
+      }
+
+      CurrentScope.Variables[TargetParameter.ActualName].Value = simplex[0];
+
+      return base.Apply();
+    }
+  }
+}
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsLevyImprovementOperator.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsLevyImprovementOperator.cs	(revision 7775)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsLevyImprovementOperator.cs	(revision 7775)
@@ -0,0 +1,48 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.TestFunctions;
+
+namespace HeuristicLab.Algorithms.ScatterSearch.TestFunctions {
+  /// <summary>
+  /// An operator that improves Levy test function solutions.
+  /// </summary>
+  [Item("TestFunctionsLevyImprovementOperator", "An operator that improves Levy test function solutions.")]
+  [StorableClass]
+  public sealed class TestFunctionsLevyImprovementOperator : TestFunctionsImprovementOperator {
+    [StorableConstructor]
+    private TestFunctionsLevyImprovementOperator(bool deserializing) : base(deserializing) { }
+    private TestFunctionsLevyImprovementOperator(TestFunctionsLevyImprovementOperator original, Cloner cloner) : base(original, cloner) { }
+    public TestFunctionsLevyImprovementOperator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new TestFunctionsLevyImprovementOperator(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      FunctionEvaluator = x => { return LevyEvaluator.Apply(x); };
+      return base.Apply();
+    }
+  }
+}
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsMatyasImprovementOperator.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsMatyasImprovementOperator.cs	(revision 7775)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsMatyasImprovementOperator.cs	(revision 7775)
@@ -0,0 +1,48 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.TestFunctions;
+
+namespace HeuristicLab.Algorithms.ScatterSearch.TestFunctions {
+  /// <summary>
+  /// An operator that improves Matyas test function solutions.
+  /// </summary>
+  [Item("TestFunctionsMatyasImprovementOperator", "An operator that improves Matyas test function solutions.")]
+  [StorableClass]
+  public sealed class TestFunctionsMatyasImprovementOperator : TestFunctionsImprovementOperator {
+    [StorableConstructor]
+    private TestFunctionsMatyasImprovementOperator(bool deserializing) : base(deserializing) { }
+    private TestFunctionsMatyasImprovementOperator(TestFunctionsMatyasImprovementOperator original, Cloner cloner) : base(original, cloner) { }
+    public TestFunctionsMatyasImprovementOperator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new TestFunctionsMatyasImprovementOperator(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      FunctionEvaluator = x => { return MatyasEvaluator.Apply(x); };
+      return base.Apply();
+    }
+  }
+}
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsPathRelinker.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsPathRelinker.cs	(revision 7775)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsPathRelinker.cs	(revision 7775)
@@ -0,0 +1,105 @@
+﻿#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;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.RealVectorEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Algorithms.ScatterSearch.TestFunctions {
+  /// <summary>
+  /// An operator that relinks paths between test functions solutions.
+  /// </summary>
+  [Item("TestFunctionsPathRelinker", "An operator that relinks paths between test functions solutions.")]
+  [StorableClass]
+  public sealed class TestFunctionsPathRelinker : PathRelinker {
+    #region Parameter properties
+    public IValueParameter<IntValue> RelinkingIntensityParameter {
+      get { return (IValueParameter<IntValue>)Parameters["RelinkingIntensity"]; }
+    }
+    #endregion
+
+    #region Properties
+    private IntValue RelinkingIntensity {
+      get { return RelinkingIntensityParameter.Value; }
+      set { RelinkingIntensityParameter.Value = value; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private TestFunctionsPathRelinker(bool deserializing) : base(deserializing) { }
+    private TestFunctionsPathRelinker(TestFunctionsPathRelinker original, Cloner cloner) : base(original, cloner) { }
+    public TestFunctionsPathRelinker()
+      : base() {
+      #region Create parameters
+      Parameters.Add(new ValueParameter<IntValue>("RelinkingIntensity", new IntValue(10)));
+      #endregion
+      ParentsParameter.ActualName = "Point";
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new TestFunctionsPathRelinker(this, cloner);
+    }
+
+    public static ItemArray<IItem> Apply(IItem initiator, IItem guide, IntValue k, PercentValue n) {
+      if (!(initiator is RealVector) || !(guide is RealVector))
+        throw new ArgumentException("Cannot relink path because one of the provided solutions or both have the wrong type.");
+      if (n.Value <= 0.0)
+        throw new ArgumentException("RelinkingAccuracy must be greater than 0.");
+
+      var v1 = initiator.Clone() as RealVector;
+      var v2 = guide as RealVector;
+
+      if (v1.Length != v2.Length)
+        throw new ArgumentException("The solutions are of different length.");
+
+      var solutions = new List<RealVector>();
+      for (int i = 0; i < k.Value; i++) {
+        var solution = v1.Clone() as RealVector;
+        for (int j = 0; j < solution.Length; j++)
+          solution[j] = v1[j] + 1 / (k.Value - i) * (v2[j] - v1[j]);
+        solutions.Add(solution);
+      }
+
+      var selection = new List<IItem>();
+      if (solutions.Count > 0) {
+        var noSol = (int)Math.Round(solutions.Count * n.Value);
+        if (noSol <= 0) noSol++;
+        var stepSize = (double)solutions.Count / (double)noSol;
+        for (int i = 0; i < noSol; i++)
+          selection.Add(solutions.ElementAt((int)Math.Round((i + 1) * stepSize - stepSize * 0.5)));
+      }
+
+      return new ItemArray<IItem>(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.");
+      return Apply(parents[0], parents[1], RelinkingIntensity, n);
+    }
+  }
+}
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsRosenbrockImprovementOperator.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsRosenbrockImprovementOperator.cs	(revision 7775)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsRosenbrockImprovementOperator.cs	(revision 7775)
@@ -0,0 +1,48 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.TestFunctions;
+
+namespace HeuristicLab.Algorithms.ScatterSearch.TestFunctions {
+  /// <summary>
+  /// An operator that improves Rosenbrock test function solutions.
+  /// </summary>
+  [Item("TestFunctionsRosenbrockImprovementOperator", "An operator that improves Rosenbrock test function solutions.")]
+  [StorableClass]
+  public sealed class TestFunctionsRosenbrockImprovementOperator : TestFunctionsImprovementOperator {
+    [StorableConstructor]
+    private TestFunctionsRosenbrockImprovementOperator(bool deserializing) : base(deserializing) { }
+    private TestFunctionsRosenbrockImprovementOperator(TestFunctionsRosenbrockImprovementOperator original, Cloner cloner) : base(original, cloner) { }
+    public TestFunctionsRosenbrockImprovementOperator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new TestFunctionsRosenbrockImprovementOperator(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      FunctionEvaluator = x => { return RosenbrockEvaluator.Apply(x); };
+      return base.Apply();
+    }
+  }
+}
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsSchwefelImprovementOperator.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsSchwefelImprovementOperator.cs	(revision 7775)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsSchwefelImprovementOperator.cs	(revision 7775)
@@ -0,0 +1,48 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.TestFunctions;
+
+namespace HeuristicLab.Algorithms.ScatterSearch.TestFunctions {
+  /// <summary>
+  /// An operator that improves Schwefel test function solutions.
+  /// </summary>
+  [Item("TestFunctionsSchwefelImprovementOperator", "An operator that improves Schwefel test function solutions.")]
+  [StorableClass]
+  public sealed class TestFunctionsSchwefelImprovementOperator : TestFunctionsImprovementOperator {
+    [StorableConstructor]
+    private TestFunctionsSchwefelImprovementOperator(bool deserializing) : base(deserializing) { }
+    private TestFunctionsSchwefelImprovementOperator(TestFunctionsSchwefelImprovementOperator original, Cloner cloner) : base(original, cloner) { }
+    public TestFunctionsSchwefelImprovementOperator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new TestFunctionsSchwefelImprovementOperator(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      FunctionEvaluator = x => { return SchwefelEvaluator.Apply(x); };
+      return base.Apply();
+    }
+  }
+}
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsSumSquaresImprovementOperator.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsSumSquaresImprovementOperator.cs	(revision 7775)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsSumSquaresImprovementOperator.cs	(revision 7775)
@@ -0,0 +1,48 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.TestFunctions;
+
+namespace HeuristicLab.Algorithms.ScatterSearch.TestFunctions {
+  /// <summary>
+  /// An operator that improves SumSquares test function solutions.
+  /// </summary>
+  [Item("TestFunctionsSumSquaresImprovementOperator", "An operator that improves SumSquares test function solutions.")]
+  [StorableClass]
+  public sealed class TestFunctionsSumSquaresImprovementOperator : TestFunctionsImprovementOperator {
+    [StorableConstructor]
+    private TestFunctionsSumSquaresImprovementOperator(bool deserializing) : base(deserializing) { }
+    private TestFunctionsSumSquaresImprovementOperator(TestFunctionsSumSquaresImprovementOperator original, Cloner cloner) : base(original, cloner) { }
+    public TestFunctionsSumSquaresImprovementOperator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new TestFunctionsSumSquaresImprovementOperator(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      FunctionEvaluator = x => { return SumSquaresEvaluator.Apply(x); };
+      return base.Apply();
+    }
+  }
+}
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsZakharovImprovementOperator.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsZakharovImprovementOperator.cs	(revision 7775)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TestFunctions/TestFunctionsZakharovImprovementOperator.cs	(revision 7775)
@@ -0,0 +1,48 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.TestFunctions;
+
+namespace HeuristicLab.Algorithms.ScatterSearch.TestFunctions {
+  /// <summary>
+  /// An operator that improves Zakharov test function solutions.
+  /// </summary>
+  [Item("TestFunctionsZakharovImprovementOperator", "An operator that improves Zakharov test function solutions.")]
+  [StorableClass]
+  public sealed class TestFunctionsZakharovImprovementOperator : TestFunctionsImprovementOperator {
+    [StorableConstructor]
+    private TestFunctionsZakharovImprovementOperator(bool deserializing) : base(deserializing) { }
+    private TestFunctionsZakharovImprovementOperator(TestFunctionsZakharovImprovementOperator original, Cloner cloner) : base(original, cloner) { }
+    public TestFunctionsZakharovImprovementOperator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new TestFunctionsZakharovImprovementOperator(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      FunctionEvaluator = x => { return ZakharovEvaluator.Apply(x); };
+      return base.Apply();
+    }
+  }
+}
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TravelingSalesman/PermutationDiversityCalculator.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TravelingSalesman/PermutationDiversityCalculator.cs	(revision 7774)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TravelingSalesman/PermutationDiversityCalculator.cs	(revision 7775)
@@ -20,4 +20,5 @@
 #endregion
 
+using System;
 using System.Linq;
 using HeuristicLab.Common;
@@ -42,15 +43,17 @@
     }
 
-    protected override int CalculateDiversity(IItem left, IItem right) {
+    protected override double CalculateDiversity(IItem left, IItem right) {
+      if (!(left is Permutation) || !(right is Permutation))
+        throw new ArgumentException("Cannot calculate diversity because one of the provided objects or both have the wrong type.");
+
       var v1 = left as Permutation;
       var v2 = right as Permutation;
-      int diversity = 0;
-      if (v1 != null && v2 != null)
-        for (int i = 0; i < v1.Length; i++) {
-          var node = v2.Select((x, index) => new { Value = x, ValueIndex = index }).First(x => x.Value == v1[i]);
-          var pred = v2[(node.ValueIndex - 1 + v2.Length) % v2.Length];
-          var succ = v2[(node.ValueIndex + 1 % v2.Length) % v2.Length];
-          if (new[] { pred, succ }.All(x => x != v1[(i + 1) % v1.Length])) diversity++;
-        }
+      double diversity = 0.0;
+      for (int i = 0; i < v1.Length; i++) {
+        var node = v2.Select((x, index) => new { Value = x, ValueIndex = index }).First(x => x.Value == v1[i]);
+        var pred = v2[(node.ValueIndex - 1 + v2.Length) % v2.Length];
+        var succ = v2[(node.ValueIndex + 1) % v2.Length];
+        if (new[] { pred, succ }.All(x => x != v1[(i + 1) % v1.Length])) diversity++;
+      }
       return diversity;
     }
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TravelingSalesman/TravelingSalesmanImprovementOperator.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TravelingSalesman/TravelingSalesmanImprovementOperator.cs	(revision 7774)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TravelingSalesman/TravelingSalesmanImprovementOperator.cs	(revision 7775)
@@ -138,11 +138,11 @@
 
       for (int i = 0; i < ImprovementAttempts.Value; i++) {
-        int a = Random.Next(currSol.Length - 1);
-        int b = Random.Next(currSol.Length - 1);
+        int a = Random.Next(currSol.Length);
+        int b = Random.Next(currSol.Length);
         Invert(currSol, a, b);
         currLength = TSPEuclideanPathEvaluator.Apply(Evaluator as TSPCoordinatesPathEvaluator, Coordinates, currSol);
         if (currLength < bestLength) {
           bestLength = currLength;
-          bestSol = (Permutation)currSol.Clone();
+          bestSol = currSol.Clone() as Permutation;
         }
         Invert(currSol, a, b);
@@ -155,11 +155,12 @@
 
     private void Invert(Permutation sol, int i, int j) {
-      if (i != j) {
-        for (int a = 0; a < Math.Abs(i - j) / 2; a++) {
-          int tmp = sol[(i + a) % sol.Length];
-          sol[(i + a) % sol.Length] = sol[(j - a + sol.Length) % sol.Length];
-          sol[(j - a + sol.Length) % sol.Length] = tmp;
-        }
-      }
+      if (i != j)
+        for (int a = 0; a < Math.Abs(i - j) / 2; a++)
+          if (sol[(i + a) % sol.Length] != sol[(j - a + sol.Length) % sol.Length]) {
+            // XOR swap
+            sol[(i + a) % sol.Length] ^= sol[(j - a + sol.Length) % sol.Length];
+            sol[(j - a + sol.Length) % sol.Length] ^= sol[(i + a) % sol.Length];
+            sol[(i + a) % sol.Length] ^= sol[(j - a + sol.Length) % sol.Length];
+          }
     }
   }
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TravelingSalesman/TravelingSalesmanMultipleGuidesPathRelinker.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TravelingSalesman/TravelingSalesmanMultipleGuidesPathRelinker.cs	(revision 7775)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TravelingSalesman/TravelingSalesmanMultipleGuidesPathRelinker.cs	(revision 7775)
@@ -0,0 +1,130 @@
+﻿#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;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.TravelingSalesman;
+
+namespace HeuristicLab.Algorithms.ScatterSearch.TravelingSalesman {
+  /// <summary>
+  /// An operator that relinks paths between traveling salesman solutions using a multiple guiding strategy.
+  /// </summary>
+  [Item("TravelingSalesmanMultipleGuidingPathRelinker", "An operator that relinks paths between traveling salesman solutions using a multiple guiding strategy.")]
+  [StorableClass]
+  public sealed class TravelingSalesmanMultipleGuidesPathRelinker : PathRelinker {
+    #region Parameter properties
+    public ILookupParameter<DistanceMatrix> DistanceMatrixParameter {
+      get { return (ILookupParameter<DistanceMatrix>)Parameters["DistanceMatrix"]; }
+    }
+    #endregion
+
+    #region Properties
+    public DistanceMatrix DistanceMatrix {
+      get { return DistanceMatrixParameter.ActualValue; }
+      set { DistanceMatrixParameter.ActualValue = value; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private TravelingSalesmanMultipleGuidesPathRelinker(bool deserializing) : base(deserializing) { }
+    private TravelingSalesmanMultipleGuidesPathRelinker(TravelingSalesmanMultipleGuidesPathRelinker original, Cloner cloner) : base(original, cloner) { }
+    public TravelingSalesmanMultipleGuidesPathRelinker()
+      : base() {
+      #region Create parameters
+      Parameters.Add(new LookupParameter<DistanceMatrix>("DistanceMatrix"));
+      #endregion
+      ParentsParameter.ActualName = "TSPTour";
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new TravelingSalesmanMultipleGuidesPathRelinker(this, cloner);
+    }
+
+    public static ItemArray<IItem> Apply(IItem initiator, IItem[] guides, DistanceMatrix distances, PercentValue n) {
+      if (!(initiator is Permutation) || guides.Any(x => !(x is Permutation)))
+        throw new ArgumentException("Cannot relink path because some of the provided solutions have the wrong type.");
+      if (n.Value <= 0.0)
+        throw new ArgumentException("RelinkingAccuracy must be greater than 0.");
+
+      var v1 = initiator.Clone() as Permutation;
+      var targets = new Permutation[guides.Length];
+      Array.Copy(guides, targets, guides.Length);
+
+      if (targets.Any(x => x.Length != v1.Length))
+        throw new ArgumentException("At least one solution is of different length.");
+
+      var solutions = new List<Permutation>();
+      for (int i = 0; i < v1.Length; i++) {
+        var currCityIndex = i;
+        var bestCityIndex = (i + 1) % v1.Length;
+        var currDistance = distances[v1[currCityIndex], v1[bestCityIndex]];
+        targets.ToList().ForEach(solution => {
+          var node = solution.Select((x, index) => new { Id = x, Index = index }).First(x => x.Id == v1[currCityIndex]);
+          var pred = solution[(node.Index - 1 + solution.Length) % solution.Length];
+          var succ = solution[(node.Index + 1) % solution.Length];
+          var results = new[] { pred, succ }.Select(x => new { Id = x, Distance = distances[x, node.Id] });
+          if (results.Any(x => x.Distance < currDistance)) {
+            var bestCity = results.OrderBy(x => x.Distance).First();
+            bestCityIndex = v1.Select((x, index) => new { Id = x, Index = index }).First(x => x.Id == bestCity.Id).Index;
+            currDistance = bestCity.Distance;
+          }
+        });
+        Invert(v1, i, bestCityIndex);
+        solutions.Add(v1.Clone() as Permutation);
+      }
+
+      var selection = new List<IItem>();
+      if (solutions.Count > 0) {
+        var noSol = (int)Math.Round(solutions.Count * n.Value);
+        if (noSol <= 0) noSol++;
+        var stepSize = (double)solutions.Count / (double)noSol;
+        for (int i = 0; i < noSol; i++)
+          selection.Add(solutions.ElementAt((int)Math.Round((i + 1) * stepSize - stepSize * 0.5)));
+      }
+
+      return new ItemArray<IItem>(selection);
+    }
+
+    private static void Invert(Permutation sol, int i, int j) {
+      if (i != j)
+        for (int a = 0; a < Math.Abs(i - j) / 2; a++)
+          if (sol[(i + a) % sol.Length] != sol[(j - a + sol.Length) % sol.Length]) {
+            // XOR swap
+            sol[(i + a) % sol.Length] ^= sol[(j - a + sol.Length) % sol.Length];
+            sol[(j - a + sol.Length) % sol.Length] ^= sol[(i + a) % sol.Length];
+            sol[(i + a) % sol.Length] ^= sol[(j - a + sol.Length) % sol.Length];
+          }
+    }
+
+    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.");
+      return Apply(parents[0], parents.Skip(1).ToArray(), DistanceMatrix, n);
+    }
+  }
+}
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TravelingSalesman/TravelingSalesmanPathRelinker.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TravelingSalesman/TravelingSalesmanPathRelinker.cs	(revision 7774)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TravelingSalesman/TravelingSalesmanPathRelinker.cs	(revision 7775)
@@ -49,28 +49,35 @@
 
     public static ItemArray<IItem> Apply(IItem initiator, IItem guide, PercentValue n) {
+      if (!(initiator is Permutation) || !(guide is Permutation))
+        throw new ArgumentException("Cannot relink path because one of the provided solutions or both have the wrong type.");
+      if (n.Value <= 0.0)
+        throw new ArgumentException("RelinkingAccuracy must be greater than 0.");
+
       var v1 = initiator.Clone() as Permutation;
       var v2 = guide as Permutation;
 
       if (v1.Length != v2.Length)
-        throw new ArgumentException("TravelingSalesmanPathRelinker: The solutions are of different length.");
-      if (n.Value == 0.0)
-        throw new ArgumentException("TravelingSalesmanPathRelinker: RelinkingAccuracy is 0.");
+        throw new ArgumentException("The solutions are of different length.");
 
       var solutions = new List<Permutation>();
-      for (int i = 0; i < v1.Length; i++) {
+      for (int i = 0; i < v1.Length; i++)
         if (v1[i] != v2[i]) {
           var target = v1.Select((x, index) => new { Value = x, ValueIndex = index }).First(x => x.Value == v2[i]);
-          // XOR swap
-          v1[i] ^= v1[target.ValueIndex];
-          v1[target.ValueIndex] ^= v1[i];
-          v1[i] ^= v1[target.ValueIndex];
-          solutions.Add((Permutation)v1.Clone());
+          if (v1[i] != v1[target.ValueIndex]) {
+            // XOR swap
+            v1[i] ^= v1[target.ValueIndex];
+            v1[target.ValueIndex] ^= v1[i];
+            v1[i] ^= v1[target.ValueIndex];
+            solutions.Add(v1.Clone() as Permutation);
+          }
         }
-      }
 
-      var stepSize = 1 / n.Value;
       var selection = new List<IItem>();
-      for (int i = 0; i < solutions.Count; i = (int)Math.Round(i + stepSize)) {
-        selection.Add(solutions.ElementAt(i));
+      if (solutions.Count > 0) {
+        var noSol = (int)Math.Round(solutions.Count * n.Value);
+        if (noSol <= 0) noSol++;
+        var stepSize = (double)solutions.Count / (double)noSol;
+        for (int i = 0; i < noSol; i++)
+          selection.Add(solutions.ElementAt((int)Math.Round((i + 1) * stepSize - stepSize * 0.5)));
       }
 
@@ -79,5 +86,6 @@
 
     protected override ItemArray<IItem> Relink(ItemArray<IItem> parents, PercentValue n) {
-      if (parents.Length != 2) throw new ArgumentException("TravelingSalesmanPathRelinker: The number of parents is not equal to 2.");
+      if (parents.Length != 2)
+        throw new ArgumentException("The number of parents is not equal to 2.");
       return Apply(parents[0], parents[1], n);
     }
Index: branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TravelingSalesman/TravelingSalesmanSimultaneousPathRelinker.cs
===================================================================
--- branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TravelingSalesman/TravelingSalesmanSimultaneousPathRelinker.cs	(revision 7775)
+++ branches/ScatterSearch/HeuristicLab.Algorithms.ScatterSearch/3.3/TravelingSalesman/TravelingSalesmanSimultaneousPathRelinker.cs	(revision 7775)
@@ -0,0 +1,103 @@
+﻿#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;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Algorithms.ScatterSearch.TravelingSalesman {
+  /// <summary>
+  /// An operator that relinks paths between traveling salesman solutions starting from both ends.
+  /// </summary>
+  [Item("TravelingSalesmanSimultaneousPathRelinker", "An operator that relinks paths between traveling salesman solutions starting from both ends.")]
+  [StorableClass]
+  public sealed class TravelingSalesmanSimultaneousPathRelinker : PathRelinker {
+    [StorableConstructor]
+    private TravelingSalesmanSimultaneousPathRelinker(bool deserializing) : base(deserializing) { }
+    private TravelingSalesmanSimultaneousPathRelinker(TravelingSalesmanSimultaneousPathRelinker original, Cloner cloner) : base(original, cloner) { }
+    public TravelingSalesmanSimultaneousPathRelinker()
+      : base() {
+      ParentsParameter.ActualName = "TSPTour";
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new TravelingSalesmanSimultaneousPathRelinker(this, cloner);
+    }
+
+    public static ItemArray<IItem> Apply(IItem initiator, IItem guide, PercentValue n) {
+      if (!(initiator is Permutation) || !(guide is Permutation))
+        throw new ArgumentException("Cannot relink path because one of the provided solutions or both have the wrong type.");
+      if (n.Value <= 0.0)
+        throw new ArgumentException("RelinkingAccuracy must be greater than 0.");
+
+      var firstInitiator = initiator.Clone() as Permutation;
+      var firstGuide = guide.Clone() as Permutation;
+      var secondInitiator = firstGuide.Clone() as Permutation;
+      var secondGuide = firstInitiator.Clone() as Permutation;
+
+      if (firstInitiator.Length != firstGuide.Length)
+        throw new ArgumentException("The solutions are of different length.");
+
+      var solutions = new List<Permutation>();
+      for (int i = 0; i < firstInitiator.Length / 2; i++) {
+        if (firstInitiator[i] != firstGuide[i]) {
+          var target = firstInitiator.Select((x, index) => new { Value = x, ValueIndex = index }).First(x => x.Value == firstGuide[i]);
+          // XOR swap
+          firstInitiator[i] ^= firstInitiator[target.ValueIndex];
+          firstInitiator[target.ValueIndex] ^= firstInitiator[i];
+          firstInitiator[i] ^= firstInitiator[target.ValueIndex];
+          solutions.Add(firstInitiator.Clone() as Permutation);
+        }
+        var j = secondInitiator.Length - 1 - i;
+        if (secondInitiator[j] != secondGuide[j]) {
+          var target = secondInitiator.Select((x, index) => new { Value = x, ValueIndex = index }).First(x => x.Value == secondGuide[j]);
+          // XOR swap
+          secondInitiator[j] ^= secondInitiator[target.ValueIndex];
+          secondInitiator[target.ValueIndex] ^= secondInitiator[j];
+          secondInitiator[j] ^= secondInitiator[target.ValueIndex];
+          solutions.Add(secondInitiator.Clone() as Permutation);
+        }
+      }
+
+      var selection = new List<IItem>();
+      if (solutions.Count > 0) {
+        var noSol = (int)Math.Round(solutions.Count * n.Value);
+        if (noSol <= 0) noSol++;
+        var stepSize = (double)solutions.Count / (double)noSol;
+        for (int i = 0; i < noSol; i++)
+          selection.Add(solutions.ElementAt((int)Math.Round((i + 1) * stepSize - stepSize * 0.5)));
+      }
+
+      return new ItemArray<IItem>(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.");
+      return Apply(parents[0], parents[1], n);
+    }
+  }
+}
