Index: /stable/HeuristicLab.Algorithms.LocalSearch/3.3/LocalSearchImprovementOperator.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.LocalSearch/3.3/LocalSearchImprovementOperator.cs	(revision 12279)
+++ /stable/HeuristicLab.Algorithms.LocalSearch/3.3/LocalSearchImprovementOperator.cs	(revision 12280)
@@ -251,5 +251,5 @@
         foreach (IAnalyzer analyzer in problem.Operators.OfType<IAnalyzer>()) {
           if (!IsSubclassOfGeneric(typeof(AlleleFrequencyAnalyzer<>), analyzer.GetType()) &&
-              !(analyzer is SingleObjectivePopulationDiversityAnalyzer)) {
+              !(analyzer is PopulationSimilarityAnalyzer)) {
             IAnalyzer clone = analyzer.Clone() as IAnalyzer;
             foreach (IScopeTreeLookupParameter param in clone.Parameters.OfType<IScopeTreeLookupParameter>())
Index: /stable/HeuristicLab.Algorithms.RAPGA/3.3/DuplicatesSelector.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.RAPGA/3.3/DuplicatesSelector.cs	(revision 12279)
+++ /stable/HeuristicLab.Algorithms.RAPGA/3.3/DuplicatesSelector.cs	(revision 12280)
@@ -25,4 +25,5 @@
 using HeuristicLab.Core;
 using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 using HeuristicLab.Selection;
@@ -37,20 +38,28 @@
   [Item("DuplicatesSelector", "A selection operator which considers a single solution representation and selects duplicates. The remaining scope then contains unique solutions and the selected scope their duplicates.")]
   [StorableClass]
-  public sealed class DuplicatesSelector : SingleObjectiveSelector, ISimilarityBasedOperator {
-    #region ISimilarityBasedOperator Members
-    [Storable]
-    public ISolutionSimilarityCalculator SimilarityCalculator { get; set; }
-    #endregion
+  public sealed class DuplicatesSelector : SingleObjectiveSelector {
+    public IValueLookupParameter<ISolutionSimilarityCalculator> SimilarityCalculatorParameter {
+      get { return (IValueLookupParameter<ISolutionSimilarityCalculator>)Parameters["SimilarityCalculator"]; }
+    }
 
     [StorableConstructor]
     private DuplicatesSelector(bool deserializing) : base(deserializing) { }
-    private DuplicatesSelector(DuplicatesSelector original, Cloner cloner)
-      : base(original, cloner) {
-      this.SimilarityCalculator = cloner.Clone(original.SimilarityCalculator);
+    private DuplicatesSelector(DuplicatesSelector original, Cloner cloner) : base(original, cloner) { }
+    public DuplicatesSelector()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<ISolutionSimilarityCalculator>("SimilarityCalculator", "The similarity calculator that should be used to calculate solution similarity."));
     }
-    public DuplicatesSelector() : base() { }
 
     public override IDeepCloneable Clone(Cloner cloner) {
       return new DuplicatesSelector(this, cloner);
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (!Parameters.ContainsKey("SimilarityCalculator"))
+        Parameters.Add(new ValueLookupParameter<ISolutionSimilarityCalculator>("SimilarityCalculator", "The similarity calculator that should be used to calculate solution similarity."));
+      #endregion
     }
 
@@ -61,5 +70,5 @@
       for (int i = 0; i < scopes.Count; i++)
         for (int j = i + 1; j < scopes.Count; j++)
-          marks[j] = SimilarityCalculator.Equals(scopes[i], scopes[j]);
+          marks[j] = SimilarityCalculatorParameter.ActualValue.Equals(scopes[i], scopes[j]);
 
 
Index: /stable/HeuristicLab.Algorithms.RAPGA/3.3/ProgressiveOffspringPreserver.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.RAPGA/3.3/ProgressiveOffspringPreserver.cs	(revision 12279)
+++ /stable/HeuristicLab.Algorithms.RAPGA/3.3/ProgressiveOffspringPreserver.cs	(revision 12280)
@@ -38,10 +38,5 @@
   [Item("ProgressiveOffspringPreserver", "An operator that progressively selects offspring by adding it to a scope list. The operator also performs duplication control.")]
   [StorableClass]
-  public sealed class ProgressiveOffspringPreserver : SingleSuccessorOperator, ISimilarityBasedOperator {
-    #region ISimilarityBasedOperator Members
-    [Storable]
-    public ISolutionSimilarityCalculator SimilarityCalculator { get; set; }
-    #endregion
-
+  public sealed class ProgressiveOffspringPreserver : SingleSuccessorOperator {
     #region Parameter Properties
     public ScopeParameter CurrentScopeParameter {
@@ -56,4 +51,7 @@
     public ILookupParameter<IntValue> MaximumPopulationSizeParameter {
       get { return (ILookupParameter<IntValue>)Parameters["MaximumPopulationSize"]; }
+    }
+    public IValueLookupParameter<ISolutionSimilarityCalculator> SimilarityCalculatorParameter {
+      get { return (IValueLookupParameter<ISolutionSimilarityCalculator>)Parameters["SimilarityCalculator"]; }
     }
     #endregion
@@ -76,18 +74,27 @@
     [StorableConstructor]
     private ProgressiveOffspringPreserver(bool deserializing) : base(deserializing) { }
-    private ProgressiveOffspringPreserver(ProgressiveOffspringPreserver original, Cloner cloner)
-      : base(original, cloner) {
-      this.SimilarityCalculator = cloner.Clone(original.SimilarityCalculator);
-    }
+    private ProgressiveOffspringPreserver(ProgressiveOffspringPreserver original, Cloner cloner) : base(original, cloner) { }
     public ProgressiveOffspringPreserver()
       : base() {
+      #region Create parameters
       Parameters.Add(new ScopeParameter("CurrentScope", "The current scope that contains the offspring."));
       Parameters.Add(new LookupParameter<ScopeList>("OffspringList", "The list that contains the offspring."));
       Parameters.Add(new LookupParameter<IntValue>("Elites", "The numer of elite solutions which are kept in each generation."));
       Parameters.Add(new LookupParameter<IntValue>("MaximumPopulationSize", "The maximum size of the population of solutions."));
+      Parameters.Add(new ValueLookupParameter<ISolutionSimilarityCalculator>("SimilarityCalculator", "The similarity calculator that should be used to calculate solution similarity."));
+      #endregion
     }
 
     public override IDeepCloneable Clone(Cloner cloner) {
       return new ProgressiveOffspringPreserver(this, cloner);
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (!Parameters.ContainsKey("SimilarityCalculator"))
+        Parameters.Add(new ValueLookupParameter<ISolutionSimilarityCalculator>("SimilarityCalculator", "The similarity calculator that should be used to calculate solution similarity."));
+      #endregion
     }
 
@@ -98,5 +105,5 @@
           var storedOffspringScope = new Scope();
           storedOffspringScope.SubScopes.AddRange(OffspringList);
-          var similarityMatrix = SimilarityCalculator.CalculateSolutionCrowdSimilarity(CurrentScope, storedOffspringScope);
+          var similarityMatrix = SimilarityCalculatorParameter.ActualValue.CalculateSolutionCrowdSimilarity(CurrentScope, storedOffspringScope);
 
           var createdOffspring = CurrentScope.SubScopes.ToArray();
Index: /stable/HeuristicLab.Algorithms.RAPGA/3.3/RAPGA.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.RAPGA/3.3/RAPGA.cs	(revision 12279)
+++ /stable/HeuristicLab.Algorithms.RAPGA/3.3/RAPGA.cs	(revision 12280)
@@ -103,6 +103,6 @@
       get { return (ValueParameter<IntValue>)Parameters["MaximumGenerations"]; }
     }
-    public IConstrainedValueParameter<ISingleObjectiveSolutionSimilarityCalculator> SimilarityCalculatorParameter {
-      get { return (IConstrainedValueParameter<ISingleObjectiveSolutionSimilarityCalculator>)Parameters["SimilarityCalculator"]; }
+    public IConstrainedValueParameter<ISolutionSimilarityCalculator> SimilarityCalculatorParameter {
+      get { return (IConstrainedValueParameter<ISolutionSimilarityCalculator>)Parameters["SimilarityCalculator"]; }
     }
     #endregion
@@ -173,5 +173,5 @@
       set { MaximumGenerationsParameter.Value = value; }
     }
-    public ISingleObjectiveSolutionSimilarityCalculator SimilarityCalculator {
+    public ISolutionSimilarityCalculator SimilarityCalculator {
       get { return SimilarityCalculatorParameter.Value; }
       set { SimilarityCalculatorParameter.Value = value; }
@@ -204,4 +204,14 @@
       if (!Parameters.ContainsKey("ReevaluateElites")) {
         Parameters.Add(new FixedValueParameter<BoolValue>("ReevaluateElites", "Flag to determine if elite individuals should be reevaluated (i.e., if stochastic fitness functions are used.)", (BoolValue)new BoolValue(false).AsReadOnly()) { Hidden = true });
+      }
+      if (Parameters.ContainsKey("SimilarityCalculator")) {
+#pragma warning disable 0618
+        var oldParameter = (IConstrainedValueParameter<ISingleObjectiveSolutionSimilarityCalculator>)Parameters["SimilarityCalculator"];
+#pragma warning restore 0618
+        Parameters.Remove(oldParameter);
+        var newParameter = new ConstrainedValueParameter<ISolutionSimilarityCalculator>("SimilarityCalculator", "The operator used to calculate the similarity between two solutions.", new ItemSet<ISolutionSimilarityCalculator>(oldParameter.ValidValues));
+        var selectedSimilarityCalculator = newParameter.ValidValues.SingleOrDefault(x => x.GetType() == oldParameter.Value.GetType());
+        newParameter.Value = selectedSimilarityCalculator;
+        Parameters.Add(newParameter);
       }
       #endregion
@@ -234,5 +244,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<ISingleObjectiveSolutionSimilarityCalculator>("SimilarityCalculator", "The operator used to calculate the similarity between two solutions."));
+      Parameters.Add(new ConstrainedValueParameter<ISolutionSimilarityCalculator>("SimilarityCalculator", "The operator used to calculate the similarity between two solutions."));
 
       RandomCreator randomCreator = new RandomCreator();
@@ -394,6 +404,4 @@
       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) {
@@ -450,5 +458,5 @@
     }
     private void ParameterizeSimilarityCalculators() {
-      foreach (ISingleObjectiveSolutionSimilarityCalculator calc in SimilarityCalculatorParameter.ValidValues) {
+      foreach (ISolutionSimilarityCalculator calc in SimilarityCalculatorParameter.ValidValues) {
         calc.QualityVariableName = Problem.Evaluator.QualityParameter.ActualName;
       }
@@ -495,16 +503,20 @@
     }
     private void UpdateSimilarityCalculators() {
-      ISingleObjectiveSolutionSimilarityCalculator oldSimilarityCalculator = SimilarityCalculatorParameter.Value;
+      ISolutionSimilarityCalculator oldSimilarityCalculator = SimilarityCalculatorParameter.Value;
       SimilarityCalculatorParameter.ValidValues.Clear();
-      ISingleObjectiveSolutionSimilarityCalculator defaultSimilarityCalculator = Problem.Operators.OfType<ISingleObjectiveSolutionSimilarityCalculator>().FirstOrDefault();
-
-      SimilarityCalculatorParameter.ValidValues.Add(new QualitySimilarityCalculator { QualityVariableName = Problem.Evaluator.QualityParameter.ActualName });
-      SimilarityCalculatorParameter.ValidValues.Add(new NoSimilarityCalculator());
-
-      foreach (ISingleObjectiveSolutionSimilarityCalculator similarityCalculator in Problem.Operators.OfType<ISingleObjectiveSolutionSimilarityCalculator>())
+      ISolutionSimilarityCalculator defaultSimilarityCalculator = Problem.Operators.OfType<ISolutionSimilarityCalculator>().FirstOrDefault();
+
+      foreach (ISolutionSimilarityCalculator similarityCalculator in Problem.Operators.OfType<ISolutionSimilarityCalculator>())
         SimilarityCalculatorParameter.ValidValues.Add(similarityCalculator);
 
+      if (!SimilarityCalculatorParameter.ValidValues.OfType<QualitySimilarityCalculator>().Any())
+        SimilarityCalculatorParameter.ValidValues.Add(new QualitySimilarityCalculator {
+          QualityVariableName = Problem.Evaluator.QualityParameter.ActualName
+        });
+      if (!SimilarityCalculatorParameter.ValidValues.OfType<NoSimilarityCalculator>().Any())
+        SimilarityCalculatorParameter.ValidValues.Add(new NoSimilarityCalculator());
+
       if (oldSimilarityCalculator != null) {
-        ISingleObjectiveSolutionSimilarityCalculator similarityCalculator = SimilarityCalculatorParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldSimilarityCalculator.GetType());
+        ISolutionSimilarityCalculator similarityCalculator = SimilarityCalculatorParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldSimilarityCalculator.GetType());
         if (similarityCalculator != null) SimilarityCalculatorParameter.Value = similarityCalculator;
         else oldSimilarityCalculator = null;
Index: /stable/HeuristicLab.Algorithms.ScatterSearch/3.3/ReferenceSetUpdateMethod.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.ScatterSearch/3.3/ReferenceSetUpdateMethod.cs	(revision 12279)
+++ /stable/HeuristicLab.Algorithms.ScatterSearch/3.3/ReferenceSetUpdateMethod.cs	(revision 12280)
@@ -36,10 +36,5 @@
   [Item("ReferenceSetUpdateMethod", "An operator that updates the reference set.")]
   [StorableClass]
-  public sealed class ReferenceSetUpdateMethod : SingleSuccessorOperator, ISimilarityBasedOperator {
-    #region ISimilarityBasedOperator Members
-    [Storable]
-    public ISolutionSimilarityCalculator SimilarityCalculator { get; set; }
-    #endregion
-
+  public sealed class ReferenceSetUpdateMethod : SingleSuccessorOperator {
     #region Parameter properties
     public ScopeParameter CurrentScopeParameter {
@@ -48,4 +43,7 @@
     public IValueLookupParameter<IntValue> ReferenceSetSizeParameter {
       get { return (IValueLookupParameter<IntValue>)Parameters["ReferenceSetSize"]; }
+    }
+    public IValueLookupParameter<ISolutionSimilarityCalculator> SimilarityCalculatorParameter {
+      get { return (IValueLookupParameter<ISolutionSimilarityCalculator>)Parameters["SimilarityCalculator"]; }
     }
     #endregion
@@ -62,8 +60,5 @@
     [StorableConstructor]
     private ReferenceSetUpdateMethod(bool deserializing) : base(deserializing) { }
-    private ReferenceSetUpdateMethod(ReferenceSetUpdateMethod original, Cloner cloner)
-      : base(original, cloner) {
-      this.SimilarityCalculator = cloner.Clone(original.SimilarityCalculator);
-    }
+    private ReferenceSetUpdateMethod(ReferenceSetUpdateMethod original, Cloner cloner) : base(original, cloner) { }
     public ReferenceSetUpdateMethod()
       : base() {
@@ -71,4 +66,5 @@
       Parameters.Add(new ScopeParameter("CurrentScope", "The current scope that contains the population and the reference set."));
       Parameters.Add(new ValueLookupParameter<IntValue>("ReferenceSetSize", "The size of the reference set."));
+      Parameters.Add(new ValueLookupParameter<ISolutionSimilarityCalculator>("SimilarityCalculator", "The similarity calculator that should be used to calculate solution similarity."));
       #endregion
     }
@@ -78,9 +74,18 @@
     }
 
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (!Parameters.ContainsKey("SimilarityCalculator"))
+        Parameters.Add(new ValueLookupParameter<ISolutionSimilarityCalculator>("SimilarityCalculator", "The similarity calculator that should be used to calculate solution similarity."));
+      #endregion
+    }
+
     public override IOperation Apply() {
       var populationSimilarity = new Dictionary<IScope, double>();
       var populationScope = CurrentScope.SubScopes[0];
       var refSetScope = CurrentScope.SubScopes[1];
-      var similarityMatrix = SimilarityCalculator.CalculateSolutionCrowdSimilarity(populationScope, refSetScope);
+      var similarityMatrix = SimilarityCalculatorParameter.ActualValue.CalculateSolutionCrowdSimilarity(populationScope, refSetScope);
       for (int i = 0; i < populationScope.SubScopes.Count; i++) {
         populationSimilarity[populationScope.SubScopes[i]] = similarityMatrix[i].Sum();
Index: /stable/HeuristicLab.Algorithms.ScatterSearch/3.3/ScatterSearch.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.ScatterSearch/3.3/ScatterSearch.cs	(revision 12279)
+++ /stable/HeuristicLab.Algorithms.ScatterSearch/3.3/ScatterSearch.cs	(revision 12280)
@@ -88,6 +88,6 @@
       get { return (IValueParameter<BoolValue>)Parameters["SetSeedRandomly"]; }
     }
-    public IConstrainedValueParameter<ISingleObjectiveSolutionSimilarityCalculator> SimilarityCalculatorParameter {
-      get { return (IConstrainedValueParameter<ISingleObjectiveSolutionSimilarityCalculator>)Parameters["SimilarityCalculator"]; }
+    public IConstrainedValueParameter<ISolutionSimilarityCalculator> SimilarityCalculatorParameter {
+      get { return (IConstrainedValueParameter<ISolutionSimilarityCalculator>)Parameters["SimilarityCalculator"]; }
     }
     #endregion
@@ -138,5 +138,5 @@
       set { SetSeedRandomlyParameter.Value = value; }
     }
-    public ISingleObjectiveSolutionSimilarityCalculator SimilarityCalculator {
+    public ISolutionSimilarityCalculator SimilarityCalculator {
       get { return SimilarityCalculatorParameter.Value; }
       set { SimilarityCalculatorParameter.Value = value; }
@@ -160,4 +160,17 @@
     [StorableHook(HookType.AfterDeserialization)]
     private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (Parameters.ContainsKey("SimilarityCalculator")) {
+#pragma warning disable 0618
+        var oldParameter = (IConstrainedValueParameter<ISingleObjectiveSolutionSimilarityCalculator>)Parameters["SimilarityCalculator"];
+#pragma warning restore 0618
+        Parameters.Remove(oldParameter);
+        var newParameter = new ConstrainedValueParameter<ISolutionSimilarityCalculator>("SimilarityCalculator", "The operator used to calculate the similarity between two solutions.", new ItemSet<ISolutionSimilarityCalculator>(oldParameter.ValidValues));
+        var selectedSimilarityCalculator = newParameter.ValidValues.SingleOrDefault(x => x.GetType() == oldParameter.Value.GetType());
+        newParameter.Value = selectedSimilarityCalculator;
+        Parameters.Add(newParameter);
+      }
+      #endregion
       Initialize();
     }
@@ -184,5 +197,5 @@
       Parameters.Add(new ValueParameter<IntValue>("Seed", "The random seed used to initialize the new pseudo random number generator.", new IntValue(0)));
       Parameters.Add(new ValueParameter<BoolValue>("SetSeedRandomly", "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true)));
-      Parameters.Add(new ConstrainedValueParameter<ISingleObjectiveSolutionSimilarityCalculator>("SimilarityCalculator", "The operator used to calculate the similarity between two solutions."));
+      Parameters.Add(new ConstrainedValueParameter<ISolutionSimilarityCalculator>("SimilarityCalculator", "The operator used to calculate the similarity between two solutions."));
       #endregion
 
@@ -390,16 +403,20 @@
     }
     private void UpdateSimilarityCalculators() {
-      ISingleObjectiveSolutionSimilarityCalculator oldSimilarityCalculator = SimilarityCalculatorParameter.Value;
+      ISolutionSimilarityCalculator oldSimilarityCalculator = SimilarityCalculatorParameter.Value;
       SimilarityCalculatorParameter.ValidValues.Clear();
-      ISingleObjectiveSolutionSimilarityCalculator defaultSimilarityCalculator = Problem.Operators.OfType<ISingleObjectiveSolutionSimilarityCalculator>().FirstOrDefault();
-
-      SimilarityCalculatorParameter.ValidValues.Add(new QualitySimilarityCalculator { QualityVariableName = Problem.Evaluator.QualityParameter.ActualName });
-      SimilarityCalculatorParameter.ValidValues.Add(new NoSimilarityCalculator { QualityVariableName = Problem.Evaluator.QualityParameter.ActualName });
-
-      foreach (ISingleObjectiveSolutionSimilarityCalculator similarityCalculator in Problem.Operators.OfType<ISingleObjectiveSolutionSimilarityCalculator>())
+      ISolutionSimilarityCalculator defaultSimilarityCalculator = Problem.Operators.OfType<ISolutionSimilarityCalculator>().FirstOrDefault();
+
+      foreach (ISolutionSimilarityCalculator similarityCalculator in Problem.Operators.OfType<ISolutionSimilarityCalculator>())
         SimilarityCalculatorParameter.ValidValues.Add(similarityCalculator);
 
+      if (!SimilarityCalculatorParameter.ValidValues.OfType<QualitySimilarityCalculator>().Any())
+        SimilarityCalculatorParameter.ValidValues.Add(new QualitySimilarityCalculator {
+          QualityVariableName = Problem.Evaluator.QualityParameter.ActualName
+        });
+      if (!SimilarityCalculatorParameter.ValidValues.OfType<NoSimilarityCalculator>().Any())
+        SimilarityCalculatorParameter.ValidValues.Add(new NoSimilarityCalculator());
+
       if (oldSimilarityCalculator != null) {
-        ISingleObjectiveSolutionSimilarityCalculator similarityCalculator = SimilarityCalculatorParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldSimilarityCalculator.GetType());
+        ISolutionSimilarityCalculator similarityCalculator = SimilarityCalculatorParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldSimilarityCalculator.GetType());
         if (similarityCalculator != null) SimilarityCalculatorParameter.Value = similarityCalculator;
         else oldSimilarityCalculator = null;
@@ -423,6 +440,4 @@
         MainLoop.OperatorGraph.Operators.OfType<PopulationRebuildMethod>().Single().QualityParameter.ActualName = Problem.Evaluator.QualityParameter.ActualName;
         MainLoop.OperatorGraph.Operators.OfType<SolutionPoolUpdateMethod>().Single().QualityParameter.ActualName = Problem.Evaluator.QualityParameter.ActualName;
-        foreach (ISimilarityBasedOperator op in MainLoop.OperatorGraph.Operators.OfType<ISimilarityBasedOperator>())
-          op.SimilarityCalculator = SimilarityCalculator;
       }
     }
@@ -449,5 +464,5 @@
     }
     private void ParameterizeSimilarityCalculators() {
-      foreach (ISingleObjectiveSolutionSimilarityCalculator calc in SimilarityCalculatorParameter.ValidValues) {
+      foreach (ISolutionSimilarityCalculator calc in SimilarityCalculatorParameter.ValidValues) {
         calc.QualityVariableName = Problem.Evaluator.QualityParameter.ActualName;
       }
Index: /stable/HeuristicLab.Algorithms.ScatterSearch/3.3/SolutionPoolUpdateMethod.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.ScatterSearch/3.3/SolutionPoolUpdateMethod.cs	(revision 12279)
+++ /stable/HeuristicLab.Algorithms.ScatterSearch/3.3/SolutionPoolUpdateMethod.cs	(revision 12280)
@@ -36,10 +36,5 @@
   [Item("SolutionPoolUpdateMethod", "An operator that updates the solution pool.")]
   [StorableClass]
-  public sealed class SolutionPoolUpdateMethod : SingleSuccessorOperator, ISimilarityBasedOperator, ISingleObjectiveOperator {
-    #region ISimilarityBasedOperator Members
-    [Storable]
-    public ISolutionSimilarityCalculator SimilarityCalculator { get; set; }
-    #endregion
-
+  public sealed class SolutionPoolUpdateMethod : SingleSuccessorOperator, ISingleObjectiveOperator {
     #region Parameter properties
     public ScopeParameter CurrentScopeParameter {
@@ -57,4 +52,7 @@
     public IValueLookupParameter<IntValue> ReferenceSetSizeParameter {
       get { return (IValueLookupParameter<IntValue>)Parameters["ReferenceSetSize"]; }
+    }
+    public IValueLookupParameter<ISolutionSimilarityCalculator> SimilarityCalculatorParameter {
+      get { return (IValueLookupParameter<ISolutionSimilarityCalculator>)Parameters["SimilarityCalculator"]; }
     }
     #endregion
@@ -82,15 +80,7 @@
     [StorableConstructor]
     private SolutionPoolUpdateMethod(bool deserializing) : base(deserializing) { }
-    private SolutionPoolUpdateMethod(SolutionPoolUpdateMethod original, Cloner cloner)
-      : base(original, cloner) {
-      this.SimilarityCalculator = cloner.Clone(original.SimilarityCalculator);
-    }
-    public SolutionPoolUpdateMethod() : base() { Initialize(); }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new SolutionPoolUpdateMethod(this, cloner);
-    }
-
-    private void Initialize() {
+    private SolutionPoolUpdateMethod(SolutionPoolUpdateMethod original, Cloner cloner) : base(original, cloner) { }
+    public SolutionPoolUpdateMethod()
+      : base() {
       #region Create parameters
       Parameters.Add(new ScopeParameter("CurrentScope", "The current scope that is the reference set."));
@@ -99,4 +89,18 @@
       Parameters.Add(new ValueLookupParameter<IItem>("Quality", "This parameter is used for name translation only."));
       Parameters.Add(new ValueLookupParameter<IntValue>("ReferenceSetSize", "The size of the reference set."));
+      Parameters.Add(new ValueLookupParameter<ISolutionSimilarityCalculator>("SimilarityCalculator", "The similarity calculator that should be used to calculate solution similarity."));
+      #endregion
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SolutionPoolUpdateMethod(this, cloner);
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (!Parameters.ContainsKey("SimilarityCalculator"))
+        Parameters.Add(new ValueLookupParameter<ISolutionSimilarityCalculator>("SimilarityCalculator", "The similarity calculator that should be used to calculate solution similarity."));
       #endregion
     }
@@ -132,5 +136,5 @@
       if (orderedOffspring.Any(hasBetterQuality)) {
         // produce the set union
-        var union = orderedParents.Union(orderedOffspring.Where(hasBetterQuality), SimilarityCalculator);
+        var union = orderedParents.Union(orderedOffspring.Where(hasBetterQuality), SimilarityCalculatorParameter.ActualValue);
         if (union.Count() > orderedParents.Count()) {
           var orderedUnion = Maximization.Value ? union.OrderByDescending(x => x.Variables[QualityParameter.ActualName].Value) :
Index: /stable/HeuristicLab.Algorithms.SimulatedAnnealing/3.3/SimulatedAnnealingImprovementOperator.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.SimulatedAnnealing/3.3/SimulatedAnnealingImprovementOperator.cs	(revision 12279)
+++ /stable/HeuristicLab.Algorithms.SimulatedAnnealing/3.3/SimulatedAnnealingImprovementOperator.cs	(revision 12280)
@@ -279,5 +279,5 @@
         foreach (IAnalyzer analyzer in problem.Operators.OfType<IAnalyzer>()) {
           if (!IsSubclassOfGeneric(typeof(AlleleFrequencyAnalyzer<>), analyzer.GetType()) &&
-              !(analyzer is SingleObjectivePopulationDiversityAnalyzer)) {
+              !(analyzer is PopulationSimilarityAnalyzer)) {
             IAnalyzer clone = analyzer.Clone() as IAnalyzer;
             foreach (IScopeTreeLookupParameter param in clone.Parameters.OfType<IScopeTreeLookupParameter>())
Index: /stable/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj
===================================================================
--- /stable/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj	(revision 12279)
+++ /stable/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj	(revision 12280)
@@ -148,6 +148,7 @@
     <Compile Include="MultiObjective\ParetoFrontAnalyzer.cs" />
     <Compile Include="Plugin.cs" />
-    <Compile Include="PopulationDiversityAnalysis\PopulationDiversityAnalyzer.cs" />
-    <Compile Include="PopulationDiversityAnalysis\SingleObjectivePopulationDiversityAnalyzer.cs" />
+    <Compile Include="PopulationSimilarityAnalysis\PopulationDiversityAnalyzer.cs" />
+    <Compile Include="PopulationSimilarityAnalysis\PopulationSimilarityAnalyzer.cs" />
+    <Compile Include="PopulationSimilarityAnalysis\SingleObjectivePopulationDiversityAnalyzer.cs" />
     <Compile Include="QualityAnalysis\BestAverageWorstQualityAnalyzer.cs" />
     <Compile Include="QualityAnalysis\BestAverageWorstQualityCalculator.cs" />
Index: /stable/HeuristicLab.Analysis/3.3/PopulationSimilarityAnalysis/PopulationDiversityAnalyzer.cs
===================================================================
--- /stable/HeuristicLab.Analysis/3.3/PopulationSimilarityAnalysis/PopulationDiversityAnalyzer.cs	(revision 12280)
+++ /stable/HeuristicLab.Analysis/3.3/PopulationSimilarityAnalysis/PopulationDiversityAnalyzer.cs	(revision 12280)
@@ -0,0 +1,252 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  // use HeuristicLab.Analysis.SingleObjectivePopulationDiversityAnalyzer instead
+  // BackwardsCompatibility3.3
+  #region Backwards compatible code, remove with 3.4
+  /// <summary>
+  /// An operator for analyzing the solution diversity in a population.
+  /// </summary>
+  [Obsolete]
+  [Item("PopulationDiversityAnalyzer", "An operator for analyzing the solution diversity in a population.")]
+  [StorableClass]
+  public abstract class PopulationDiversityAnalyzer<T> : SingleSuccessorOperator, IAnalyzer, ISingleObjectiveOperator where T : class, IItem {
+    public virtual bool EnabledByDefault {
+      get { return false; }
+    }
+
+    public LookupParameter<BoolValue> MaximizationParameter {
+      get { return (LookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    public ScopeTreeLookupParameter<T> SolutionParameter {
+      get { return (ScopeTreeLookupParameter<T>)Parameters["Solution"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (ValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+    public ValueParameter<BoolValue> StoreHistoryParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["StoreHistory"]; }
+    }
+    public ValueParameter<IntValue> UpdateIntervalParameter {
+      get { return (ValueParameter<IntValue>)Parameters["UpdateInterval"]; }
+    }
+    public LookupParameter<IntValue> UpdateCounterParameter {
+      get { return (LookupParameter<IntValue>)Parameters["UpdateCounter"]; }
+    }
+
+    [StorableConstructor]
+    protected PopulationDiversityAnalyzer(bool deserializing) : base(deserializing) { }
+    protected PopulationDiversityAnalyzer(PopulationDiversityAnalyzer<T> original, Cloner cloner) : base(original, cloner) { }
+    public PopulationDiversityAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem."));
+      Parameters.Add(new ScopeTreeLookupParameter<T>("Solution", "The solutions whose diversity should be analyzed."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The qualities of the solutions which should be analyzed."));
+      Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", "The result collection where the population diversity analysis results should be stored."));
+      Parameters.Add(new ValueParameter<BoolValue>("StoreHistory", "True if the history of the population diversity analysis should be stored.", new BoolValue(false)));
+      Parameters.Add(new ValueParameter<IntValue>("UpdateInterval", "The interval in which the population diversity analysis should be applied.", new IntValue(1)));
+      Parameters.Add(new LookupParameter<IntValue>("UpdateCounter", "The value which counts how many times the operator was called since the last update.", "PopulationDiversityAnalyzerUpdateCounter"));
+
+      MaximizationParameter.Hidden = true;
+      SolutionParameter.Hidden = true;
+      QualityParameter.Hidden = true;
+      ResultsParameter.Hidden = true;
+      UpdateCounterParameter.Hidden = true;
+    }
+
+    public override IOperation Apply() {
+      int updateInterval = UpdateIntervalParameter.Value.Value;
+      IntValue updateCounter = UpdateCounterParameter.ActualValue;
+      // if counter does not yet exist then initialize it with update interval 
+      // to make sure the solutions are analyzed on the first application of this operator
+      if (updateCounter == null) {
+        updateCounter = new IntValue(updateInterval);
+        UpdateCounterParameter.ActualValue = updateCounter;
+      } else updateCounter.Value++;
+
+      //analyze solutions only every 'updateInterval' times
+      if (updateCounter.Value == updateInterval) {
+        updateCounter.Value = 0;
+
+        bool max = MaximizationParameter.ActualValue.Value;
+        ItemArray<T> solutions = SolutionParameter.ActualValue;
+        ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+        bool storeHistory = StoreHistoryParameter.Value.Value;
+        int count = solutions.Length;
+
+        if (count > 1) {
+          // sort solutions by quality
+          T[] sortedSolutions = null;
+          if (max)
+            sortedSolutions = solutions
+              .Select((x, index) => new { Solution = x, Quality = qualities[index] })
+              .OrderByDescending(x => x.Quality)
+              .Select(x => x.Solution)
+              .ToArray();
+          else
+            sortedSolutions = solutions
+              .Select((x, index) => new { Solution = x, Quality = qualities[index] })
+              .OrderBy(x => x.Quality)
+              .Select(x => x.Solution)
+              .ToArray();
+
+          // calculate solution similarities
+          double[,] similarities = CalculateSimilarities(sortedSolutions);
+
+          // calculate minimum, average and maximum similarities
+          double similarity;
+          double[] minSimilarities = new double[count];
+          double[] avgSimilarities = new double[count];
+          double[] maxSimilarities = new double[count];
+          for (int i = 0; i < count; i++) {
+            minSimilarities[i] = 1;
+            avgSimilarities[i] = 0;
+            maxSimilarities[i] = 0;
+            for (int j = 0; j < count; j++) {
+              if (i != j) {
+                similarity = similarities[i, j];
+
+                if ((similarity < 0) || (similarity > 1))
+                  throw new InvalidOperationException("Solution similarities have to be in the interval [0;1].");
+
+                if (minSimilarities[i] > similarity) minSimilarities[i] = similarity;
+                avgSimilarities[i] += similarity;
+                if (maxSimilarities[i] < similarity) maxSimilarities[i] = similarity;
+              }
+            }
+            avgSimilarities[i] = avgSimilarities[i] / (count - 1);
+          }
+          double avgMinSimilarity = minSimilarities.Average();
+          double avgAvgSimilarity = avgSimilarities.Average();
+          double avgMaxSimilarity = maxSimilarities.Average();
+
+          // fetch results collection
+          ResultCollection results;
+          if (!ResultsParameter.ActualValue.ContainsKey(Name + " Results")) {
+            results = new ResultCollection();
+            ResultsParameter.ActualValue.Add(new Result(Name + " Results", results));
+          } else {
+            results = (ResultCollection)ResultsParameter.ActualValue[Name + " Results"].Value;
+          }
+
+          // store similarities
+          HeatMap similaritiesHeatMap = new HeatMap(similarities, "Solution Similarities", 0.0, 1.0);
+          if (!results.ContainsKey("Solution Similarities"))
+            results.Add(new Result("Solution Similarities", similaritiesHeatMap));
+          else
+            results["Solution Similarities"].Value = similaritiesHeatMap;
+
+          // store similarities history
+          if (storeHistory) {
+            if (!results.ContainsKey("Solution Similarities History")) {
+              HeatMapHistory history = new HeatMapHistory();
+              history.Add(similaritiesHeatMap);
+              results.Add(new Result("Solution Similarities History", history));
+            } else {
+              ((HeatMapHistory)results["Solution Similarities History"].Value).Add(similaritiesHeatMap);
+            }
+          }
+
+          // store average minimum, average and maximum similarity
+          if (!results.ContainsKey("Average Minimum Solution Similarity"))
+            results.Add(new Result("Average Minimum Solution Similarity", new DoubleValue(avgMinSimilarity)));
+          else
+            ((DoubleValue)results["Average Minimum Solution Similarity"].Value).Value = avgMinSimilarity;
+
+          if (!results.ContainsKey("Average Average Solution Similarity"))
+            results.Add(new Result("Average Average Solution Similarity", new DoubleValue(avgAvgSimilarity)));
+          else
+            ((DoubleValue)results["Average Average Solution Similarity"].Value).Value = avgAvgSimilarity;
+
+          if (!results.ContainsKey("Average Maximum Solution Similarity"))
+            results.Add(new Result("Average Maximum Solution Similarity", new DoubleValue(avgMaxSimilarity)));
+          else
+            ((DoubleValue)results["Average Maximum Solution Similarity"].Value).Value = avgMaxSimilarity;
+
+          // store average minimum, average and maximum solution similarity data table
+          DataTable minAvgMaxSimilarityDataTable;
+          if (!results.ContainsKey("Average Minimum/Average/Maximum Solution Similarity")) {
+            minAvgMaxSimilarityDataTable = new DataTable("Average Minimum/Average/Maximum Solution Similarity");
+            minAvgMaxSimilarityDataTable.VisualProperties.XAxisTitle = "Iteration";
+            minAvgMaxSimilarityDataTable.VisualProperties.YAxisTitle = "Solution Similarity";
+            minAvgMaxSimilarityDataTable.Rows.Add(new DataRow("Average Minimum Solution Similarity", null));
+            minAvgMaxSimilarityDataTable.Rows["Average Minimum Solution Similarity"].VisualProperties.StartIndexZero = true;
+            minAvgMaxSimilarityDataTable.Rows.Add(new DataRow("Average Average Solution Similarity", null));
+            minAvgMaxSimilarityDataTable.Rows["Average Average Solution Similarity"].VisualProperties.StartIndexZero = true;
+            minAvgMaxSimilarityDataTable.Rows.Add(new DataRow("Average Maximum Solution Similarity", null));
+            minAvgMaxSimilarityDataTable.Rows["Average Maximum Solution Similarity"].VisualProperties.StartIndexZero = true;
+            results.Add(new Result("Average Minimum/Average/Maximum Solution Similarity", minAvgMaxSimilarityDataTable));
+          } else {
+            minAvgMaxSimilarityDataTable = (DataTable)results["Average Minimum/Average/Maximum Solution Similarity"].Value;
+          }
+          minAvgMaxSimilarityDataTable.Rows["Average Minimum Solution Similarity"].Values.Add(avgMinSimilarity);
+          minAvgMaxSimilarityDataTable.Rows["Average Average Solution Similarity"].Values.Add(avgAvgSimilarity);
+          minAvgMaxSimilarityDataTable.Rows["Average Maximum Solution Similarity"].Values.Add(avgMaxSimilarity);
+
+          // store minimum, average, maximum similarities data table
+          DataTable minAvgMaxSimilaritiesDataTable = new DataTable("Minimum/Average/Maximum Solution Similarities");
+          minAvgMaxSimilaritiesDataTable.VisualProperties.XAxisTitle = "Solution Index";
+          minAvgMaxSimilaritiesDataTable.VisualProperties.YAxisTitle = "Solution Similarity";
+          minAvgMaxSimilaritiesDataTable.Rows.Add(new DataRow("Minimum Solution Similarity", null, minSimilarities));
+          minAvgMaxSimilaritiesDataTable.Rows["Minimum Solution Similarity"].VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
+          minAvgMaxSimilaritiesDataTable.Rows.Add(new DataRow("Average Solution Similarity", null, avgSimilarities));
+          minAvgMaxSimilaritiesDataTable.Rows["Average Solution Similarity"].VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
+          minAvgMaxSimilaritiesDataTable.Rows.Add(new DataRow("Maximum Solution Similarity", null, maxSimilarities));
+          minAvgMaxSimilaritiesDataTable.Rows["Maximum Solution Similarity"].VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
+          if (!results.ContainsKey("Minimum/Average/Maximum Solution Similarities")) {
+            results.Add(new Result("Minimum/Average/Maximum Solution Similarities", minAvgMaxSimilaritiesDataTable));
+          } else {
+            results["Minimum/Average/Maximum Solution Similarities"].Value = minAvgMaxSimilaritiesDataTable;
+          }
+
+          // store minimum, average, maximum similarities history
+          if (storeHistory) {
+            if (!results.ContainsKey("Minimum/Average/Maximum Solution Similarities History")) {
+              DataTableHistory history = new DataTableHistory();
+              history.Add(minAvgMaxSimilaritiesDataTable);
+              results.Add(new Result("Minimum/Average/Maximum Solution Similarities History", history));
+            } else {
+              ((DataTableHistory)results["Minimum/Average/Maximum Solution Similarities History"].Value).Add(minAvgMaxSimilaritiesDataTable);
+            }
+          }
+        }
+      }
+      return base.Apply();
+    }
+
+    protected abstract double[,] CalculateSimilarities(T[] solutions);
+  }
+  #endregion
+}
Index: /stable/HeuristicLab.Analysis/3.3/PopulationSimilarityAnalysis/PopulationSimilarityAnalyzer.cs
===================================================================
--- /stable/HeuristicLab.Analysis/3.3/PopulationSimilarityAnalysis/PopulationSimilarityAnalyzer.cs	(revision 12280)
+++ /stable/HeuristicLab.Analysis/3.3/PopulationSimilarityAnalysis/PopulationSimilarityAnalyzer.cs	(revision 12280)
@@ -0,0 +1,267 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// An operator for analyzing the solution similarity in a population.
+  /// </summary>
+  [Item("PopulationSimilarityAnalyzer", "An operator for analyzing the solution similarity in a population.")]
+  [StorableClass]
+  public class PopulationSimilarityAnalyzer : SingleSuccessorOperator, IAnalyzer, ISimilarityBasedOperator {
+    private const string DiversityResultNameParameterName = "DiversityResultsName";
+
+    #region Backwards compatible code, remove with 3.4
+    private ISolutionSimilarityCalculator oldSimilarityCalculator;
+    [Storable(AllowOneWay = true, Name = "SimilarityCalculator")]
+    [Obsolete]
+    private ISolutionSimilarityCalculator SimilarityCalculator { set { oldSimilarityCalculator = value; } }
+    #endregion
+
+    public virtual bool EnabledByDefault {
+      get { return false; }
+    }
+    public ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+    public IValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (IValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+    public IConstrainedValueParameter<ISolutionSimilarityCalculator> SimilarityCalculatorParameter {
+      get { return (IConstrainedValueParameter<ISolutionSimilarityCalculator>)Parameters["SimilarityCalculator"]; }
+    }
+    public IValueParameter<BoolValue> StoreHistoryParameter {
+      get { return (IValueParameter<BoolValue>)Parameters["StoreHistory"]; }
+    }
+    public IValueParameter<IntValue> UpdateIntervalParameter {
+      get { return (IValueParameter<IntValue>)Parameters["UpdateInterval"]; }
+    }
+    public ILookupParameter<IntValue> UpdateCounterParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["UpdateCounter"]; }
+    }
+    public IFixedValueParameter<StringValue> DiversityResultNameParameter {
+      get { return (FixedValueParameter<StringValue>)Parameters[DiversityResultNameParameterName]; }
+    }
+
+    public string DiversityResultName {
+      get { return DiversityResultNameParameter.Value.Value; }
+      set { DiversityResultNameParameter.Value.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected PopulationSimilarityAnalyzer(bool deserializing) : base(deserializing) { }
+    protected PopulationSimilarityAnalyzer(PopulationSimilarityAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public PopulationSimilarityAnalyzer(IEnumerable<ISolutionSimilarityCalculator> validSimilarityCalculators)
+      : base() {
+      Parameters.Add(new ScopeParameter("CurrentScope", "The current scope that contains the solutions which should be analyzed."));
+      Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", "The result collection where the population diversity analysis results should be stored."));
+      Parameters.Add(new ConstrainedValueParameter<ISolutionSimilarityCalculator>("SimilarityCalculator", "The similarity calculator that should be used to calculate population similarity."));
+      Parameters.Add(new ValueParameter<BoolValue>("StoreHistory", "True if the history of the population diversity analysis should be stored.", new BoolValue(false)));
+      Parameters.Add(new ValueParameter<IntValue>("UpdateInterval", "The interval in which the population diversity analysis should be applied.", new IntValue(1)));
+      Parameters.Add(new LookupParameter<IntValue>("UpdateCounter", "The value which counts how many times the operator was called since the last update.", "PopulationDiversityAnalyzerUpdateCounter"));
+      Parameters.Add(new FixedValueParameter<StringValue>(DiversityResultNameParameterName, "Specifies how the diversity results should be named.", new StringValue("PopulationDiversity")));
+
+      var similarityCalculators = SimilarityCalculatorParameter.ValidValues;
+      foreach (var sc in validSimilarityCalculators)
+        similarityCalculators.Add(sc);
+
+
+      ResultsParameter.Hidden = true;
+      UpdateCounterParameter.Hidden = true;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PopulationSimilarityAnalyzer(this, cloner);
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (!Parameters.ContainsKey(DiversityResultNameParameterName))
+        Parameters.Add(new FixedValueParameter<StringValue>(DiversityResultNameParameterName, "Specifies how the diversity results should be named.", new StringValue("PopulationDiversity")));
+
+      if (!Parameters.ContainsKey("SimilarityCalculator"))
+        Parameters.Add(new ConstrainedValueParameter<ISolutionSimilarityCalculator>("SimilarityCalculator", "The similarity calculator that should be used to calculate solution similarity."));
+
+      SimilarityCalculatorParameter.ValidValues.Add(oldSimilarityCalculator);
+      #endregion
+    }
+
+    public override IOperation Apply() {
+      int updateInterval = UpdateIntervalParameter.Value.Value;
+      IntValue updateCounter = UpdateCounterParameter.ActualValue;
+      // if counter does not yet exist then initialize it with update interval
+      // to make sure the solutions are analyzed on the first application of this operator
+      if (updateCounter == null) {
+        updateCounter = new IntValue(updateInterval);
+        UpdateCounterParameter.ActualValue = updateCounter;
+      }
+      //analyze solutions only every 'updateInterval' times
+      if (updateCounter.Value != updateInterval) {
+        updateCounter.Value++;
+        return base.Apply();
+      }
+      updateCounter.Value = 1;
+
+      bool storeHistory = StoreHistoryParameter.Value.Value;
+      int count = CurrentScopeParameter.ActualValue.SubScopes.Count;
+
+      if (count > 1) {
+        var similarityCalculator = SimilarityCalculatorParameter.Value;
+        // calculate solution similarities
+        var similarityMatrix = similarityCalculator.CalculateSolutionCrowdSimilarity(CurrentScopeParameter.ActualValue);
+        double[,] similarities = new double[similarityMatrix.Length, similarityMatrix[0].Length];
+        for (int i = 0; i < similarityMatrix.Length; i++)
+          for (int j = 0; j < similarityMatrix[0].Length; j++)
+            similarities[i, j] = similarityMatrix[i][j];
+
+        // calculate minimum, average and maximum similarities
+        double similarity;
+        double[] minSimilarities = new double[count];
+        double[] avgSimilarities = new double[count];
+        double[] maxSimilarities = new double[count];
+        for (int i = 0; i < count; i++) {
+          minSimilarities[i] = 1;
+          avgSimilarities[i] = 0;
+          maxSimilarities[i] = 0;
+          for (int j = 0; j < count; j++) {
+            if (i != j) {
+              similarity = similarities[i, j];
+
+              if ((similarity < 0) || (similarity > 1))
+                throw new InvalidOperationException("Solution similarities have to be in the interval [0;1].");
+
+              if (minSimilarities[i] > similarity) minSimilarities[i] = similarity;
+              avgSimilarities[i] += similarity;
+              if (maxSimilarities[i] < similarity) maxSimilarities[i] = similarity;
+            }
+          }
+          avgSimilarities[i] = avgSimilarities[i] / (count - 1);
+        }
+        double avgMinSimilarity = minSimilarities.Average();
+        double avgAvgSimilarity = avgSimilarities.Average();
+        double avgMaxSimilarity = maxSimilarities.Average();
+
+        // fetch results collection
+        ResultCollection results;
+        if (!ResultsParameter.ActualValue.ContainsKey(DiversityResultName)) {
+          results = new ResultCollection();
+          ResultsParameter.ActualValue.Add(new Result(DiversityResultName, results));
+        } else {
+          results = (ResultCollection)ResultsParameter.ActualValue[DiversityResultName].Value;
+        }
+
+        // store similarities
+        HeatMap similaritiesHeatMap = new HeatMap(similarities, "Solution Similarities", 0.0, 1.0);
+        if (!results.ContainsKey("Solution Similarities"))
+          results.Add(new Result("Solution Similarities", similaritiesHeatMap));
+        else
+          results["Solution Similarities"].Value = similaritiesHeatMap;
+
+        // store similarities history
+        if (storeHistory) {
+          if (!results.ContainsKey("Solution Similarities History")) {
+            HeatMapHistory history = new HeatMapHistory();
+            history.Add(similaritiesHeatMap);
+            results.Add(new Result("Solution Similarities History", history));
+          } else {
+            ((HeatMapHistory)results["Solution Similarities History"].Value).Add(similaritiesHeatMap);
+          }
+        }
+
+        // store average minimum, average and maximum similarity
+        if (!results.ContainsKey("Average Minimum Solution Similarity"))
+          results.Add(new Result("Average Minimum Solution Similarity", new DoubleValue(avgMinSimilarity)));
+        else
+          ((DoubleValue)results["Average Minimum Solution Similarity"].Value).Value = avgMinSimilarity;
+
+        if (!results.ContainsKey("Average Average Solution Similarity"))
+          results.Add(new Result("Average Average Solution Similarity", new DoubleValue(avgAvgSimilarity)));
+        else
+          ((DoubleValue)results["Average Average Solution Similarity"].Value).Value = avgAvgSimilarity;
+
+        if (!results.ContainsKey("Average Maximum Solution Similarity"))
+          results.Add(new Result("Average Maximum Solution Similarity", new DoubleValue(avgMaxSimilarity)));
+        else
+          ((DoubleValue)results["Average Maximum Solution Similarity"].Value).Value = avgMaxSimilarity;
+
+        // store average minimum, average and maximum solution similarity data table
+        DataTable minAvgMaxSimilarityDataTable;
+        if (!results.ContainsKey("Average Minimum/Average/Maximum Solution Similarity")) {
+          minAvgMaxSimilarityDataTable = new DataTable("Average Minimum/Average/Maximum Solution Similarity");
+          minAvgMaxSimilarityDataTable.VisualProperties.XAxisTitle = "Iteration";
+          minAvgMaxSimilarityDataTable.VisualProperties.YAxisTitle = "Solution Similarity";
+          minAvgMaxSimilarityDataTable.Rows.Add(new DataRow("Average Minimum Solution Similarity", null));
+          minAvgMaxSimilarityDataTable.Rows["Average Minimum Solution Similarity"].VisualProperties.StartIndexZero = true;
+          minAvgMaxSimilarityDataTable.Rows.Add(new DataRow("Average Average Solution Similarity", null));
+          minAvgMaxSimilarityDataTable.Rows["Average Average Solution Similarity"].VisualProperties.StartIndexZero = true;
+          minAvgMaxSimilarityDataTable.Rows.Add(new DataRow("Average Maximum Solution Similarity", null));
+          minAvgMaxSimilarityDataTable.Rows["Average Maximum Solution Similarity"].VisualProperties.StartIndexZero = true;
+          results.Add(new Result("Average Minimum/Average/Maximum Solution Similarity", minAvgMaxSimilarityDataTable));
+        } else {
+          minAvgMaxSimilarityDataTable = (DataTable)results["Average Minimum/Average/Maximum Solution Similarity"].Value;
+        }
+        minAvgMaxSimilarityDataTable.Rows["Average Minimum Solution Similarity"].Values.Add(avgMinSimilarity);
+        minAvgMaxSimilarityDataTable.Rows["Average Average Solution Similarity"].Values.Add(avgAvgSimilarity);
+        minAvgMaxSimilarityDataTable.Rows["Average Maximum Solution Similarity"].Values.Add(avgMaxSimilarity);
+
+        // store minimum, average, maximum similarities data table
+        DataTable minAvgMaxSimilaritiesDataTable = new DataTable("Minimum/Average/Maximum Solution Similarities");
+        minAvgMaxSimilaritiesDataTable.VisualProperties.XAxisTitle = "Solution Index";
+        minAvgMaxSimilaritiesDataTable.VisualProperties.YAxisTitle = "Solution Similarity";
+        minAvgMaxSimilaritiesDataTable.Rows.Add(new DataRow("Minimum Solution Similarity", null, minSimilarities));
+        minAvgMaxSimilaritiesDataTable.Rows["Minimum Solution Similarity"].VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
+        minAvgMaxSimilaritiesDataTable.Rows.Add(new DataRow("Average Solution Similarity", null, avgSimilarities));
+        minAvgMaxSimilaritiesDataTable.Rows["Average Solution Similarity"].VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
+        minAvgMaxSimilaritiesDataTable.Rows.Add(new DataRow("Maximum Solution Similarity", null, maxSimilarities));
+        minAvgMaxSimilaritiesDataTable.Rows["Maximum Solution Similarity"].VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
+        if (!results.ContainsKey("Minimum/Average/Maximum Solution Similarities")) {
+          results.Add(new Result("Minimum/Average/Maximum Solution Similarities", minAvgMaxSimilaritiesDataTable));
+        } else {
+          results["Minimum/Average/Maximum Solution Similarities"].Value = minAvgMaxSimilaritiesDataTable;
+        }
+
+        // store minimum, average, maximum similarities history
+        if (storeHistory) {
+          if (!results.ContainsKey("Minimum/Average/Maximum Solution Similarities History")) {
+            DataTableHistory history = new DataTableHistory();
+            history.Add(minAvgMaxSimilaritiesDataTable);
+            results.Add(new Result("Minimum/Average/Maximum Solution Similarities History", history));
+          } else {
+            ((DataTableHistory)results["Minimum/Average/Maximum Solution Similarities History"].Value).Add(minAvgMaxSimilaritiesDataTable);
+          }
+        }
+      }
+      return base.Apply();
+    }
+  }
+}
Index: /stable/HeuristicLab.Analysis/3.3/PopulationSimilarityAnalysis/SingleObjectivePopulationDiversityAnalyzer.cs
===================================================================
--- /stable/HeuristicLab.Analysis/3.3/PopulationSimilarityAnalysis/SingleObjectivePopulationDiversityAnalyzer.cs	(revision 12280)
+++ /stable/HeuristicLab.Analysis/3.3/PopulationSimilarityAnalysis/SingleObjectivePopulationDiversityAnalyzer.cs	(revision 12280)
@@ -0,0 +1,49 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Analysis {
+  // use HeuristicLab.Analysis.PopulationSimilarityAnalyzer instead
+  // BackwardsCompatibility3.3
+  #region Backwards compatible code, remove with 3.4
+  /// <summary>
+  /// An operator for analyzing the solution diversity in a population.
+  /// </summary>
+  [Obsolete]
+  [NonDiscoverableType]
+  [Item("SingleObjectivePopulationDiversityAnalyzer", "An operator for analyzing the solution diversity in a population.")]
+  [StorableClass]
+  public class SingleObjectivePopulationDiversityAnalyzer : PopulationSimilarityAnalyzer {
+    [StorableConstructor]
+    protected SingleObjectivePopulationDiversityAnalyzer(bool deserializing) : base(deserializing) { }
+    protected SingleObjectivePopulationDiversityAnalyzer(SingleObjectivePopulationDiversityAnalyzer original, Cloner cloner) : base(original, cloner) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SingleObjectivePopulationDiversityAnalyzer(this, cloner);
+    }
+  }
+  #endregion
+}
Index: /stable/HeuristicLab.Optimization.Operators/3.3/NoSimilarityCalculator.cs
===================================================================
--- /stable/HeuristicLab.Optimization.Operators/3.3/NoSimilarityCalculator.cs	(revision 12279)
+++ /stable/HeuristicLab.Optimization.Operators/3.3/NoSimilarityCalculator.cs	(revision 12280)
@@ -32,4 +32,6 @@
   [Item("NoSimilarityCalculator", "An item that performs similarity calculation between two solutions. The item always considers two solutions to be distinct.")]
   public sealed class NoSimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator {
+    protected override bool IsCommutative { get { return true; } }
+
     private NoSimilarityCalculator(bool deserializing) : base(deserializing) { }
     private NoSimilarityCalculator(NoSimilarityCalculator original, Cloner cloner) : base(original, cloner) { }
Index: /stable/HeuristicLab.Optimization.Operators/3.3/QualitySimilarityCalculator.cs
===================================================================
--- /stable/HeuristicLab.Optimization.Operators/3.3/QualitySimilarityCalculator.cs	(revision 12279)
+++ /stable/HeuristicLab.Optimization.Operators/3.3/QualitySimilarityCalculator.cs	(revision 12280)
@@ -34,4 +34,6 @@
   [Item("QualitySimilarityCalculator", "An item that performs similarity calculation between two solutions. The item only considers the qualities of the two solutions.")]
   public sealed class QualitySimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator {
+    protected override bool IsCommutative { get { return true; } }
+
     private QualitySimilarityCalculator(bool deserializing) : base(deserializing) { }
     private QualitySimilarityCalculator(QualitySimilarityCalculator original, Cloner cloner) : base(original, cloner) { }
Index: /stable/HeuristicLab.Optimization.Operators/3.3/SingleObjectiveSolutionSimilarityCalculator.cs
===================================================================
--- /stable/HeuristicLab.Optimization.Operators/3.3/SingleObjectiveSolutionSimilarityCalculator.cs	(revision 12279)
+++ /stable/HeuristicLab.Optimization.Operators/3.3/SingleObjectiveSolutionSimilarityCalculator.cs	(revision 12280)
@@ -31,18 +31,12 @@
   [Item("SimilarityCalculator", "A base class for items that perform similarity calculation between two solutions.")]
   [StorableClass]
+#pragma warning disable 0618
   public abstract class SingleObjectiveSolutionSimilarityCalculator : SolutionSimilarityCalculator, ISingleObjectiveSolutionSimilarityCalculator {
-    #region Properties
-    [Storable]
-    public string SolutionVariableName { get; set; }
-    [Storable]
-    public string QualityVariableName { get; set; }
-    #endregion
-
+#pragma warning restore 0618
     [StorableConstructor]
     protected SingleObjectiveSolutionSimilarityCalculator(bool deserializing) : base(deserializing) { }
     protected SingleObjectiveSolutionSimilarityCalculator(SingleObjectiveSolutionSimilarityCalculator original, Cloner cloner)
       : base(original, cloner) {
-      this.SolutionVariableName = original.SolutionVariableName;
-      this.QualityVariableName = original.QualityVariableName;
+
     }
     protected SingleObjectiveSolutionSimilarityCalculator() : base() { }
Index: /stable/HeuristicLab.Optimization.Operators/3.3/SolutionSimilarityCalculator.cs
===================================================================
--- /stable/HeuristicLab.Optimization.Operators/3.3/SolutionSimilarityCalculator.cs	(revision 12279)
+++ /stable/HeuristicLab.Optimization.Operators/3.3/SolutionSimilarityCalculator.cs	(revision 12280)
@@ -24,4 +24,5 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
+using HeuristicLab.Data;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
@@ -33,7 +34,21 @@
   [StorableClass]
   public abstract class SolutionSimilarityCalculator : Item, ISolutionSimilarityCalculator {
+    protected abstract bool IsCommutative { get; }
+
+    #region Properties
+    [Storable]
+    public string SolutionVariableName { get; set; }
+    [Storable]
+    public string QualityVariableName { get; set; }
+    #endregion
+
     [StorableConstructor]
     protected SolutionSimilarityCalculator(bool deserializing) : base(deserializing) { }
-    protected SolutionSimilarityCalculator(SolutionSimilarityCalculator original, Cloner cloner) : base(original, cloner) { }
+
+    protected SolutionSimilarityCalculator(SolutionSimilarityCalculator original, Cloner cloner)
+      : base(original, cloner) {
+      this.SolutionVariableName = original.SolutionVariableName;
+      this.QualityVariableName = original.QualityVariableName;
+    }
     protected SolutionSimilarityCalculator() : base() { }
 
@@ -71,7 +86,17 @@
       for (int i = 0; i < individuals.Count; i++) similarityMatrix[i] = new double[individuals.Count];
 
-      for (int i = 0; i < individuals.Count; i++) {
-        for (int j = i; j < individuals.Count; j++) {
-          similarityMatrix[i][j] = similarityMatrix[j][i] = CalculateSolutionSimilarity(individuals[i], individuals[j]);
+      if (IsCommutative) {
+        for (int i = 0; i < individuals.Count; i++) {
+          for (int j = i; j < individuals.Count; j++) {
+            similarityMatrix[i][j] = similarityMatrix[j][i] = CalculateSolutionSimilarity(individuals[i], individuals[j]);
+          }
+        }
+      } else {
+        for (int i = 0; i < individuals.Count; i++) {
+          for (int j = i; j < individuals.Count; j++) {
+            similarityMatrix[i][j] = CalculateSolutionSimilarity(individuals[i], individuals[j]);
+            if (i == j) continue;
+            similarityMatrix[j][i] = CalculateSolutionSimilarity(individuals[j], individuals[i]);
+          }
         }
       }
@@ -81,6 +106,58 @@
 
     public abstract double CalculateSolutionSimilarity(IScope leftSolution, IScope rightSolution);
-    public abstract bool Equals(IScope x, IScope y);
-    public abstract int GetHashCode(IScope obj);
+
+    public virtual bool Equals(IScope x, IScope y) {
+      if (ReferenceEquals(x, y)) return true;
+      if (x == null || y == null) return false;
+
+      var q1 = x.Variables[QualityVariableName].Value;
+      var q2 = y.Variables[QualityVariableName].Value;
+
+      return CheckQualityEquality(q1, q2) && CalculateSolutionSimilarity(x, y).IsAlmost(1.0);
+    }
+
+    public virtual int GetHashCode(IScope scope) {
+      var quality = scope.Variables[QualityVariableName].Value;
+      var dv = quality as DoubleValue;
+      if (dv != null)
+        return dv.Value.GetHashCode();
+
+      var da = quality as DoubleArray;
+      if (da != null) {
+        int hash = 17;
+        unchecked {
+          for (int i = 0; i < da.Length; ++i) {
+            hash += hash * 23 + da[i].GetHashCode();
+          }
+          return hash;
+        }
+      }
+      return 0;
+    }
+
+    private static bool CheckQualityEquality(IItem q1, IItem q2) {
+      var d1 = q1 as DoubleValue;
+      var d2 = q2 as DoubleValue;
+
+      if (d1 != null && d2 != null)
+        return d1.Value.IsAlmost(d2.Value);
+
+      var da1 = q1 as DoubleArray;
+      var da2 = q2 as DoubleArray;
+
+      if (da1 != null && da2 != null) {
+        if (da1.Length != da2.Length)
+          throw new ArgumentException("The quality arrays must have the same length.");
+
+        for (int i = 0; i < da1.Length; ++i) {
+          if (!da1[i].IsAlmost(da2[i]))
+            return false;
+        }
+
+        return true;
+      }
+
+      throw new ArgumentException("Could not determine quality equality.");
+    }
   }
 }
Index: /stable/HeuristicLab.Optimization.Views/3.3/HeuristicLab.Optimization.Views-3.3.csproj
===================================================================
--- /stable/HeuristicLab.Optimization.Views/3.3/HeuristicLab.Optimization.Views-3.3.csproj	(revision 12279)
+++ /stable/HeuristicLab.Optimization.Views/3.3/HeuristicLab.Optimization.Views-3.3.csproj	(revision 12280)
@@ -148,9 +148,9 @@
       <DependentUpon>CreateNewSingleEncodingDialog.cs</DependentUpon>
     </Compile>
-    <Compile Include="ISingleObjectiveSolutionSimilarityCalculatorView.cs">
-      <SubType>UserControl</SubType>
-    </Compile>
-    <Compile Include="ISingleObjectiveSolutionSimilarityCalculatorView.Designer.cs">
-      <DependentUpon>ISingleObjectiveSolutionSimilarityCalculatorView.cs</DependentUpon>
+    <Compile Include="ISolutionSimilarityCalculatorView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="ISolutionSimilarityCalculatorView.Designer.cs">
+      <DependentUpon>ISolutionSimilarityCalculatorView.cs</DependentUpon>
     </Compile>
     <Compile Include="ExperimentListView.cs">
@@ -159,10 +159,4 @@
     <Compile Include="ExperimentListView.Designer.cs">
       <DependentUpon>ExperimentListView.cs</DependentUpon>
-    </Compile>
-    <Compile Include="ISimilarityCalculatorView.cs">
-      <SubType>UserControl</SubType>
-    </Compile>
-    <Compile Include="ISimilarityCalculatorView.Designer.cs">
-      <DependentUpon>ISimilarityCalculatorView.cs</DependentUpon>
     </Compile>
     <Compile Include="MultiEncodingView.cs">
Index: able/HeuristicLab.Optimization.Views/3.3/ISimilarityCalculatorView.Designer.cs
===================================================================
--- /stable/HeuristicLab.Optimization.Views/3.3/ISimilarityCalculatorView.Designer.cs	(revision 12279)
+++ 	(revision )
@@ -1,53 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-namespace HeuristicLab.Optimization.Views {
-  partial class ISimilarityCalculatorView {
-    /// <summary> 
-    /// Required designer variable.
-    /// </summary>
-    private System.ComponentModel.IContainer components = null;
-
-    /// <summary> 
-    /// Clean up any resources being used.
-    /// </summary>
-    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
-    protected override void Dispose(bool disposing) {
-      if (disposing && (components != null)) {
-        components.Dispose();
-      }
-      base.Dispose(disposing);
-    }
-
-    #region Component Designer generated code
-
-    /// <summary> 
-    /// Required method for Designer support - do not modify 
-    /// the contents of this method with the code editor.
-    /// </summary>
-    private void InitializeComponent() {
-      components = new System.ComponentModel.Container();
-      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
-    }
-
-    #endregion
-  }
-}
Index: able/HeuristicLab.Optimization.Views/3.3/ISimilarityCalculatorView.cs
===================================================================
--- /stable/HeuristicLab.Optimization.Views/3.3/ISimilarityCalculatorView.cs	(revision 12279)
+++ 	(revision )
@@ -1,33 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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.MainForm;
-using HeuristicLab.MainForm.WindowsForms;
-
-namespace HeuristicLab.Optimization.Views {
-  [View("ISimilarityCalculator View")]
-  [Content(typeof(ISolutionSimilarityCalculator), true)]
-  public partial class ISimilarityCalculatorView : AsynchronousContentView {
-    public ISimilarityCalculatorView() {
-      InitializeComponent();
-    }
-  }
-}
Index: able/HeuristicLab.Optimization.Views/3.3/ISingleObjectiveSolutionSimilarityCalculatorView.Designer.cs
===================================================================
--- /stable/HeuristicLab.Optimization.Views/3.3/ISingleObjectiveSolutionSimilarityCalculatorView.Designer.cs	(revision 12279)
+++ 	(revision )
@@ -1,112 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-namespace HeuristicLab.Optimization.Views {
-  partial class ISingleObjectiveSolutionSimilarityCalculatorView {
-    /// <summary> 
-    /// Required designer variable.
-    /// </summary>
-    private System.ComponentModel.IContainer components = null;
-
-    /// <summary> 
-    /// Clean up any resources being used.
-    /// </summary>
-    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
-    protected override void Dispose(bool disposing) {
-      if (disposing && (components != null)) {
-        components.Dispose();
-      }
-      base.Dispose(disposing);
-    }
-
-    #region Component Designer generated code
-
-    /// <summary> 
-    /// Required method for Designer support - do not modify 
-    /// the contents of this method with the code editor.
-    /// </summary>
-    private void InitializeComponent() {
-      this.label1 = new System.Windows.Forms.Label();
-      this.label2 = new System.Windows.Forms.Label();
-      this.qualityVariableNameTextBox = new System.Windows.Forms.TextBox();
-      this.solutionVariableNameTextBox = new System.Windows.Forms.TextBox();
-      this.SuspendLayout();
-      // 
-      // label1
-      // 
-      this.label1.AutoSize = true;
-      this.label1.Location = new System.Drawing.Point(3, 6);
-      this.label1.Name = "label1";
-      this.label1.Size = new System.Drawing.Size(135, 13);
-      this.label1.TabIndex = 0;
-      this.label1.Text = "Variable Name of Solution: ";
-      // 
-      // label2
-      // 
-      this.label2.AutoSize = true;
-      this.label2.Location = new System.Drawing.Point(3, 32);
-      this.label2.Name = "label2";
-      this.label2.Size = new System.Drawing.Size(126, 13);
-      this.label2.TabIndex = 1;
-      this.label2.Text = "Variable Name of Quality:";
-      // 
-      // qualityVariableNameTextBox
-      // 
-      this.qualityVariableNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-      this.qualityVariableNameTextBox.Location = new System.Drawing.Point(144, 29);
-      this.qualityVariableNameTextBox.Name = "qualityVariableNameTextBox";
-      this.qualityVariableNameTextBox.Size = new System.Drawing.Size(287, 20);
-      this.qualityVariableNameTextBox.TabIndex = 2;
-      this.qualityVariableNameTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.qualityVariableNameTextBox_Validating);
-      // 
-      // solutionVariableNameTextBox
-      // 
-      this.solutionVariableNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-      this.solutionVariableNameTextBox.Location = new System.Drawing.Point(144, 3);
-      this.solutionVariableNameTextBox.Name = "solutionVariableNameTextBox";
-      this.solutionVariableNameTextBox.Size = new System.Drawing.Size(287, 20);
-      this.solutionVariableNameTextBox.TabIndex = 3;
-      this.solutionVariableNameTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.solutionVariableNameTextBox_Validating);
-      // 
-      // ISingleObjectiveSolutionSimilarityCalculatorView
-      // 
-      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
-      this.Controls.Add(this.solutionVariableNameTextBox);
-      this.Controls.Add(this.qualityVariableNameTextBox);
-      this.Controls.Add(this.label2);
-      this.Controls.Add(this.label1);
-      this.Name = "ISingleObjectiveSolutionSimilarityCalculatorView";
-      this.Size = new System.Drawing.Size(434, 53);
-      this.ResumeLayout(false);
-      this.PerformLayout();
-
-    }
-
-    #endregion
-
-    private System.Windows.Forms.Label label1;
-    private System.Windows.Forms.Label label2;
-    private System.Windows.Forms.TextBox qualityVariableNameTextBox;
-    private System.Windows.Forms.TextBox solutionVariableNameTextBox;
-  }
-}
Index: able/HeuristicLab.Optimization.Views/3.3/ISingleObjectiveSolutionSimilarityCalculatorView.cs
===================================================================
--- /stable/HeuristicLab.Optimization.Views/3.3/ISingleObjectiveSolutionSimilarityCalculatorView.cs	(revision 12279)
+++ 	(revision )
@@ -1,61 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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.MainForm;
-using HeuristicLab.MainForm.WindowsForms;
-
-namespace HeuristicLab.Optimization.Views {
-  [View("ISingleObjectiveSolutionSimilarityCalculator View")]
-  [Content(typeof(ISingleObjectiveSolutionSimilarityCalculator), true)]
-  public partial class ISingleObjectiveSolutionSimilarityCalculatorView : ISimilarityCalculatorView {
-    public ISingleObjectiveSolutionSimilarityCalculatorView() {
-      InitializeComponent();
-    }
-
-    public new ISingleObjectiveSolutionSimilarityCalculator Content {
-      get { return (ISingleObjectiveSolutionSimilarityCalculator)base.Content; }
-      set { base.Content = value; }
-    }
-
-    protected override void OnContentChanged() {
-      base.OnContentChanged();
-      if (Content == null) {
-        solutionVariableNameTextBox.Clear();
-        qualityVariableNameTextBox.Clear();
-      } else {
-        solutionVariableNameTextBox.Text = Content.SolutionVariableName;
-        qualityVariableNameTextBox.Text = Content.QualityVariableName;
-      }
-    }
-
-    private void solutionVariableNameTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
-      if (Content != null && Content.SolutionVariableName != solutionVariableNameTextBox.Text) {
-        Content.SolutionVariableName = solutionVariableNameTextBox.Text;
-      }
-    }
-
-    private void qualityVariableNameTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
-      if (Content != null && Content.QualityVariableName != qualityVariableNameTextBox.Text) {
-        Content.QualityVariableName = qualityVariableNameTextBox.Text;
-      }
-    }
-  }
-}
Index: /stable/HeuristicLab.Optimization.Views/3.3/ISolutionSimilarityCalculatorView.Designer.cs
===================================================================
--- /stable/HeuristicLab.Optimization.Views/3.3/ISolutionSimilarityCalculatorView.Designer.cs	(revision 12280)
+++ /stable/HeuristicLab.Optimization.Views/3.3/ISolutionSimilarityCalculatorView.Designer.cs	(revision 12280)
@@ -0,0 +1,112 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+namespace HeuristicLab.Optimization.Views {
+  partial class ISolutionSimilarityCalculatorView {
+    /// <summary> 
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary> 
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      this.label1 = new System.Windows.Forms.Label();
+      this.label2 = new System.Windows.Forms.Label();
+      this.qualityVariableNameTextBox = new System.Windows.Forms.TextBox();
+      this.solutionVariableNameTextBox = new System.Windows.Forms.TextBox();
+      this.SuspendLayout();
+      // 
+      // label1
+      // 
+      this.label1.AutoSize = true;
+      this.label1.Location = new System.Drawing.Point(3, 6);
+      this.label1.Name = "label1";
+      this.label1.Size = new System.Drawing.Size(135, 13);
+      this.label1.TabIndex = 0;
+      this.label1.Text = "Variable Name of Solution: ";
+      // 
+      // label2
+      // 
+      this.label2.AutoSize = true;
+      this.label2.Location = new System.Drawing.Point(3, 32);
+      this.label2.Name = "label2";
+      this.label2.Size = new System.Drawing.Size(126, 13);
+      this.label2.TabIndex = 1;
+      this.label2.Text = "Variable Name of Quality:";
+      // 
+      // qualityVariableNameTextBox
+      // 
+      this.qualityVariableNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.qualityVariableNameTextBox.Location = new System.Drawing.Point(144, 29);
+      this.qualityVariableNameTextBox.Name = "qualityVariableNameTextBox";
+      this.qualityVariableNameTextBox.Size = new System.Drawing.Size(287, 20);
+      this.qualityVariableNameTextBox.TabIndex = 2;
+      this.qualityVariableNameTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.qualityVariableNameTextBox_Validating);
+      // 
+      // solutionVariableNameTextBox
+      // 
+      this.solutionVariableNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.solutionVariableNameTextBox.Location = new System.Drawing.Point(144, 3);
+      this.solutionVariableNameTextBox.Name = "solutionVariableNameTextBox";
+      this.solutionVariableNameTextBox.Size = new System.Drawing.Size(287, 20);
+      this.solutionVariableNameTextBox.TabIndex = 3;
+      this.solutionVariableNameTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.solutionVariableNameTextBox_Validating);
+      // 
+      // ISingleObjectiveSolutionSimilarityCalculatorView
+      // 
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+      this.Controls.Add(this.solutionVariableNameTextBox);
+      this.Controls.Add(this.qualityVariableNameTextBox);
+      this.Controls.Add(this.label2);
+      this.Controls.Add(this.label1);
+      this.Name = "ISingleObjectiveSolutionSimilarityCalculatorView";
+      this.Size = new System.Drawing.Size(434, 53);
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.Label label1;
+    private System.Windows.Forms.Label label2;
+    private System.Windows.Forms.TextBox qualityVariableNameTextBox;
+    private System.Windows.Forms.TextBox solutionVariableNameTextBox;
+  }
+}
Index: /stable/HeuristicLab.Optimization.Views/3.3/ISolutionSimilarityCalculatorView.cs
===================================================================
--- /stable/HeuristicLab.Optimization.Views/3.3/ISolutionSimilarityCalculatorView.cs	(revision 12280)
+++ /stable/HeuristicLab.Optimization.Views/3.3/ISolutionSimilarityCalculatorView.cs	(revision 12280)
@@ -0,0 +1,61 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
+
+namespace HeuristicLab.Optimization.Views {
+  [View("ISolutionSimilarityCalculator View")]
+  [Content(typeof(ISolutionSimilarityCalculator), true)]
+  public partial class ISolutionSimilarityCalculatorView : AsynchronousContentView {
+    public ISolutionSimilarityCalculatorView() {
+      InitializeComponent();
+    }
+
+    public new ISolutionSimilarityCalculator Content {
+      get { return (ISolutionSimilarityCalculator)base.Content; }
+      set { base.Content = value; }
+    }
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      if (Content == null) {
+        solutionVariableNameTextBox.Clear();
+        qualityVariableNameTextBox.Clear();
+      } else {
+        solutionVariableNameTextBox.Text = Content.SolutionVariableName;
+        qualityVariableNameTextBox.Text = Content.QualityVariableName;
+      }
+    }
+
+    private void solutionVariableNameTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      if (Content != null && Content.SolutionVariableName != solutionVariableNameTextBox.Text) {
+        Content.SolutionVariableName = solutionVariableNameTextBox.Text;
+      }
+    }
+
+    private void qualityVariableNameTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      if (Content != null && Content.QualityVariableName != qualityVariableNameTextBox.Text) {
+        Content.QualityVariableName = qualityVariableNameTextBox.Text;
+      }
+    }
+  }
+}
Index: /stable/HeuristicLab.Optimization/3.3/Interfaces/ISimilarityBasedOperator.cs
===================================================================
--- /stable/HeuristicLab.Optimization/3.3/Interfaces/ISimilarityBasedOperator.cs	(revision 12279)
+++ /stable/HeuristicLab.Optimization/3.3/Interfaces/ISimilarityBasedOperator.cs	(revision 12280)
@@ -24,5 +24,5 @@
 namespace HeuristicLab.Optimization {
   public interface ISimilarityBasedOperator : IOperator {
-    ISolutionSimilarityCalculator SimilarityCalculator { get; set; }
+    IConstrainedValueParameter<ISolutionSimilarityCalculator> SimilarityCalculatorParameter { get; }
   }
 }
Index: /stable/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveSolutionSimilarityCalculator.cs
===================================================================
--- /stable/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveSolutionSimilarityCalculator.cs	(revision 12279)
+++ /stable/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveSolutionSimilarityCalculator.cs	(revision 12280)
@@ -20,11 +20,17 @@
 #endregion
 
+using System;
+
 namespace HeuristicLab.Optimization {
+  // use HeuristicLab.Optimization.ISolutionSimilarityCalculator instead
+  // BackwardsCompatibility3.3
+  #region Backwards compatible code, remove with 3.4
   /// <summary>
   /// An interface which represents an operator for similarity calculation between single objective solutions.
   /// </summary>
+  [Obsolete("use HeuristicLab.Optimization.ISolutionSimilarityCalculator instead")]
   public interface ISingleObjectiveSolutionSimilarityCalculator : ISolutionSimilarityCalculator, ISingleObjectiveOperator {
-    string SolutionVariableName { get; set; }
-    string QualityVariableName { get; set; }
+
   }
+  #endregion
 }
Index: /stable/HeuristicLab.Optimization/3.3/Interfaces/ISolutionSimilarityCalculator.cs
===================================================================
--- /stable/HeuristicLab.Optimization/3.3/Interfaces/ISolutionSimilarityCalculator.cs	(revision 12279)
+++ /stable/HeuristicLab.Optimization/3.3/Interfaces/ISolutionSimilarityCalculator.cs	(revision 12280)
@@ -28,4 +28,7 @@
   /// </summary>
   public interface ISolutionSimilarityCalculator : IItem, IEqualityComparer<IScope> {
+    string SolutionVariableName { get; set; }
+    string QualityVariableName { get; set; }
+
     /// <summary>
     /// Calculates the similarity of two solutions.
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs	(revision 12279)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs	(revision 12280)
@@ -233,5 +233,5 @@
       Operators.Add(new MinAverageMaxSymbolicExpressionTreeLengthAnalyzer());
       Operators.Add(new SymbolicExpressionTreeLengthAnalyzer());
-      Operators.Add(new SingleObjectivePopulationDiversityAnalyzer());
+      Operators.Add(new PopulationSimilarityAnalyzer(new[] { new SymbolicExpressionTreeBottomUpSimilarityCalculator() }));
       ParameterizeOperators();
     }
@@ -357,7 +357,4 @@
         op.SolutionVariableName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
       }
-      foreach (var op in operators.OfType<SingleObjectivePopulationDiversityAnalyzer>()) {
-        op.SimilarityCalculator = new SymbolicExpressionTreeBottomUpSimilarityCalculator();
-      }
     }
 
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeBottomUpSimilarityCalculator.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeBottomUpSimilarityCalculator.cs	(revision 12279)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeBottomUpSimilarityCalculator.cs	(revision 12280)
@@ -36,4 +36,7 @@
   public class SymbolicExpressionTreeBottomUpSimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator {
     private readonly HashSet<string> commutativeSymbols = new HashSet<string> { "Addition", "Multiplication", "Average", "And", "Or", "Xor" };
+
+    protected override bool IsCommutative { get { return true; } }
+
     public SymbolicExpressionTreeBottomUpSimilarityCalculator() { }
 
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeMaxCommonSubtreeSimilarityCalculator.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeMaxCommonSubtreeSimilarityCalculator.cs	(revision 12279)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeMaxCommonSubtreeSimilarityCalculator.cs	(revision 12280)
@@ -31,4 +31,6 @@
   [Item("SymbolicExpressionTreeMaxCommonSubtreeSimilarityCalculator", "A similarity calculator based on the size of the maximum common subtree between two trees")]
   public class SymbolicExpressionTreeMaxCommonSubtreeSimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator {
+    protected override bool IsCommutative { get { return true; } }
+
     [Storable]
     private readonly SymbolicExpressionTreeNodeEqualityComparer comparer;
Index: /stable/HeuristicLab.Problems.Knapsack/3.3/KnapsackProblem.cs
===================================================================
--- /stable/HeuristicLab.Problems.Knapsack/3.3/KnapsackProblem.cs	(revision 12279)
+++ /stable/HeuristicLab.Problems.Knapsack/3.3/KnapsackProblem.cs	(revision 12280)
@@ -29,4 +29,5 @@
 using HeuristicLab.Encodings.BinaryVectorEncoding;
 using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
@@ -81,7 +82,4 @@
     private BestKnapsackSolutionAnalyzer BestKnapsackSolutionAnalyzer {
       get { return Operators.OfType<BestKnapsackSolutionAnalyzer>().FirstOrDefault(); }
-    }
-    private SingleObjectivePopulationDiversityAnalyzer SingleObjectivePopulationDiversityAnalyzer {
-      get { return Operators.OfType<SingleObjectivePopulationDiversityAnalyzer>().FirstOrDefault(); }
     }
     #endregion
@@ -248,11 +246,4 @@
         BestKnapsackSolutionAnalyzer.ValuesParameter.Hidden = true;
       }
-
-      if (SingleObjectivePopulationDiversityAnalyzer != null) {
-        SingleObjectivePopulationDiversityAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name;
-        SingleObjectivePopulationDiversityAnalyzer.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
-        SingleObjectivePopulationDiversityAnalyzer.ResultsParameter.ActualName = "Results";
-        SingleObjectivePopulationDiversityAnalyzer.SimilarityCalculator = Operators.OfType<KnapsackSimilarityCalculator>().SingleOrDefault();
-      }
     }
     private void InitializeOperators() {
@@ -261,7 +252,9 @@
       Operators.Add(new KnapsackSimultaneousPathRelinker());
       Operators.Add(new KnapsackSimilarityCalculator());
+      Operators.Add(new QualitySimilarityCalculator());
+      Operators.Add(new NoSimilarityCalculator());
 
       Operators.Add(new BestKnapsackSolutionAnalyzer());
-      Operators.Add(new SingleObjectivePopulationDiversityAnalyzer());
+      Operators.Add(new PopulationSimilarityAnalyzer(Operators.OfType<ISolutionSimilarityCalculator>()));
       ParameterizeAnalyzer();
       foreach (IBinaryVectorOperator op in ApplicationManager.Manager.GetInstances<IBinaryVectorOperator>()) {
@@ -317,5 +310,5 @@
         op.ParentsParameter.Hidden = true;
       }
-      foreach (KnapsackSimilarityCalculator op in Operators.OfType<KnapsackSimilarityCalculator>()) {
+      foreach (ISolutionSimilarityCalculator op in Operators.OfType<ISolutionSimilarityCalculator>()) {
         op.SolutionVariableName = SolutionCreator.BinaryVectorParameter.ActualName;
         op.QualityVariableName = Evaluator.QualityParameter.ActualName;
Index: /stable/HeuristicLab.Problems.Knapsack/3.3/SimilarityCalculators/KnapsackSimilarityCalculator.cs
===================================================================
--- /stable/HeuristicLab.Problems.Knapsack/3.3/SimilarityCalculators/KnapsackSimilarityCalculator.cs	(revision 12279)
+++ /stable/HeuristicLab.Problems.Knapsack/3.3/SimilarityCalculators/KnapsackSimilarityCalculator.cs	(revision 12280)
@@ -35,4 +35,6 @@
   [Item("KnapsackSimilarityCalculator", "An operator that performs similarity calculation between two knapsack solutions. The operator calculates the similarity based on the number of elements the two solutions have in common.")]
   public sealed class KnapsackSimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator {
+    protected override bool IsCommutative { get { return true; } }
+
     private KnapsackSimilarityCalculator(bool deserializing) : base(deserializing) { }
     private KnapsackSimilarityCalculator(KnapsackSimilarityCalculator original, Cloner cloner) : base(original, cloner) { }
Index: /stable/HeuristicLab.Problems.QuadraticAssignment/3.3/QAPSimilarityCalculator.cs
===================================================================
--- /stable/HeuristicLab.Problems.QuadraticAssignment/3.3/QAPSimilarityCalculator.cs	(revision 12279)
+++ /stable/HeuristicLab.Problems.QuadraticAssignment/3.3/QAPSimilarityCalculator.cs	(revision 12280)
@@ -35,4 +35,6 @@
   [Item("QAPSimilarityCalculator", "An operator that performs similarity calculation between two quadratic assignment solutions. The operator calculates the similarity based on the number of edges the two solutions have in common.")]
   public sealed class QAPSimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator {
+    protected override bool IsCommutative { get { return true; } }
+
     private QAPSimilarityCalculator(bool deserializing) : base(deserializing) { }
     private QAPSimilarityCalculator(QAPSimilarityCalculator original, Cloner cloner) : base(original, cloner) { }
Index: /stable/HeuristicLab.Problems.TestFunctions/3.3/SimilarityCalculators/SingleObjectiveTestFunctionSimilarityCalculator.cs
===================================================================
--- /stable/HeuristicLab.Problems.TestFunctions/3.3/SimilarityCalculators/SingleObjectiveTestFunctionSimilarityCalculator.cs	(revision 12279)
+++ /stable/HeuristicLab.Problems.TestFunctions/3.3/SimilarityCalculators/SingleObjectiveTestFunctionSimilarityCalculator.cs	(revision 12280)
@@ -38,8 +38,8 @@
   [StorableClass]
   public sealed class SingleObjectiveTestFunctionSimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator {
-    #region Properties
+    protected override bool IsCommutative { get { return true; } }
+
     [Storable]
     public DoubleMatrix Bounds { get; set; }
-    #endregion
 
     [StorableConstructor]
Index: /stable/HeuristicLab.Problems.TestFunctions/3.3/SingleObjectiveTestFunctionProblem.cs
===================================================================
--- /stable/HeuristicLab.Problems.TestFunctions/3.3/SingleObjectiveTestFunctionProblem.cs	(revision 12279)
+++ /stable/HeuristicLab.Problems.TestFunctions/3.3/SingleObjectiveTestFunctionProblem.cs	(revision 12280)
@@ -29,4 +29,5 @@
 using HeuristicLab.Encodings.RealVectorEncoding;
 using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
@@ -71,7 +72,4 @@
     private BestSingleObjectiveTestFunctionSolutionAnalyzer BestSingleObjectiveTestFunctionSolutionAnalyzer {
       get { return Operators.OfType<BestSingleObjectiveTestFunctionSolutionAnalyzer>().FirstOrDefault(); }
-    }
-    private SingleObjectivePopulationDiversityAnalyzer SingleObjectivePopulationDiversityAnalyzer {
-      get { return Operators.OfType<SingleObjectivePopulationDiversityAnalyzer>().FirstOrDefault(); }
     }
     #endregion
@@ -258,11 +256,4 @@
         BestSingleObjectiveTestFunctionSolutionAnalyzer.BoundsParameter.ActualName = BoundsParameter.Name;
       }
-
-      if (SingleObjectivePopulationDiversityAnalyzer != null) {
-        SingleObjectivePopulationDiversityAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name;
-        SingleObjectivePopulationDiversityAnalyzer.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
-        SingleObjectivePopulationDiversityAnalyzer.ResultsParameter.ActualName = "Results";
-        SingleObjectivePopulationDiversityAnalyzer.SimilarityCalculator = Operators.OfType<SingleObjectiveTestFunctionSimilarityCalculator>().SingleOrDefault();
-      }
     }
     private void InitializeOperators() {
@@ -270,7 +261,9 @@
       Operators.Add(new SingleObjectiveTestFunctionPathRelinker());
       Operators.Add(new SingleObjectiveTestFunctionSimilarityCalculator());
+      Operators.Add(new QualitySimilarityCalculator());
+      Operators.Add(new NoSimilarityCalculator());
 
       Operators.Add(new BestSingleObjectiveTestFunctionSolutionAnalyzer());
-      Operators.Add(new SingleObjectivePopulationDiversityAnalyzer());
+      Operators.Add(new PopulationSimilarityAnalyzer(Operators.OfType<ISolutionSimilarityCalculator>()));
       ParameterizeAnalyzers();
       Operators.AddRange(ApplicationManager.Manager.GetInstances<IRealVectorOperator>().Cast<IOperator>());
@@ -325,5 +318,6 @@
       try {
         BestKnownSolutionParameter.Value = Evaluator.GetBestKnownSolution(ProblemSize.Value);
-      } catch (ArgumentException e) {
+      }
+      catch (ArgumentException e) {
         ErrorHandling.ShowErrorDialog(e);
         ProblemSize.Value = Evaluator.MinimumProblemSize;
@@ -391,8 +385,9 @@
         op.ParentsParameter.Hidden = true;
       }
-      foreach (var op in Operators.OfType<SingleObjectiveTestFunctionSimilarityCalculator>()) {
+      foreach (var op in Operators.OfType<ISolutionSimilarityCalculator>()) {
         op.SolutionVariableName = SolutionCreator.RealVectorParameter.ActualName;
         op.QualityVariableName = Evaluator.QualityParameter.ActualName;
-        op.Bounds = Bounds;
+        var calc = op as SingleObjectiveTestFunctionSimilarityCalculator;
+        if (calc != null) calc.Bounds = Bounds;
       }
     }
Index: /stable/HeuristicLab.Problems.TravelingSalesman/3.3/SimilarityCalculators/TSPSimilarityCalculator.cs
===================================================================
--- /stable/HeuristicLab.Problems.TravelingSalesman/3.3/SimilarityCalculators/TSPSimilarityCalculator.cs	(revision 12279)
+++ /stable/HeuristicLab.Problems.TravelingSalesman/3.3/SimilarityCalculators/TSPSimilarityCalculator.cs	(revision 12280)
@@ -35,4 +35,6 @@
   [Item("TSPSimilarityCalculator", "An operator that performs similarity calculation between two traveling salesman solutions. The operator calculates the similarity based on the number of edges the two solutions have in common.")]
   public sealed class TSPSimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator {
+    protected override bool IsCommutative { get { return true; } }
+
     private TSPSimilarityCalculator(bool deserializing) : base(deserializing) { }
     private TSPSimilarityCalculator(TSPSimilarityCalculator original, Cloner cloner) : base(original, cloner) { }
Index: /stable/HeuristicLab.Problems.TravelingSalesman/3.3/TravelingSalesmanProblem.cs
===================================================================
--- /stable/HeuristicLab.Problems.TravelingSalesman/3.3/TravelingSalesmanProblem.cs	(revision 12279)
+++ /stable/HeuristicLab.Problems.TravelingSalesman/3.3/TravelingSalesmanProblem.cs	(revision 12280)
@@ -30,4 +30,5 @@
 using HeuristicLab.Encodings.PermutationEncoding;
 using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
@@ -81,7 +82,4 @@
     private TSPAlleleFrequencyAnalyzer TSPAlleleFrequencyAnalyzer {
       get { return Operators.OfType<TSPAlleleFrequencyAnalyzer>().FirstOrDefault(); }
-    }
-    private SingleObjectivePopulationDiversityAnalyzer SingleObjectivePopulationDiversityAnalyzer {
-      get { return Operators.OfType<SingleObjectivePopulationDiversityAnalyzer>().FirstOrDefault(); }
     }
     #endregion
@@ -236,8 +234,10 @@
       Operators.Add(new TSPSimultaneousPathRelinker());
       Operators.Add(new TSPSimilarityCalculator());
+      Operators.Add(new QualitySimilarityCalculator());
+      Operators.Add(new NoSimilarityCalculator());
 
       Operators.Add(new BestTSPSolutionAnalyzer());
       Operators.Add(new TSPAlleleFrequencyAnalyzer());
-      Operators.Add(new SingleObjectivePopulationDiversityAnalyzer());
+      Operators.Add(new PopulationSimilarityAnalyzer(Operators.OfType<ISolutionSimilarityCalculator>()));
       ParameterizeAnalyzers();
       var operators = new HashSet<IPermutationOperator>(new IPermutationOperator[] {
@@ -319,11 +319,4 @@
         TSPAlleleFrequencyAnalyzer.ResultsParameter.ActualName = "Results";
       }
-
-      if (SingleObjectivePopulationDiversityAnalyzer != null) {
-        SingleObjectivePopulationDiversityAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name;
-        SingleObjectivePopulationDiversityAnalyzer.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
-        SingleObjectivePopulationDiversityAnalyzer.ResultsParameter.ActualName = "Results";
-        SingleObjectivePopulationDiversityAnalyzer.SimilarityCalculator = Operators.OfType<TSPSimilarityCalculator>().SingleOrDefault();
-      }
     }
     private void ParameterizeOperators() {
@@ -366,5 +359,5 @@
         op.ParentsParameter.Hidden = true;
       }
-      foreach (TSPSimilarityCalculator op in Operators.OfType<TSPSimilarityCalculator>()) {
+      foreach (ISolutionSimilarityCalculator op in Operators.OfType<ISolutionSimilarityCalculator>()) {
         op.SolutionVariableName = SolutionCreator.PermutationParameter.ActualName;
         op.QualityVariableName = Evaluator.QualityParameter.ActualName;
Index: /stable/HeuristicLab.Problems.VehicleRouting/3.4/SimilarityCalculators/VRPSimilarityCalculator.cs
===================================================================
--- /stable/HeuristicLab.Problems.VehicleRouting/3.4/SimilarityCalculators/VRPSimilarityCalculator.cs	(revision 12279)
+++ /stable/HeuristicLab.Problems.VehicleRouting/3.4/SimilarityCalculators/VRPSimilarityCalculator.cs	(revision 12280)
@@ -40,8 +40,8 @@
   [StorableClass]
   public sealed class VRPSimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator {
-    #region Properties
+    protected override bool IsCommutative { get { return true; } }
+
     [Storable]
     public IVRPProblemInstance ProblemInstance { get; set; }
-    #endregion
 
     private VRPSimilarityCalculator(bool deserializing) : base(deserializing) { }
Index: /stable/HeuristicLab.Problems.VehicleRouting/3.4/VehicleRoutingProblem.cs
===================================================================
--- /stable/HeuristicLab.Problems.VehicleRouting/3.4/VehicleRoutingProblem.cs	(revision 12279)
+++ /stable/HeuristicLab.Problems.VehicleRouting/3.4/VehicleRoutingProblem.cs	(revision 12280)
@@ -29,4 +29,5 @@
 using HeuristicLab.Data;
 using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
@@ -114,7 +115,4 @@
       set { SolutionCreatorParameter.Value = value; }
     }
-    private SingleObjectivePopulationDiversityAnalyzer SingleObjectivePopulationDiversityAnalyzer {
-      get { return Operators.OfType<SingleObjectivePopulationDiversityAnalyzer>().FirstOrDefault(); }
-    }
     #endregion
 
@@ -256,5 +254,7 @@
           ApplicationManager.Manager.GetInstances<IGeneralVRPOperator>().Cast<IOperator>()).OrderBy(op => op.Name));
         Operators.Add(new VRPSimilarityCalculator());
-        Operators.Add(new SingleObjectivePopulationDiversityAnalyzer());
+        Operators.Add(new QualitySimilarityCalculator());
+        Operators.Add(new NoSimilarityCalculator());
+        Operators.Add(new PopulationSimilarityAnalyzer(Operators.OfType<ISolutionSimilarityCalculator>()));
 
         IVRPCreator defaultCreator = null;
@@ -287,14 +287,9 @@
           op.ParentsParameter.Hidden = true;
         }
-        foreach (VRPSimilarityCalculator op in Operators.OfType<VRPSimilarityCalculator>()) {
+        foreach (ISolutionSimilarityCalculator op in Operators.OfType<ISolutionSimilarityCalculator>()) {
           op.SolutionVariableName = SolutionCreator.VRPToursParameter.ActualName;
           op.QualityVariableName = ProblemInstance.SolutionEvaluator.QualityParameter.ActualName;
-          op.ProblemInstance = ProblemInstance;
-        }
-        if (SingleObjectivePopulationDiversityAnalyzer != null) {
-          SingleObjectivePopulationDiversityAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name;
-          SingleObjectivePopulationDiversityAnalyzer.QualityParameter.ActualName = ProblemInstance.SolutionEvaluator.QualityParameter.ActualName;
-          SingleObjectivePopulationDiversityAnalyzer.ResultsParameter.ActualName = "Results";
-          SingleObjectivePopulationDiversityAnalyzer.SimilarityCalculator = Operators.OfType<VRPSimilarityCalculator>().SingleOrDefault();
+          var calc = op as VRPSimilarityCalculator;
+          if (calc != null) calc.ProblemInstance = ProblemInstance;
         }
       }
