Index: branches/2521_ProblemRefactoring/HeuristicLab.Algorithms.CMAEvolutionStrategy/3.4/CMAAnalyzer.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Algorithms.CMAEvolutionStrategy/3.4/CMAAnalyzer.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Algorithms.CMAEvolutionStrategy/3.4/CMAAnalyzer.cs	(revision 17747)
@@ -22,4 +22,5 @@
 using System;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Analysis;
 using HeuristicLab.Common;
@@ -30,5 +31,4 @@
 using HeuristicLab.Optimization;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 
 namespace HeuristicLab.Algorithms.CMAEvolutionStrategy {
@@ -98,5 +98,5 @@
         progress.Rows.Add(new DataRow("Avg Quality"));
         progress.VisualProperties.YAxisLogScale = true;
-        results.Add(new Result("Progress", progress));
+        results.Add(new Result("Progress", "The quality progress over time on a log scale.", progress));
       }
       progress.Rows["AxisRatio"].Values.Add(sp.AxisRatio);
@@ -114,5 +114,5 @@
         for (int i = 0; i < sp.C.GetLength(0); i++)
           scaling.Rows.Add(new DataRow("Axis" + i.ToString()));
-        results.Add(new Result("Scaling", scaling));
+        results.Add(new Result("Scaling", "The extent to which the individual dimensions are scaled by the mutation.", scaling));
       }
       for (int i = 0; i < sp.C.GetLength(0); i++)
@@ -126,5 +126,5 @@
         for (int i = 0; i < vector.Length; i++)
           realVector.Rows.Add(new DataRow("Axis" + i.ToString()));
-        results.Add(new Result("Object Variables", realVector));
+        results.Add(new Result("Object Variables", "The value of the centroid point.", realVector));
       }
       for (int i = 0; i < vector.Length; i++)
@@ -141,5 +141,5 @@
         for (int i = 0; i < vector.Length; i++)
           stdDevs.Rows.Add(new DataRow("Axis" + i.ToString()));
-        results.Add(new Result("Standard Deviations", stdDevs));
+        results.Add(new Result("Standard Deviations", "The standard deviations of the various axis, as well as the minimum and maximum standard deviation.", stdDevs));
       }
       for (int i = 0; i < vector.Length; i++)
Index: branches/2521_ProblemRefactoring/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/HillClimber.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/HillClimber.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/HillClimber.cs	(revision 17747)
@@ -94,6 +94,6 @@
       Parameters.Add(MaximumIterationsParameter = new FixedValueParameter<IntValue>("Maximum Iterations", "", new IntValue(100)));
 
-      Results.Add(BestQualityResult = new Result<DoubleValue>("Best Quality"));
-      Results.Add(IterationsResult = new Result<IntValue>("Iterations"));
+      Results.Add(BestQualityResult = new Result<DoubleValue>("Best Quality", "The best quality found so far."));
+      Results.Add(IterationsResult = new Result<IntValue>("Iterations", "The current iteration."));
     }
 
Index: branches/2521_ProblemRefactoring/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/ParameterlessPopulationPyramid.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/ParameterlessPopulationPyramid.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/ParameterlessPopulationPyramid.cs	(revision 17747)
@@ -229,14 +229,14 @@
       // Set up the results display
       if (!Results.TryGetValue("Iterations", out var result))
-        Results.Add(new Result("Iterations", resultsIterations = new IntValue(0)));
+        Results.Add(new Result("Iterations", "The current iteration.", resultsIterations = new IntValue(0)));
       else result.Value = resultsIterations = new IntValue(0);
       if (!Results.TryGetValue("Evaluations", out var result2))
-        Results.Add(new Result("Evaluations", resultsEvaluations = new IntValue(0)));
+        Results.Add(new Result("Evaluations", "The number of evaluations that have been performed.", resultsEvaluations = new IntValue(0)));
       else result2.Value = resultsEvaluations = new IntValue(0);
       if (!Results.TryGetValue("Best Quality", out var result4))
-        Results.Add(new Result("Best Quality", resultsBestQuality = new DoubleValue(tracker.BestQuality)));
+        Results.Add(new Result("Best Quality", "The best quality that has been observed so far.", resultsBestQuality = new DoubleValue(tracker.BestQuality)));
       else result4.Value = resultsBestQuality = new DoubleValue(tracker.BestQuality);
       if (!Results.TryGetValue("Evaluation Best Solution Was Found", out var result5))
-        Results.Add(new Result("Evaluation Best Solution Was Found", resultsBestFoundOnEvaluation = new IntValue(tracker.BestFoundOnEvaluation)));
+        Results.Add(new Result("Evaluation Best Solution Was Found", "The number of evaluations at which the best solution was found.", resultsBestFoundOnEvaluation = new IntValue(tracker.BestFoundOnEvaluation)));
       else result5.Value = resultsBestFoundOnEvaluation = new IntValue(tracker.BestFoundOnEvaluation);
       var table = new DataTable("Qualities");
@@ -245,5 +245,5 @@
       ResultsQualitiesIteration.VisualProperties.LineStyle = DataRowVisualProperties.DataRowLineStyle.Dot;
       if (!Results.TryGetValue("Qualities", out var result6))
-        Results.Add(new Result("Qualities", table));
+        Results.Add(new Result("Qualities", "An analysis of the quality progress over time.", table));
       else result6.Value = table;
 
@@ -251,5 +251,5 @@
       table.Rows.Add(ResultsLevels = new DataRow("Levels"));
       if (!Results.TryGetValue("Pyramid Levels", out var result7))
-        Results.Add(new Result("Pyramid Levels", table));
+        Results.Add(new Result("Pyramid Levels", "The number of levels of the pyramid.", table));
       else result7.Value = table;
 
@@ -257,5 +257,5 @@
       table.Rows.Add(ResultsSolutions = new DataRow("Solutions"));
       if (!Results.TryGetValue("Stored Solutions", out var result8))
-        Results.Add(new Result("Stored Solutions", table));
+        Results.Add(new Result("Stored Solutions", "The number of solutions that are found over time.", table));
       else result8.Value = table;
 
Index: branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/AlleleFrequencyAnalyzer.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/AlleleFrequencyAnalyzer.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/AlleleFrequencyAnalyzer.cs	(revision 17747)
@@ -23,4 +23,5 @@
 using System.Collections.Generic;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -29,5 +30,4 @@
 using HeuristicLab.Optimization;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 
 namespace HeuristicLab.Analysis {
@@ -165,5 +165,5 @@
         if (!ResultsParameter.ActualValue.ContainsKey(Name + " Results")) {
           results = new ResultCollection();
-          ResultsParameter.ActualValue.Add(new Result(Name + " Results", results));
+          ResultsParameter.ActualValue.Add(new Result(Name + " Results", "Collection of allele frequency analysis results", results));
         } else {
           results = (ResultCollection)ResultsParameter.ActualValue[Name + " Results"].Value;
@@ -173,5 +173,5 @@
         AlleleFrequencyCollection frequenciesCollection = new AlleleFrequencyCollection(frequencies);
         if (!results.ContainsKey("Allele Frequencies"))
-          results.Add(new Result("Allele Frequencies", frequenciesCollection));
+          results.Add(new Result("Allele Frequencies", "Displays for all alleles in the population the frequencies with which these occur.", frequenciesCollection));
         else
           results["Allele Frequencies"].Value = frequenciesCollection;
@@ -182,5 +182,5 @@
             AlleleFrequencyCollectionHistory history = new AlleleFrequencyCollectionHistory();
             history.Add(frequenciesCollection);
-            results.Add(new Result("Allele Frequencies History", history));
+            results.Add(new Result("Allele Frequencies History", "Snapshots of the allele frequency of each generation.", history));
           } else {
             ((AlleleFrequencyCollectionHistory)results["Allele Frequencies History"].Value).Add(frequenciesCollection);
@@ -215,5 +215,5 @@
           allelesTable.Rows["Lost Alleles of Best Known Solution"].VisualProperties.StartIndexZero = true;
 
-          results.Add(new Result("Alleles", allelesTable));
+          results.Add(new Result("Alleles", "Tabular summary of the allele frequency analysis", allelesTable));
         } else {
           allelesTable = (DataTable)results["Alleles"].Value;
@@ -234,25 +234,25 @@
         // store alleles values
         if (!results.ContainsKey("Unique Alleles"))
-          results.Add(new Result("Unique Alleles", new DoubleValue(frequenciesCollection.Count)));
+          results.Add(new Result("Unique Alleles", "The number of unique alleles currently in the population.", new DoubleValue(frequenciesCollection.Count)));
         else
           ((DoubleValue)results["Unique Alleles"].Value).Value = frequenciesCollection.Count;
 
         if (!results.ContainsKey("Unique Alleles of Best Known Solution"))
-          results.Add(new Result("Unique Alleles of Best Known Solution", new DoubleValue(uniqueRelevantAllelesCount)));
+          results.Add(new Result("Unique Alleles of Best Known Solution", "The number of alleles from the best-known solution that are currently present in the population.", new DoubleValue(uniqueRelevantAllelesCount)));
         else
           ((DoubleValue)results["Unique Alleles of Best Known Solution"].Value).Value = uniqueRelevantAllelesCount;
 
         if (!results.ContainsKey("Fixed Alleles"))
-          results.Add(new Result("Fixed Alleles", new DoubleValue(fixedAllelesCount)));
+          results.Add(new Result("Fixed Alleles", "The number of alleles, that are present in every individual of the population.", new DoubleValue(fixedAllelesCount)));
         else
           ((DoubleValue)results["Fixed Alleles"].Value).Value = fixedAllelesCount;
 
         if (!results.ContainsKey("Fixed Alleles of Best Known Solution"))
-          results.Add(new Result("Fixed Alleles of Best Known Solution", new DoubleValue(fixedRelevantAllelesCount)));
+          results.Add(new Result("Fixed Alleles of Best Known Solution", "The number of alles from the best-known solution that are present in every individual of the population.", new DoubleValue(fixedRelevantAllelesCount)));
         else
           ((DoubleValue)results["Fixed Alleles of Best Known Solution"].Value).Value = fixedRelevantAllelesCount;
 
         if (!results.ContainsKey("Lost Alleles of Best Known Solution"))
-          results.Add(new Result("Lost Alleles of Best Known Solution", new DoubleValue(lostRelevantAllelesCount)));
+          results.Add(new Result("Lost Alleles of Best Known Solution", "The number of alles from the best-known solution that are currently not present in the population.", new DoubleValue(lostRelevantAllelesCount)));
         else
           ((DoubleValue)results["Lost Alleles of Best Known Solution"].Value).Value = lostRelevantAllelesCount;
@@ -282,10 +282,10 @@
 
           if (!results.ContainsKey("Scatter Plot"))
-            results.Add(new Result("Scatter Plot", plot));
+            results.Add(new Result("Scatter Plot", "A plot that shows the correlation between number of unique alleles that an individual shares with the best-known solution and its relative quality.", plot));
           else
             results["Scatter Plot"].Value = plot;
           if (storeHistory) {
             if (!results.ContainsKey("Scatter Plot History")) {
-              results.Add(new Result("Scatter Plot History", new ScatterPlotHistory()));
+              results.Add(new Result("Scatter Plot History", "Snapshots of the scatter plot that show correlation between shared alleles with best-known solution and relative solution quality.", new ScatterPlotHistory()));
             }
             ((ScatterPlotHistory)results["Scatter Plot History"].Value).Add(plot);
@@ -300,5 +300,5 @@
 
           if (!results.ContainsKey("Average Contained Alleles of Best Known Solution"))
-            results.Add(new Result("Average Contained Alleles of Best Known Solution", new DoubleValue(avgContainedReleventAlleles)));
+            results.Add(new Result("Average Contained Alleles of Best Known Solution", "Average number of alleles that individuals share with the best-known solution.", new DoubleValue(avgContainedReleventAlleles)));
           else
             ((DoubleValue)results["Average Contained Alleles of Best Known Solution"].Value).Value = avgContainedReleventAlleles;
Index: branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/BestScopeSolutionAnalyzer.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/BestScopeSolutionAnalyzer.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/BestScopeSolutionAnalyzer.cs	(revision 17747)
@@ -124,5 +124,5 @@
         var solution = cloner.Clone(currentBestScope);
 
-        results.Add(new Result(BestSolutionResultName, solution));
+        results.Add(new Result(BestSolutionResultName, "The best solution found so far.", solution));
       } else {
         var bestSolution = (IScope)results[BestSolutionResultName].Value;
Index: branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/RankBasedParetoFrontAnalyzer.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/RankBasedParetoFrontAnalyzer.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/RankBasedParetoFrontAnalyzer.cs	(revision 17747)
@@ -22,4 +22,5 @@
 using System.Collections.Generic;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -27,5 +28,4 @@
 using HeuristicLab.Optimization;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 
 namespace HeuristicLab.Analysis {
@@ -72,10 +72,10 @@
       if (results.ContainsKey("Pareto Front"))
         results["Pareto Front"].Value = front;
-      else results.Add(new Result("Pareto Front", front));
+      else results.Add(new Result("Pareto Front", "A tabular presentation of the current Pareto front.", front));
 
       if (populationLevel) {
         if (results.ContainsKey("Pareto Archive"))
           results["Pareto Archive"].Value = paretoArchive;
-        else results.Add(new Result("Pareto Archive", paretoArchive));
+        else results.Add(new Result("Pareto Archive", "The individual solutions on the Pareto front.", paretoArchive));
       }
     }
Index: branches/2521_ProblemRefactoring/HeuristicLab.Encodings.BinaryVectorEncoding/3.3/BinaryVectorMultiObjectiveProblem.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Encodings.BinaryVectorEncoding/3.3/BinaryVectorMultiObjectiveProblem.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Encodings.BinaryVectorEncoding/3.3/BinaryVectorMultiObjectiveProblem.cs	(revision 17747)
@@ -33,10 +33,15 @@
   [StorableType("b64caac0-a23a-401a-bb7e-ffa3e22b80ea")]
   public abstract class BinaryVectorMultiObjectiveProblem : MultiObjectiveProblem<BinaryVectorEncoding, BinaryVector> {
-    [Storable] protected IResultParameter<ParetoFrontScatterPlot<BinaryVector>> BestResultParameter { get; private set; }
     [Storable] protected ReferenceParameter<IntValue> DimensionRefParameter { get; private set; }
+    [Storable] public IResult<ParetoFrontScatterPlot<BinaryVector>> BestParetoFrontResult { get; private set; }
 
     public int Dimension {
       get { return DimensionRefParameter.Value.Value; }
       protected set { DimensionRefParameter.Value.Value = value; }
+    }
+
+    protected ParetoFrontScatterPlot<BinaryVector> BestParetoFront {
+      get => BestParetoFrontResult.Value;
+      set => BestParetoFrontResult.Value = value;
     }
 
@@ -50,6 +55,7 @@
     protected BinaryVectorMultiObjectiveProblem(BinaryVectorMultiObjectiveProblem original, Cloner cloner)
       : base(original, cloner) {
-      BestResultParameter = cloner.Clone(original.BestResultParameter);
       DimensionRefParameter = cloner.Clone(original.DimensionRefParameter);
+      BestParetoFrontResult = cloner.Clone(original.BestParetoFrontResult);
+
       RegisterEventHandlers();
     }
@@ -59,6 +65,6 @@
       EncodingParameter.ReadOnly = true;
       EvaluatorParameter.ReadOnly = true;
-      Parameters.Add(BestResultParameter = new ResultParameter<ParetoFrontScatterPlot<BinaryVector>>("Best Pareto Front", "The best Pareto front found."));
       Parameters.Add(DimensionRefParameter = new ReferenceParameter<IntValue>("Dimension", "The dimension of the binary vector problem.", Encoding.LengthParameter));
+      Results.Add(BestParetoFrontResult = new Result<ParetoFrontScatterPlot<BinaryVector>>("Best Pareto Front", "The best Pareto front found so far."));
 
       Operators.Add(new HammingSimilarityCalculator());
@@ -75,5 +81,5 @@
       var plot = new ParetoFrontScatterPlot<BinaryVector>(fronts, individuals, qualities, Objectives, BestKnownFront);
 
-      BestResultParameter.ActualValue = plot;
+      BestParetoFront = plot;
     }
 
Index: branches/2521_ProblemRefactoring/HeuristicLab.Encodings.BinaryVectorEncoding/3.3/BinaryVectorProblem.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Encodings.BinaryVectorEncoding/3.3/BinaryVectorProblem.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Encodings.BinaryVectorEncoding/3.3/BinaryVectorProblem.cs	(revision 17747)
@@ -37,12 +37,12 @@
     [Storable] public IResult<ISingleObjectiveSolutionContext<BinaryVector>> BestSolutionResult { get; private set; }
 
-    private ISingleObjectiveSolutionContext<BinaryVector> BestSolution {
-      get => BestSolutionResult.Value;
-      set => BestSolutionResult.Value = value;
-    }
-
     public int Dimension {
       get { return DimensionRefParameter.Value.Value; }
       protected set { DimensionRefParameter.Value.Value = value; }
+    }
+
+    protected ISingleObjectiveSolutionContext<BinaryVector> BestSolution {
+      get => BestSolutionResult.Value;
+      set => BestSolutionResult.Value = value;
     }
 
@@ -66,5 +66,5 @@
       EvaluatorParameter.ReadOnly = true;
       Parameters.Add(DimensionRefParameter = new ReferenceParameter<IntValue>("Dimension", "The dimension of the binary vector problem.", Encoding.LengthParameter));
-      Results.Add(BestSolutionResult = new Result<ISingleObjectiveSolutionContext<BinaryVector>>("Best Solution"));
+      Results.Add(BestSolutionResult = new Result<ISingleObjectiveSolutionContext<BinaryVector>>("Best Solution", "The best solution found so far."));
 
       Operators.Add(new HammingSimilarityCalculator());
Index: branches/2521_ProblemRefactoring/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorMultiObjectiveProblem.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorMultiObjectiveProblem.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorMultiObjectiveProblem.cs	(revision 17747)
@@ -35,7 +35,7 @@
   [StorableType("11916b0f-4c34-4ece-acae-e28d11211b43")]
   public abstract class IntegerVectorMultiObjectiveProblem : MultiObjectiveProblem<IntegerVectorEncoding, IntegerVector> {
-    [Storable] protected IResultParameter<ParetoFrontScatterPlot<IntegerVector>> BestResultParameter { get; private set; }
     [Storable] protected ReferenceParameter<IntValue> DimensionRefParameter { get; private set; }
     [Storable] protected ReferenceParameter<IntMatrix> BoundsRefParameter { get; private set; }
+    [Storable] public IResult<ParetoFrontScatterPlot<IntegerVector>> BestParetoFrontResult { get; private set; }
 
     public int Dimension {
@@ -49,4 +49,9 @@
     }
 
+    protected ParetoFrontScatterPlot<IntegerVector> BestParetoFront {
+      get => BestParetoFrontResult.Value;
+      set => BestParetoFrontResult.Value = value;
+    }
+
     [StorableConstructor]
     protected IntegerVectorMultiObjectiveProblem(StorableConstructorFlag _) : base(_) { }
@@ -58,7 +63,7 @@
     protected IntegerVectorMultiObjectiveProblem(IntegerVectorMultiObjectiveProblem original, Cloner cloner)
       : base(original, cloner) {
-      BestResultParameter = cloner.Clone(original.BestResultParameter);
       DimensionRefParameter = cloner.Clone(original.DimensionRefParameter);
       BoundsRefParameter = cloner.Clone(original.BoundsRefParameter);
+      BestParetoFrontResult = cloner.Clone(original.BestParetoFrontResult);
       RegisterEventHandlers();
     }
@@ -68,7 +73,7 @@
       EncodingParameter.ReadOnly = true;
       EvaluatorParameter.ReadOnly = true;
-      Parameters.Add(BestResultParameter = new ResultParameter<ParetoFrontScatterPlot<IntegerVector>>("Best Pareto Front", "The best Pareto front found."));
       Parameters.Add(DimensionRefParameter = new ReferenceParameter<IntValue>("Dimension", "The dimension of the integer vector problem.", Encoding.LengthParameter));
       Parameters.Add(BoundsRefParameter = new ReferenceParameter<IntMatrix>("Bounds", "The bounds of the integer vector problem.", Encoding.BoundsParameter));
+      Results.Add(BestParetoFrontResult = new Result<ParetoFrontScatterPlot<IntegerVector>>("Best Pareto Front", "The best Pareto front found so far."));
 
       Operators.Add(new HammingSimilarityCalculator());
@@ -85,5 +90,5 @@
       var plot = new ParetoFrontScatterPlot<IntegerVector>(fronts, individuals, qualities, Objectives, BestKnownFront);
 
-      BestResultParameter.ActualValue = plot;
+      BestParetoFront = plot;
     }
 
Index: branches/2521_ProblemRefactoring/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorProblem.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorProblem.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorProblem.cs	(revision 17747)
@@ -36,7 +36,7 @@
   [StorableType("c6081457-a3de-45ce-9f47-e0eb1c851bd2")]
   public abstract class IntegerVectorProblem : SingleObjectiveProblem<IntegerVectorEncoding, IntegerVector> {
-    [Storable] protected IResultParameter<IntegerVector> BestResultParameter { get; private set; }
     [Storable] protected ReferenceParameter<IntValue> DimensionRefParameter { get; private set; }
     [Storable] protected ReferenceParameter<IntMatrix> BoundsRefParameter { get; private set; }
+    [Storable] public IResult<ISingleObjectiveSolutionContext<IntegerVector>> BestSolutionResult { get; private set; }
 
     public int Dimension {
@@ -50,4 +50,9 @@
     }
 
+    protected ISingleObjectiveSolutionContext<IntegerVector> BestSolution {
+      get => BestSolutionResult.Value;
+      set => BestSolutionResult.Value = value;
+    }
+
     [StorableConstructor]
     protected IntegerVectorProblem(StorableConstructorFlag _) : base(_) { }
@@ -59,7 +64,7 @@
     protected IntegerVectorProblem(IntegerVectorProblem original, Cloner cloner)
       : base(original, cloner) {
-      BestResultParameter = cloner.Clone(original.BestResultParameter);
       DimensionRefParameter = cloner.Clone(original.DimensionRefParameter);
       BoundsRefParameter = cloner.Clone(original.BoundsRefParameter);
+      BestSolutionResult = cloner.Clone(original.BestSolutionResult);
       RegisterEventHandlers();
     }
@@ -69,7 +74,7 @@
       EncodingParameter.ReadOnly = true;
       EvaluatorParameter.ReadOnly = true;
-      Parameters.Add(BestResultParameter = new ResultParameter<IntegerVector>("Best Solution", "The best solution."));
       Parameters.Add(DimensionRefParameter = new ReferenceParameter<IntValue>("Dimension", "The dimension of the integer vector problem.", Encoding.LengthParameter));
       Parameters.Add(BoundsRefParameter = new ReferenceParameter<IntMatrix>("Bounds", "The bounding box and step sizes of the values.", Encoding.BoundsParameter));
+      Results.Add(BestSolutionResult = new Result<ISingleObjectiveSolutionContext<IntegerVector>>("Best Solution", "The best solution found so far."));
 
       Operators.Add(new HammingSimilarityCalculator());
@@ -82,11 +87,9 @@
     }
 
-    public override void Analyze(ISingleObjectiveSolutionContext<IntegerVector>[] solutionContext, IRandom random) {
-      base.Analyze(solutionContext, random);
-
-      var best = GetBest(solutionContext);
-
-      //TODO reimplement code below using results directly
-      //results.AddOrUpdateResult("Best Solution", (IntegerVector)best.EncodedSolution.Clone());
+    public override void Analyze(ISingleObjectiveSolutionContext<IntegerVector>[] solutionContexts, IRandom random) {
+      base.Analyze(solutionContexts, random);
+      var best = GetBest(solutionContexts);
+      if (BestSolution == null || IsBetter(best, BestSolution))
+        BestSolution = best.Clone() as SingleObjectiveSolutionContext<IntegerVector>;
     }
 
Index: branches/2521_ProblemRefactoring/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkageMultiObjectiveProblem.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkageMultiObjectiveProblem.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkageMultiObjectiveProblem.cs	(revision 17747)
@@ -36,9 +36,14 @@
   public abstract class LinearLinkageMultiObjectiveProblem : MultiObjectiveProblem<LinearLinkageEncoding, LinearLinkage> {
     [Storable] protected ReferenceParameter<IntValue> DimensionRefParameter { get; private set; }
-    public IValueParameter<IntValue> DimensionParameter => DimensionRefParameter;
+    [Storable] public IResult<ParetoFrontScatterPlot<LinearLinkage>> BestParetoFrontResult { get; private set; }
 
     public int Dimension {
       get { return DimensionRefParameter.Value.Value; }
       set { DimensionRefParameter.Value.Value = value; }
+    }
+
+    protected ParetoFrontScatterPlot<LinearLinkage> BestParetoFront {
+      get => BestParetoFrontResult.Value;
+      set => BestParetoFrontResult.Value = value;
     }
 
@@ -53,4 +58,6 @@
       : base(original, cloner) {
       DimensionRefParameter = cloner.Clone(original.DimensionRefParameter);
+      BestParetoFrontResult = cloner.Clone(original.BestParetoFrontResult);
+
       RegisterEventHandlers();
     }
@@ -61,5 +68,5 @@
       EvaluatorParameter.ReadOnly = true;
       Parameters.Add(DimensionRefParameter = new ReferenceParameter<IntValue>("Dimension", "The dimension of the linear linkage problem.", Encoding.LengthParameter));
-
+      Results.Add(BestParetoFrontResult = new Result<ParetoFrontScatterPlot<LinearLinkage>>("Best Pareto Front", "The best Pareto front found so far."));
 
       Operators.Add(new HammingSimilarityCalculator());
@@ -75,5 +82,6 @@
       var fronts = DominationCalculator.CalculateAllParetoFrontsIndices(individuals, qualities, Maximization);
       var plot = new ParetoFrontScatterPlot<LinearLinkage>(fronts, individuals, qualities, Objectives, BestKnownFront);
-      results.AddOrUpdateResult("Pareto Front Scatter Plot", plot);
+
+      BestParetoFront = plot;
     }
 
Index: branches/2521_ProblemRefactoring/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkageProblem.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkageProblem.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkageProblem.cs	(revision 17747)
@@ -37,8 +37,14 @@
   public abstract class LinearLinkageProblem : SingleObjectiveProblem<LinearLinkageEncoding, LinearLinkage> {
     [Storable] protected ReferenceParameter<IntValue> DimensionRefParameter { get; private set; }
+    [Storable] public IResult<ISingleObjectiveSolutionContext<LinearLinkage>> BestSolutionResult { get; private set; }
 
     public int Dimension {
       get { return DimensionRefParameter.Value.Value; }
       set { DimensionRefParameter.Value.Value = value; }
+    }
+
+    protected ISingleObjectiveSolutionContext<LinearLinkage> BestSolution {
+      get => BestSolutionResult.Value;
+      set => BestSolutionResult.Value = value;
     }
 
@@ -53,4 +59,5 @@
       : base(original, cloner) {
       DimensionRefParameter = cloner.Clone(original.DimensionRefParameter);
+      BestSolutionResult = cloner.Clone(original.BestSolutionResult);
       RegisterEventHandlers();
     }
@@ -61,4 +68,5 @@
       EvaluatorParameter.ReadOnly = true;
       Parameters.Add(DimensionRefParameter = new ReferenceParameter<IntValue>("Dimension", "The dimension of the linear linkage problem.", Encoding.LengthParameter));
+      Results.Add(BestSolutionResult = new Result<ISingleObjectiveSolutionContext<LinearLinkage>>("Best Solution", "The best solution found so far."));
 
       Operators.Add(new HammingSimilarityCalculator());
@@ -73,10 +81,7 @@
     public override void Analyze(ISingleObjectiveSolutionContext<LinearLinkage>[] solutionContexts, IRandom random) {
       base.Analyze(solutionContexts, random);
-
-      //TODO: reimplement code below using results directly
-
-      //var best = GetBestSolution(vectors, qualities);
-
-      //results.AddOrUpdateResult("Best Solution", (Item)best.Item1.Clone());
+      var best = GetBest(solutionContexts);
+      if (BestSolution == null || IsBetter(best, BestSolution))
+        BestSolution = best.Clone() as SingleObjectiveSolutionContext<LinearLinkage>;
     }
 
Index: branches/2521_ProblemRefactoring/HeuristicLab.Encodings.PermutationEncoding/3.3/PermutationMultiObjectiveProblem.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Encodings.PermutationEncoding/3.3/PermutationMultiObjectiveProblem.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Encodings.PermutationEncoding/3.3/PermutationMultiObjectiveProblem.cs	(revision 17747)
@@ -37,4 +37,5 @@
     [Storable] protected ReferenceParameter<IntValue> DimensionRefParameter { get; private set; }
     [Storable] protected ReferenceParameter<EnumValue<PermutationTypes>> PermutationTypeRefParameter { get; private set; }
+    [Storable] public IResult<ParetoFrontScatterPlot<Permutation>> BestParetoFrontResult { get; private set; }
 
     public int Dimension {
@@ -46,4 +47,9 @@
       get { return PermutationTypeRefParameter.Value.Value; }
       set { PermutationTypeRefParameter.Value.Value = value; }
+    }
+
+    protected ParetoFrontScatterPlot<Permutation> BestParetoFront {
+      get => BestParetoFrontResult.Value;
+      set => BestParetoFrontResult.Value = value;
     }
 
@@ -59,4 +65,6 @@
       DimensionRefParameter = cloner.Clone(original.DimensionRefParameter);
       PermutationTypeRefParameter = cloner.Clone(original.PermutationTypeRefParameter);
+      BestParetoFrontResult = cloner.Clone(original.BestParetoFrontResult);
+
       RegisterEventHandlers();
     }
@@ -68,4 +76,5 @@
       Parameters.Add(DimensionRefParameter = new ReferenceParameter<IntValue>("Dimension", "The dimension of the permutation problem.", Encoding.LengthParameter));
       Parameters.Add(PermutationTypeRefParameter = new ReferenceParameter<EnumValue<PermutationTypes>>("Type", "The type of the permutation.", Encoding.PermutationTypeParameter));
+      Results.Add(BestParetoFrontResult = new Result<ParetoFrontScatterPlot<Permutation>>("Best Pareto Front", "The best Pareto front found so far."));
 
       Operators.Add(new HammingSimilarityCalculator());
@@ -81,5 +90,6 @@
       var fronts = DominationCalculator.CalculateAllParetoFrontsIndices(individuals, qualities, Maximization);
       var plot = new ParetoFrontScatterPlot<Permutation>(fronts, individuals, qualities, Objectives, BestKnownFront);
-      results.AddOrUpdateResult("Pareto Front Scatter Plot", plot);
+
+      BestParetoFront = plot;
     }
 
Index: branches/2521_ProblemRefactoring/HeuristicLab.Encodings.PermutationEncoding/3.3/PermutationProblem.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Encodings.PermutationEncoding/3.3/PermutationProblem.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Encodings.PermutationEncoding/3.3/PermutationProblem.cs	(revision 17747)
@@ -38,4 +38,5 @@
     [Storable] protected ReferenceParameter<IntValue> DimensionRefParameter { get; private set; }
     [Storable] protected ReferenceParameter<EnumValue<PermutationTypes>> PermutationTypeRefParameter { get; private set; }
+    [Storable] public IResult<ISingleObjectiveSolutionContext<Permutation>> BestSolutionResult { get; private set; }
 
     public int Dimension {
@@ -47,4 +48,9 @@
       get { return PermutationTypeRefParameter.Value.Value; }
       set { PermutationTypeRefParameter.Value.Value = value; }
+    }
+
+    protected ISingleObjectiveSolutionContext<Permutation> BestSolution {
+      get => BestSolutionResult.Value;
+      set => BestSolutionResult.Value = value;
     }
 
@@ -60,4 +66,5 @@
       DimensionRefParameter = cloner.Clone(original.DimensionRefParameter);
       PermutationTypeRefParameter = cloner.Clone(original.PermutationTypeRefParameter);
+      BestSolutionResult = cloner.Clone(original.BestSolutionResult);
       RegisterEventHandlers();
     }
@@ -69,4 +76,5 @@
       Parameters.Add(DimensionRefParameter = new ReferenceParameter<IntValue>("Dimension", "The dimension of the permutation problem.", Encoding.LengthParameter));
       Parameters.Add(PermutationTypeRefParameter = new ReferenceParameter<EnumValue<PermutationTypes>>("Type", "The type of the permutation.", Encoding.PermutationTypeParameter));
+      Results.Add(BestSolutionResult = new Result<ISingleObjectiveSolutionContext<Permutation>>("Best Solution", "The best solution found so far."));
 
       Operators.Add(new HammingSimilarityCalculator());
@@ -81,8 +89,7 @@
     public override void Analyze(ISingleObjectiveSolutionContext<Permutation>[] solutionContexts, IRandom random) {
       base.Analyze(solutionContexts, random);
-
-      //TODO reimplement code below using results directly                                                                       solutionContexts
-      //var best = GetBestSolution(permutations, qualities);
-      //results.AddOrUpdateResult("Best Solution", (IItem)best.Item1.Clone());
+      var best = GetBest(solutionContexts);
+      if (BestSolution == null || IsBetter(best, BestSolution))
+        BestSolution = best.Clone() as SingleObjectiveSolutionContext<Permutation>;
     }
 
Index: branches/2521_ProblemRefactoring/HeuristicLab.Encodings.RealVectorEncoding/3.3/RealVectorMultiObjectiveProblem.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Encodings.RealVectorEncoding/3.3/RealVectorMultiObjectiveProblem.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Encodings.RealVectorEncoding/3.3/RealVectorMultiObjectiveProblem.cs	(revision 17747)
@@ -37,4 +37,5 @@
     [Storable] protected ReferenceParameter<IntValue> DimensionRefParameter { get; private set; }
     [Storable] protected ReferenceParameter<DoubleMatrix> BoundsRefParameter { get; private set; }
+    [Storable] public IResult<ParetoFrontScatterPlot<RealVector>> BestParetoFrontResult { get; private set; }
 
     public int Dimension {
@@ -46,4 +47,9 @@
       get { return BoundsRefParameter.Value; }
       set { BoundsRefParameter.Value = value; }
+    }
+
+    protected ParetoFrontScatterPlot<RealVector> BestParetoFront {
+      get => BestParetoFrontResult.Value;
+      set => BestParetoFrontResult.Value = value;
     }
 
@@ -59,4 +65,5 @@
       DimensionRefParameter = cloner.Clone(original.DimensionRefParameter);
       BoundsRefParameter = cloner.Clone(original.BoundsRefParameter);
+      BestParetoFrontResult = cloner.Clone(original.BestParetoFrontResult);
       RegisterEventHandlers();
     }
@@ -68,5 +75,5 @@
       Parameters.Add(DimensionRefParameter = new ReferenceParameter<IntValue>("Dimension", "The dimension of the real vector problem.", Encoding.LengthParameter));
       Parameters.Add(BoundsRefParameter = new ReferenceParameter<DoubleMatrix>("Bounds", "The bounding box of the values.", Encoding.BoundsParameter));
-
+      Results.Add(BestParetoFrontResult = new Result<ParetoFrontScatterPlot<RealVector>>("Best Pareto Front", "The best Pareto front found so far."));
 
       Operators.Add(new HammingSimilarityCalculator());
@@ -82,5 +89,6 @@
       var fronts = DominationCalculator.CalculateAllParetoFrontsIndices(individuals, qualities, Maximization);
       var plot = new ParetoFrontScatterPlot<RealVector>(fronts, individuals, qualities, Objectives, BestKnownFront);
-      results.AddOrUpdateResult("Pareto Front Scatter Plot", plot);
+
+      BestParetoFront = plot;
     }
 
Index: branches/2521_ProblemRefactoring/HeuristicLab.Encodings.RealVectorEncoding/3.3/RealVectorProblem.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Encodings.RealVectorEncoding/3.3/RealVectorProblem.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Encodings.RealVectorEncoding/3.3/RealVectorProblem.cs	(revision 17747)
@@ -38,4 +38,5 @@
     [Storable] protected ReferenceParameter<IntValue> DimensionRefParameter { get; private set; }
     [Storable] protected ReferenceParameter<DoubleMatrix> BoundsRefParameter { get; private set; }
+    [Storable] public IResult<ISingleObjectiveSolutionContext<RealVector>> BestSolutionResult { get; private set; }
 
     public int Dimension {
@@ -47,4 +48,9 @@
       get { return BoundsRefParameter.Value; }
       set { BoundsRefParameter.Value = value; }
+    }
+
+    protected ISingleObjectiveSolutionContext<RealVector> BestSolution {
+      get => BestSolutionResult.Value;
+      set => BestSolutionResult.Value = value;
     }
 
@@ -60,4 +66,5 @@
       DimensionRefParameter = cloner.Clone(original.DimensionRefParameter);
       BoundsRefParameter = cloner.Clone(original.BoundsRefParameter);
+      BestSolutionResult = cloner.Clone(original.BestSolutionResult);
       RegisterEventHandlers();
     }
@@ -69,4 +76,5 @@
       Parameters.Add(DimensionRefParameter = new ReferenceParameter<IntValue>("Dimension", "The dimension of the real vector problem.", Encoding.LengthParameter));
       Parameters.Add(BoundsRefParameter = new ReferenceParameter<DoubleMatrix>("Bounds", "The bounding box of the values.", Encoding.BoundsParameter));
+      Results.Add(BestSolutionResult = new Result<ISingleObjectiveSolutionContext<RealVector>>("Best Solution", "The best solution found so far."));
 
       Operators.Add(new HammingSimilarityCalculator());
@@ -82,10 +90,7 @@
     public override void Analyze(ISingleObjectiveSolutionContext<RealVector>[] solutionContexts, IRandom random) {
       base.Analyze(solutionContexts, random);
-
-      //TODO: reimplement code below using results directly
-
-      //var best = GetBestSolution(vectors, qualities);
-
-      //results.AddOrUpdateResult("Best Solution", (IItem)best.Item1.Clone());
+      var best = GetBest(solutionContexts);
+      if (BestSolution == null || IsBetter(best, BestSolution))
+        BestSolution = best.Clone() as SingleObjectiveSolutionContext<RealVector>;
     }
 
Index: branches/2521_ProblemRefactoring/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/SymbolicExpressionTreeMultiObjectiveProblem.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/SymbolicExpressionTreeMultiObjectiveProblem.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/SymbolicExpressionTreeMultiObjectiveProblem.cs	(revision 17747)
@@ -38,4 +38,5 @@
     [Storable] private ReferenceParameter<IntValue> TreeDepthRefParameter { get; set; }
     [Storable] private ReferenceParameter<ISymbolicExpressionGrammar> GrammarRefParameter { get; set; }
+    [Storable] public IResult<ParetoFrontScatterPlot<ISymbolicExpressionTree>> BestParetoFrontResult { get; private set; }
 
     public int TreeLength {
@@ -54,5 +55,9 @@
     }
 
-    // persistence
+    protected ParetoFrontScatterPlot<ISymbolicExpressionTree> BestParetoFront {
+      get => BestParetoFrontResult.Value;
+      set => BestParetoFrontResult.Value = value;
+    }
+
     [StorableConstructor]
     protected SymbolicExpressionTreeMultiObjectiveProblem(StorableConstructorFlag _) : base(_) { }
@@ -62,6 +67,4 @@
     }
 
-
-    // cloning
     protected SymbolicExpressionTreeMultiObjectiveProblem(SymbolicExpressionTreeMultiObjectiveProblem original, Cloner cloner)
       : base(original, cloner) {
@@ -69,4 +72,5 @@
       TreeDepthRefParameter = cloner.Clone(original.TreeDepthRefParameter);
       GrammarRefParameter = cloner.Clone(original.GrammarRefParameter);
+      BestParetoFrontResult = cloner.Clone(original.BestParetoFrontResult);
       RegisterEventHandlers();
     }
@@ -79,4 +83,5 @@
       Parameters.Add(TreeDepthRefParameter = new ReferenceParameter<IntValue>("TreeDepth", "The maximum depth of the tree.", Encoding.TreeDepthParameter));
       Parameters.Add(GrammarRefParameter = new ReferenceParameter<ISymbolicExpressionGrammar>("Grammar", "The grammar that describes a valid tree.", Encoding.GrammarParameter));
+      Results.Add(BestParetoFrontResult = new Result<ParetoFrontScatterPlot<ISymbolicExpressionTree>>("Best Pareto Front", "The best Pareto front found so far."));
 
       Parameterize();
@@ -90,5 +95,6 @@
       var fronts = DominationCalculator.CalculateAllParetoFrontsIndices(trees, qualities, Maximization);
       var plot = new ParetoFrontScatterPlot<ISymbolicExpressionTree>(fronts, trees, qualities, Objectives, BestKnownFront);
-      results.AddOrUpdateResult("Pareto Front Scatter Plot", plot);
+
+      BestParetoFront = plot;
     }
 
Index: branches/2521_ProblemRefactoring/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/SymbolicExpressionTreeProblem.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/SymbolicExpressionTreeProblem.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/SymbolicExpressionTreeProblem.cs	(revision 17747)
@@ -39,4 +39,5 @@
     [Storable] protected ReferenceParameter<IntValue> TreeDepthRefParameter { get; private set; }
     [Storable] protected ReferenceParameter<ISymbolicExpressionGrammar> GrammarRefParameter { get; private set; }
+    [Storable] public IResult<ISingleObjectiveSolutionContext<ISymbolicExpressionTree>> BestSolutionResult { get; private set; }
 
     public int TreeLength {
@@ -55,4 +56,9 @@
     }
 
+    protected ISingleObjectiveSolutionContext<ISymbolicExpressionTree> BestSolution {
+      get => BestSolutionResult.Value;
+      set => BestSolutionResult.Value = value;
+    }
+
     // persistence
     [StorableConstructor]
@@ -69,4 +75,5 @@
       TreeDepthRefParameter = cloner.Clone(original.TreeDepthRefParameter);
       GrammarRefParameter = cloner.Clone(original.GrammarRefParameter);
+      BestSolutionResult = cloner.Clone(original.BestSolutionResult);
       RegisterEventHandlers();
     }
@@ -80,4 +87,5 @@
       Parameters.Add(TreeDepthRefParameter = new ReferenceParameter<IntValue>("TreeDepth", "The maximum depth of the tree.", Encoding.TreeDepthParameter));
       Parameters.Add(GrammarRefParameter = new ReferenceParameter<ISymbolicExpressionGrammar>("Grammar", "The grammar that describes a valid tree.", Encoding.GrammarParameter));
+      Results.Add(BestSolutionResult = new Result<ISingleObjectiveSolutionContext<ISymbolicExpressionTree>>("Best Solution", "The best solution found so far."));
 
       // TODO: These should be added in the SingleObjectiveProblem base class (if they were accessible from there)
@@ -90,23 +98,8 @@
 
     public override void Analyze(ISingleObjectiveSolutionContext<ISymbolicExpressionTree>[] solutionContexts, IRandom random) {
-      //TODO reimplement code below using results directly
-
-      //if (!results.ContainsKey("Best Solution Quality")) {
-      //  results.Add(new Result("Best Solution Quality", typeof(DoubleValue)));
-      //}
-      //if (!results.ContainsKey("Best Solution")) {
-      //  results.Add(new Result("Best Solution", typeof(ISymbolicExpressionTree)));
-      //}
-
-      //var bestQuality = Maximization ? qualities.Max() : qualities.Min();
-
-      //if (results["Best Solution Quality"].Value == null ||
-      //    IsBetter(bestQuality, ((DoubleValue)results["Best Solution Quality"].Value).Value)) {
-      //  var bestIdx = Array.IndexOf(qualities, bestQuality);
-      //  var bestClone = (IItem)trees[bestIdx].Clone();
-
-      //  results["Best Solution"].Value = bestClone;
-      //  results["Best Solution Quality"].Value = new DoubleValue(bestQuality);
-      //}
+      base.Analyze(solutionContexts, random);
+      var best = GetBest(solutionContexts);
+      if (BestSolution == null || IsBetter(best, BestSolution))
+        BestSolution = best.Clone() as SingleObjectiveSolutionContext<ISymbolicExpressionTree>;
     }
 
Index: branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/Results/Result.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/Results/Result.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/Results/Result.cs	(revision 17747)
@@ -151,11 +151,9 @@
     }
 
-    public Result(string name) : this(name, typeof(T)) { }
-    public Result(string name, Type dataType) : this(name, string.Empty, dataType) { }
-    public Result(string name, string description, Type dataType) : base(name, description, dataType) { }
-
-    public Result(string name, T value) : this(name, string.Empty, value.GetType(), value) { }
-    public Result(string name, string description, T value) : this(name, description, value.GetType(), value) { }
-    public Result(string name, string description, Type dataType, IItem value) : base(name, description, dataType, value) { }
+    //public Result(string name) : this(name, string.Empty) { }
+    public Result(string name, string description) : base(name, description, typeof(T)) { }
+    
+    //public Result(string name, T value) : this(name, string.Empty, value) { }
+    public Result(string name, string description, T value) : base(name, description, typeof(T), value) { }
   }
 }
Index: branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/Results/ResultCollection.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/Results/ResultCollection.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/Results/ResultCollection.cs	(revision 17747)
@@ -75,8 +75,8 @@
     }
 
-    public void AddOrUpdateResult(string name, IItem value) {
+    public void AddOrUpdateResult(string name, IItem value, string description = null) {
       IResult res;
       if (!TryGetValue(name, out res)) {
-        res = new Result(name, value);
+        res = new Result(name, description ?? string.Empty, value);
         Add(res);
       } else res.Value = value;
Index: branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/Results/ResultParameter.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/Results/ResultParameter.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/Results/ResultParameter.cs	(revision 17747)
@@ -114,5 +114,5 @@
       if (!results.TryGetValue(ActualName, out result)) {
         if (DefaultValue == null) return null;
-        result = ItemDescription == Description ? new Result(ActualName, (T)DefaultValue.Clone()) : new Result(ActualName, Description, (T)DefaultValue.Clone());
+        result = new Result(ActualName, Description, (T)DefaultValue.Clone());
         results.Add(result);
       }
@@ -143,5 +143,5 @@
       IResult result;
       if (!results.TryGetValue(ActualName, out result)) {
-        result = ItemDescription == Description ? new Result(ActualName, value) : new Result(ActualName, Description, value);
+        result = new Result(ActualName, Description, value);
         results.Add(result);
       } else result.Value = value;
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/ExternalEvaluationProblem.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/ExternalEvaluationProblem.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/ExternalEvaluationProblem.cs	(revision 17747)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2019 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -26,4 +26,5 @@
 using System.Threading;
 using Google.ProtocolBuffers;
+using HEAL.Attic;
 using HeuristicLab.Analysis;
 using HeuristicLab.Common;
@@ -32,5 +33,4 @@
 using HeuristicLab.Optimization;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 
 namespace HeuristicLab.Problems.ExternalEvaluation {
@@ -40,5 +40,7 @@
   // BackwardsCompatibility3.3
   // Rename class to SingleObjectiveExternalEvaluationProblem
-  public class ExternalEvaluationProblem : SingleObjectiveProblem<IEncoding<IEncodedSolution>, IEncodedSolution>, IExternalEvaluationProblem {
+  public class ExternalEvaluationProblem<TEncoding, TEncodedSolution> : SingleObjectiveProblem<TEncoding, TEncodedSolution>, IExternalEvaluationProblem
+    where TEncoding : class, IEncoding
+    where TEncodedSolution : class, IEncodedSolution {
 
     public static new Image StaticItemImage {
@@ -56,15 +58,11 @@
       get { return (IValueParameter<SolutionMessageBuilder>)Parameters["MessageBuilder"]; }
     }
-    public IFixedValueParameter<SingleObjectiveOptimizationSupportScript> SupportScriptParameter {
-      get { return (IFixedValueParameter<SingleObjectiveOptimizationSupportScript>)Parameters["SupportScript"]; }
-    }
-
-    private IFixedValueParameter<BoolValue> MaximizationParameter {
-      get { return (IFixedValueParameter<BoolValue>)Parameters["Maximization"]; }
+    public IFixedValueParameter<SingleObjectiveOptimizationSupportScript<TEncodedSolution>> SupportScriptParameter {
+      get { return (IFixedValueParameter<SingleObjectiveOptimizationSupportScript<TEncodedSolution>>)Parameters["SupportScript"]; }
     }
     #endregion
 
     #region Properties
-    public new IEncoding<IEncodedSolution> Encoding {
+    public new TEncoding Encoding {
       get { return base.Encoding; }
       set { base.Encoding = value; }
@@ -79,8 +77,8 @@
       get { return MessageBuilderParameter.Value; }
     }
-    public SingleObjectiveOptimizationSupportScript OptimizationSupportScript {
+    public SingleObjectiveOptimizationSupportScript<TEncodedSolution> OptimizationSupportScript {
       get { return SupportScriptParameter.Value; }
     }
-    private ISingleObjectiveOptimizationSupport OptimizationSupport {
+    private ISingleObjectiveOptimizationSupport<TEncodedSolution> OptimizationSupport {
       get { return SupportScriptParameter.Value; }
     }
@@ -89,16 +87,16 @@
     [StorableConstructor]
     protected ExternalEvaluationProblem(StorableConstructorFlag _) : base(_) { }
-    protected ExternalEvaluationProblem(ExternalEvaluationProblem original, Cloner cloner) : base(original, cloner) { }
+    protected ExternalEvaluationProblem(ExternalEvaluationProblem<TEncoding, TEncodedSolution> original, Cloner cloner) : base(original, cloner) { }
     public override IDeepCloneable Clone(Cloner cloner) {
-      return new ExternalEvaluationProblem(this, cloner);
+      return new ExternalEvaluationProblem<TEncoding, TEncodedSolution>(this, cloner);
     }
-    public ExternalEvaluationProblem()
-      : base() {
-      Parameters.Remove("Maximization"); // readonly in base class
-      Parameters.Add(new FixedValueParameter<BoolValue>("Maximization", "Set to false if the problem should be minimized.", new BoolValue()));
+    public ExternalEvaluationProblem(TEncoding encoding)
+      : base(encoding) {
+      MaximizationParameter.ReadOnly = false;
+      MaximizationParameter.Value = new BoolValue(); // is a read-only bool value in base class
       Parameters.Add(new OptionalValueParameter<EvaluationCache>("Cache", "Cache of previously evaluated solutions."));
       Parameters.Add(new ValueParameter<CheckedItemCollection<IEvaluationServiceClient>>("Clients", "The clients that are used to communicate with the external application.", new CheckedItemCollection<IEvaluationServiceClient>() { new EvaluationServiceClient() }));
       Parameters.Add(new ValueParameter<SolutionMessageBuilder>("MessageBuilder", "The message builder that converts from HeuristicLab objects to SolutionMessage representation.", new SolutionMessageBuilder()) { Hidden = true });
-      Parameters.Add(new FixedValueParameter<SingleObjectiveOptimizationSupportScript>("SupportScript", "A script that can provide neighborhood and analyze the results of the optimization.", new SingleObjectiveOptimizationSupportScript()));
+      Parameters.Add(new FixedValueParameter<SingleObjectiveOptimizationSupportScript<TEncodedSolution>>("SupportScript", "A script that can provide neighborhood and analyze the results of the optimization.", new SingleObjectiveOptimizationSupportScript<TEncodedSolution>(Results)));
 
       Operators.Add(new BestScopeSolutionAnalyzer());
@@ -106,30 +104,23 @@
 
     #region Single Objective Problem Overrides
-    public override bool Maximization {
-      get { return Parameters.ContainsKey("Maximization") && ((IValueParameter<BoolValue>)Parameters["Maximization"]).Value.Value; }
+    public override ISingleObjectiveEvaluationResult Evaluate(TEncodedSolution solution, IRandom random, CancellationToken cancellationToken) {
+      var qualityMessage = Evaluate(BuildSolutionMessage(solution), cancellationToken);
+      if (!qualityMessage.HasExtension(SingleObjectiveQualityMessage.QualityMessage_))
+        throw new InvalidOperationException("The received message is not a SingleObjectiveQualityMessage.");
+      var quality = qualityMessage.GetExtension(SingleObjectiveQualityMessage.QualityMessage_).Quality;
+      return new SingleObjectiveEvaluationResult(quality);
+
+    }
+    public virtual QualityMessage Evaluate(SolutionMessage solutionMessage, CancellationToken cancellationToken) {
+      return Cache == null
+        ? EvaluateOnNextAvailableClient(solutionMessage, cancellationToken)
+        : Cache.GetValue(solutionMessage, EvaluateOnNextAvailableClient, GetQualityMessageExtensions(), cancellationToken);
     }
 
-    public virtual void SetMaximization(bool maximization) {
-      MaximizationParameter.Value.Value = maximization;
+    public override void Analyze(ISingleObjectiveSolutionContext<TEncodedSolution>[] solutions,  IRandom random) {
+      OptimizationSupport.Analyze(solutions, random);
     }
-
-    public override double Evaluate(IEncodedSolution individual, IRandom random) {
-      var qualityMessage = Evaluate(BuildSolutionMessage(individual));
-      if (!qualityMessage.HasExtension(SingleObjectiveQualityMessage.QualityMessage_))
-        throw new InvalidOperationException("The received message is not a SingleObjectiveQualityMessage.");
-      return qualityMessage.GetExtension(SingleObjectiveQualityMessage.QualityMessage_).Quality;
-    }
-    public virtual QualityMessage Evaluate(SolutionMessage solutionMessage) {
-      return Cache == null
-        ? EvaluateOnNextAvailableClient(solutionMessage)
-        : Cache.GetValue(solutionMessage, EvaluateOnNextAvailableClient, GetQualityMessageExtensions());
-    }
-
-    public override void Analyze(IEncodedSolution[] individuals, double[] qualities, ResultCollection results, IRandom random) {
-      OptimizationSupport.Analyze(individuals, qualities, results, random);
-    }
-
-    public override IEnumerable<IEncodedSolution> GetNeighbors(IEncodedSolution individual, IRandom random) {
-      return OptimizationSupport.GetNeighbors(individual, random);
+    public override IEnumerable<TEncodedSolution> GetNeighbors(TEncodedSolution solutions, IRandom random) {
+      return OptimizationSupport.GetNeighbors(solutions, random);
     }
     #endregion
@@ -143,7 +134,7 @@
     #region Evaluation
     private HashSet<IEvaluationServiceClient> activeClients = new HashSet<IEvaluationServiceClient>();
-    private object clientLock = new object();
+    private readonly object clientLock = new object();
 
-    private QualityMessage EvaluateOnNextAvailableClient(SolutionMessage message) {
+    private QualityMessage EvaluateOnNextAvailableClient(SolutionMessage message, CancellationToken cancellationToken) {
       IEvaluationServiceClient client = null;
       lock (clientLock) {
@@ -158,6 +149,5 @@
       try {
         return client.Evaluate(message, GetQualityMessageExtensions());
-      }
-      finally {
+      } finally {
         lock (clientLock) {
           activeClients.Remove(client);
@@ -167,5 +157,5 @@
     }
 
-    private SolutionMessage BuildSolutionMessage(IEncodedSolution solution, int solutionId = 0) {
+    private SolutionMessage BuildSolutionMessage(TEncodedSolution solution, int solutionId = 0) {
       lock (clientLock) {
         SolutionMessage.Builder protobufBuilder = SolutionMessage.CreateBuilder();
@@ -176,6 +166,5 @@
           try {
             MessageBuilder.AddToMessage(variable.Value, variable.Name, protobufBuilder);
-          }
-          catch (ArgumentException ex) {
+          } catch (ArgumentException ex) {
             throw new InvalidOperationException(string.Format("ERROR while building solution message: Parameter {0} cannot be added to the message", Name), ex);
           }
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/HeuristicLab.Problems.ExternalEvaluation-3.4.csproj
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/HeuristicLab.Problems.ExternalEvaluation-3.4.csproj	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/HeuristicLab.Problems.ExternalEvaluation-3.4.csproj	(revision 17747)
@@ -138,5 +138,5 @@
     <Compile Include="MultiObjectiveExternalEvaluationProblem.cs" />
     <Compile Include="ExternalEvaluationProblemInstances.cs" />
-    <Compile Include="SingleObjectiveExternalEvaluationProblem.cs" />
+    <Compile Include="ExternalEvaluationProblem.cs" />
     <Compile Include="Interfaces\IEvaluationServiceClient.cs" />
     <Compile Include="Interfaces\IEvaluationChannel.cs" />
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Interfaces/ISingleObjectiveOptimizationSupport.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Interfaces/ISingleObjectiveOptimizationSupport.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Interfaces/ISingleObjectiveOptimizationSupport.cs	(revision 17747)
@@ -30,4 +30,5 @@
     where TEncodedSolution : class, IEncodedSolution {
 
+    void InitializeResults();
     void Analyze(ISingleObjectiveSolutionContext<TEncodedSolution>[] solutionContexts, IRandom random);
     IEnumerable<TEncodedSolution> GetNeighbors(TEncodedSolution individual, IRandom random);
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Programmable/CompiledMultiObjectiveOptimizationSupport.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Programmable/CompiledMultiObjectiveOptimizationSupport.cs	(revision 17746)
+++ 	(revision )
@@ -1,14 +1,0 @@
-﻿using HeuristicLab.Core;
-using HeuristicLab.Optimization;
-
-namespace HeuristicLab.Problems.ExternalEvaluation {
-  public class CompiledMultiObjectiveOptimizationSupport : CompiledOptimizationSupport, IMultiObjectiveOptimizationSupport {
-
-    public void Analyze(IEncodedSolution[] individuals, double[][] qualities, ResultCollection results, IRandom random) {
-      // Use vars.yourVariable to access variables in the variable store i.e. yourVariable
-      // Write or update results given the range of vectors and resulting qualities
-    }
-
-    // Implement further classes and methods
-  }
-}
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Programmable/CompiledOptimizationSupport.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Programmable/CompiledOptimizationSupport.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Programmable/CompiledOptimizationSupport.cs	(revision 17747)
@@ -20,8 +20,11 @@
 #endregion
 
+using HeuristicLab.Optimization;
+
 namespace HeuristicLab.Problems.ExternalEvaluation {
   public abstract class CompiledOptimizationSupport {
 
     public dynamic vars { get; set; }
+    public ResultCollection Results { get; set; }
   }
 }
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Programmable/CompiledSingleObjectiveOptimizationSupport.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Programmable/CompiledSingleObjectiveOptimizationSupport.cs	(revision 17746)
+++ 	(revision )
@@ -1,36 +1,0 @@
-﻿using System.Collections.Generic;
-using HeuristicLab.Core;
-using HeuristicLab.Optimization;
-
-namespace HeuristicLab.Problems.ExternalEvaluation {
-  public class CompiledSingleObjectiveOptimizationSupport : CompiledOptimizationSupport, ISingleObjectiveOptimizationSupport {
-
-    public void Analyze(IEncodedSolution[] individuals, double[] qualities, ResultCollection results, IRandom random) {
-      // Use vars.yourVariable to access variables in the variable store i.e. yourVariable
-      // Write or update results given the range of vectors and resulting qualities
-      // Uncomment the following lines if you want to retrieve the best individual
-      // Maximization:
-      // var bestIndex = qualities.Select((v, i) => Tuple.Create(i, v)).OrderByDescending(x => x.Item2).First().Item1;
-      // Minimization:
-      // var bestIndex = qualities.Select((v, i) => Tuple.Create(i, v)).OrderBy(x => x.Item2).First().Item1;
-      // var best = individuals[bestIndex];
-    }
-
-    public IEnumerable<IEncodedSolution> GetNeighbors(IEncodedSolution individual, IRandom random) {
-      // Use vars.yourVariable to access variables in the variable store i.e. yourVariable
-      // Create new vectors, based on the given one that represent small changes
-      // This method is only called from move-based algorithms (Local Search, Simulated Annealing, etc.)
-      while (true) {
-        // Algorithm will draw only a finite amount of samples
-        // Change to a for-loop to return a concrete amount of neighbors
-        var neighbor = (IEncodedSolution)individual.Clone();
-        // For instance, perform a single bit-flip in a binary parameter
-        //var bIndex = random.Next(neighbor.BinaryVector("b").Length);
-        //neighbor.BinaryVector("b")[bIndex] = !neighbor.BinaryVector("b")[bIndex];
-        yield return neighbor;
-      }
-    }
-
-    // Implement further classes and methods
-  }
-}
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Programmable/MultiObjective/MultiObjectiveOptimizationSupportScript.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Programmable/MultiObjective/MultiObjectiveOptimizationSupportScript.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Programmable/MultiObjective/MultiObjectiveOptimizationSupportScript.cs	(revision 17747)
@@ -33,5 +33,5 @@
     private MultiObjectiveOptimizationSupportScript(StorableConstructorFlag _) : base(_) { }
     private MultiObjectiveOptimizationSupportScript(MultiObjectiveOptimizationSupportScript<TEncodedSolution> original, Cloner cloner) : base(original, cloner) { }
-    public MultiObjectiveOptimizationSupportScript() {
+    public MultiObjectiveOptimizationSupportScript() : base() {
       var codeTemplate = Templates.CompiledMultiObjectiveOptimizationSupport;
       codeTemplate = codeTemplate.Replace("ENCODING_NAMESPACE", typeof(TEncodedSolution).Namespace);
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Programmable/MultiObjectiveOptimizationSupportScript.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Programmable/MultiObjectiveOptimizationSupportScript.cs	(revision 17746)
+++ 	(revision )
@@ -1,45 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-using HeuristicLab.Optimization;
-using HEAL.Attic;
-using HeuristicLab.Problems.ExternalEvaluation.Programmable;
-
-namespace HeuristicLab.Problems.ExternalEvaluation {
-  [Item("ProblemDefinitionScript", "Script that defines the parameter vector and evaluates the solution for a programmable problem.")]
-  [StorableType("617A7BEE-1B2F-4E39-A814-54CC4DFA2F02")]
-  public sealed class MultiObjectiveOptimizationSupportScript : OptimizationSupportScript<IMultiObjectiveOptimizationSupport>, IMultiObjectiveOptimizationSupport {
-    [StorableConstructor]
-    private MultiObjectiveOptimizationSupportScript(StorableConstructorFlag _) : base(_) { }
-    private MultiObjectiveOptimizationSupportScript(MultiObjectiveOptimizationSupportScript original, Cloner cloner) : base(original, cloner) { }
-    public MultiObjectiveOptimizationSupportScript() : base(Templates.CompiledMultiObjectiveOptimizationSupport) { }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new MultiObjectiveOptimizationSupportScript(this, cloner);
-    }
-
-    void IMultiObjectiveOptimizationSupport.Analyze(IEncodedSolution[] individuals, double[][] qualities, ResultCollection results, IRandom random) {
-      CompiledInstance.Analyze(individuals, qualities, results, random);
-    }
-  }
-}
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Programmable/OptimizationSupportScript.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Programmable/OptimizationSupportScript.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Programmable/OptimizationSupportScript.cs	(revision 17747)
@@ -23,6 +23,7 @@
 using System.Linq;
 using System.Reflection;
+using HEAL.Attic;
 using HeuristicLab.Common;
-using HEAL.Attic;
+using HeuristicLab.Optimization;
 using HeuristicLab.Scripting;
 
@@ -38,4 +39,10 @@
     }
 
+    [Storable]
+    private ResultCollection results;
+    public ResultCollection Results {
+      get { return results; }
+    }
+
     [StorableConstructor]
     protected OptimizationSupportScript(StorableConstructorFlag _) : base(_) { }
@@ -43,14 +50,16 @@
       : base(original, cloner) {
       variableStore = cloner.Clone(original.variableStore);
+      results = cloner.Clone(original.results);
     }
-
-    protected OptimizationSupportScript()
-      : base() {
+    
+    [Obsolete("Do not use this constructor.")]
+    protected OptimizationSupportScript() : base() {
       variableStore = new VariableStore();
     }
 
-    protected OptimizationSupportScript(string code)
-      : base(code) {
+    protected OptimizationSupportScript(ResultCollection results)
+      : base() {
       variableStore = new VariableStore();
+      this.results = results;
     }
 
@@ -86,4 +95,5 @@
         inst = (CompiledOptimizationSupport)Activator.CreateInstance(types.Single(x => typeof(CompiledOptimizationSupport).IsAssignableFrom(x)));
         inst.vars = new Variables(VariableStore);
+        inst.Results = results;
       } catch (Exception e) {
         compiledInstance = null;
@@ -93,5 +103,5 @@
       var concreteInst = inst as T;
       if (concreteInst == null)
-        throw new OptimizationSupportException("The optimization support class does not implement ISingleObjectiveOptimizationSupport." + Environment.NewLine + "Please implement that interface in the subclass of CompiledOptimizationSupport.");
+        throw new OptimizationSupportException($"The optimization support class does not implement {typeof(T).FullName}." + Environment.NewLine + "Please implement that interface in the subclass of CompiledOptimizationSupport.");
 
       CompiledInstance = concreteInst;
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Programmable/SingleObjective/CompiledSingleObjectiveOptimizationSupport.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Programmable/SingleObjective/CompiledSingleObjectiveOptimizationSupport.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Programmable/SingleObjective/CompiledSingleObjectiveOptimizationSupport.cs	(revision 17747)
@@ -8,13 +8,23 @@
   public class CompiledSingleObjectiveOptimizationSupport : CompiledOptimizationSupport, ISingleObjectiveOptimizationSupport<SOLUTION_CLASS> {
 
-    public void Analyze(SOLUTION_CLASS[] solutions, double[] qualities, ResultCollection results, IRandom random) {
+    // private Result<StringValue> myResult;
+
+    public void InitializeResults() {
+      // Initialize the results that you intend to produce
+      // Uncomment the field above and the code below to add to the problem's results
+      // if (!Results.TryGetValue("My Result", out myResult))
+      //   Results.Add(myResult = new Result<StringValue>("My Result", "My result description."));
+    }
+
+    public void Analyze(ISingleObjectiveSolutionContext<SOLUTION_CLASS>[] solutionContexts, IRandom random) {
       // Use vars.yourVariable to access variables in the variable store i.e. yourVariable
       // Write or update results given the range of vectors and resulting qualities
-      // Uncomment the following lines if you want to retrieve the best individual
+      // Uncomment the following lines if you want to retrieve the current best individual
       // Maximization:
-      // var bestIndex = qualities.Select((v, i) => Tuple.Create(i, v)).OrderByDescending(x => x.Item2).First().Item1;
+      // var best = solutionContexts.OrderByDescending(x => x.EvaluationResult.Quality).First();
       // Minimization:
-      // var bestIndex = qualities.Select((v, i) => Tuple.Create(i, v)).OrderBy(x => x.Item2).First().Item1;
-      // var best = solutions[bestIndex];
+      // var best = solutionContexts.OrderBy(x => x.EvaluationResult.Quality).First();
+      // 
+      // myResult.Value = new StringValue("Custom result");
     }
 
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Programmable/SingleObjective/SingleObjectiveOptimizationSupportScript.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Programmable/SingleObjective/SingleObjectiveOptimizationSupportScript.cs	(revision 17746)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Programmable/SingleObjective/SingleObjectiveOptimizationSupportScript.cs	(revision 17747)
@@ -20,4 +20,5 @@
 #endregion
 
+using System;
 using System.Collections.Generic;
 using HEAL.Attic;
@@ -36,5 +37,7 @@
     private SingleObjectiveOptimizationSupportScript(StorableConstructorFlag _) : base(_) { }
     private SingleObjectiveOptimizationSupportScript(SingleObjectiveOptimizationSupportScript<TEncodedSolution> original, Cloner cloner) : base(original, cloner) { }
-    public SingleObjectiveOptimizationSupportScript() : base() {
+    [Obsolete("Do not use this constructor.")]
+    public SingleObjectiveOptimizationSupportScript() : this(null) { }
+    public SingleObjectiveOptimizationSupportScript(ResultCollection results) : base(results) {
       var codeTemplate = Templates.CompiledSingleObjectiveOptimizationSupport;
       codeTemplate = codeTemplate.Replace("ENCODING_NAMESPACE", typeof(TEncodedSolution).Namespace);
@@ -45,4 +48,8 @@
     public override IDeepCloneable Clone(Cloner cloner) {
       return new SingleObjectiveOptimizationSupportScript<TEncodedSolution>(this, cloner);
+    }
+
+    void ISingleObjectiveOptimizationSupport<TEncodedSolution>.InitializeResults() {
+      CompiledInstance.InitializeResults();
     }
 
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Programmable/SingleObjectiveOptimizationSupportScript.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/Programmable/SingleObjectiveOptimizationSupportScript.cs	(revision 17746)
+++ 	(revision )
@@ -1,50 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 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.Collections.Generic;
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-using HeuristicLab.Optimization;
-using HEAL.Attic;
-using HeuristicLab.Problems.ExternalEvaluation.Programmable;
-
-namespace HeuristicLab.Problems.ExternalEvaluation {
-  [Item("ProblemDefinitionScript", "Script that defines the parameter vector and evaluates the solution for a programmable problem.")]
-  [StorableType("3EB74171-6ECB-4479-861E-DA4EB39FE70C")]
-  public sealed class SingleObjectiveOptimizationSupportScript : OptimizationSupportScript<ISingleObjectiveOptimizationSupport>, ISingleObjectiveOptimizationSupport {
-    [StorableConstructor]
-    private SingleObjectiveOptimizationSupportScript(StorableConstructorFlag _) : base(_) { }
-    private SingleObjectiveOptimizationSupportScript(SingleObjectiveOptimizationSupportScript original, Cloner cloner) : base(original, cloner) { }
-    public SingleObjectiveOptimizationSupportScript() : base(Templates.CompiledSingleObjectiveOptimizationSupport) { }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new SingleObjectiveOptimizationSupportScript(this, cloner);
-    }
-
-    void ISingleObjectiveOptimizationSupport.Analyze(IEncodedSolution[] individuals, double[] qualities, ResultCollection results, IRandom random) {
-      CompiledInstance.Analyze(individuals, qualities, results, random);
-    }
-
-    IEnumerable<IEncodedSolution> ISingleObjectiveOptimizationSupport.GetNeighbors(IEncodedSolution individual, IRandom random) {
-      return CompiledInstance.GetNeighbors(individual, random);
-    }
-  }
-}
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/SingleObjectiveExternalEvaluationProblem.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/SingleObjectiveExternalEvaluationProblem.cs	(revision 17746)
+++ 	(revision )
@@ -1,176 +1,0 @@
-﻿#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.Collections.Generic;
-using System.Drawing;
-using System.Linq;
-using System.Threading;
-using Google.ProtocolBuffers;
-using HEAL.Attic;
-using HeuristicLab.Analysis;
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-using HeuristicLab.Data;
-using HeuristicLab.Optimization;
-using HeuristicLab.Parameters;
-
-namespace HeuristicLab.Problems.ExternalEvaluation {
-  [Item("External Evaluation Problem (single-objective)", "A problem that is evaluated in a different process.")]
-  [Creatable(CreatableAttribute.Categories.ExternalEvaluationProblems, Priority = 100)]
-  [StorableType("115EB3A5-A8A8-4A2E-9799-9485FE896DEC")]
-  // BackwardsCompatibility3.3
-  // Rename class to SingleObjectiveExternalEvaluationProblem
-  public class ExternalEvaluationProblem<TEncoding, TEncodedSolution> : SingleObjectiveProblem<TEncoding, TEncodedSolution>, IExternalEvaluationProblem
-    where TEncoding : class, IEncoding
-    where TEncodedSolution : class, IEncodedSolution {
-
-    public static new Image StaticItemImage {
-      get { return HeuristicLab.Common.Resources.VSImageLibrary.Type; }
-    }
-
-    #region Parameters
-    public OptionalValueParameter<EvaluationCache> CacheParameter {
-      get { return (OptionalValueParameter<EvaluationCache>)Parameters["Cache"]; }
-    }
-    public IValueParameter<CheckedItemCollection<IEvaluationServiceClient>> ClientsParameter {
-      get { return (IValueParameter<CheckedItemCollection<IEvaluationServiceClient>>)Parameters["Clients"]; }
-    }
-    public IValueParameter<SolutionMessageBuilder> MessageBuilderParameter {
-      get { return (IValueParameter<SolutionMessageBuilder>)Parameters["MessageBuilder"]; }
-    }
-    public IFixedValueParameter<SingleObjectiveOptimizationSupportScript<TEncodedSolution>> SupportScriptParameter {
-      get { return (IFixedValueParameter<SingleObjectiveOptimizationSupportScript<TEncodedSolution>>)Parameters["SupportScript"]; }
-    }
-    #endregion
-
-    #region Properties
-    public new TEncoding Encoding {
-      get { return base.Encoding; }
-      set { base.Encoding = value; }
-    }
-    public EvaluationCache Cache {
-      get { return CacheParameter.Value; }
-    }
-    public CheckedItemCollection<IEvaluationServiceClient> Clients {
-      get { return ClientsParameter.Value; }
-    }
-    public SolutionMessageBuilder MessageBuilder {
-      get { return MessageBuilderParameter.Value; }
-    }
-    public SingleObjectiveOptimizationSupportScript<TEncodedSolution> OptimizationSupportScript {
-      get { return SupportScriptParameter.Value; }
-    }
-    private ISingleObjectiveOptimizationSupport<TEncodedSolution> OptimizationSupport {
-      get { return SupportScriptParameter.Value; }
-    }
-    #endregion
-
-    [StorableConstructor]
-    protected ExternalEvaluationProblem(StorableConstructorFlag _) : base(_) { }
-    protected ExternalEvaluationProblem(ExternalEvaluationProblem<TEncoding, TEncodedSolution> original, Cloner cloner) : base(original, cloner) { }
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new ExternalEvaluationProblem<TEncoding, TEncodedSolution>(this, cloner);
-    }
-    public ExternalEvaluationProblem(TEncoding encoding)
-      : base(encoding) {
-      MaximizationParameter.Value = new BoolValue(); // is a read-only bool value in base class TODO: change to set ReadOnly false
-      Parameters.Add(new OptionalValueParameter<EvaluationCache>("Cache", "Cache of previously evaluated solutions."));
-      Parameters.Add(new ValueParameter<CheckedItemCollection<IEvaluationServiceClient>>("Clients", "The clients that are used to communicate with the external application.", new CheckedItemCollection<IEvaluationServiceClient>() { new EvaluationServiceClient() }));
-      Parameters.Add(new ValueParameter<SolutionMessageBuilder>("MessageBuilder", "The message builder that converts from HeuristicLab objects to SolutionMessage representation.", new SolutionMessageBuilder()) { Hidden = true });
-      Parameters.Add(new FixedValueParameter<SingleObjectiveOptimizationSupportScript<TEncodedSolution>>("SupportScript", "A script that can provide neighborhood and analyze the results of the optimization.", new SingleObjectiveOptimizationSupportScript<TEncodedSolution>()));
-
-      Operators.Add(new BestScopeSolutionAnalyzer());
-    }
-
-    #region Single Objective Problem Overrides
-    public override ISingleObjectiveEvaluationResult Evaluate(TEncodedSolution solution, IRandom random, CancellationToken cancellationToken) {
-      var qualityMessage = Evaluate(BuildSolutionMessage(solution), cancellationToken);
-      if (!qualityMessage.HasExtension(SingleObjectiveQualityMessage.QualityMessage_))
-        throw new InvalidOperationException("The received message is not a SingleObjectiveQualityMessage.");
-      var quality = qualityMessage.GetExtension(SingleObjectiveQualityMessage.QualityMessage_).Quality;
-      return new SingleObjectiveEvaluationResult(quality);
-
-    }
-    public virtual QualityMessage Evaluate(SolutionMessage solutionMessage, CancellationToken cancellationToken) {
-      return Cache == null
-        ? EvaluateOnNextAvailableClient(solutionMessage, cancellationToken)
-        : Cache.GetValue(solutionMessage, EvaluateOnNextAvailableClient, GetQualityMessageExtensions(), cancellationToken);
-    }
-
-    public override void Analyze(ISingleObjectiveSolutionContext<TEncodedSolution>[] solutions,  IRandom random) {
-      OptimizationSupport.Analyze(solutions, random);
-    }
-    public override IEnumerable<TEncodedSolution> GetNeighbors(TEncodedSolution solutions, IRandom random) {
-      return OptimizationSupport.GetNeighbors(solutions, random);
-    }
-    #endregion
-
-    public virtual ExtensionRegistry GetQualityMessageExtensions() {
-      var extensions = ExtensionRegistry.CreateInstance();
-      extensions.Add(SingleObjectiveQualityMessage.QualityMessage_);
-      return extensions;
-    }
-
-    #region Evaluation
-    private HashSet<IEvaluationServiceClient> activeClients = new HashSet<IEvaluationServiceClient>();
-    private readonly object clientLock = new object();
-
-    private QualityMessage EvaluateOnNextAvailableClient(SolutionMessage message, CancellationToken cancellationToken) {
-      IEvaluationServiceClient client = null;
-      lock (clientLock) {
-        client = Clients.CheckedItems.FirstOrDefault(c => !activeClients.Contains(c));
-        while (client == null && Clients.CheckedItems.Any()) {
-          Monitor.Wait(clientLock);
-          client = Clients.CheckedItems.FirstOrDefault(c => !activeClients.Contains(c));
-        }
-        if (client != null)
-          activeClients.Add(client);
-      }
-      try {
-        return client.Evaluate(message, GetQualityMessageExtensions());
-      } finally {
-        lock (clientLock) {
-          activeClients.Remove(client);
-          Monitor.PulseAll(clientLock);
-        }
-      }
-    }
-
-    private SolutionMessage BuildSolutionMessage(TEncodedSolution solution, int solutionId = 0) {
-      lock (clientLock) {
-        SolutionMessage.Builder protobufBuilder = SolutionMessage.CreateBuilder();
-        protobufBuilder.SolutionId = solutionId;
-        var scope = new Scope();
-        ScopeUtil.CopyEncodedSolutionToScope(scope, Encoding, solution);
-        foreach (var variable in scope.Variables) {
-          try {
-            MessageBuilder.AddToMessage(variable.Value, variable.Name, protobufBuilder);
-          } catch (ArgumentException ex) {
-            throw new InvalidOperationException(string.Format("ERROR while building solution message: Parameter {0} cannot be added to the message", Name), ex);
-          }
-        }
-        return protobufBuilder.Build();
-      }
-    }
-    #endregion
-  }
-}
