Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/AlgorithmExecutor.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/AlgorithmExecutor.cs	(revision 6017)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/AlgorithmExecutor.cs	(revision 6018)
@@ -10,4 +10,8 @@
       executor.StartSync();
     }
+    public static void StartSync(this IAlgorithm algorithm, CancellationToken cancellationToken) {
+      var executor = new AlgorithmExecutor(algorithm, cancellationToken);
+      executor.StartSync();
+    }
   }
 
@@ -18,4 +22,6 @@
     private IAlgorithm algorithm;
     private AutoResetEvent waitHandle = new AutoResetEvent(false);
+    private CancellationToken cancellationToken;
+    private bool useCancellationToken = false;
 
     public AlgorithmExecutor(IAlgorithm algorithm) {
@@ -23,8 +29,20 @@
     }
 
+    public AlgorithmExecutor(IAlgorithm algorithm, CancellationToken cancellationToken) {
+      this.algorithm = algorithm;
+      this.cancellationToken = cancellationToken;
+      this.useCancellationToken = true;
+    }
+
     public void StartSync() {
       algorithm.Stopped += new EventHandler(algorithm_Stopped);
       algorithm.Paused += new EventHandler(algorithm_Paused);
-      algorithm.Start();
+      
+      if(useCancellationToken && algorithm is EngineAlgorithm && ((EngineAlgorithm)algorithm).Engine is SequentialEngine.SequentialEngine) {
+        ((SequentialEngine.SequentialEngine)((EngineAlgorithm)algorithm).Engine).Start(cancellationToken);
+      } else {
+        algorithm.Start();
+      }
+
       waitHandle.WaitOne();
       waitHandle.Dispose();
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/BestParameterConfigurationAnalyzer.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/BestParameterConfigurationAnalyzer.cs	(revision 6017)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/BestParameterConfigurationAnalyzer.cs	(revision 6018)
@@ -7,6 +7,4 @@
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-using System.Collections.Generic;
-using System;
 
 namespace HeuristicLab.Problems.MetaOptimization {
@@ -39,9 +37,9 @@
       get { return (LookupParameter<RunCollection>)Parameters["Population"]; }
     }
-    public LookupParameter<DoubleArray> ProblemQualityReferencesParameter {
-      get { return (LookupParameter<DoubleArray>)Parameters["ProblemQualityReferences"]; }
-    }
     public LookupParameter<ConstrainedItemList<IProblem>> ProblemsParameter {
       get { return (LookupParameter<ConstrainedItemList<IProblem>>)Parameters[MetaOptimizationProblem.ProblemsParameterName]; }
+    }
+    public LookupParameter<BoolValue> MaximizationParameter {
+      get { return (LookupParameter<BoolValue>)Parameters["Maximization"]; }
     }
 
@@ -55,6 +53,6 @@
       Parameters.Add(new LookupParameter<IRun>("BestKnownSolution", ""));
       Parameters.Add(new LookupParameter<RunCollection>("Population", ""));
-      Parameters.Add(new LookupParameter<DoubleArray>("ProblemQualityReferences", ""));
       Parameters.Add(new LookupParameter<ConstrainedItemList<IProblem>>(MetaOptimizationProblem.ProblemsParameterName));
+      Parameters.Add(new LookupParameter<BoolValue>("Maximization", "Set to false if the problem should be minimized."));
     }
 
@@ -71,6 +69,11 @@
       DoubleValue bestKnownQuality = BestKnownQualityParameter.ActualValue;
       ItemArray<ParameterConfigurationTree> parameterTrees = ParameterConfigurationParameter.ActualValue;
+      bool maximization = MaximizationParameter.ActualValue.Value;
 
-      int idxBest = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index;
+      int idxBest;
+      if (maximization)
+        idxBest = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).Last().index;
+      else
+        idxBest = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index;
 
       ParameterConfigurationTree best = (ParameterConfigurationTree)parameterTrees[idxBest];
@@ -79,5 +82,7 @@
       best.CollectParameterValues(bestRun.Parameters);
 
-      if (bestKnownQuality == null || qualities[idxBest].Value < bestKnownQuality.Value) { // todo: respect Maximization:true/false
+      if (bestKnownQuality == null || 
+        (!maximization && (qualities[idxBest].Value < bestKnownQuality.Value) ||
+        (maximization && (qualities[idxBest].Value > bestKnownQuality.Value)))) {
         BestKnownQualityParameter.ActualValue = new DoubleValue(qualities[idxBest].Value);
 
@@ -96,5 +101,5 @@
       int i = 0;
       RunCollection rc = new RunCollection();
-      foreach (ParameterConfigurationTree pt in parameterTrees.OrderBy(x => x.AverageQualityNormalized)) { // todo: respect Maximization:true/false
+      foreach (ParameterConfigurationTree pt in (maximization ? parameterTrees.OrderByDescending(x => x.Quality) : parameterTrees.OrderBy(x => x.Quality))) {
         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 6017)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/PMOBestSolutionHistoryAnalyzer.cs	(revision 6018)
@@ -7,7 +7,4 @@
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-using System.Collections.Generic;
-using System;
-using HeuristicLab.Analysis;
 
 namespace HeuristicLab.Problems.MetaOptimization {
@@ -34,4 +31,7 @@
       get { return (LookupParameter<IntValue>)Parameters["Generations"]; }
     }
+    public LookupParameter<BoolValue> MaximizationParameter {
+      get { return (LookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
 
     public PMOBestSolutionHistoryAnalyzer()
@@ -42,4 +42,5 @@
       Parameters.Add(new LookupParameter<ConstrainedItemList<IProblem>>(MetaOptimizationProblem.ProblemsParameterName));
       Parameters.Add(new LookupParameter<IntValue>("Generations", ""));
+      Parameters.Add(new LookupParameter<BoolValue>("Maximization", "Set to false if the problem should be minimized."));
     }
 
@@ -56,5 +57,12 @@
       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
+      bool maximization = MaximizationParameter.ActualValue.Value;
+
+      int idxBest;
+      if (maximization)
+        idxBest = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).Last().index;
+      else
+        idxBest = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index;
+
       ParameterConfigurationTree best = parameterTrees[idxBest];
 
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/PMOProblemQualitiesAnalyzer.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/PMOProblemQualitiesAnalyzer.cs	(revision 6017)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/PMOProblemQualitiesAnalyzer.cs	(revision 6018)
@@ -1,3 +1,4 @@
 ﻿using System.Linq;
+using HeuristicLab.Analysis;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -7,7 +8,4 @@
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-using System.Collections.Generic;
-using System;
-using HeuristicLab.Analysis;
 
 namespace HeuristicLab.Problems.MetaOptimization {
@@ -31,4 +29,7 @@
       get { return (LookupParameter<ConstrainedItemList<IProblem>>)Parameters[MetaOptimizationProblem.ProblemsParameterName]; }
     }
+    public LookupParameter<BoolValue> MaximizationParameter {
+      get { return (LookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
 
     public PMOProblemQualitiesAnalyzer()
@@ -38,4 +39,5 @@
       Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", ""));
       Parameters.Add(new LookupParameter<ConstrainedItemList<IProblem>>(MetaOptimizationProblem.ProblemsParameterName));
+      Parameters.Add(new LookupParameter<BoolValue>("Maximization", "Set to false if the problem should be minimized."));
     }
 
@@ -51,7 +53,16 @@
       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;
-      
+      bool maximization = MaximizationParameter.ActualValue.Value;
+
+      int idxBest ;
+      int idxWorst;
+      if (maximization) {
+        idxBest = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).Last().index;
+        idxWorst = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index;
+      } else {
+        idxBest = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index;
+        idxWorst = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).Last().index;
+      }
+
       int problemCount = ProblemsParameter.ActualValue.Count;
 
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/ReferenceQualityAnalyzer.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/ReferenceQualityAnalyzer.cs	(revision 6017)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/ReferenceQualityAnalyzer.cs	(revision 6018)
@@ -7,6 +7,4 @@
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-using System.Collections.Generic;
-using System;
 
 namespace HeuristicLab.Problems.MetaOptimization {
@@ -17,5 +15,5 @@
   [StorableClass]
   public sealed class ReferenceQualityAnalyzer : SingleSuccessorOperator, IAnalyzer {
-    
+
     public ValueLookupParameter<ResultCollection> ResultsParameter {
       get { return (ValueLookupParameter<ResultCollection>)Parameters["Results"]; }
@@ -27,9 +25,18 @@
       get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
     }
-    public LookupParameter<DoubleArray> ProblemQualityReferenceParameter {
-      get { return (LookupParameter<DoubleArray>)Parameters["ProblemQualityReferences"]; }
+    public LookupParameter<DoubleArray> ReferenceQualityAveragesParameter {
+      get { return (LookupParameter<DoubleArray>)Parameters["ReferenceQualityAverages"]; }
+    }
+    public LookupParameter<DoubleArray> ReferenceQualityDeviationsParameter {
+      get { return (LookupParameter<DoubleArray>)Parameters["ReferenceQualityDeviations"]; }
+    }
+    public LookupParameter<DoubleArray> ReferenceEvaluatedSolutionAveragesParameter {
+      get { return (LookupParameter<DoubleArray>)Parameters["ReferenceEvaluatedSolutionAverages"]; }
     }
     public LookupParameter<ConstrainedItemList<IProblem>> ProblemsParameter {
       get { return (LookupParameter<ConstrainedItemList<IProblem>>)Parameters[MetaOptimizationProblem.ProblemsParameterName]; }
+    }
+    public LookupParameter<BoolValue> MaximizationParameter {
+      get { return (LookupParameter<BoolValue>)Parameters["Maximization"]; }
     }
 
@@ -39,6 +46,9 @@
       Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", ""));
       Parameters.Add(new ScopeTreeLookupParameter<ParameterConfigurationTree>("ParameterConfigurationTree", ""));
-      Parameters.Add(new LookupParameter<DoubleArray>("ProblemQualityReferences", ""));
+      Parameters.Add(new LookupParameter<DoubleArray>("ReferenceQualityAverages", ""));
+      Parameters.Add(new LookupParameter<DoubleArray>("ReferenceQualityDeviations", ""));
+      Parameters.Add(new LookupParameter<DoubleArray>("ReferenceEvaluatedSolutionAverages", ""));
       Parameters.Add(new LookupParameter<ConstrainedItemList<IProblem>>(MetaOptimizationProblem.ProblemsParameterName, ""));
+      Parameters.Add(new LookupParameter<BoolValue>("Maximization", "Set to false if the problem should be minimized."));
     }
 
@@ -54,10 +64,21 @@
       ItemArray<ParameterConfigurationTree> solutions = ParameterConfigurationParameter.ActualValue;
       ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+      bool maximization = MaximizationParameter.ActualValue.Value;
 
-      if (ProblemQualityReferenceParameter.ActualValue == null) {
-        DoubleArray referenceQualities = CalculateReferenceQualities(solutions);
-        ProblemQualityReferenceParameter.ActualValue = referenceQualities;
-        NormalizePopulation(solutions, qualities, referenceQualities);
-        results.Add(new Result("QualityReferences", referenceQualities));
+      if (ReferenceQualityAveragesParameter.ActualValue == null) {
+        // this is generation zero. calculate the reference values and apply them on population. in future generations `AlgorithmRunsAnalyzer` will do the nomalization
+        DoubleArray referenceQualityAverages = CalculateReferenceQualityAverages(solutions, maximization);
+        DoubleArray referenceQualityDeviations = CalculateReferenceQualityDeviations(solutions, maximization);
+        DoubleArray referenceEvaluatedSolutionAverages = CalculateReferenceEvaluatedSolutionAverages(solutions, maximization);
+
+        ReferenceQualityAveragesParameter.ActualValue = referenceQualityAverages;
+        ReferenceQualityDeviationsParameter.ActualValue = referenceQualityDeviations;
+        ReferenceEvaluatedSolutionAveragesParameter.ActualValue = referenceEvaluatedSolutionAverages;
+
+        NormalizePopulation(solutions, qualities, referenceQualityAverages, referenceQualityDeviations, referenceEvaluatedSolutionAverages, 1, 1, 1, maximization);
+
+        results.Add(new Result("ReferenceQualities", referenceQualityAverages));
+        results.Add(new Result("ReferenceQualityDeviations", referenceQualityDeviations));
+        results.Add(new Result("ReferenceEvaluatedSolutionAverages", referenceEvaluatedSolutionAverages));
       }
 
@@ -65,15 +86,61 @@
     }
 
-    private DoubleArray CalculateReferenceQualities(ItemArray<ParameterConfigurationTree> solutions) {
-      DoubleArray referenceQualities = new DoubleArray(ProblemsParameter.ActualValue.Count);
+    private DoubleArray CalculateReferenceQualityAverages(ItemArray<ParameterConfigurationTree> solutions, bool maximization) {
+      DoubleArray references = new DoubleArray(ProblemsParameter.ActualValue.Count);
       for (int pi = 0; pi < ProblemsParameter.ActualValue.Count; pi++) {
-        referenceQualities[pi] = solutions.Where(x => x.AverageQualities != null).Select(x => x.AverageQualities[pi]).Min(); // todo: respect minimization / maximization
+        if (maximization)
+          references[pi] = solutions.Where(x => x.AverageQualities != null).Select(x => x.AverageQualities[pi]).Max();
+        else
+          references[pi] = solutions.Where(x => x.AverageQualities != null).Select(x => x.AverageQualities[pi]).Min();
       }
-      return referenceQualities;
+      return references;
     }
 
-    private void NormalizePopulation(ItemArray<ParameterConfigurationTree> solutions, ItemArray<DoubleValue> qualities, DoubleArray referenceQualities) {
+    private DoubleArray CalculateReferenceQualityDeviations(ItemArray<ParameterConfigurationTree> solutions, bool maximization) {
+      DoubleArray references = new DoubleArray(ProblemsParameter.ActualValue.Count);
+      for (int pi = 0; pi < ProblemsParameter.ActualValue.Count; pi++) {
+        if (maximization)
+          references[pi] = solutions.Where(x => x.QualityStandardDeviations != null).Select(x => x.QualityStandardDeviations[pi]).Max();
+        else
+          references[pi] = solutions.Where(x => x.QualityStandardDeviations != null).Select(x => x.QualityStandardDeviations[pi]).Min();
+      }
+      return references;
+    }
+
+    private DoubleArray CalculateReferenceEvaluatedSolutionAverages(ItemArray<ParameterConfigurationTree> solutions, bool maximization) {
+      DoubleArray references = new DoubleArray(ProblemsParameter.ActualValue.Count);
+      for (int pi = 0; pi < ProblemsParameter.ActualValue.Count; pi++) {
+        if (maximization)
+          references[pi] = solutions.Where(x => x.AverageEvaluatedSolutions != null).Select(x => x.AverageEvaluatedSolutions[pi]).Max();
+        else
+          references[pi] = solutions.Where(x => x.AverageEvaluatedSolutions != null).Select(x => x.AverageEvaluatedSolutions[pi]).Min();
+      }
+      return references;
+    }
+
+    private void NormalizePopulation(ItemArray<ParameterConfigurationTree> solutions, ItemArray<DoubleValue> qualities,
+          DoubleArray referenceQualityAverages,
+          DoubleArray referenceQualityDeviations,
+          DoubleArray referenceEvaluatedSolutionAverages,
+          double qualityAveragesWeight,
+          double qualityDeviationsWeight,
+          double evaluatedSolutionsWeight,
+          bool maximization) {
       for (int i = 0; i < solutions.Length; i++) {
-        qualities[i].Value = MetaOptimizationUtil.NormalizeQualities(solutions[i], referenceQualities.ToArray());
+        if (solutions[i].AverageQualities == null || solutions[i].QualityStandardDeviations == null || solutions[i].AverageEvaluatedSolutions == null) {
+          // this parameterConfigurationTree has not been evaluated correctly (due to a faulty configuration, which led to an exception)
+          // since we are in generation zero, there is no WorstQuality available for a penalty value
+          double penaltyValue = maximization ? double.MinValue : double.MaxValue;
+          qualities[i].Value = penaltyValue;
+        } else {
+          qualities[i].Value = MetaOptimizationUtil.Normalize(solutions[i],
+            referenceQualityAverages.ToArray(),
+            referenceQualityDeviations.ToArray(),
+            referenceEvaluatedSolutionAverages.ToArray(),
+            qualityAveragesWeight,
+            qualityDeviationsWeight,
+            evaluatedSolutionsWeight,
+            maximization);
+        }
       }
     }
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/SolutionCacheAnalyzer.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/SolutionCacheAnalyzer.cs	(revision 6017)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/SolutionCacheAnalyzer.cs	(revision 6018)
@@ -7,6 +7,4 @@
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-using System.Collections.Generic;
-using System;
 
 namespace HeuristicLab.Problems.MetaOptimization {
@@ -27,7 +25,4 @@
       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]; }
@@ -45,5 +40,4 @@
       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", ""));
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ParameterConfigurationTree.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ParameterConfigurationTree.cs	(revision 6017)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ParameterConfigurationTree.cs	(revision 6018)
@@ -16,10 +16,10 @@
 
     [Storable]
-    private DoubleValue averageQualityNormalized;
-    public DoubleValue AverageQualityNormalized {
-      get { return averageQualityNormalized; }
-      set {
-        if (averageQualityNormalized != value) {
-          averageQualityNormalized = value;
+    private DoubleValue quality;
+    public DoubleValue Quality {
+      get { return quality; }
+      set {
+        if (quality != value) {
+          quality = value;
           OnQualityChanged();
         }
@@ -28,14 +28,36 @@
 
     [Storable]
-    private DoubleArray qualitiesNormalized;
-    public DoubleArray QualitiesNormalized {
-      get { return qualitiesNormalized; }
-      set {
-        if (qualitiesNormalized != value) {
-          qualitiesNormalized = value;
-        }
-      }
-    }
-
+    private DoubleArray normalizedQualityAverages;
+    public DoubleArray NormalizedQualityAverages {
+      get { return normalizedQualityAverages; }
+      set {
+        if (normalizedQualityAverages != value) {
+          normalizedQualityAverages = value;
+        }
+      }
+    }
+
+    [Storable]
+    private DoubleArray normalizedQualityDeviations;
+    public DoubleArray NormalizedQualityDeviations {
+      get { return normalizedQualityDeviations; }
+      set {
+        if (normalizedQualityDeviations != value) {
+          normalizedQualityDeviations = value;
+        }
+      }
+    }
+
+    [Storable]
+    private DoubleArray normalizedEvaluatedSolutions;
+    public DoubleArray NormalizedEvaluatedSolutions {
+      get { return normalizedEvaluatedSolutions; }
+      set {
+        if (normalizedEvaluatedSolutions != value) {
+          normalizedEvaluatedSolutions = value;
+        }
+      }
+    }
+    
     [Storable]
     private DoubleArray bestQualities;
@@ -85,4 +107,11 @@
 
     [Storable]
+    private DoubleArray averageEvaluatedSolutions;
+    public DoubleArray AverageEvaluatedSolutions {
+      get { return averageEvaluatedSolutions; }
+      set { averageEvaluatedSolutions = value; }
+    }
+
+    [Storable]
     private IntValue repetitions;
     public IntValue Repetitions {
@@ -116,11 +145,4 @@
       }
     }
-
-    //[Storable]
-    //protected string name;
-    //public string Name {
-    //  get { return name; }
-    //  set { name = value; }
-    //}
 
     #region constructors and cloning
@@ -136,5 +158,5 @@
       algproblemitem.ProblemParameter.Value = problem;
       this.discoverValidValues = false;
-      
+
       this.parameterConfigurations.Add(new SingleValuedParameterConfiguration("Algorithm", algproblemitem.AlgorithmParameter));
       this.parameterConfigurations.Add(new SingleValuedParameterConfiguration("Problem", algproblemitem.ProblemParameter));
@@ -145,6 +167,8 @@
     protected ParameterConfigurationTree(ParameterConfigurationTree original, Cloner cloner)
       : base(original, cloner) {
-      this.averageQualityNormalized = cloner.Clone(original.averageQualityNormalized);
-      this.qualitiesNormalized = cloner.Clone(original.qualitiesNormalized);
+      this.quality = cloner.Clone(original.quality);
+      this.normalizedQualityAverages = cloner.Clone(original.normalizedQualityAverages);
+      this.normalizedQualityDeviations = cloner.Clone(original.normalizedQualityDeviations);
+      this.normalizedEvaluatedSolutions = cloner.Clone(original.normalizedEvaluatedSolutions);
       this.bestQualities = cloner.Clone(original.BestQualities);
       this.averageQualities = cloner.Clone(original.averageQualities);
@@ -153,4 +177,5 @@
       this.qualityVariances = cloner.Clone(original.qualityVariances);
       this.averageExecutionTimes = cloner.Clone(original.averageExecutionTimes);
+      this.averageEvaluatedSolutions = cloner.Clone(original.averageEvaluatedSolutions);
       this.repetitions = cloner.Clone(original.repetitions);
       this.runs = cloner.Clone(original.runs);
@@ -171,4 +196,5 @@
     public virtual void CollectResultValues(IDictionary<string, IItem> values) {
       values.Add("RunsAverageExecutionTimes", AverageExecutionTimes);
+      values.Add("RunsAverageEvaluatedSolutions", AverageEvaluatedSolutions);
       values.Add("Repetitions", Repetitions);
       values.Add("RunsBestQualities", BestQualities);
@@ -177,6 +203,6 @@
       values.Add("RunsQualityVariances", QualityVariances);
       values.Add("RunsQualityStandardDeviations", QualityStandardDeviations);
-      values.Add("QualitiesNormalized", QualitiesNormalized);
-      values.Add("AverageQualityNormalized", AverageQualityNormalized);
+      values.Add("QualitiesNormalized", NormalizedQualityAverages);
+      values.Add("AverageQualityNormalized", Quality);
       values.Add("Runs", Runs);
     }
@@ -209,15 +235,5 @@
 
       algorithm.CollectParameterValues(this.Parameters);
-      //((IProblem)ProblemConfiguration.ActualValue.Value).CollectParameterValues(this.Parameters);
-      //CollectAlgorithmParameterValues((IAlgorithm)AlgorithmConfiguration.ActualValue.Value, parameters);
-    }
-
-    //protected virtual void CollectAlgorithmParameterValues(IAlgorithm algorithm, IDictionary<string, IItem> values) {
-    //  var algorithmValues = new Dictionary<string, IItem>();
-    //  algorithm.CollectParameterValues(algorithmValues);
-    //  foreach (var value in algorithmValues) {
-    //    values.Add("Algorithm." + value.Key, value.Value);
-    //  }
-    //}
+    }
 
     public Experiment GenerateExperiment(IAlgorithm algorithm, bool createBatchRuns, int repetitions) {
@@ -294,12 +310,14 @@
         var sb = new StringBuilder();
         if (!string.IsNullOrEmpty(algorithmInfo)) {
-          sb.Append("Algorithm: ");
+          sb.Append("Algorithm (");
           sb.Append(algorithmInfo);
+          sb.Append(")");
         }
         if (!string.IsNullOrEmpty(problemInfo)) {
           if (sb.Length > 0)
             sb.Append(", ");
-          sb.Append("Problem: ");
+          sb.Append("Problem( ");
           sb.Append(problemInfo);
+          sb.Append(")");
         }
         return sb.ToString();
@@ -311,6 +329,4 @@
       ProblemConfiguration.CollectOptimizedParameterNames(parameterNames, string.Empty);
     }
-
-   
   }
 }
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 6017)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ParameterConfigurations/ParameterConfiguration.cs	(revision 6018)
@@ -92,4 +92,5 @@
           if (this.valueConfigurations != null) DeregisterValueConfigurationEvents();
           this.valueConfigurations = value;
+          KeepActualValueConfigurationIndexConsistent();
           if (this.valueConfigurations != null) RegisterValueConfigurationEvents();
         }
@@ -144,5 +145,5 @@
       set { autoPopulateValueConfigurations = value; }
     }
-    
+
 
     #region Constructors and Cloning
@@ -258,5 +259,5 @@
         } else {
           IItem val;
-          if (ActualValue.Value != null && ActualValue.ValueDataType == t) {
+          if (ActualValue.Value != null && ActualValue.Value.GetType() == t) {
             val = (IItem)ActualValue.Value.Clone(); // use existing value for that type (if available)
           } else {
@@ -363,10 +364,14 @@
     void ValueConfigurations_CheckedItemsChanged(object sender, Collections.CollectionItemsChangedEventArgs<IndexedItem<IValueConfiguration>> e) {
       OnToStringChanged();
-    }
+      KeepActualValueConfigurationIndexConsistent();
+    }
+
     void ValueConfigurations_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs<IndexedItem<IValueConfiguration>> e) {
       OnToStringChanged();
+      KeepActualValueConfigurationIndexConsistent();
     }
     void ValueConfigurations_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs<IndexedItem<IValueConfiguration>> e) {
       OnToStringChanged();
+      KeepActualValueConfigurationIndexConsistent();
     }
 
@@ -440,5 +445,5 @@
     }
 
-    public string ParameterInfoString {
+    public virtual string ParameterInfoString {
       get {
         StringBuilder sb = new StringBuilder();
@@ -455,5 +460,5 @@
           }
 
-          if (this.ActualValue.Value is IParameterizedItem) {
+          if (this.ValueConfigurations[actualValueConfigurationIndex] is ParameterizedValueConfiguration) {
             string subParams = this.ValueConfigurations[actualValueConfigurationIndex].ParameterInfoString;
             if (!string.IsNullOrEmpty(subParams)) {
@@ -583,4 +588,23 @@
       }
     }
+
+    /// <summary>
+    /// Ensures that the ActualValueConfigurationIndex has a valid value
+    /// Only indices of items which are checked are allowed
+    /// </summary>
+    private void KeepActualValueConfigurationIndexConsistent() {
+      if (this.valueConfigurations != null && this.valueConfigurations.CheckedItems.Count() > 0) {
+        if(this.valueConfigurations.Count <= this.actualValueConfigurationIndex &&
+           this.valueConfigurations.CheckedItems.Count(x => x.Index == this.actualValueConfigurationIndex) == 1) {
+          // everything is ok; do nothing
+        } else {
+          // current index is invalid, set new one
+          this.ActualValueConfigurationIndex = this.valueConfigurations.CheckedItems.First().Index;
+        }
+      } else {
+        // no checked valueConfiguration is available; cannot be used
+        this.ActualValueConfigurationIndex = -1;
+      }
+    }
   }
 }
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ParameterConfigurations/SingleValuedParameterConfiguration.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ParameterConfigurations/SingleValuedParameterConfiguration.cs	(revision 6017)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ParameterConfigurations/SingleValuedParameterConfiguration.cs	(revision 6018)
@@ -24,5 +24,5 @@
       this.discoverValidValues = false;
       this.validValues = new ItemSet<IItem> { valueConfiguration.ActualValue.Value };
-      this.validTypes = new Type[] {valueConfiguration.ActualValue.ValueDataType};
+      this.validTypes = new Type[] { valueConfiguration.ActualValue.ValueDataType };
       this.IsNullable = false;
       this.itemImage = valueConfiguration.ItemImage;
@@ -69,4 +69,14 @@
       OnToStringChanged();
     }
+
+    public override string ParameterInfoString {
+      get {
+        if (this.Optimize) {
+          return string.Format("{0} ({1})", this.Name, this.ValueConfigurations.Single().ParameterInfoString);
+        } else {
+          return string.Empty;
+        }
+      }
+    }
   }
 }
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Evaluators/AlgorithmEvaluator.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Evaluators/AlgorithmEvaluator.cs	(revision 6017)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Evaluators/AlgorithmEvaluator.cs	(revision 6018)
@@ -64,5 +64,5 @@
       var sw = new Stopwatch();
       sw.Start();
-      algorithm.StartSync();
+      algorithm.StartSync(CancellationToken);
       sw.Stop();
       Console.WriteLine("{0},{1}: {2} (Grammar: {3})", ProblemIndexParameter.ActualValue.Value, RepetitionIndexParameter.ActualValue.Value, sw.Elapsed, PrintGrammar(srp.SymbolicExpressionTreeGrammar));
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Evaluators/AlgorithmRunsAnalyzer.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Evaluators/AlgorithmRunsAnalyzer.cs	(revision 6017)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Evaluators/AlgorithmRunsAnalyzer.cs	(revision 6018)
@@ -2,12 +2,11 @@
 using System.Collections.Generic;
 using System.Linq;
-using System.Text;
+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 HeuristicLab.Core;
-using HeuristicLab.Common;
-using HeuristicLab.Parameters;
-using HeuristicLab.Data;
-using HeuristicLab.Optimization;
 
 namespace HeuristicLab.Problems.MetaOptimization {
@@ -32,6 +31,12 @@
       get { return (ILookupParameter<IItemList<IProblem>>)Parameters[MetaOptimizationProblem.ProblemsParameterName]; }
     }
-    public LookupParameter<DoubleArray> ProblemQualityReferencesParameter {
-      get { return (LookupParameter<DoubleArray>)Parameters["ProblemQualityReferences"]; }
+    public LookupParameter<DoubleArray> ReferenceQualityAveragesParameter {
+      get { return (LookupParameter<DoubleArray>)Parameters["ReferenceQualityAverages"]; }
+    }
+    public LookupParameter<DoubleArray> ReferenceQualityDeviationsParameter {
+      get { return (LookupParameter<DoubleArray>)Parameters["ReferenceQualityDeviations"]; }
+    }
+    public LookupParameter<DoubleArray> ReferenceEvaluatedSolutionAveragesParameter {
+      get { return (LookupParameter<DoubleArray>)Parameters["ReferenceEvaluatedSolutionAverages"]; }
     }
     public LookupParameter<ResultCollection> ResultsParameter {
@@ -47,4 +52,7 @@
       get { return (ScopeTreeLookupParameter<IntValue>)Parameters["RepetitionIndex"]; }
     }
+    public LookupParameter<BoolValue> MaximizationParameter {
+      get { return (LookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
     #endregion
 
@@ -58,9 +66,12 @@
       Parameters.Add(new LookupParameter<ParameterConfigurationTree>("ParameterConfigurationTree", ""));
       Parameters.Add(new LookupParameter<IItemList<IProblem>>(MetaOptimizationProblem.ProblemsParameterName, ""));
-      Parameters.Add(new LookupParameter<DoubleArray>("ProblemQualityReferences", ""));
+      Parameters.Add(new LookupParameter<DoubleArray>("ReferenceQualityAverages", ""));
+      Parameters.Add(new LookupParameter<DoubleArray>("ReferenceQualityDeviations", ""));
+      Parameters.Add(new LookupParameter<DoubleArray>("ReferenceEvaluatedSolutionAverages", ""));
       Parameters.Add(new LookupParameter<ResultCollection>("Results", ""));
       Parameters.Add(new ScopeTreeLookupParameter<IAlgorithm>("Algorithm", "The finished algorithms containing Runs."));
       Parameters.Add(new ScopeTreeLookupParameter<IntValue>("ProblemIndex", "The index of the problem an algorithm was executed with."));
       Parameters.Add(new ScopeTreeLookupParameter<IntValue>("RepetitionIndex", "The index of the repetition"));
+      Parameters.Add(new LookupParameter<BoolValue>("Maximization", "Set to false if the problem should be minimized."));
     }
     protected AlgorithmRunsAnalyzer(AlgorithmRunsAnalyzer original, Cloner cloner)
@@ -78,8 +89,13 @@
       IEnumerable<string> parameterNames = parameterConfiguration.GetOptimizedParameterNames();
       IItemList<IProblem> problems = ProblemsParameter.ActualValue;
+      bool maximization = MaximizationParameter.ActualValue.Value;
       int repetitions = RepetitionsParameter.ActualValue.Value;
-      var resultNames = new List<string> { "BestQuality", "Execution Time" };
+      var resultNames = new List<string> { "BestQuality", "Execution Time", "EvaluatedSolutions" };
       int currentGeneration = GenerationsParameter.ActualValue != null ? GenerationsParameter.ActualValue.Value : 0;
-      double[] referenceQualities = GetReferenceQualities(problems.Count);
+      double[] referenceQualityAverages;
+      double[] referenceQualityDeviations;
+      double[] referenceEvaluatedSolutionAverages;
+      GetReferenceValues(problems.Count, out referenceQualityAverages, out referenceQualityDeviations, out referenceEvaluatedSolutionAverages);
+
       ResultCollection results = ResultsParameter.ActualValue;
 
@@ -88,7 +104,9 @@
         var qualities = new double[problems.Count][];
         var executionTimes = new TimeSpan[problems.Count][];
+        var evaluatedSolutions = new int[problems.Count][];
 
         for (int i = 0; i < problems.Count; i++) {
           qualities[i] = new double[repetitions];
+          evaluatedSolutions[i] = new int[repetitions];
           executionTimes[i] = new TimeSpan[repetitions];
         }
@@ -98,5 +116,5 @@
           int repetitionIndex = repetitionIndices[i].Value;
 
-          IRun run = algorithms[i].Runs.First();
+          IRun run = algorithms[i].Runs.Single();
           MetaOptimizationUtil.ClearResults(run, resultNames);
           MetaOptimizationUtil.ClearParameters(run, parameterNames);
@@ -107,22 +125,33 @@
           qualities[problemIndex][repetitionIndex] = (((DoubleValue)run.Results["BestQuality"]).Value);
           executionTimes[problemIndex][repetitionIndex] = (((TimeSpanValue)run.Results["Execution Time"]).Value);
+          evaluatedSolutions[problemIndex][repetitionIndex] = (((IntValue)run.Results["EvaluatedSolutions"]).Value);
           runs.Add((IRun)run.Clone());
         }
 
         parameterConfiguration.AverageExecutionTimes = new ItemList<TimeSpanValue>(executionTimes.Select(t => new TimeSpanValue(TimeSpan.FromMilliseconds(t.Average(ts => ts.TotalMilliseconds)))));
+        parameterConfiguration.AverageEvaluatedSolutions = new DoubleArray(evaluatedSolutions.Select(x => x.Average()).ToArray());
         parameterConfiguration.Repetitions = new IntValue(repetitions);
-        parameterConfiguration.BestQualities = new DoubleArray(qualities.Select(q => q.Min()).ToArray()); // todo: respect Maximization:true/false
         parameterConfiguration.AverageQualities = new DoubleArray(qualities.Select(q => q.Average()).ToArray());
-        parameterConfiguration.WorstQualities = new DoubleArray(qualities.Select(q => q.Max()).ToArray()); // todo: respect Maximization:true/false
+
+        if(maximization)
+          parameterConfiguration.BestQualities = new DoubleArray(qualities.Select(q => q.Max()).ToArray());
+        else
+          parameterConfiguration.BestQualities = new DoubleArray(qualities.Select(q => q.Min()).ToArray());
+        
+        if (maximization)
+          parameterConfiguration.WorstQualities = new DoubleArray(qualities.Select(q => q.Min()).ToArray());
+        else
+          parameterConfiguration.WorstQualities = new DoubleArray(qualities.Select(q => q.Max()).ToArray());
+
         parameterConfiguration.QualityVariances = new DoubleArray(qualities.Select(q => q.Variance()).ToArray());
         parameterConfiguration.QualityStandardDeviations = new DoubleArray(qualities.Select(q => q.StandardDeviation()).ToArray());
         parameterConfiguration.Runs = runs;
 
-        this.QualityParameter.ActualValue = new DoubleValue(MetaOptimizationUtil.NormalizeQualities(parameterConfiguration, referenceQualities));
+        this.QualityParameter.ActualValue = new DoubleValue(MetaOptimizationUtil.Normalize(parameterConfiguration, referenceQualityAverages, referenceQualityDeviations, referenceEvaluatedSolutionAverages, 1, 1, 1, maximization));
       } else {
         // something terrible happened -> most probably due to invalid parameters.
         // penalty with worst quality from latest generation!
 
-        double penaltyValue = results.ContainsKey("CurrentWorstQuality") ? ((DoubleValue)results["CurrentWorstQuality"]).Value : referenceQualities.Max(); // todo: respect min/max
+        double penaltyValue = results.ContainsKey("CurrentWorstQuality") ? ((DoubleValue)results["CurrentWorstQuality"]).Value : referenceQualityAverages.Max(); // todo: respect min/max
         this.QualityParameter.ActualValue = new DoubleValue(penaltyValue);
       }
@@ -131,16 +160,20 @@
     }
 
-    private double[] GetReferenceQualities(int problemsCount) {
-      double[] referenceQualities;
-      if (ProblemQualityReferencesParameter.ActualValue == null) {
+    private void GetReferenceValues(int problemsCount, out double[] referenceQualityAverages, out double[] referenceQualityDeviations, out double[] referenceEvaluatedSolutionAverages) {
+      if (ReferenceQualityAveragesParameter.ActualValue == null) {
         // this is generation zero. no reference qualities for normalization have been calculated yet. in this special case the ReferenceQualityAnalyzer will do the normalization
-        referenceQualities = new double[problemsCount];
-        for (int i = 0; i < referenceQualities.Length; i++) {
-          referenceQualities[i] = 1;
+        referenceQualityAverages = new double[problemsCount];
+        referenceQualityDeviations = new double[problemsCount];
+        referenceEvaluatedSolutionAverages = new double[problemsCount];
+        for (int i = 0; i < referenceQualityAverages.Length; i++) {
+          referenceQualityAverages[i] = 1;
+          referenceQualityDeviations[i] = 1;
+          referenceEvaluatedSolutionAverages[i] = 1;
         }
       } else {
-        referenceQualities = ProblemQualityReferencesParameter.ActualValue.ToArray();
+        referenceQualityAverages = ReferenceQualityAveragesParameter.ActualValue.ToArray();
+        referenceQualityDeviations = ReferenceQualityDeviationsParameter.ActualValue.ToArray();
+        referenceEvaluatedSolutionAverages = ReferenceEvaluatedSolutionAveragesParameter.ActualValue.ToArray();
       }
-      return referenceQualities;
     }
   }
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Evaluators/AlgorithmSubScopesCreator.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Evaluators/AlgorithmSubScopesCreator.cs	(revision 6017)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Evaluators/AlgorithmSubScopesCreator.cs	(revision 6018)
@@ -9,5 +9,5 @@
 
 namespace HeuristicLab.Problems.MetaOptimization {
-  [Item("ChildrenCreator", "An operator which is used to prepare crossover. The sub-scopes of the current scope the operator is applied on represent the parents. The operator creates new and empty scopes for each child, adds the scopes that represent the child's parents as sub-scopes to the child and adds the child as sub-scope to the current scope.")]
+  [Item("AlgorithmSubScopesCreator", "An operator which ...")]
   [StorableClass]
   public class AlgorithmSubScopesCreator : SingleSuccessorOperator {
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Evaluators/PMOEvaluator.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Evaluators/PMOEvaluator.cs	(revision 6017)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Evaluators/PMOEvaluator.cs	(revision 6018)
@@ -1,13 +1,9 @@
-﻿using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+﻿using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
 using HeuristicLab.Operators;
-using HeuristicLab.Common;
-using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-using HeuristicLab.Parameters;
-using HeuristicLab.Data;
-using HeuristicLab.Optimization;
 
 namespace HeuristicLab.Problems.MetaOptimization {
@@ -34,7 +30,4 @@
     public LookupParameter<IntValue> RepetitionsParameter {
       get { return (LookupParameter<IntValue>)Parameters[MetaOptimizationProblem.RepetitionsParameterName]; }
-    }
-    public LookupParameter<DoubleArray> ProblemQualityReferencesParameter {
-      get { return (LookupParameter<DoubleArray>)Parameters["ProblemQualityReferences"]; }
     }
     public LookupParameter<IntValue> GenerationsParameter {
@@ -70,5 +63,4 @@
       Parameters.Add(new LookupParameter<ParameterConfigurationTree>("ParameterConfigurationTree", ""));
       Parameters.Add(new LookupParameter<IntValue>(MetaOptimizationProblem.RepetitionsParameterName, "Number of evaluations on one problem."));
-      Parameters.Add(new LookupParameter<DoubleArray>("ProblemQualityReferences", ""));
       Parameters.Add(new LookupParameter<IntValue>("Generations", ""));
       Parameters.Add(new ScopeParameter("CurrentScope", "The current scope which represents a population of solutions on which the genetic algorithm should be applied."));
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/MetaOptimizationUtil.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/MetaOptimizationUtil.cs	(revision 6017)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/MetaOptimizationUtil.cs	(revision 6018)
@@ -34,12 +34,44 @@
     }
 
-    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];
+    public static double Normalize(
+          ParameterConfigurationTree parameterConfigurationTree,
+          double[] referenceQualityAverages,
+          double[] referenceQualityDeviations,
+          double[] referenceEvaluatedSolutionAverages,
+          double qualityAveragesWeight,
+          double qualityDeviationsWeight,
+          double evaluatedSolutionsWeight,
+          bool maximization) {
+
+      double[] qualityAveragesNormalized = new double[referenceQualityAverages.Length];
+      double[] qualityDeviationsNormalized = new double[referenceQualityDeviations.Length];
+      double[] evaluatedSolutionAveragesNormalized = new double[referenceEvaluatedSolutionAverages.Length];
+
+      for (int i = 0; i < referenceQualityAverages.Length; i++) {
+        qualityAveragesNormalized[i] = parameterConfigurationTree.AverageQualities[i] / referenceQualityAverages[i];
+        qualityDeviationsNormalized[i] = parameterConfigurationTree.QualityStandardDeviations[i] / referenceQualityDeviations[i];
+        evaluatedSolutionAveragesNormalized[i] = parameterConfigurationTree.AverageEvaluatedSolutions[i] / referenceEvaluatedSolutionAverages[i];
       }
-      parameterConfigurationTree.QualitiesNormalized = new DoubleArray(qualitiesNormalized);
-      parameterConfigurationTree.AverageQualityNormalized = new DoubleValue(qualitiesNormalized.Average());
-      return parameterConfigurationTree.AverageQualityNormalized.Value;
+      parameterConfigurationTree.NormalizedQualityAverages = new DoubleArray(qualityAveragesNormalized);
+      parameterConfigurationTree.NormalizedQualityDeviations = new DoubleArray(qualityDeviationsNormalized);
+      parameterConfigurationTree.NormalizedEvaluatedSolutions = new DoubleArray(evaluatedSolutionAveragesNormalized);
+
+      double qualityAveragesNormalizedValue = qualityAveragesNormalized.Average() * qualityAveragesWeight;
+      double qualityDeviationsNormalizedValue = qualityDeviationsNormalized.Average() * qualityDeviationsWeight;
+      double evaluatedSolutionAveragesNormalizedValue = evaluatedSolutionAveragesNormalized.Average() * evaluatedSolutionsWeight;
+
+      if (maximization) {
+        // deviation and evaluatedSolutions are always minimization problems. so if maximization=true, flip the values around 1.0 (e.g. 1.15 -> 0.85)
+        qualityDeviationsNormalizedValue -= (qualityDeviationsNormalizedValue - 1) * 2;
+        evaluatedSolutionAveragesNormalizedValue -= (evaluatedSolutionAveragesNormalizedValue - 1) * 2;
+      }
+
+      qualityAveragesNormalizedValue *= qualityAveragesWeight;
+      qualityDeviationsNormalizedValue *= qualityDeviationsWeight;
+      evaluatedSolutionAveragesNormalizedValue *= evaluatedSolutionsWeight;
+
+      parameterConfigurationTree.Quality = new DoubleValue(new double[] {qualityAveragesNormalizedValue, qualityDeviationsNormalizedValue, evaluatedSolutionAveragesNormalizedValue}.Average());
+      
+      return parameterConfigurationTree.Quality.Value;
     }
 
@@ -51,5 +83,5 @@
       algorithm.Problem = problem;
       ((EngineAlgorithm)algorithm).Engine = new SequentialEngine.SequentialEngine();
-      if(randomize) parameterConfigurationTree.Randomize(random);
+      if (randomize) parameterConfigurationTree.Randomize(random);
       parameterConfigurationTree.Parameterize(algorithm);
       return algorithm;
