Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/BestParameterConfigurationAnalyzer.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/BestParameterConfigurationAnalyzer.cs	(revision 5357)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/BestParameterConfigurationAnalyzer.cs	(revision 5359)
@@ -12,5 +12,5 @@
 namespace HeuristicLab.Problems.MetaOptimization {
   /// <summary>
-  /// TODO An operator for analyzing the best solution of Traveling Salesman Problems given in path representation using city coordinates.
+  /// TODO 
   /// </summary>
   [Item("BestParameterConfigurationAnalyzer", "")]
@@ -98,7 +98,8 @@
       foreach (ParameterConfigurationTree pt in parameterTrees.OrderBy(x => x.AverageQualityNormalized)) { // todo: respect Maximization:true/false
         IRun run = new Run();
-        run.Name = string.Format("Individuum ({0})", i);
+        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);
         i++;
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/ReferenceQualityAnalyzer.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/ReferenceQualityAnalyzer.cs	(revision 5357)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/ReferenceQualityAnalyzer.cs	(revision 5359)
@@ -59,5 +59,5 @@
         ProblemQualityReferenceParameter.ActualValue = referenceQualities;
         NormalizePopulation(solutions, qualities, referenceQualities);
-        results.Add(new Result("ProblemsAverageQualityReferences", referenceQualities));
+        results.Add(new Result("QualityReferences", referenceQualities));
       }
 
@@ -75,5 +75,5 @@
     private void NormalizePopulation(ItemArray<ParameterConfigurationTree> solutions, ItemArray<DoubleValue> qualities, DoubleArray referenceQualities) {
       for (int i = 0; i < solutions.Length; i++) {
-        qualities[i].Value = ParameterConfigurationEvaluator.NormalizeQualities(solutions[i], referenceQualities.ToArray());
+        qualities[i].Value = MetaOptimizationUtil.NormalizeQualities(solutions[i], referenceQualities.ToArray());
       }
     }
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/SolutionCacheAnalyzer.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/SolutionCacheAnalyzer.cs	(revision 5359)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/SolutionCacheAnalyzer.cs	(revision 5359)
@@ -0,0 +1,95 @@
+﻿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("SolutionCacheAnalyzer", "")]
+  [StorableClass]
+  public sealed class SolutionCacheAnalyzer : 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<IProblem>> ProblemsParameter {
+      get { return (LookupParameter<ConstrainedItemList<IProblem>>)Parameters[MetaOptimizationProblem.ProblemsParameterName]; }
+    }
+    public LookupParameter<IntValue> GenerationsParameter {
+      get { return (LookupParameter<IntValue>)Parameters["Generations"]; }
+    }
+    public ValueParameter<BoolValue> StoreAllRunsParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["StoreAllRuns"]; }
+    }
+
+    public SolutionCacheAnalyzer()
+      : 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<IProblem>>(MetaOptimizationProblem.ProblemsParameterName, ""));
+      Parameters.Add(new LookupParameter<IntValue>("Generations", ""));
+      Parameters.Add(new ValueParameter<BoolValue>("StoreAllRuns", "If true all runs ever executed are stored. Otherwise only the runs from the latest generateion are stored for caching purposes.", new BoolValue(false)));
+    }
+
+    [StorableConstructor]
+    private SolutionCacheAnalyzer(bool deserializing) : base(deserializing) { }
+    private SolutionCacheAnalyzer(SolutionCacheAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SolutionCacheAnalyzer(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      ResultCollection results = ResultsParameter.ActualValue;
+      ItemArray<ParameterConfigurationTree> solutions = ParameterConfigurationParameter.ActualValue;
+      ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+      ItemDictionary<StringValue, RunCollection> allRuns = ResultsParameter.ActualValue.ContainsKey("SolutionCache") ? (ItemDictionary<StringValue, RunCollection>)ResultsParameter.ActualValue["SolutionCache"].Value : new ItemDictionary<StringValue, RunCollection>();
+      bool storeAllRuns = ((BoolValue)StoreAllRunsParameter.ActualValue).Value;
+
+      if (!storeAllRuns) {
+        allRuns.Clear();
+      }
+
+      foreach (var solution in solutions) {
+        string key = solution.ParameterInfoString;
+        bool first = false;
+        if (allRuns.Count(x => x.Key.Value == key) == 0) {
+          allRuns.Add(new StringValue(key), new RunCollection());
+          first = true; // no other runs yet
+        }
+
+        var runCollection = allRuns.Single(x => x.Key.Value == key).Value;
+        foreach (var run in solution.Runs) {
+          if (!((BoolValue)run.Results["Meta.FromCache"]).Value || first) {
+            run.Results["Meta.FromCache"] = new BoolValue(true);
+            runCollection.Add(run);
+          }
+        }
+      }
+
+      if (!results.ContainsKey("SolutionCache")) {
+        results.Add(new Result("SolutionCache", allRuns));
+      }
+
+      return base.Apply();
+    }
+  }
+}
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ParameterConfigurationTree.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ParameterConfigurationTree.cs	(revision 5357)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ParameterConfigurationTree.cs	(revision 5359)
@@ -126,5 +126,6 @@
     protected ParameterConfigurationTree(ParameterConfigurationTree original, Cloner cloner)
       : base(original, cloner) {
-      this.name = original.name;
+      this.averageQualityNormalized = cloner.Clone(original.averageQualityNormalized);
+      this.qualitiesNormalized = cloner.Clone(original.qualitiesNormalized);
       this.bestQualities = cloner.Clone(original.BestQualities);
       this.averageQualities = cloner.Clone(original.averageQualities);
@@ -139,4 +140,5 @@
         this.parameters.Add(p.Key, cloner.Clone(p.Value));
       }
+      this.name = original.name;
     }
     public override IDeepCloneable Clone(Cloner cloner) {
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ParameterConfigurations/ParameterConfiguration.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ParameterConfigurations/ParameterConfiguration.cs	(revision 5357)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ParameterConfigurations/ParameterConfiguration.cs	(revision 5359)
@@ -369,5 +369,12 @@
         StringBuilder sb = new StringBuilder();
         if (this.Optimize) {
-          sb.Append(string.Format("{0}: {1}", parameterName, this.ActualValue.Value != null ? this.ActualValue.Value.ToString() : "null"));
+          var vc = this.ValueConfigurations[actualValueConfigurationIndex];
+          if (IsSubclassOfRawGeneric(typeof(ValueTypeValue<>), vc.GetType())) {
+            // for int, double, bool use the value directly
+            sb.Append(string.Format("{0}: {1}", parameterName, this.ActualValue.Value != null ? this.ActualValue.Value.ToString() : "null"));
+          } else {
+            // for other types use NumberedName (this also uses the Number-Property for otherwise ambiguous ValueConfigurations)
+            sb.Append(string.Format("{0}: {1}", parameterName, vc.NumberedName));
+          }
 
           if (this.ActualValue.Value is IParameterizedItem) {
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ValueConfigurations/CheckedValueConfigurationCollection.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ValueConfigurations/CheckedValueConfigurationCollection.cs	(revision 5357)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ValueConfigurations/CheckedValueConfigurationCollection.cs	(revision 5359)
@@ -50,4 +50,5 @@
 
     private void RegisterEvents() {
+      this.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<IValueConfiguration>>(CheckedValueConfigurationList_ItemsAdded);
       this.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<IValueConfiguration>>(CheckedValueConfigurationList_ItemsRemoved);
     }
@@ -55,4 +56,14 @@
     private void DeregisterEvents() {
       this.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<IValueConfiguration>>(CheckedValueConfigurationList_ItemsRemoved);
+      this.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<IValueConfiguration>>(CheckedValueConfigurationList_ItemsAdded);
+    }
+
+    void CheckedValueConfigurationList_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IValueConfiguration>> e) {
+      foreach (var item in e.Items) {
+        if(this.Where(x => x.ItemName == item.Value.ItemName).Count() > 0) {
+          int maxNumber = this.Where(x => x.ItemName == item.Value.ItemName).Select(x => x.Number).Max();
+          item.Value.Number = maxNumber + 1;
+        }
+      }
     }
 
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ValueConfigurations/ValueConfiguration.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ValueConfigurations/ValueConfiguration.cs	(revision 5357)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ValueConfigurations/ValueConfiguration.cs	(revision 5359)
@@ -15,5 +15,13 @@
   // TODO: ItemName/Descr, storability
   [StorableClass]
-  public class ValueConfiguration : Item, IValueConfiguration {
+  public class ValueConfiguration : NamedItem, IValueConfiguration {
+    public override bool CanChangeName {
+      get { return true; }
+    }
+
+    public override bool CanChangeDescription {
+      get { return true; }
+    }
+
     [Storable]
     protected bool isOptimizable;
@@ -80,4 +88,16 @@
           rangeConstraint = value;
           RegisterActualValueEvents();
+        }
+      }
+    }
+
+    [Storable]
+    protected int number = -1;
+    public int Number {
+      get { return number; }
+      set {
+        if (value != number) {
+          number = value;
+          OnToStringChanged();
         }
       }
@@ -113,4 +133,5 @@
       this.isOptimizable = original.isOptimizable;
       this.optimize = original.optimize;
+      this.number = original.number;
       RegisterActualValueEvents();
       RegisterRangeConstraintEvents();
@@ -193,19 +214,31 @@
     public override string ToString() {
       if (ActualValue != null && ActualValue.Value != null) {
+        string name = NumberedName;
+
         if (ActualValue.Value is IParameterizedItem) {
           if (Optimize) {
-            return string.Format("{0} (Optimize)", ActualValue.Value.ItemName);
+            return string.Format("{0} (Optimize)", name);
           } else {
-            return string.Format("{0}", ActualValue.Value.ItemName);
+            return string.Format("{0}", name);
           }
         } else {
           if (Optimize) {
-            return string.Format("{0} (Optimize: {1})", ActualValue.Value.ItemName, RangeConstraint);
+            return string.Format("{0} (Optimize: {1})", name, RangeConstraint);
           } else {
-            return string.Format("{0}: {1}", ActualValue.Value.ItemName, ActualValue.Value);
+            return string.Format("{0}: {1}", name, ActualValue.Value);
           }
         }
       } else {
         return base.ToString();
+      }
+    }
+
+    public string NumberedName {
+      get {
+        if (this.number == 0) {
+          return ActualValue.Value.ItemName;
+        } else {
+          return string.Format("{0} {1}", ActualValue.Value.ItemName, number);
+        }
       }
     }
@@ -227,5 +260,5 @@
     public virtual void Parameterize(IParameterizedItem item) {
       foreach (IParameterConfiguration pc in this.ParameterConfigurations) {
-        pc.Parameterize((IValueParameter)item.Parameters[pc.ParameterName]);
+        if(pc.Optimize) pc.Parameterize((IValueParameter)item.Parameters[pc.ParameterName]);
       }
     }
@@ -287,4 +320,10 @@
       }
     }
+
+    public IEnumerable<string> GetOptimizedParameterNames() {
+      var list = new List<string>();
+      this.CollectOptimizedParameterNames(list, "");
+      return list;
+    }
   }
 }
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Evaluators/ParameterConfigurationEvaluator.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Evaluators/ParameterConfigurationEvaluator.cs	(revision 5357)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Evaluators/ParameterConfigurationEvaluator.cs	(revision 5359)
@@ -82,14 +82,15 @@
       IAlgorithm algorithm = (IAlgorithm)Activator.CreateInstance(AlgorithmTypeParameter.ActualValue.Value);
       IItemList<IProblem> problems = ProblemsParameter.ActualValue;
-      ItemDictionary<StringValue, RunCollection> runsCache = ResultsParameter.ActualValue.ContainsKey("Runs") ? (ItemDictionary<StringValue, RunCollection>)ResultsParameter.ActualValue["Runs"].Value : null;
+      ItemDictionary<StringValue, RunCollection> solutionCache = ResultsParameter.ActualValue.ContainsKey("SolutionCache") ? (ItemDictionary<StringValue, RunCollection>)ResultsParameter.ActualValue["SolutionCache"].Value : null;
       double[] referenceQualities = GetReferenceQualities(problems);
+      int currentGeneration = GenerationsParameter.ActualValue != null ? GenerationsParameter.ActualValue.Value : 0;
+      int repetitions = Repetitions.Value;
 
       RunCollection runs;
-      if (runsCache != null && runsCache.Count(x => x.Key.Value == parameterConfiguration.ParameterInfoString) > 0) {
-        runs = runsCache.Single(x => x.Key.Value == parameterConfiguration.ParameterInfoString).Value;
-        Console.WriteLine("Used Cache for {0}", parameterConfiguration.ParameterInfoString);
+      if (solutionCache != null && solutionCache.Count(x => x.Key.Value == parameterConfiguration.ParameterInfoString) > 0) {
+        runs = solutionCache.Single(x => x.Key.Value == parameterConfiguration.ParameterInfoString).Value;
       } else {
         do {
-          runs = ExecuteAlgorithm(parameterConfiguration, algorithm, problems, Repetitions.Value, GenerationsParameter.ActualValue != null ? GenerationsParameter.ActualValue.Value : 0);
+          runs = ExecuteAlgorithm(parameterConfiguration, algorithm, problems, repetitions, currentGeneration);
           if (runs == null) {
             Repair(parameterConfiguration, random);
@@ -98,5 +99,5 @@
         } while (runs == null);
       }
-
+      
       List<List<double>> qualities = new List<List<double>>();
       List<List<TimeSpan>> executionTimes = new List<List<TimeSpan>>();
@@ -117,5 +118,5 @@
       parameterConfiguration.Runs = (RunCollection)runs.Clone();
 
-      this.QualityParameter.ActualValue = new DoubleValue(NormalizeQualities(parameterConfiguration, referenceQualities));
+      this.QualityParameter.ActualValue = new DoubleValue(MetaOptimizationUtil.NormalizeQualities(parameterConfiguration, referenceQualities));
 
       return base.Apply();
@@ -147,13 +148,8 @@
     /// Executes an algorithm 
     /// </summary>
-    /// <param name="parameterConfiguration"></param>
-    /// <param name="algorithm"></param>
-    /// <param name="problems"></param>
-    /// <returns></returns>
     private static RunCollection ExecuteAlgorithm(ParameterConfigurationTree parameterConfiguration, IAlgorithm algorithm, IItemList<IProblem> problems, int repetitions, int currentGeneration) {
       IAlgorithm algorithmClone = (IAlgorithm)algorithm.Clone();
-      var parameterNames = new List<string>();
+      var parameterNames = parameterConfiguration.GetOptimizedParameterNames();
       var resultNames = new List<string> { "BestQuality", "Execution Time" };
-      parameterConfiguration.CollectOptimizedParameterNames(parameterNames, "");
 
       // set parameters
@@ -186,5 +182,6 @@
           int problemIndex = problems.IndexOf(problem) + 1;
           IRun run = algorithmClone.Runs.Last();
-          CleanRun(run, resultNames, parameterNames);
+          MetaOptimizationUtil.ClearResults(run, resultNames);
+          MetaOptimizationUtil.ClearParameters(run, parameterNames);
           run.Results.Add("Meta.FromCache", new BoolValue(false));
           run.Results.Add("Meta.Generation", new IntValue(currentGeneration));
@@ -197,46 +194,4 @@
       return algorithmClone.Runs;
     }
-
-    /// <summary>
-    /// Removes all information from the run which is not needed for lated analysis
-    /// only keep the results which are important and the parameters which were optimized
-    /// </summary>
-    private static void CleanRun(IRun run, IEnumerable<string> resultsToKeep, IEnumerable<string> parametersToKeep) {
-      var resultsToRemove = new List<string>();
-      var parametersToRemove = new List<string>();
-      foreach (var result in run.Results) {
-        if (!resultsToKeep.Contains(result.Key))
-          resultsToRemove.Add(result.Key);
-      }
-      foreach (var parameter in run.Parameters) {
-        if (!parametersToKeep.Contains(parameter.Key))
-          parametersToRemove.Add(parameter.Key);
-      }
-
-      foreach (var result in resultsToRemove)
-        run.Results.Remove(result);
-      foreach (var parameter in parametersToRemove)
-        run.Parameters.Remove(parameter);
-    }
-
-    public static double NormalizeQualities(ParameterConfigurationTree parameterConfigurationTree, double[] referenceQualities) {
-      double[] qualitiesNormalized = new double[referenceQualities.Length];
-      for (int i = 0; i < referenceQualities.Length; i++) {
-        qualitiesNormalized[i] = parameterConfigurationTree.AverageQualities[i] / referenceQualities[i];
-      }
-      parameterConfigurationTree.QualitiesNormalized = new DoubleArray(qualitiesNormalized);
-      parameterConfigurationTree.AverageQualityNormalized = new DoubleValue(qualitiesNormalized.Average());
-      return parameterConfigurationTree.AverageQualityNormalized.Value;
-    }
-
-    public static double Variance(IEnumerable<double> source) {
-      double avg = source.Average();
-      double d = source.Aggregate(0.0, (total, next) => total += Math.Pow(next - avg, 2));
-      return d / (source.Count() - 1);
-    }
-
-    public static double StandardDeviation(IEnumerable<double> source) {
-      return Math.Sqrt(source.Variance());
-    }
   }
 }
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/HeuristicLab.Problems.MetaOptimization-3.3.csproj
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/HeuristicLab.Problems.MetaOptimization-3.3.csproj	(revision 5357)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/HeuristicLab.Problems.MetaOptimization-3.3.csproj	(revision 5359)
@@ -134,8 +134,9 @@
     <Compile Include="Analyzers\BestParameterConfigurationAnalyzer.cs" />
     <Compile Include="ConstrainedTypeValue.cs" />
+    <Compile Include="MetaOptimizationUtil.cs" />
     <Compile Include="TypeValue.cs" />
     <None Include="Properties\AssemblyInfo.cs.frame" />
     <None Include="HeuristicLabProblemsMetaOptimizationPlugin.cs.frame" />
-    <Compile Include="Analyzers\RunsAnalyzer.cs" />
+    <Compile Include="Analyzers\SolutionCacheAnalyzer.cs" />
     <Compile Include="Analyzers\ReferenceQualityAnalyzer.cs" />
     <Compile Include="ConstrainedItemList.cs" />
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Interfaces/IValueConfiguration.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Interfaces/IValueConfiguration.cs	(revision 5357)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Interfaces/IValueConfiguration.cs	(revision 5359)
@@ -8,4 +8,7 @@
     IItemCollection<IParameterConfiguration> ParameterConfigurations { get; }
     IRange RangeConstraint { get; }
+    int Number { get; set; } // if larger than 0 it will be visible in the name. this can be used when multiple ValueConfiguration with the same name exist in a list
+    string NumberedName { get; }
+
     event EventHandler ValueChanged;
     
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/MetaOptimizationProblem.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/MetaOptimizationProblem.cs	(revision 5357)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/MetaOptimizationProblem.cs	(revision 5359)
@@ -104,6 +104,6 @@
       get { return Operators.OfType<ReferenceQualityAnalyzer>().FirstOrDefault(); }
     }
-    private RunsAnalyzer RunsAnalyzer {
-      get { return Operators.OfType<RunsAnalyzer>().FirstOrDefault(); }
+    private SolutionCacheAnalyzer RunsAnalyzer {
+      get { return Operators.OfType<SolutionCacheAnalyzer>().FirstOrDefault(); }
     }
     #endregion
@@ -169,5 +169,5 @@
       Operators.Add(new BestParameterConfigurationAnalyzer());
       Operators.Add(new ReferenceQualityAnalyzer());
-      Operators.Add(new RunsAnalyzer());
+      Operators.Add(new SolutionCacheAnalyzer());
     }
     private void ParameterizeSolutionCreator() {
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/MetaOptimizationUtil.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/MetaOptimizationUtil.cs	(revision 5359)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/MetaOptimizationUtil.cs	(revision 5359)
@@ -0,0 +1,55 @@
+﻿using System;
+using System.Linq;
+using System.Threading;
+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 HeuristicLab.Algorithms.GeneticAlgorithm;
+using System.Threading.Tasks;
+using System.Diagnostics;
+using System.Reflection;
+
+namespace HeuristicLab.Problems.MetaOptimization {
+  public static class MetaOptimizationUtil {
+    /// <summary>
+    /// Removes those results from the run which are not declared in resultsToKeep
+    /// </summary>
+    public static void ClearResults(IRun run, IEnumerable<string> resultsToKeep) {
+      var resultsToRemove = new List<string>();
+      foreach (var result in run.Results) {
+        if (!resultsToKeep.Contains(result.Key))
+          resultsToRemove.Add(result.Key);
+      }
+      foreach (var result in resultsToRemove)
+        run.Results.Remove(result);
+    }
+
+    /// <summary>
+    /// Removes those parameters from the run which are not declared in parametersToKeep
+    /// </summary>
+    public static void ClearParameters(IRun run, IEnumerable<string> parametersToKeep) {
+      var parametersToRemove = new List<string>();
+      foreach (var parameter in run.Parameters) {
+        if (!parametersToKeep.Contains(parameter.Key))
+          parametersToRemove.Add(parameter.Key);
+      }
+      foreach (var parameter in parametersToRemove)
+        run.Parameters.Remove(parameter);
+    }
+
+    public static double NormalizeQualities(ParameterConfigurationTree parameterConfigurationTree, double[] referenceQualities) {
+      double[] qualitiesNormalized = new double[referenceQualities.Length];
+      for (int i = 0; i < referenceQualities.Length; i++) {
+        qualitiesNormalized[i] = parameterConfigurationTree.AverageQualities[i] / referenceQualities[i];
+      }
+      parameterConfigurationTree.QualitiesNormalized = new DoubleArray(qualitiesNormalized);
+      parameterConfigurationTree.AverageQualityNormalized = new DoubleValue(qualitiesNormalized.Average());
+      return parameterConfigurationTree.AverageQualityNormalized.Value;
+    }
+  }
+}
