Index: /branches/2521_ProblemRefactoring/HeuristicLab.Encodings.RealVectorEncoding/3.3/HeuristicLab.Encodings.RealVectorEncoding-3.3.csproj
===================================================================
--- /branches/2521_ProblemRefactoring/HeuristicLab.Encodings.RealVectorEncoding/3.3/HeuristicLab.Encodings.RealVectorEncoding-3.3.csproj	(revision 16948)
+++ /branches/2521_ProblemRefactoring/HeuristicLab.Encodings.RealVectorEncoding/3.3/HeuristicLab.Encodings.RealVectorEncoding-3.3.csproj	(revision 16949)
@@ -115,4 +115,6 @@
   <ItemGroup>
     <Compile Include="Creators\NormalDistributedRealVectorCreator.cs" />
+    <Compile Include="RealVectorMultiObjectiveProblem.cs" />
+    <Compile Include="RealVectorProblem.cs" />
     <Compile Include="Interfaces\IRealVectorAdditiveMoveQualityOperator.cs" />
     <Compile Include="Interfaces\IRealVectorBoundedOperator.cs" />
@@ -205,4 +207,9 @@
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Analysis\3.3\HeuristicLab.Analysis-3.3.csproj">
+      <Project>{887425b4-4348-49ed-a457-b7d2c26ddbf9}</Project>
+      <Name>HeuristicLab.Analysis-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Collections\3.3\HeuristicLab.Collections-3.3.csproj">
       <Project>{958B43BC-CC5C-4FA2-8628-2B3B01D890B6}</Project>
Index: /branches/2521_ProblemRefactoring/HeuristicLab.Encodings.RealVectorEncoding/3.3/RealVectorMultiObjectiveProblem.cs
===================================================================
--- /branches/2521_ProblemRefactoring/HeuristicLab.Encodings.RealVectorEncoding/3.3/RealVectorMultiObjectiveProblem.cs	(revision 16949)
+++ /branches/2521_ProblemRefactoring/HeuristicLab.Encodings.RealVectorEncoding/3.3/RealVectorMultiObjectiveProblem.cs	(revision 16949)
@@ -0,0 +1,86 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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 HEAL.Attic;
+using HeuristicLab.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+
+namespace HeuristicLab.Encodings.RealVectorEncoding {
+  [StorableType("135697c1-1b2b-46b6-a518-1c6efae09475")]
+  public abstract class RealVectorMultiObjectiveProblem : MultiObjectiveProblem<RealVectorEncoding, RealVector> {
+    public int Length {
+      get { return Encoding.Length; }
+      set { Encoding.Length = value; }
+    }
+
+    [StorableConstructor]
+    protected RealVectorMultiObjectiveProblem(StorableConstructorFlag _) : base(_) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterEventHandlers();
+    }
+
+    protected RealVectorMultiObjectiveProblem(RealVectorMultiObjectiveProblem original, Cloner cloner)
+      : base(original, cloner) {
+      RegisterEventHandlers();
+    }
+
+    protected RealVectorMultiObjectiveProblem() : this(new RealVectorEncoding() { Length = 10 }) { }
+    protected RealVectorMultiObjectiveProblem(RealVectorEncoding encoding) : base(encoding) {
+      EncodingParameter.ReadOnly = true;
+
+      Operators.Add(new HammingSimilarityCalculator());
+      Operators.Add(new PopulationSimilarityAnalyzer(Operators.OfType<ISolutionSimilarityCalculator>()));
+
+      Parameterize();
+      RegisterEventHandlers();
+    }
+
+    public override void Analyze(RealVector[] individuals, double[][] qualities, ResultCollection results, IRandom random) {
+      base.Analyze(individuals, qualities, results, random);
+      // TODO: Calculate Pareto front and add to results
+    }
+
+    protected override void OnEncodingChanged() {
+      base.OnEncodingChanged();
+      Parameterize();
+    }
+
+    private void Parameterize() {
+      foreach (var similarityCalculator in Operators.OfType<ISolutionSimilarityCalculator>()) {
+        similarityCalculator.SolutionVariableName = Encoding.Name;
+        similarityCalculator.QualityVariableName = Evaluator.QualitiesParameter.ActualName;
+      }
+    }
+
+    private void RegisterEventHandlers() {
+      Encoding.LengthParameter.Value.ValueChanged += LengthParameter_ValueChanged;
+    }
+
+    protected virtual void LengthParameter_ValueChanged(object sender, EventArgs e) { }
+  }
+}
Index: /branches/2521_ProblemRefactoring/HeuristicLab.Encodings.RealVectorEncoding/3.3/RealVectorProblem.cs
===================================================================
--- /branches/2521_ProblemRefactoring/HeuristicLab.Encodings.RealVectorEncoding/3.3/RealVectorProblem.cs	(revision 16949)
+++ /branches/2521_ProblemRefactoring/HeuristicLab.Encodings.RealVectorEncoding/3.3/RealVectorProblem.cs	(revision 16949)
@@ -0,0 +1,91 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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 HEAL.Attic;
+using HeuristicLab.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+
+namespace HeuristicLab.Encodings.RealVectorEncoding {
+  [StorableType("7860a955-af16-459a-9cd8-51667e06d38e")]
+  public abstract class RealVectorProblem : SingleObjectiveProblem<RealVectorEncoding, RealVector> {
+    public int Length {
+      get { return Encoding.Length; }
+      set { Encoding.Length = value; }
+    }
+
+    [StorableConstructor]
+    protected RealVectorProblem(StorableConstructorFlag _) : base(_) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterEventHandlers();
+    }
+
+    protected RealVectorProblem(RealVectorProblem original, Cloner cloner)
+      : base(original, cloner) {
+      RegisterEventHandlers();
+    }
+
+    protected RealVectorProblem() : this(new RealVectorEncoding() { Length = 10 }) { }
+    protected RealVectorProblem(RealVectorEncoding encoding) : base(encoding) {
+      EncodingParameter.ReadOnly = true;
+
+      Operators.Add(new HammingSimilarityCalculator());
+      Operators.Add(new QualitySimilarityCalculator());
+      Operators.Add(new PopulationSimilarityAnalyzer(Operators.OfType<ISolutionSimilarityCalculator>()));
+
+      Parameterize();
+      RegisterEventHandlers();
+    }
+
+    public override void Analyze(RealVector[] individuals, double[] qualities, ResultCollection results, IRandom random) {
+      base.Analyze(individuals, qualities, results, random);
+      var orderedIndividuals = individuals.Zip(qualities, (i, q) => new { Individual = i, Quality = q }).OrderBy(z => z.Quality);
+      var best = Maximization ? orderedIndividuals.Last().Individual : orderedIndividuals.First().Individual;
+
+      results.AddOrUpdateResult("Best Solution", (IItem)best.Clone());
+    }
+
+    protected override void OnEncodingChanged() {
+      base.OnEncodingChanged();
+      Parameterize();
+    }
+
+    private void Parameterize() {
+      foreach (var similarityCalculator in Operators.OfType<ISolutionSimilarityCalculator>()) {
+        similarityCalculator.SolutionVariableName = Encoding.Name;
+        similarityCalculator.QualityVariableName = Evaluator.QualityParameter.ActualName;
+      }
+    }
+
+    private void RegisterEventHandlers() {
+      Encoding.LengthParameter.Value.ValueChanged += LengthParameter_ValueChanged;
+    }
+
+    protected virtual void LengthParameter_ValueChanged(object sender, EventArgs e) { }
+  }
+}
Index: /branches/2521_ProblemRefactoring/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/SymbolicExpressionTreeProblem.cs
===================================================================
--- /branches/2521_ProblemRefactoring/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/SymbolicExpressionTreeProblem.cs	(revision 16948)
+++ /branches/2521_ProblemRefactoring/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/SymbolicExpressionTreeProblem.cs	(revision 16949)
@@ -46,5 +46,8 @@
     }
 
-    protected SymbolicExpressionTreeProblem(SymbolicExpressionTreeEncoding encoding) : base(encoding) { }
+    protected SymbolicExpressionTreeProblem(SymbolicExpressionTreeEncoding encoding)
+      : base(encoding) {
+      EncodingParameter.ReadOnly = true;
+    }
 
     public override void Analyze(ISymbolicExpressionTree[] trees, double[] qualities, ResultCollection results,
Index: /branches/2521_ProblemRefactoring/HeuristicLab.Problems.TestFunctions.MultiObjective/3.3/MultiObjectiveTestFunctionProblem.cs
===================================================================
--- /branches/2521_ProblemRefactoring/HeuristicLab.Problems.TestFunctions.MultiObjective/3.3/MultiObjectiveTestFunctionProblem.cs	(revision 16948)
+++ /branches/2521_ProblemRefactoring/HeuristicLab.Problems.TestFunctions.MultiObjective/3.3/MultiObjectiveTestFunctionProblem.cs	(revision 16949)
@@ -35,5 +35,6 @@
   [Creatable(CreatableAttribute.Categories.Problems, Priority = 95)]
   [Item("Test Function (multi-objective)", "Test functions with real valued inputs and multiple objectives.")]
-  public class MultiObjectiveTestFunctionProblem : MultiObjectiveProblem<RealVectorEncoding, RealVector>, IProblemInstanceConsumer<MOTFData> {
+  public class MultiObjectiveTestFunctionProblem : RealVectorMultiObjectiveProblem,
+    IProblemInstanceConsumer<MOTFData> {
 
     #region Parameter Properties
Index: /branches/2521_ProblemRefactoring/HeuristicLab.Problems.TestFunctions/3.3/Analyzers/BestSingleObjectiveTestFunctionSolutionAnalyzer.cs
===================================================================
--- /branches/2521_ProblemRefactoring/HeuristicLab.Problems.TestFunctions/3.3/Analyzers/BestSingleObjectiveTestFunctionSolutionAnalyzer.cs	(revision 16948)
+++ /branches/2521_ProblemRefactoring/HeuristicLab.Problems.TestFunctions/3.3/Analyzers/BestSingleObjectiveTestFunctionSolutionAnalyzer.cs	(revision 16949)
@@ -20,5 +20,7 @@
 #endregion
 
+using System;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -28,7 +30,9 @@
 using HeuristicLab.Optimization;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
+using HeuristicLab.PluginInfrastructure;
 
 namespace HeuristicLab.Problems.TestFunctions {
+  // BackwardsCompatibility3.3
+  #region Backwards compatible code, remove with 3.4
   /// <summary>
   /// An operator for analyzing the best solution for a SingleObjectiveTestFunction problem.
@@ -36,4 +40,6 @@
   [Item("BestSingleObjectiveTestFunctionSolutionAnalyzer", "An operator for analyzing the best solution for a SingleObjectiveTestFunction problem.")]
   [StorableType("A0F04F9F-DD27-44D8-A1F6-B289F1F40DE2")]
+  [NonDiscoverableType]
+  [Obsolete("Use the Analyze method of the test function problem class")]
   public class BestSingleObjectiveTestFunctionSolutionAnalyzer : SingleSuccessorOperator, IBestSingleObjectiveTestFunctionSolutionAnalyzer {
     public virtual bool EnabledByDefault {
@@ -145,3 +151,4 @@
     }
   }
+  #endregion
 }
Index: /branches/2521_ProblemRefactoring/HeuristicLab.Problems.TestFunctions/3.3/SingleObjectiveTestFunctionProblem.cs
===================================================================
--- /branches/2521_ProblemRefactoring/HeuristicLab.Problems.TestFunctions/3.3/SingleObjectiveTestFunctionProblem.cs	(revision 16948)
+++ /branches/2521_ProblemRefactoring/HeuristicLab.Problems.TestFunctions/3.3/SingleObjectiveTestFunctionProblem.cs	(revision 16949)
@@ -23,4 +23,5 @@
 using System.Collections.Generic;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Analysis;
 using HeuristicLab.Common;
@@ -29,7 +30,5 @@
 using HeuristicLab.Encodings.RealVectorEncoding;
 using HeuristicLab.Optimization;
-using HeuristicLab.Optimization.Operators;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 using HeuristicLab.Problems.Instances;
 
@@ -38,6 +37,5 @@
   [StorableType("F0AB7236-2C9B-49DC-9D4F-A3558FD9E992")]
   [Creatable(CreatableAttribute.Categories.Problems, Priority = 90)]
-  public sealed class SingleObjectiveTestFunctionProblem :
-    SingleObjectiveProblem<RealVectorEncoding, RealVector>,
+  public sealed class SingleObjectiveTestFunctionProblem : RealVectorProblem,
     IProblemInstanceConsumer<SOTFData> {
 
@@ -73,8 +71,4 @@
       get { return TestFunctionParameter.Value; }
       set { TestFunctionParameter.Value = value; }
-    }
-
-    private BestSingleObjectiveTestFunctionSolutionAnalyzer BestSingleObjectiveTestFunctionSolutionAnalyzer {
-      get { return Operators.OfType<BestSingleObjectiveTestFunctionSolutionAnalyzer>().FirstOrDefault(); }
     }
     #endregion
@@ -121,4 +115,48 @@
     }
 
+    public override void Analyze(RealVector[] realVectors, double[] qualities, ResultCollection results, IRandom random) {
+
+      bool max = Maximization;
+      DoubleValue bestKnownQuality = BestKnownQualityParameter.Value;
+      SingleObjectiveTestFunctionSolution solution = null;
+      if (results.TryGetValue("Best Solution", out var res)) {
+        solution = (SingleObjectiveTestFunctionSolution)res.Value;
+      }
+
+      int i = -1;
+      if (!max) i = qualities.Select((x, index) => new { index, quality = x }).OrderBy(x => x.quality).First().index;
+      else i = qualities.Select((x, index) => new { index, quality = x }).OrderByDescending(x => x.quality).First().index;
+
+      if (bestKnownQuality == null ||
+          max && qualities[i] > bestKnownQuality.Value
+          || !max && qualities[i] < bestKnownQuality.Value) {
+        BestKnownQualityParameter.Value = new DoubleValue(qualities[i]);
+        BestKnownSolutionParameter.Value = (RealVector)realVectors[i].Clone();
+        if (solution != null)
+          solution.BestKnownRealVector = BestKnownSolutionParameter.Value;
+      }
+
+      if (solution == null) {
+        solution = new SingleObjectiveTestFunctionSolution((RealVector)realVectors[i].Clone(),
+                                                           new DoubleValue(qualities[i]),
+                                                           TestFunctionParameter.Value);
+        solution.Population = realVectors[i].Length == 2
+          ? new ItemArray<RealVector>(realVectors.Select(x => x.Clone()).Cast<RealVector>())
+          : null;
+        solution.BestKnownRealVector = BestKnownSolutionParameter.Value;
+        solution.Bounds = BoundsParameter.Value;
+        results.Add(new Result("Best Solution", solution));
+      } else {
+        if (max && qualities[i] > solution.BestQuality.Value
+          || !max && qualities[i] < solution.BestQuality.Value) {
+          solution.BestRealVector = (RealVector)realVectors[i].Clone();
+          solution.BestQuality = new DoubleValue(qualities[i]);
+        }
+        solution.Population = realVectors[i].Length == 2
+          ? new ItemArray<RealVector>(realVectors.Select(x => x.Clone()).Cast<RealVector>())
+          : null;
+      }
+    }
+
     #region Events
     protected override void OnEncodingChanged() {
@@ -162,11 +200,7 @@
       Operators.Add(new SingleObjectiveTestFunctionPathRelinker());
       Operators.Add(new SingleObjectiveTestFunctionSimilarityCalculator());
-      Operators.Add(new HammingSimilarityCalculator());
       Operators.Add(new EuclideanSimilarityCalculator());
-      Operators.Add(new QualitySimilarityCalculator());
       Operators.Add(new AdditiveMoveEvaluator());
 
-      Operators.Add(new BestSingleObjectiveTestFunctionSolutionAnalyzer());
-      Operators.Add(new PopulationSimilarityAnalyzer(Operators.OfType<ISolutionSimilarityCalculator>()));
       Parameterize();
     }
@@ -174,11 +208,13 @@
     private void Parameterize() {
       var operators = new List<IItem>();
-      if (BestSingleObjectiveTestFunctionSolutionAnalyzer != null) {
-        operators.Add(BestSingleObjectiveTestFunctionSolutionAnalyzer);
-        BestSingleObjectiveTestFunctionSolutionAnalyzer.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
-        BestSingleObjectiveTestFunctionSolutionAnalyzer.BestKnownQualityParameter.ActualName = BestKnownQualityParameter.Name;
-        BestSingleObjectiveTestFunctionSolutionAnalyzer.BestKnownSolutionParameter.ActualName = BestKnownSolutionParameter.Name;
-        BestSingleObjectiveTestFunctionSolutionAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name;
-        BestSingleObjectiveTestFunctionSolutionAnalyzer.TestFunctionParameter.ActualName = TestFunctionParameter.Name;
+      foreach (var op in Operators.OfType<PopulationSimilarityAnalyzer>()) {
+        var calcs = Operators.OfType<ISolutionSimilarityCalculator>().ToArray();
+        op.SimilarityCalculatorParameter.ValidValues.Clear();
+        foreach (var c in calcs) {
+          // TODO: unified encoding parameters
+          c.SolutionVariableName = ((IRealVectorSolutionOperator)Encoding.SolutionCreator).RealVectorParameter.ActualName;
+          c.QualityVariableName = Evaluator.QualityParameter.ActualName;
+          op.SimilarityCalculatorParameter.ValidValues.Add(c);
+        }
       }
       foreach (var op in Operators.OfType<ISingleObjectiveTestFunctionAdditiveMoveEvaluator>()) {
