Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/RunsAnalyzer.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/RunsAnalyzer.cs	(revision 5303)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/RunsAnalyzer.cs	(revision 5303)
@@ -0,0 +1,83 @@
+﻿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;
+
+namespace HeuristicLab.Problems.MetaOptimization {
+  /// <summary>
+  /// TODO
+  /// </summary>
+  [Item("RunsAnalyzer", "")]
+  [StorableClass]
+  public sealed class RunsAnalyzer : SingleSuccessorOperator, IAnalyzer {
+
+    public ValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (ValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+    public ScopeTreeLookupParameter<ParameterConfigurationTree> ParameterConfigurationParameter {
+      get { return (ScopeTreeLookupParameter<ParameterConfigurationTree>)Parameters["ParameterConfigurationTree"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public LookupParameter<DoubleArray> ProblemQualityReferenceParameter {
+      get { return (LookupParameter<DoubleArray>)Parameters["ProblemQualityReferences"]; }
+    }
+    public LookupParameter<ConstrainedItemList<ISingleObjectiveProblem>> ProblemsParameter {
+      get { return (LookupParameter<ConstrainedItemList<ISingleObjectiveProblem>>)Parameters[MetaOptimizationProblem.ProblemsParameterName]; }
+    }
+    public ValueLookupParameter<ItemDictionary<StringValue, RunCollection>> RunsParameter {
+      get { return (ValueLookupParameter<ItemDictionary<StringValue, RunCollection>>)Parameters["Runs"]; }
+    }
+
+    public RunsAnalyzer()
+      : base() {
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", ""));
+      Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", ""));
+      Parameters.Add(new ScopeTreeLookupParameter<ParameterConfigurationTree>("ParameterConfigurationTree", ""));
+      Parameters.Add(new LookupParameter<DoubleArray>("ProblemQualityReferences", ""));
+      Parameters.Add(new LookupParameter<ConstrainedItemList<ISingleObjectiveProblem>>(MetaOptimizationProblem.ProblemsParameterName, ""));
+      Parameters.Add(new ValueLookupParameter<ItemDictionary<StringValue, RunCollection>>("Runs", "", new ItemDictionary<StringValue, RunCollection>()));
+    }
+
+    [StorableConstructor]
+    private RunsAnalyzer(bool deserializing) : base(deserializing) { }
+    private RunsAnalyzer(RunsAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RunsAnalyzer(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      ResultCollection results = ResultsParameter.ActualValue;
+      ItemArray<ParameterConfigurationTree> solutions = ParameterConfigurationParameter.ActualValue;
+      ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+      ItemDictionary<StringValue, RunCollection> allRuns = RunsParameter.ActualValue;
+
+      foreach (var solution in solutions) {
+        string key = solution.ParameterInfoString;
+        if (allRuns.Count(x => x.Key.Value == key) == 0) {
+          allRuns.Add(new StringValue(key), new RunCollection());
+        }
+
+        foreach (var run in solution.Runs) {
+          if (!((BoolValue)run.Results["Meta.FromCache"]).Value) {
+            run.Results["Meta.FromCache"] = new BoolValue(true);
+            allRuns.Single(x => x.Key.Value == key).Value.Add(run);
+          }
+        }
+      }
+
+      if (!results.ContainsKey("Runs")) {
+        results.Add(new Result("Runs", allRuns));
+      }
+
+      return base.Apply();
+    }
+  }
+}
