Index: branches/ScatterSearch (trunk integration)/HeuristicLab.Problems.Knapsack/3.3/HeuristicLab.Problems.Knapsack-3.3.csproj
===================================================================
--- branches/ScatterSearch (trunk integration)/HeuristicLab.Problems.Knapsack/3.3/HeuristicLab.Problems.Knapsack-3.3.csproj	(revision 7787)
+++ branches/ScatterSearch (trunk integration)/HeuristicLab.Problems.Knapsack/3.3/HeuristicLab.Problems.Knapsack-3.3.csproj	(revision 7789)
@@ -109,4 +109,5 @@
   <ItemGroup>
     <Compile Include="Evaluators\KnapsackEvaluator.cs" />
+    <Compile Include="Improvers\KnapsackImprovementOperator.cs" />
     <Compile Include="Interfaces\IKnapsackEvaluator.cs" />
     <Compile Include="Interfaces\IKnapsackMoveEvaluator.cs" />
@@ -115,7 +116,11 @@
     <Compile Include="MoveEvaluators\KnapsackMoveEvaluator.cs" />
     <Compile Include="MoveEvaluators\KnapsackOneBitflipMoveEvaluator.cs" />
+    <Compile Include="PathRelinkers\KnapsackMultipleGuidesPathRelinker.cs" />
+    <Compile Include="PathRelinkers\KnapsackPathRelinker.cs" />
+    <Compile Include="PathRelinkers\KnapsackSimultaneousPathRelinker.cs" />
     <Compile Include="Plugin.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Analyzers\BestKnapsackSolutionAnalyzer.cs" />
+    <Compile Include="SimilarityCalculators\KnapsackSimilarityCalculator.cs" />
   </ItemGroup>
   <ItemGroup>
@@ -159,4 +164,8 @@
       <Name>HeuristicLab.Operators-3.3</Name>
       <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Optimization.Operators\3.3\HeuristicLab.Optimization.Operators-3.3.csproj">
+      <Project>{25087811-F74C-4128-BC86-8324271DA13E}</Project>
+      <Name>HeuristicLab.Optimization.Operators-3.3</Name>
     </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Optimization\3.3\HeuristicLab.Optimization-3.3.csproj">
@@ -198,4 +207,5 @@
     </BootstrapperPackage>
   </ItemGroup>
+  <ItemGroup />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
Index: branches/ScatterSearch (trunk integration)/HeuristicLab.Problems.Knapsack/3.3/Improvers/KnapsackImprovementOperator.cs
===================================================================
--- branches/ScatterSearch (trunk integration)/HeuristicLab.Problems.Knapsack/3.3/Improvers/KnapsackImprovementOperator.cs	(revision 7789)
+++ branches/ScatterSearch (trunk integration)/HeuristicLab.Problems.Knapsack/3.3/Improvers/KnapsackImprovementOperator.cs	(revision 7789)
@@ -0,0 +1,145 @@
+﻿#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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.BinaryVectorEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.Knapsack {
+  /// <summary>
+  /// An operator that improves knapsack solutions.
+  /// </summary>
+  [Item("KnapsackImprovementOperator", "An operator that improves knapsack solutions.")]
+  [StorableClass]
+  public sealed class KnapsackImprovementOperator : SingleSuccessorOperator, IImprovementOperator {
+    #region Parameter properties
+    public ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+    public ILookupParameter<IntValue> KnapsackCapacityParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["KnapsackCapacity"]; }
+    }
+    public ILookupParameter<DoubleValue> PenaltyParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Penalty"]; }
+    }
+    public IValueLookupParameter<IItem> TargetParameter {
+      get { return (IValueLookupParameter<IItem>)Parameters["Target"]; }
+    }
+    public ILookupParameter<IntArray> ValuesParameter {
+      get { return (ILookupParameter<IntArray>)Parameters["Values"]; }
+    }
+    public ILookupParameter<IntArray> WeightsParameter {
+      get { return (ILookupParameter<IntArray>)Parameters["Weights"]; }
+    }
+    #endregion
+
+    #region Properties
+    private IScope CurrentScope {
+      get { return CurrentScopeParameter.ActualValue; }
+    }
+    private IntValue KnapsackCapacity {
+      get { return KnapsackCapacityParameter.ActualValue; }
+      set { KnapsackCapacityParameter.ActualValue = value; }
+    }
+    private DoubleValue Penalty {
+      get { return PenaltyParameter.ActualValue; }
+      set { PenaltyParameter.ActualValue = value; }
+    }
+    private IItem Target {
+      get { return TargetParameter.ActualValue; }
+    }
+    private IntArray Values {
+      get { return ValuesParameter.ActualValue; }
+      set { ValuesParameter.ActualValue = value; }
+    }
+    private IntArray Weights {
+      get { return WeightsParameter.ActualValue; }
+      set { WeightsParameter.ActualValue = value; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private KnapsackImprovementOperator(bool deserializing) : base(deserializing) { }
+    private KnapsackImprovementOperator(KnapsackImprovementOperator original, Cloner cloner) : base(original, cloner) { }
+    public KnapsackImprovementOperator()
+      : base() {
+      #region Create parameters
+      Parameters.Add(new ScopeParameter("CurrentScope"));
+      Parameters.Add(new LookupParameter<IntValue>("KnapsackCapacity"));
+      Parameters.Add(new LookupParameter<DoubleValue>("Penalty"));
+      Parameters.Add(new ValueLookupParameter<IItem>("Target"));
+      Parameters.Add(new LookupParameter<IntArray>("Values"));
+      Parameters.Add(new LookupParameter<IntArray>("Weights"));
+      #endregion
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new KnapsackImprovementOperator(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      BinaryVector sol = CurrentScope.Variables[TargetParameter.ActualName].Value as BinaryVector;
+
+      // calculate value-to-weight ratio
+      double[] ratio = new double[Values.Length];
+      for (int i = 0; i < ratio.Length; i++)
+        ratio[i] = (double)Values[i] / (double)Weights[i];
+
+
+      // calculate order for ratio
+      int[] order = new int[ratio.Length];
+      ratio.Select((x, index) => new { Value = x, ValueIndex = index })
+           .OrderBy(x => x.Value)
+           .Select((x, index) => new { ValueIndex = x.ValueIndex, ItemIndex = index }).ToList()
+           .ForEach(x => order[x.ItemIndex] = x.ValueIndex);
+
+      int j = sol.Length - 1;
+      while (KnapsackEvaluator.Apply(sol, KnapsackCapacity, Penalty, Weights, Values)
+                              .SumWeights.Value > KnapsackCapacity.Value && j >= 0)
+        sol[order[j--]] = false;
+
+      // calculate weight
+      int weight = 0;
+      for (int i = 0; i < sol.Length; i++)
+        if (sol[i]) weight += Weights[i];
+
+      // improve solution
+      bool feasible = true; j = 0;
+      while (feasible && j < sol.Length) {
+        while (sol[order[j]]) j++;
+        if (weight + Weights[order[j]] <= KnapsackCapacity.Value) {
+          sol[order[j]] = true;
+          weight += Weights[order[j]];
+        } else feasible = false;
+      }
+
+      CurrentScope.Variables[TargetParameter.ActualName].Value = sol;
+
+      return base.Apply();
+    }
+  }
+}
Index: branches/ScatterSearch (trunk integration)/HeuristicLab.Problems.Knapsack/3.3/KnapsackProblem.cs
===================================================================
--- branches/ScatterSearch (trunk integration)/HeuristicLab.Problems.Knapsack/3.3/KnapsackProblem.cs	(revision 7787)
+++ branches/ScatterSearch (trunk integration)/HeuristicLab.Problems.Knapsack/3.3/KnapsackProblem.cs	(revision 7789)
@@ -28,4 +28,5 @@
 using HeuristicLab.Encodings.BinaryVectorEncoding;
 using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
@@ -244,4 +245,10 @@
     }
     private void InitializeOperators() {
+      Operators.Add(new KnapsackImprovementOperator());
+      Operators.Add(new KnapsackMultipleGuidesPathRelinker());
+      Operators.Add(new KnapsackPathRelinker());
+      Operators.Add(new KnapsackSimultaneousPathRelinker());
+      Operators.Add(new KnapsackSimilarityCalculator());
+
       Operators.Add(new BestKnapsackSolutionAnalyzer());
       ParameterizeAnalyzer();
@@ -290,4 +297,16 @@
         op.BinaryVectorParameter.Hidden = true;
       }
+      foreach (IImprovementOperator op in Operators.OfType<IImprovementOperator>()) {
+        op.TargetParameter.ActualName = SolutionCreator.BinaryVectorParameter.ActualName;
+        op.TargetParameter.Hidden = true;
+      }
+      foreach (IPathRelinker op in Operators.OfType<IPathRelinker>()) {
+        op.ParentsParameter.ActualName = SolutionCreator.BinaryVectorParameter.ActualName;
+        op.ParentsParameter.Hidden = true;
+      }
+      foreach (ISimilarityCalculator op in Operators.OfType<ISimilarityCalculator>()) {
+        op.TargetParameter.ActualName = SolutionCreator.BinaryVectorParameter.ActualName;
+        op.TargetParameter.Hidden = true;
+      }
     }
     #endregion
Index: branches/ScatterSearch (trunk integration)/HeuristicLab.Problems.Knapsack/3.3/PathRelinkers/KnapsackMultipleGuidesPathRelinker.cs
===================================================================
--- branches/ScatterSearch (trunk integration)/HeuristicLab.Problems.Knapsack/3.3/PathRelinkers/KnapsackMultipleGuidesPathRelinker.cs	(revision 7789)
+++ branches/ScatterSearch (trunk integration)/HeuristicLab.Problems.Knapsack/3.3/PathRelinkers/KnapsackMultipleGuidesPathRelinker.cs	(revision 7789)
@@ -0,0 +1,84 @@
+﻿#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.Optimization.Operators;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.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() { }
+
+    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.");
+
+      BinaryVector v1 = initiator.Clone() as BinaryVector;
+      BinaryVector[] 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.");
+
+      IList<BinaryVector> solutions = new List<BinaryVector>();
+      for (int i = 0; i < v1.Length; i++) {
+        // TODO: path relinking
+      }
+
+      IList<IItem> selection = new List<IItem>();
+      if (solutions.Count > 0) {
+        int noSol = (int)(solutions.Count * n.Value);
+        if (noSol <= 0) noSol++;
+        double stepSize = (double)solutions.Count / (double)noSol;
+        for (int i = 0; i < noSol; i++)
+          selection.Add(solutions.ElementAt((int)((i + 1) * stepSize - stepSize * 0.5)));
+      }
+
+      return 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 smaller than 2.");
+      return Apply(parents[0], parents.Skip(1).ToArray(), n);
+    }
+  }
+}
Index: branches/ScatterSearch (trunk integration)/HeuristicLab.Problems.Knapsack/3.3/PathRelinkers/KnapsackPathRelinker.cs
===================================================================
--- branches/ScatterSearch (trunk integration)/HeuristicLab.Problems.Knapsack/3.3/PathRelinkers/KnapsackPathRelinker.cs	(revision 7789)
+++ branches/ScatterSearch (trunk integration)/HeuristicLab.Problems.Knapsack/3.3/PathRelinkers/KnapsackPathRelinker.cs	(revision 7789)
@@ -0,0 +1,85 @@
+﻿#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.Optimization.Operators;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.Knapsack {
+  /// <summary>
+  /// An operator that relinks paths between knapsack solutions.
+  /// </summary>
+  [Item("KnapsackPathRelinker", "An operator that relinks paths between knapsack solutions.")]
+  [StorableClass]
+  public sealed class KnapsackPathRelinker : PathRelinker {
+    [StorableConstructor]
+    private KnapsackPathRelinker(bool deserializing) : base(deserializing) { }
+    private KnapsackPathRelinker(KnapsackPathRelinker original, Cloner cloner) : base(original, cloner) { }
+    public KnapsackPathRelinker() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new KnapsackPathRelinker(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.");
+
+      BinaryVector v1 = initiator.Clone() as BinaryVector;
+      BinaryVector v2 = guide as BinaryVector;
+
+      if (v1.Length != v2.Length)
+        throw new ArgumentException("The solutions are of different length.");
+
+      IList<BinaryVector> solutions = new List<BinaryVector>();
+      for (int i = 0; i < v1.Length; i++)
+        if (v1[i] != v2[i]) {
+          v1[i] = v2[i];
+          solutions.Add(v1.Clone() as BinaryVector);
+        }
+
+      IList<IItem> selection = new List<IItem>();
+      if (solutions.Count > 0) {
+        int noSol = (int)(solutions.Count * n.Value);
+        if (noSol <= 0) noSol++;
+        double stepSize = (double)solutions.Count / (double)noSol;
+        for (int i = 0; i < noSol; i++)
+          selection.Add(solutions.ElementAt((int)((i + 1) * stepSize - stepSize * 0.5)));
+      }
+
+      return 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 (trunk integration)/HeuristicLab.Problems.Knapsack/3.3/PathRelinkers/KnapsackSimultaneousPathRelinker.cs
===================================================================
--- branches/ScatterSearch (trunk integration)/HeuristicLab.Problems.Knapsack/3.3/PathRelinkers/KnapsackSimultaneousPathRelinker.cs	(revision 7789)
+++ branches/ScatterSearch (trunk integration)/HeuristicLab.Problems.Knapsack/3.3/PathRelinkers/KnapsackSimultaneousPathRelinker.cs	(revision 7789)
@@ -0,0 +1,93 @@
+﻿#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.Optimization.Operators;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.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() { }
+
+    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.");
+
+      BinaryVector firstInitiator = initiator.Clone() as BinaryVector;
+      BinaryVector firstGuide = guide.Clone() as BinaryVector;
+      BinaryVector secondInitiator = firstGuide.Clone() as BinaryVector;
+      BinaryVector secondGuide = firstInitiator.Clone() as BinaryVector;
+
+      if (firstInitiator.Length != firstGuide.Length)
+        throw new ArgumentException("The solutions are of different length.");
+
+      IList<BinaryVector> 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);
+        }
+        int j = secondInitiator.Length - 1 - i;
+        if (secondInitiator[j] != secondGuide[j]) {
+          secondInitiator[j] = secondGuide[j];
+          solutions.Add(secondInitiator.Clone() as BinaryVector);
+        }
+      }
+
+      IList<IItem> selection = new List<IItem>();
+      if (solutions.Count > 0) {
+        int noSol = (int)(solutions.Count * n.Value);
+        if (noSol <= 0) noSol++;
+        double stepSize = (double)solutions.Count / (double)noSol;
+        for (int i = 0; i < noSol; i++)
+          selection.Add(solutions.ElementAt((int)((i + 1) * stepSize - stepSize * 0.5)));
+      }
+
+      return 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 (trunk integration)/HeuristicLab.Problems.Knapsack/3.3/SimilarityCalculators/KnapsackSimilarityCalculator.cs
===================================================================
--- branches/ScatterSearch (trunk integration)/HeuristicLab.Problems.Knapsack/3.3/SimilarityCalculators/KnapsackSimilarityCalculator.cs	(revision 7789)
+++ branches/ScatterSearch (trunk integration)/HeuristicLab.Problems.Knapsack/3.3/SimilarityCalculators/KnapsackSimilarityCalculator.cs	(revision 7789)
@@ -0,0 +1,54 @@
+﻿#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.Encodings.BinaryVectorEncoding;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.Knapsack {
+  /// <summary>
+  /// An operator that performs similarity calculation between two knapsack solutions.
+  /// </summary>
+  [Item("KnapsackSimilarityCalculator", "An operator that performs similarity calculation between two knapsack solutions.")]
+  [StorableClass]
+  public sealed class KnapsackSimilarityCalculator : SimilarityCalculator {
+    [StorableConstructor]
+    private KnapsackSimilarityCalculator(bool deserializing) : base(deserializing) { }
+    private KnapsackSimilarityCalculator(KnapsackSimilarityCalculator original, Cloner cloner) : base(original, cloner) { }
+    public KnapsackSimilarityCalculator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new KnapsackSimilarityCalculator(this, cloner);
+    }
+
+    protected override double CalculateDiversity(IScope left, IScope right) {
+      BinaryVector sol1 = left.Variables[TargetParameter.ActualName].Value as BinaryVector;
+      BinaryVector sol2 = right.Variables[TargetParameter.ActualName].Value as BinaryVector;
+
+      double similarity = 0.0;
+      for (int i = 0; i < sol1.Length; i++)
+        if (sol1[i] == sol2[i]) similarity++;
+      return similarity / sol1.Length;
+    }
+  }
+}
