Index: trunk/sources/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj	(revision 3618)
+++ trunk/sources/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj	(revision 3623)
@@ -87,4 +87,10 @@
     <Compile Include="BestAverageWorstQualityCalculator.cs" />
     <Compile Include="BestQualityMemorizer.cs" />
+    <Compile Include="PopulationQualityAnalyzer.cs" />
+    <Compile Include="PopulationValueAnalyzer.cs" />
+    <Compile Include="MinAverageMaxValueCalculator.cs" />
+    <Compile Include="PopulationMinAverageMaxValueAnalyzer.cs" />
+    <Compile Include="SolutionValueAnalyzer.cs" />
+    <Compile Include="SolutionQualityAnalyzer.cs" />
     <Compile Include="MultiAnalyzer.cs" />
     <Compile Include="PopulationBestAverageWorstQualityAnalyzer.cs" />
Index: trunk/sources/HeuristicLab.Analysis/3.3/MinAverageMaxValueCalculator.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/MinAverageMaxValueCalculator.cs	(revision 3623)
+++ trunk/sources/HeuristicLab.Analysis/3.3/MinAverageMaxValueCalculator.cs	(revision 3623)
@@ -0,0 +1,82 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// An operator which calculates the minimum, average and maximum of a value in the current population.
+  /// </summary>
+  [Item("MinAverageMaxValueCalculator", "An operator which calculates the minimum, average and maximum of a value in the current population.")]
+  [StorableClass]
+  public sealed class MinAverageMaxValueCalculator : SingleSuccessorOperator {
+    public ILookupParameter<ItemArray<DoubleValue>> ValueParameter {
+      get { return (ILookupParameter<ItemArray<DoubleValue>>)Parameters["Value"]; }
+    }
+    public IValueLookupParameter<DoubleValue> MinValueParameter {
+      get { return (IValueLookupParameter<DoubleValue>)Parameters["MinValue"]; }
+    }
+    public IValueLookupParameter<DoubleValue> AverageValueParameter {
+      get { return (IValueLookupParameter<DoubleValue>)Parameters["AverageValue"]; }
+    }
+    public IValueLookupParameter<DoubleValue> MaxValueParameter {
+      get { return (IValueLookupParameter<DoubleValue>)Parameters["MaxValue"]; }
+    }
+
+    public MinAverageMaxValueCalculator()
+      : base() {
+      Parameters.Add(new SubScopesLookupParameter<DoubleValue>("Value", "The value contained in each sub-scope for which the minimum, average and maximum should be calculated."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("MinValue", "The minimum of the value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("AverageValue", "The average of the value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("MaxValue", "The maximum of the value."));
+    }
+
+
+    public override IOperation Apply() {
+      ItemArray<DoubleValue> values = ValueParameter.ActualValue;
+
+      if (values.Length > 0) {
+        double min = double.MaxValue, max = double.MinValue, sum = 0.0;
+        for (int i = 0; i < values.Length; i++) {
+          if (values[i].Value < min) min = values[i].Value;
+          if (values[i].Value > max) max = values[i].Value;
+          sum += values[i].Value;
+        }
+
+        DoubleValue minValue = MinValueParameter.ActualValue;
+        if (minValue == null) MinValueParameter.ActualValue = new DoubleValue(min);
+        else minValue.Value = min;
+        DoubleValue averageValue = AverageValueParameter.ActualValue;
+        if (averageValue == null) AverageValueParameter.ActualValue = new DoubleValue(sum / values.Length);
+        else averageValue.Value = sum / values.Length;
+        DoubleValue maxValue = MaxValueParameter.ActualValue;
+        if (maxValue == null) MaxValueParameter.ActualValue = new DoubleValue(max);
+        else maxValue.Value = max;
+      }
+      return base.Apply();
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Analysis/3.3/PopulationBestAverageWorstQualityAnalyzer.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/PopulationBestAverageWorstQualityAnalyzer.cs	(revision 3618)
+++ trunk/sources/HeuristicLab.Analysis/3.3/PopulationBestAverageWorstQualityAnalyzer.cs	(revision 3623)
@@ -57,4 +57,7 @@
       get { return (ValueLookupParameter<DoubleValue>)Parameters["CurrentWorstQuality"]; }
     }
+    public ValueLookupParameter<DataTable> QualitiesParameter {
+      get { return (ValueLookupParameter<DataTable>)Parameters["Qualities"]; }
+    }
     public ValueLookupParameter<DoubleValue> AbsoluteDifferenceBestKnownToBestParameter {
       get { return (ValueLookupParameter<DoubleValue>)Parameters["AbsoluteDifferenceBestKnownToBest"]; }
@@ -84,7 +87,8 @@
       Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentAverageQuality", "The average quality value of all solutions in the current population."));
       Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentWorstQuality", "The worst quality value found in the current population."));
+      Parameters.Add(new ValueLookupParameter<DataTable>("Qualities", "The data table to store the current best, current average, current worst, best and best known quality value."));
       Parameters.Add(new ValueLookupParameter<DoubleValue>("AbsoluteDifferenceBestKnownToBest", "The absolute difference of the best known quality value to the best quality value."));
       Parameters.Add(new ValueLookupParameter<PercentValue>("RelativeDifferenceBestKnownToBest", "The relative difference of the best known quality value to the best quality value."));
-      Parameters.Add(new ValueLookupParameter<VariableCollection>("Results", "The variable collection where results should be stored."));
+      Parameters.Add(new ValueLookupParameter<VariableCollection>("Results", "The results collection where the analysis values should be stored."));
       #endregion
 
Index: trunk/sources/HeuristicLab.Analysis/3.3/PopulationMinAverageMaxValueAnalyzer.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/PopulationMinAverageMaxValueAnalyzer.cs	(revision 3623)
+++ trunk/sources/HeuristicLab.Analysis/3.3/PopulationMinAverageMaxValueAnalyzer.cs	(revision 3623)
@@ -0,0 +1,105 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// An operator which analyzes the minimum, average and maximum of a value in the current population.
+  /// </summary>
+  [Item("PopulationMinAverageMaxValueAnalyzer", "An operator which analyzes the minimum, average and maximum of a value in the current population.")]
+  [StorableClass]
+  public sealed class PopulationMinAverageMaxValueAnalyzer : AlgorithmOperator, IPopulationAnalyzer {
+    #region Parameter properties
+    public SubScopesLookupParameter<DoubleValue> ValueParameter {
+      get { return (SubScopesLookupParameter<DoubleValue>)Parameters["Value"]; }
+    }
+    public ValueLookupParameter<DoubleValue> MinValueParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["MinValue"]; }
+    }
+    public ValueLookupParameter<DoubleValue> AverageValueParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["AverageValue"]; }
+    }
+    public ValueLookupParameter<DoubleValue> MaxValueParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["MaxValue"]; }
+    }
+    public ValueLookupParameter<DataTable> ValuesParameter {
+      get { return (ValueLookupParameter<DataTable>)Parameters["Values"]; }
+    }
+    public ValueLookupParameter<VariableCollection> ResultsParameter {
+      get { return (ValueLookupParameter<VariableCollection>)Parameters["Results"]; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private PopulationMinAverageMaxValueAnalyzer(bool deserializing) : base() { }
+    public PopulationMinAverageMaxValueAnalyzer()
+      : base() {
+      Initialize();
+    }
+
+    private void Initialize() {
+      #region Create parameters
+      Parameters.Add(new SubScopesLookupParameter<DoubleValue>("Value", "The value contained in each solution which should be analyzed."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("MinValue", "The minimum of the value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("AverageValue", "The average of the value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("MaxValue", "The maximum of the value."));
+      Parameters.Add(new ValueLookupParameter<DataTable>("Values", "The data table to store the minimum, average and maximum of the value."));
+      Parameters.Add(new ValueLookupParameter<VariableCollection>("Results", "The results collection where the analysis values should be stored."));
+      #endregion
+
+      #region Create operators
+      MinAverageMaxValueCalculator minAverageMaxValueCalculator = new MinAverageMaxValueCalculator();
+      DataTableValuesCollector dataTableValuesCollector = new DataTableValuesCollector();
+      ResultsCollector resultsCollector = new ResultsCollector();
+
+      minAverageMaxValueCalculator.AverageValueParameter.ActualName = "AverageValue";
+      minAverageMaxValueCalculator.MaxValueParameter.ActualName = "MaxValue";
+      minAverageMaxValueCalculator.MinValueParameter.ActualName = "MinValue";
+      minAverageMaxValueCalculator.ValueParameter.ActualName = "Value";
+
+      dataTableValuesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Minimum Value", null, "MinValue"));
+      dataTableValuesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Average Value", null, "AverageValue"));
+      dataTableValuesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Maximum Value", null, "MaxValue"));
+      dataTableValuesCollector.DataTableParameter.ActualName = "Values";
+
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Minimum Value", null, "MinValue"));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Average Value", null, "AverageValue"));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Maximum Value", null, "MaxValue"));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>("Values"));
+      resultsCollector.ResultsParameter.ActualName = "Results";
+      #endregion
+
+      #region Create operator graph
+      OperatorGraph.InitialOperator = minAverageMaxValueCalculator;
+      minAverageMaxValueCalculator.Successor = dataTableValuesCollector;
+      dataTableValuesCollector.Successor = resultsCollector;
+      resultsCollector.Successor = null;
+      #endregion
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Analysis/3.3/PopulationQualityAnalyzer.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/PopulationQualityAnalyzer.cs	(revision 3623)
+++ trunk/sources/HeuristicLab.Analysis/3.3/PopulationQualityAnalyzer.cs	(revision 3623)
@@ -0,0 +1,127 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// An operator which analyzes the solution qualities in the current population.
+  /// </summary>
+  [Item("PopulationQualityAnalyzer", "An operator which analyzes the solution qualities in the current population.")]
+  [StorableClass]
+  public sealed class PopulationQualityAnalyzer : AlgorithmOperator, IPopulationAnalyzer {
+    #region Parameter properties
+    public ValueLookupParameter<BoolValue> MaximizationParameter {
+      get { return (ValueLookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    public SubScopesLookupParameter<DoubleValue> QualityParameter {
+      get { return (SubScopesLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ValueLookupParameter<DoubleValue> BestKnownQualityParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestKnownQuality"]; }
+    }
+    public ValueLookupParameter<DoubleValue> BestQualityParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestQuality"]; }
+    }
+    public ValueLookupParameter<DataTable> QualitiesParameter {
+      get { return (ValueLookupParameter<DataTable>)Parameters["Qualities"]; }
+    }
+    public ValueLookupParameter<DoubleValue> AbsoluteDifferenceBestKnownToBestParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["AbsoluteDifferenceBestKnownToBest"]; }
+    }
+    public ValueLookupParameter<PercentValue> RelativeDifferenceBestKnownToBestParameter {
+      get { return (ValueLookupParameter<PercentValue>)Parameters["RelativeDifferenceBestKnownToBest"]; }
+    }
+    public ValueLookupParameter<VariableCollection> ResultsParameter {
+      get { return (ValueLookupParameter<VariableCollection>)Parameters["Results"]; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private PopulationQualityAnalyzer(bool deserializing) : base() { }
+    public PopulationQualityAnalyzer()
+      : base() {
+      Initialize();
+    }
+
+    private void Initialize() {
+      #region Create parameters
+      Parameters.Add(new ValueLookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem, otherwise false."));
+      Parameters.Add(new SubScopesLookupParameter<DoubleValue>("Quality", "The value which represents the quality of a solution."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestKnownQuality", "The best known quality value found so far."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestQuality", "The best quality value found in the current run."));
+      Parameters.Add(new ValueLookupParameter<DataTable>("Qualities", "The data table to store the best, best known and all other quality values."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("AbsoluteDifferenceBestKnownToBest", "The absolute difference of the best known quality value to the best quality value."));
+      Parameters.Add(new ValueLookupParameter<PercentValue>("RelativeDifferenceBestKnownToBest", "The relative difference of the best known quality value to the best quality value."));
+      Parameters.Add(new ValueLookupParameter<VariableCollection>("Results", "The results collection where the analysis values should be stored."));
+      #endregion
+
+      #region Create operators
+      BestQualityMemorizer bestQualityMemorizer1 = new BestQualityMemorizer();
+      BestQualityMemorizer bestQualityMemorizer2 = new BestQualityMemorizer();
+      DataTableValuesCollector dataTableValuesCollector = new DataTableValuesCollector();
+      QualityDifferenceCalculator qualityDifferenceCalculator = new QualityDifferenceCalculator();
+      ResultsCollector resultsCollector = new ResultsCollector();
+
+      bestQualityMemorizer1.BestQualityParameter.ActualName = "BestQuality";
+      bestQualityMemorizer1.MaximizationParameter.ActualName = "Maximization";
+      bestQualityMemorizer1.QualityParameter.ActualName = "Quality";
+
+      bestQualityMemorizer2.BestQualityParameter.ActualName = "BestKnownQuality";
+      bestQualityMemorizer2.MaximizationParameter.ActualName = "Maximization";
+      bestQualityMemorizer2.QualityParameter.ActualName = "Quality";
+
+      dataTableValuesCollector.CollectedValues.Add(new SubScopesLookupParameter<DoubleValue>("Quality", null, "Quality"));
+      dataTableValuesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Best Quality", null, "BestQuality"));
+      dataTableValuesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Best Known Quality", null, "BestKnownQuality"));
+      dataTableValuesCollector.DataTableParameter.ActualName = "Qualities";
+
+      qualityDifferenceCalculator.AbsoluteDifferenceParameter.ActualName = "AbsoluteDifferenceBestKnownToBest";
+      qualityDifferenceCalculator.FirstQualityParameter.ActualName = "BestKnownQuality";
+      qualityDifferenceCalculator.RelativeDifferenceParameter.ActualName = "RelativeDifferenceBestKnownToBest";
+      qualityDifferenceCalculator.SecondQualityParameter.ActualName = "BestQuality";
+
+      resultsCollector.CollectedValues.Add(new SubScopesLookupParameter<DoubleValue>("Quality", null, "Quality"));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Best Quality", null, "BestQuality"));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Best Known Quality", null, "BestKnownQuality"));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Absolute Difference of Best Known Quality to Best Quality", null, "AbsoluteDifferenceBestKnownToBest"));
+      resultsCollector.CollectedValues.Add(new LookupParameter<PercentValue>("Relative Difference of Best Known Quality to Best Quality", null, "RelativeDifferenceBestKnownToBest"));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>("Qualities"));
+      resultsCollector.ResultsParameter.ActualName = "Results";
+      #endregion
+
+      #region Create operator graph
+      OperatorGraph.InitialOperator = bestQualityMemorizer1;
+      bestQualityMemorizer1.Successor = bestQualityMemorizer2;
+      bestQualityMemorizer2.Successor = dataTableValuesCollector;
+      dataTableValuesCollector.Successor = qualityDifferenceCalculator;
+      qualityDifferenceCalculator.Successor = resultsCollector;
+      resultsCollector.Successor = null;
+      #endregion
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Analysis/3.3/PopulationValueAnalyzer.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/PopulationValueAnalyzer.cs	(revision 3623)
+++ trunk/sources/HeuristicLab.Analysis/3.3/PopulationValueAnalyzer.cs	(revision 3623)
@@ -0,0 +1,82 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// An operator which analyzes a value in the current population.
+  /// </summary>
+  [Item("PopulationValueAnalyzer", "An operator which analyzes a value in the current population.")]
+  [StorableClass]
+  public sealed class PopulationValueAnalyzer : AlgorithmOperator, IPopulationAnalyzer {
+    #region Parameter properties
+    public SubScopesLookupParameter<DoubleValue> ValueParameter {
+      get { return (SubScopesLookupParameter<DoubleValue>)Parameters["Value"]; }
+    }
+    public ValueLookupParameter<DataTable> ValuesParameter {
+      get { return (ValueLookupParameter<DataTable>)Parameters["Values"]; }
+    }
+    public ValueLookupParameter<VariableCollection> ResultsParameter {
+      get { return (ValueLookupParameter<VariableCollection>)Parameters["Results"]; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private PopulationValueAnalyzer(bool deserializing) : base() { }
+    public PopulationValueAnalyzer()
+      : base() {
+      Initialize();
+    }
+
+    private void Initialize() {
+      #region Create parameters
+      Parameters.Add(new SubScopesLookupParameter<DoubleValue>("Value", "The value contained in each solution which should be analyzed."));
+      Parameters.Add(new ValueLookupParameter<DataTable>("Values", "The data table to store the values."));
+      Parameters.Add(new ValueLookupParameter<VariableCollection>("Results", "The results collection where the analysis values should be stored."));
+      #endregion
+
+      #region Create operators
+      DataTableValuesCollector dataTableValuesCollector = new DataTableValuesCollector();
+      ResultsCollector resultsCollector = new ResultsCollector();
+
+      dataTableValuesCollector.CollectedValues.Add(new SubScopesLookupParameter<DoubleValue>("Value", null, "Value"));
+      dataTableValuesCollector.DataTableParameter.ActualName = "Values";
+
+      resultsCollector.CollectedValues.Add(new SubScopesLookupParameter<DoubleValue>("Value", null, "Value"));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>("Values"));
+      resultsCollector.ResultsParameter.ActualName = "Results";
+      #endregion
+
+      #region Create operator graph
+      OperatorGraph.InitialOperator = dataTableValuesCollector;
+      dataTableValuesCollector.Successor = resultsCollector;
+      resultsCollector.Successor = null;
+      #endregion
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Analysis/3.3/SolutionQualityAnalyzer.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/SolutionQualityAnalyzer.cs	(revision 3623)
+++ trunk/sources/HeuristicLab.Analysis/3.3/SolutionQualityAnalyzer.cs	(revision 3623)
@@ -0,0 +1,127 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// An operator which analyzes the quality of the current solution.
+  /// </summary>
+  [Item("SolutionQualityAnalyzer", "An operator which analyzes the quality of the current solution.")]
+  [StorableClass]
+  public sealed class SolutionQualityAnalyzer : AlgorithmOperator, ISolutionAnalyzer {
+    #region Parameter properties
+    public ValueLookupParameter<BoolValue> MaximizationParameter {
+      get { return (ValueLookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    public LookupParameter<DoubleValue> QualityParameter {
+      get { return (LookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ValueLookupParameter<DoubleValue> BestKnownQualityParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestKnownQuality"]; }
+    }
+    public ValueLookupParameter<DoubleValue> BestQualityParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["BestQuality"]; }
+    }
+    public ValueLookupParameter<DataTable> QualitiesParameter {
+      get { return (ValueLookupParameter<DataTable>)Parameters["Qualities"]; }
+    }
+    public ValueLookupParameter<DoubleValue> AbsoluteDifferenceBestKnownToBestParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["AbsoluteDifferenceBestKnownToBest"]; }
+    }
+    public ValueLookupParameter<PercentValue> RelativeDifferenceBestKnownToBestParameter {
+      get { return (ValueLookupParameter<PercentValue>)Parameters["RelativeDifferenceBestKnownToBest"]; }
+    }
+    public ValueLookupParameter<VariableCollection> ResultsParameter {
+      get { return (ValueLookupParameter<VariableCollection>)Parameters["Results"]; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private SolutionQualityAnalyzer(bool deserializing) : base() { }
+    public SolutionQualityAnalyzer()
+      : base() {
+      Initialize();
+    }
+
+    private void Initialize() {
+      #region Create parameters
+      Parameters.Add(new ValueLookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem, otherwise false."));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The value which represents the quality of the solution."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestKnownQuality", "The best known quality value found so far."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("BestQuality", "The best quality value found in the current run."));
+      Parameters.Add(new ValueLookupParameter<DataTable>("Qualities", "The data table to store the current, best and best known quality value."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("AbsoluteDifferenceBestKnownToBest", "The absolute difference of the best known quality value to the best quality value."));
+      Parameters.Add(new ValueLookupParameter<PercentValue>("RelativeDifferenceBestKnownToBest", "The relative difference of the best known quality value to the best quality value."));
+      Parameters.Add(new ValueLookupParameter<VariableCollection>("Results", "The results collection where the analysis values should be stored."));
+      #endregion
+
+      #region Create operators
+      BestQualityMemorizer bestQualityMemorizer1 = new BestQualityMemorizer();
+      BestQualityMemorizer bestQualityMemorizer2 = new BestQualityMemorizer();
+      DataTableValuesCollector dataTableValuesCollector = new DataTableValuesCollector();
+      QualityDifferenceCalculator qualityDifferenceCalculator = new QualityDifferenceCalculator();
+      ResultsCollector resultsCollector = new ResultsCollector();
+
+      bestQualityMemorizer1.BestQualityParameter.ActualName = "BestQuality";
+      bestQualityMemorizer1.MaximizationParameter.ActualName = "Maximization";
+      bestQualityMemorizer1.QualityParameter.ActualName = "Quality";
+
+      bestQualityMemorizer2.BestQualityParameter.ActualName = "BestKnownQuality";
+      bestQualityMemorizer2.MaximizationParameter.ActualName = "Maximization";
+      bestQualityMemorizer2.QualityParameter.ActualName = "Quality";
+
+      dataTableValuesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Current Quality", null, "Quality"));
+      dataTableValuesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Best Quality", null, "BestQuality"));
+      dataTableValuesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Best Known Quality", null, "BestKnownQuality"));
+      dataTableValuesCollector.DataTableParameter.ActualName = "Qualities";
+
+      qualityDifferenceCalculator.AbsoluteDifferenceParameter.ActualName = "AbsoluteDifferenceBestKnownToBest";
+      qualityDifferenceCalculator.FirstQualityParameter.ActualName = "BestKnownQuality";
+      qualityDifferenceCalculator.RelativeDifferenceParameter.ActualName = "RelativeDifferenceBestKnownToBest";
+      qualityDifferenceCalculator.SecondQualityParameter.ActualName = "BestQuality";
+
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Current Quality", null, "Quality"));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Best Quality", null, "BestQuality"));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Best Known Quality", null, "BestKnownQuality"));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Absolute Difference of Best Known Quality to Best Quality", null, "AbsoluteDifferenceBestKnownToBest"));
+      resultsCollector.CollectedValues.Add(new LookupParameter<PercentValue>("Relative Difference of Best Known Quality to Best Quality", null, "RelativeDifferenceBestKnownToBest"));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>("Qualities"));
+      resultsCollector.ResultsParameter.ActualName = "Results";
+      #endregion
+
+      #region Create operator graph
+      OperatorGraph.InitialOperator = bestQualityMemorizer1;
+      bestQualityMemorizer1.Successor = bestQualityMemorizer2;
+      bestQualityMemorizer2.Successor = dataTableValuesCollector;
+      dataTableValuesCollector.Successor = qualityDifferenceCalculator;
+      qualityDifferenceCalculator.Successor = resultsCollector;
+      resultsCollector.Successor = null;
+      #endregion
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Analysis/3.3/SolutionValueAnalyzer.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/SolutionValueAnalyzer.cs	(revision 3623)
+++ trunk/sources/HeuristicLab.Analysis/3.3/SolutionValueAnalyzer.cs	(revision 3623)
@@ -0,0 +1,82 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// An operator which analyzes a value of the current solution.
+  /// </summary>
+  [Item("SolutionValueAnalyzer", "An operator which analyzes a value of the current solution.")]
+  [StorableClass]
+  public sealed class SolutionValueAnalyzer : AlgorithmOperator, ISolutionAnalyzer {
+    #region Parameter properties
+    public LookupParameter<DoubleValue> ValueParameter {
+      get { return (LookupParameter<DoubleValue>)Parameters["Value"]; }
+    }
+    public ValueLookupParameter<DataTable> ValuesParameter {
+      get { return (ValueLookupParameter<DataTable>)Parameters["Values"]; }
+    }
+    public ValueLookupParameter<VariableCollection> ResultsParameter {
+      get { return (ValueLookupParameter<VariableCollection>)Parameters["Results"]; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private SolutionValueAnalyzer(bool deserializing) : base() { }
+    public SolutionValueAnalyzer()
+      : base() {
+      Initialize();
+    }
+
+    private void Initialize() {
+      #region Create parameters
+      Parameters.Add(new LookupParameter<DoubleValue>("Value", "The value of the solution which should be analyzed."));
+      Parameters.Add(new ValueLookupParameter<DataTable>("Values", "The data table to store the value."));
+      Parameters.Add(new ValueLookupParameter<VariableCollection>("Results", "The results collection where the analysis values should be stored."));
+      #endregion
+
+      #region Create operators
+      DataTableValuesCollector dataTableValuesCollector = new DataTableValuesCollector();
+      ResultsCollector resultsCollector = new ResultsCollector();
+
+      dataTableValuesCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Value", null, "Value"));
+      dataTableValuesCollector.DataTableParameter.ActualName = "Values";
+
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Value", null, "Value"));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>("Values"));
+      resultsCollector.ResultsParameter.ActualName = "Results";
+      #endregion
+
+      #region Create operator graph
+      OperatorGraph.InitialOperator = dataTableValuesCollector;
+      dataTableValuesCollector.Successor = resultsCollector;
+      resultsCollector.Successor = null;
+      #endregion
+    }
+  }
+}
