Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/BestParameterConfigurationAnalyzer.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/BestParameterConfigurationAnalyzer.cs	(revision 5522)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/BestParameterConfigurationAnalyzer.cs	(revision 5576)
@@ -97,10 +97,5 @@
       RunCollection rc = new RunCollection();
       foreach (ParameterConfigurationTree pt in parameterTrees.OrderBy(x => x.AverageQualityNormalized)) { // todo: respect Maximization:true/false
-        IRun run = new Run();
-        run.Name = string.Format("Individual {0} ({1})", i, pt.ParameterInfoString);
-        pt.CollectResultValues(run.Results);
-        pt.CollectParameterValues(run.Parameters);
-        MetaOptimizationUtil.ClearParameters(run, pt.GetOptimizedParameterNames());
-        rc.Add(run);
+        rc.Add(pt.ToRun(string.Format("Individual {0} ({1})", i, pt.ParameterInfoString)));
         i++;
       }
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/PMOBestSolutionHistoryAnalyzer.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/PMOBestSolutionHistoryAnalyzer.cs	(revision 5576)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/PMOBestSolutionHistoryAnalyzer.cs	(revision 5576)
@@ -0,0 +1,79 @@
+﻿using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using System.Collections.Generic;
+using System;
+using HeuristicLab.Analysis;
+
+namespace HeuristicLab.Problems.MetaOptimization {
+  /// <summary>
+  /// TODO 
+  /// </summary>
+  [Item("PMOBestSolutionHistoryAnalyzer", "")]
+  [StorableClass]
+  public sealed class PMOBestSolutionHistoryAnalyzer : SingleSuccessorOperator, IAnalyzer {
+
+    public ScopeTreeLookupParameter<ParameterConfigurationTree> ParameterConfigurationParameter {
+      get { return (ScopeTreeLookupParameter<ParameterConfigurationTree>)Parameters["ParameterConfigurationTree"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (ValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+    public LookupParameter<ConstrainedItemList<IProblem>> ProblemsParameter {
+      get { return (LookupParameter<ConstrainedItemList<IProblem>>)Parameters[MetaOptimizationProblem.ProblemsParameterName]; }
+    }
+    public LookupParameter<IntValue> GenerationsParameter {
+      get { return (LookupParameter<IntValue>)Parameters["Generations"]; }
+    }
+
+    public PMOBestSolutionHistoryAnalyzer()
+      : base() {
+      Parameters.Add(new ScopeTreeLookupParameter<ParameterConfigurationTree>("ParameterConfigurationTree", ""));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", ""));
+      Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", ""));
+      Parameters.Add(new LookupParameter<ConstrainedItemList<IProblem>>(MetaOptimizationProblem.ProblemsParameterName));
+      Parameters.Add(new LookupParameter<IntValue>("Generations", ""));
+    }
+
+    [StorableConstructor]
+    private PMOBestSolutionHistoryAnalyzer(bool deserializing) : base(deserializing) { }
+    private PMOBestSolutionHistoryAnalyzer(PMOBestSolutionHistoryAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PMOBestSolutionHistoryAnalyzer(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+      ResultCollection results = ResultsParameter.ActualValue;
+      ItemArray<ParameterConfigurationTree> parameterTrees = ParameterConfigurationParameter.ActualValue;
+      int currentGeneration = GenerationsParameter.ActualValue.Value;
+      int idxBest = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index; // todo: respect Min/Max
+      ParameterConfigurationTree best = parameterTrees[idxBest];
+
+      string key = "BestSolutionHistory";
+      RunCollection bestSolutionHistory;
+      if (!results.ContainsKey(key)) {
+        bestSolutionHistory = new RunCollection();
+        results.Add(new Result(key, bestSolutionHistory));
+      } else {
+        bestSolutionHistory = results[key].Value as RunCollection;
+      }
+      if (bestSolutionHistory.Count == 0 || best.ParameterInfoString != ((StringValue)bestSolutionHistory.Last().Results["Meta.ParameterInfoString"]).Value) {
+        IRun run = best.ToRun(string.Format("{0}: {1}", currentGeneration, best.ParameterInfoString));
+        run.Results.Add("Meta.Generation", new IntValue(currentGeneration));
+        run.Results.Add("Meta.ParameterInfoString", new StringValue(best.ParameterInfoString));
+        bestSolutionHistory.Add(run);
+      }
+
+      return base.Apply();
+    }
+  }
+}
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/PMOProblemQualitiesAnalyzer.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/PMOProblemQualitiesAnalyzer.cs	(revision 5576)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/PMOProblemQualitiesAnalyzer.cs	(revision 5576)
@@ -0,0 +1,102 @@
+﻿using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using System.Collections.Generic;
+using System;
+using HeuristicLab.Analysis;
+
+namespace HeuristicLab.Problems.MetaOptimization {
+  /// <summary>
+  /// TODO 
+  /// </summary>
+  [Item("PMOProblemQualitiesAnalyzer", "")]
+  [StorableClass]
+  public sealed class PMOProblemQualitiesAnalyzer : SingleSuccessorOperator, IAnalyzer {
+
+    public ScopeTreeLookupParameter<ParameterConfigurationTree> ParameterConfigurationParameter {
+      get { return (ScopeTreeLookupParameter<ParameterConfigurationTree>)Parameters["ParameterConfigurationTree"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (ValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+    public LookupParameter<ConstrainedItemList<IProblem>> ProblemsParameter {
+      get { return (LookupParameter<ConstrainedItemList<IProblem>>)Parameters[MetaOptimizationProblem.ProblemsParameterName]; }
+    }
+
+    public PMOProblemQualitiesAnalyzer()
+      : base() {
+      Parameters.Add(new ScopeTreeLookupParameter<ParameterConfigurationTree>("ParameterConfigurationTree", ""));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", ""));
+      Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", ""));
+      Parameters.Add(new LookupParameter<ConstrainedItemList<IProblem>>(MetaOptimizationProblem.ProblemsParameterName));
+    }
+
+    [StorableConstructor]
+    private PMOProblemQualitiesAnalyzer(bool deserializing) : base(deserializing) { }
+    private PMOProblemQualitiesAnalyzer(PMOProblemQualitiesAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PMOProblemQualitiesAnalyzer(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+      ResultCollection results = ResultsParameter.ActualValue;
+      ItemArray<ParameterConfigurationTree> parameterTrees = ParameterConfigurationParameter.ActualValue;
+      int idxBest = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index; // todo: respect Min/Max
+      int idxWorst = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).Last().index;
+      
+      int problemCount = ProblemsParameter.ActualValue.Count;
+
+      double[][] problemQualities = GetProblemQualities(parameterTrees, problemCount);
+
+      for (int i = 0; i < problemCount; i++) {
+        DataTable problemQualitiesDataTable;
+        string resultKey = "Problem." + i;
+        if (!results.ContainsKey(resultKey)) {
+          problemQualitiesDataTable = new DataTable();
+          problemQualitiesDataTable.Name = resultKey + " Qualities";
+          results.Add(new Result(resultKey, problemQualitiesDataTable));
+        } else {
+          problemQualitiesDataTable = results[resultKey].Value as DataTable;
+        }
+
+        AddValue(problemQualitiesDataTable, parameterTrees[idxBest].AverageQualities[i], "BestQuality", "BestQuality");
+        AddValue(problemQualitiesDataTable, problemQualities[i].Average(), "AverageQuality", "BestQuality");
+        AddValue(problemQualitiesDataTable, parameterTrees[idxWorst].AverageQualities[i], "WorstQuality", "BestQuality"); 
+      }
+
+      return base.Apply();
+    }
+
+    private static double[][] GetProblemQualities(ItemArray<ParameterConfigurationTree> parameterTrees, int problemCount) {
+      double[][] problemQualities = new double[problemCount][];
+      for (int i = 0; i < problemCount; i++) {
+        problemQualities[i] = new double[parameterTrees.Length];
+        for (int j = 0; j < parameterTrees.Length; j++) {
+          problemQualities[i][j] = parameterTrees[j].AverageQualities[i];
+        }
+      }
+      return problemQualities;
+    }
+
+    private static void AddValue(DataTable table, double data, string name, string description) {
+      DataRow row;
+      table.Rows.TryGetValue(name, out row);
+      if (row == null) {
+        row = new DataRow(name, description);
+        row.Values.Add(data);
+        table.Rows.Add(row);
+      } else {
+        row.Values.Add(data);
+      }
+    }
+  }
+}
