Index: /branches/RAPGA/HeuristicLab.Algorithms.RAPGA/3.3/HeuristicLab.Algorithms.RAPGA-3.3.csproj
===================================================================
--- /branches/RAPGA/HeuristicLab.Algorithms.RAPGA/3.3/HeuristicLab.Algorithms.RAPGA-3.3.csproj	(revision 8348)
+++ /branches/RAPGA/HeuristicLab.Algorithms.RAPGA/3.3/HeuristicLab.Algorithms.RAPGA-3.3.csproj	(revision 8349)
@@ -97,4 +97,5 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="DuplicateSelector.cs" />
     <Compile Include="RAPGA.cs" />
     <Compile Include="RAPGAMainLoop.cs" />
Index: /branches/RAPGA/HeuristicLab.Algorithms.RAPGA/3.3/RAPGA.cs
===================================================================
--- /branches/RAPGA/HeuristicLab.Algorithms.RAPGA/3.3/RAPGA.cs	(revision 8348)
+++ /branches/RAPGA/HeuristicLab.Algorithms.RAPGA/3.3/RAPGA.cs	(revision 8349)
@@ -66,7 +66,7 @@
     private IValueParameter<IntValue> MinimumPopulationSizeParameter {
       get { return (IValueParameter<IntValue>)Parameters["MinimumPopulationSize"]; }
-    } 
+    }
     private IValueParameter<IntValue> MaximumPopulationSizeParameter {
-      get { return (IValueParameter<IntValue>) Parameters["MaximumPopulationSize"]; }
+      get { return (IValueParameter<IntValue>)Parameters["MaximumPopulationSize"]; }
     }
     private IValueParameter<DoubleValue> ComparisonFactorParameter {
@@ -96,4 +96,7 @@
     private ValueParameter<IntValue> MaximumGenerationsParameter {
       get { return (ValueParameter<IntValue>)Parameters["MaximumGenerations"]; }
+    }
+    public IConstrainedValueParameter<ISolutionSimilarityCalculator> SimilarityCalculatorParameter {
+      get { return (IConstrainedValueParameter<ISolutionSimilarityCalculator>)Parameters["SimilarityCalculator"]; }
     }
     #endregion
@@ -155,4 +158,8 @@
       get { return MaximumGenerationsParameter.Value; }
       set { MaximumGenerationsParameter.Value = value; }
+    }
+    public ISolutionSimilarityCalculator SimilarityCalculator {
+      get { return SimilarityCalculatorParameter.Value; }
+      set { SimilarityCalculatorParameter.Value = value; }
     }
     private RandomCreator RandomCreator {
@@ -194,4 +201,5 @@
       Parameters.Add(new ValueParameter<MultiAnalyzer>("Analyzer", "The operator used to analyze each generation.", new MultiAnalyzer()));
       Parameters.Add(new ValueParameter<IntValue>("MaximumGenerations", "The maximum number of generations which should be processed.", new IntValue(1000)));
+      Parameters.Add(new ConstrainedValueParameter<ISolutionSimilarityCalculator>("SimilarityCalculator", "The operator used to calculate the similarity between two solutions."));
 
       RandomCreator randomCreator = new RandomCreator();
@@ -249,5 +257,5 @@
 
     public override void Prepare() {
-      if (Problem != null) base.Prepare();
+      if (Problem != null && SimilarityCalculator != null) base.Prepare();
     }
 
@@ -258,5 +266,4 @@
       foreach (IOperator op in Problem.Operators.OfType<IOperator>()) ParameterizeStochasticOperator(op);
       ParameterizeSolutionsCreator();
-      ParameterizeGeneticAlgorithmMainLoop();
       ParameterizeSelectors();
       ParameterizeAnalyzers();
@@ -265,4 +272,6 @@
       UpdateMutators();
       UpdateAnalyzers();
+      UpdateSimilarityCalculators();
+      ParameterizeRAPGAMainLoop();
       Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
       base.OnProblemChanged();
@@ -277,5 +286,5 @@
       ParameterizeStochasticOperator(Problem.Evaluator);
       ParameterizeSolutionsCreator();
-      ParameterizeGeneticAlgorithmMainLoop();
+      ParameterizeRAPGAMainLoop();
       ParameterizeSelectors();
       ParameterizeAnalyzers();
@@ -284,9 +293,11 @@
     }
     protected override void Problem_OperatorsChanged(object sender, EventArgs e) {
-      foreach (IOperator op in Problem.Operators) ParameterizeStochasticOperator(op);
+      foreach (IOperator op in Problem.Operators.OfType<IOperator>()) ParameterizeStochasticOperator(op);
       ParameterizeIterationBasedOperators();
       UpdateCrossovers();
       UpdateMutators();
       UpdateAnalyzers();
+      UpdateSimilarityCalculators();
+      ParameterizeRAPGAMainLoop();
       base.Problem_OperatorsChanged(sender, e);
     }
@@ -307,5 +318,5 @@
     }
     private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) {
-      ParameterizeGeneticAlgorithmMainLoop();
+      ParameterizeRAPGAMainLoop();
       ParameterizeSelectors();
       ParameterizeAnalyzers();
@@ -328,8 +339,10 @@
       SolutionsCreator.SolutionCreatorParameter.ActualName = Problem.SolutionCreatorParameter.Name;
     }
-    private void ParameterizeGeneticAlgorithmMainLoop() {
+    private void ParameterizeRAPGAMainLoop() {
       RAPGAMainLoop.EvaluatorParameter.ActualName = Problem.EvaluatorParameter.Name;
       RAPGAMainLoop.MaximizationParameter.ActualName = Problem.MaximizationParameter.Name;
       RAPGAMainLoop.QualityParameter.ActualName = Problem.Evaluator.QualityParameter.ActualName;
+      foreach (ISimilarityBasedOperator op in RAPGAMainLoop.OperatorGraph.Operators.OfType<ISimilarityBasedOperator>())
+        op.SimilarityCalculator = SimilarityCalculator;
     }
     private void ParameterizeStochasticOperator(IOperator op) {
@@ -416,4 +429,20 @@
       Analyzer.Operators.Add(qualityAnalyzer, qualityAnalyzer.EnabledByDefault);
     }
+    private void UpdateSimilarityCalculators() {
+      ISolutionSimilarityCalculator oldSimilarityCalculator = SimilarityCalculatorParameter.Value;
+      SimilarityCalculatorParameter.ValidValues.Clear();
+      ISolutionSimilarityCalculator defaultSimilarityCalculator = Problem.Operators.OfType<ISolutionSimilarityCalculator>().FirstOrDefault();
+
+      foreach (ISolutionSimilarityCalculator similarityCalculator in Problem.Operators.OfType<ISolutionSimilarityCalculator>())
+        SimilarityCalculatorParameter.ValidValues.Add(similarityCalculator);
+
+      if (oldSimilarityCalculator != null) {
+        ISolutionSimilarityCalculator similarityCalculator = SimilarityCalculatorParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldSimilarityCalculator.GetType());
+        if (similarityCalculator != null) SimilarityCalculatorParameter.Value = similarityCalculator;
+        else oldSimilarityCalculator = null;
+      }
+      if (oldSimilarityCalculator == null && defaultSimilarityCalculator != null)
+        SimilarityCalculatorParameter.Value = defaultSimilarityCalculator;
+    }
     private RAPGAMainLoop FindMainLoop(IOperator start) {
       IOperator mainLoop = start;
Index: /branches/RAPGA/HeuristicLab.Algorithms.RAPGA/3.3/RAPGAMainLoop.cs
===================================================================
--- /branches/RAPGA/HeuristicLab.Algorithms.RAPGA/3.3/RAPGAMainLoop.cs	(revision 8348)
+++ /branches/RAPGA/HeuristicLab.Algorithms.RAPGA/3.3/RAPGAMainLoop.cs	(revision 8349)
@@ -151,8 +151,10 @@
       ConditionalSelector conditionalSelector = new ConditionalSelector();
       RightReducer rightReducer1 = new RightReducer();
+      UniformSubScopesProcessor uniformSubScopesProcessor3 = new UniformSubScopesProcessor();
+      SubScopesRemover subScopesRemover = new SubScopesRemover();
+      DuplicateSelector duplicateSelector = new DuplicateSelector();
+      LeftReducer leftReducer = new LeftReducer();
       SubScopesCounter subScopesCounter1 = new SubScopesCounter();
       IntCounter intCounter1 = new IntCounter();
-      UniformSubScopesProcessor uniformSubScopesProcessor3 = new UniformSubScopesProcessor();
-      SubScopesRemover subScopesRemover = new SubScopesRemover();
       Comparator comparator2 = new Comparator();
       ConditionalBranch conditionalBranch1 = new ConditionalBranch();
@@ -217,4 +219,10 @@
       conditionalSelector.CopySelected.Value = false;
 
+      duplicateSelector.CopySelected.Value = false;
+
+      uniformSubScopesProcessor3.Parallel.Value = true;
+
+      subScopesRemover.RemoveAllSubScopes = true;
+
       subScopesCounter1.Name = "Count Successful Offspring";
       subScopesCounter1.ValueParameter.ActualName = "NumberOfSuccessfulOffspring";
@@ -223,8 +231,4 @@
       intCounter1.IncrementParameter.Value = null;
       intCounter1.ValueParameter.ActualName = EvaluatedSolutionsParameter.Name;
-
-      uniformSubScopesProcessor3.Parallel.Value = true;
-
-      subScopesRemover.RemoveAllSubScopes = true;
 
       comparator2.Comparison = new Comparison(ComparisonType.GreaterOrEqual);
@@ -267,5 +271,5 @@
       assigner2.RightSideParameter.Value = new IntValue(0);
 
-      subScopesCounter2.Name = "Increment EvaluatedSolutions";
+      subScopesCounter2.Name = "Set CurrentPopulationSize";
       subScopesCounter2.ValueParameter.ActualName = "CurrentPopulationSize";
 
@@ -304,9 +308,11 @@
       evaluator.Successor = comparator1;
       conditionalSelector.Successor = rightReducer1;
-      rightReducer1.Successor = subScopesCounter1;
+      rightReducer1.Successor = uniformSubScopesProcessor3;
+      uniformSubScopesProcessor3.Operator = subScopesRemover;
+      uniformSubScopesProcessor3.Successor = duplicateSelector;
+      duplicateSelector.Successor = leftReducer;
+      leftReducer.Successor = subScopesCounter1;
       subScopesCounter1.Successor = intCounter1;
-      intCounter1.Successor = uniformSubScopesProcessor3;
-      uniformSubScopesProcessor3.Operator = subScopesRemover;
-      uniformSubScopesProcessor3.Successor = comparator2;
+      intCounter1.Successor = comparator2;
       comparator2.Successor = conditionalBranch1;
       conditionalBranch1.TrueBranch = bestSelector1;
