Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification-3.4.csproj
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification-3.4.csproj	(revision 7733)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification-3.4.csproj	(revision 7734)
@@ -118,4 +118,6 @@
     <Compile Include="SingleObjective\SymbolicClassificationSingleObjectiveOverfittingAnalyzer.cs" />
     <Compile Include="SingleObjective\SymbolicClassificationSingleObjectiveValidationBestSolutionAnalyzer.cs" />
+    <Compile Include="SingleObjective\SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer.cs" />
+    <Compile Include="SingleObjective\SymbolicClassificationSingleObjectiveValidationParetoBestSolutionAnalyzer.cs" />
     <Compile Include="SymbolicDiscriminantFunctionClassificationModel.cs" />
     <Compile Include="Interfaces\ISymbolicClassificationModel.cs" />
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveProblem.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveProblem.cs	(revision 7733)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveProblem.cs	(revision 7734)
@@ -76,4 +76,6 @@
       Operators.Add(new SymbolicClassificationSingleObjectiveValidationBestSolutionAnalyzer());
       Operators.Add(new SymbolicClassificationSingleObjectiveOverfittingAnalyzer());
+      Operators.Add(new SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer());
+      Operators.Add(new SymbolicClassificationSingleObjectiveValidationParetoBestSolutionAnalyzer());
       ParameterizeOperators();
     }
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer.cs	(revision 7734)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer.cs	(revision 7734)
@@ -0,0 +1,83 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Classification {
+  /// <summary>
+  /// An operator that collects the training Pareto-best symbolic classificatino solutions for single objective symbolic classificatino problems.
+  /// </summary>
+  [Item("SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer", "An operator that collects the training Pareto-best symbolic classification solutions for single objective symbolic classification problems.")]
+  [StorableClass]
+  public sealed class SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer : SymbolicDataAnalysisSingleObjectiveTrainingParetoBestSolutionAnalyzer<ISymbolicClassificationSolution>,
+  ISymbolicDataAnalysisInterpreterOperator, ISymbolicDataAnalysisBoundedOperator {
+    private const string ProblemDataParameterName = "ProblemData";
+    private const string SymbolicDataAnalysisTreeInterpreterParameterName = "SymbolicDataAnalysisTreeInterpreter";
+    private const string EstimationLimitsParameterName = "EstimationLimits";
+    private const string ApplyLinearScalingParameterName = "ApplyLinearScaling";
+    #region parameter properties
+    public ILookupParameter<IClassificationProblemData> ProblemDataParameter {
+      get { return (ILookupParameter<IClassificationProblemData>)Parameters[ProblemDataParameterName]; }
+    }
+    public ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter> SymbolicDataAnalysisTreeInterpreterParameter {
+      get { return (ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>)Parameters[SymbolicDataAnalysisTreeInterpreterParameterName]; }
+    }
+    public IValueLookupParameter<DoubleLimit> EstimationLimitsParameter {
+      get { return (IValueLookupParameter<DoubleLimit>)Parameters[EstimationLimitsParameterName]; }
+    }
+    public IValueParameter<BoolValue> ApplyLinearScalingParameter {
+      get { return (IValueParameter<BoolValue>)Parameters[ApplyLinearScalingParameterName]; }
+    }
+    #endregion
+
+    #region properties
+    public BoolValue ApplyLinearScaling {
+      get { return ApplyLinearScalingParameter.Value; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer(bool deserializing) : base(deserializing) { }
+    private SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer(SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<IClassificationProblemData>(ProblemDataParameterName, "The problem data for the symbolic classification solution."));
+      Parameters.Add(new LookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>(SymbolicDataAnalysisTreeInterpreterParameterName, "The symbolic data analysis tree interpreter for the symbolic expression tree."));
+      Parameters.Add(new ValueLookupParameter<DoubleLimit>(EstimationLimitsParameterName, "The lower and upper limit for the estimated values produced by the symbolic classification model."));
+      Parameters.Add(new ValueParameter<BoolValue>(ApplyLinearScalingParameterName, "Flag that indicates if the produced symbolic classification solution should be linearly scaled.", new BoolValue(false)));
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer(this, cloner);
+    }
+
+    protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree) {
+      var model = new SymbolicDiscriminantFunctionClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
+      if (ApplyLinearScaling.Value)
+        SymbolicDiscriminantFunctionClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
+      return new SymbolicDiscriminantFunctionClassificationSolution(model, (IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveValidationParetoBestSolutionAnalyzer.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveValidationParetoBestSolutionAnalyzer.cs	(revision 7734)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveValidationParetoBestSolutionAnalyzer.cs	(revision 7734)
@@ -0,0 +1,73 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Classification {
+  /// <summary>
+  /// An operator that collects the validation Pareto-best symbolic classification solutions for single objective symbolic classification problems.
+  /// </summary>
+  [Item("SymbolicClassificationSingleObjectiveValidationParetoBestSolutionAnalyzer", "An operator that collects the validation Pareto-best symbolic classification solutions for single objective symbolic classification problems.")]
+  [StorableClass]
+  public sealed class SymbolicClassificationSingleObjectiveValidationParetoBestSolutionAnalyzer : SymbolicDataAnalysisSingleObjectiveValidationParetoBestSolutionAnalyzer<ISymbolicClassificationSolution, ISymbolicClassificationSingleObjectiveEvaluator, IClassificationProblemData>,
+  ISymbolicDataAnalysisInterpreterOperator, ISymbolicDataAnalysisBoundedOperator {
+    private const string EstimationLimitsParameterName = "EstimationLimits";
+    private const string ApplyLinearScalingParameterName = "ApplyLinearScaling";
+    #region parameter properties
+    public IValueLookupParameter<DoubleLimit> EstimationLimitsParameter {
+      get { return (IValueLookupParameter<DoubleLimit>)Parameters[EstimationLimitsParameterName]; }
+    }
+    public IValueParameter<BoolValue> ApplyLinearScalingParameter {
+      get { return (IValueParameter<BoolValue>)Parameters[ApplyLinearScalingParameterName]; }
+    }
+    #endregion
+
+    #region properties
+    public BoolValue ApplyLinearScaling {
+      get { return ApplyLinearScalingParameter.Value; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private SymbolicClassificationSingleObjectiveValidationParetoBestSolutionAnalyzer(bool deserializing) : base(deserializing) { }
+    private SymbolicClassificationSingleObjectiveValidationParetoBestSolutionAnalyzer(SymbolicClassificationSingleObjectiveValidationParetoBestSolutionAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public SymbolicClassificationSingleObjectiveValidationParetoBestSolutionAnalyzer()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<DoubleLimit>(EstimationLimitsParameterName, "The lower and upper limit for the estimated values produced by the symbolic classification model."));
+      Parameters.Add(new ValueParameter<BoolValue>(ApplyLinearScalingParameterName, "Flag that indicates if the produced symbolic classification solution should be linearly scaled.", new BoolValue(false)));
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SymbolicClassificationSingleObjectiveValidationParetoBestSolutionAnalyzer(this, cloner);
+    }
+
+    protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree) {
+      var model = new SymbolicDiscriminantFunctionClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
+      if (ApplyLinearScaling.Value)
+        SymbolicDiscriminantFunctionClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
+      return new SymbolicDiscriminantFunctionClassificationSolution(model, (IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4.csproj
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4.csproj	(revision 7733)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4.csproj	(revision 7734)
@@ -114,4 +114,5 @@
     <Compile Include="MultiObjective\SymbolicRegressionMultiObjectiveValidationBestSolutionAnalyzer.cs" />
     <Compile Include="Plugin.cs" />
+    <Compile Include="SingleObjective\SymbolicRegressionSingleObjectiveValidationParetoBestSolutionAnalyzer.cs" />
     <Compile Include="SingleObjective\SymbolicRegressionSingleObjectiveTrainingParetoBestSolutionAnalyzer.cs" />
     <Compile Include="SingleObjective\Evaluators\SymbolicRegressionSingleObjectiveMaxAbsoluteErrorEvaluator.cs" />
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/SymbolicRegressionSingleObjectiveProblem.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/SymbolicRegressionSingleObjectiveProblem.cs	(revision 7733)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/SymbolicRegressionSingleObjectiveProblem.cs	(revision 7734)
@@ -79,4 +79,5 @@
       Operators.Add(new SymbolicRegressionSingleObjectiveOverfittingAnalyzer());
       Operators.Add(new SymbolicRegressionSingleObjectiveTrainingParetoBestSolutionAnalyzer());
+      Operators.Add(new SymbolicRegressionSingleObjectiveValidationParetoBestSolutionAnalyzer());
 
       ParameterizeOperators();
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/SymbolicRegressionSingleObjectiveValidationParetoBestSolutionAnalyzer.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/SymbolicRegressionSingleObjectiveValidationParetoBestSolutionAnalyzer.cs	(revision 7734)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/SymbolicRegressionSingleObjectiveValidationParetoBestSolutionAnalyzer.cs	(revision 7734)
@@ -0,0 +1,73 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
+  /// <summary>
+  /// An operator that collects the validation Pareto-best symbolic regression solutions for single objective symbolic regression problems.
+  /// </summary>
+  [Item("SymbolicRegressionSingleObjectiveValidationParetoBestSolutionAnalyzer", "An operator that collects the validation Pareto-best symbolic regression solutions for single objective symbolic regression problems.")]
+  [StorableClass]
+  public sealed class SymbolicRegressionSingleObjectiveValidationParetoBestSolutionAnalyzer : SymbolicDataAnalysisSingleObjectiveValidationParetoBestSolutionAnalyzer<ISymbolicRegressionSolution, ISymbolicRegressionSingleObjectiveEvaluator, IRegressionProblemData>,
+  ISymbolicDataAnalysisInterpreterOperator, ISymbolicDataAnalysisBoundedOperator {
+    private const string EstimationLimitsParameterName = "EstimationLimits";
+    private const string ApplyLinearScalingParameterName = "ApplyLinearScaling";
+    #region parameter properties
+    public IValueLookupParameter<DoubleLimit> EstimationLimitsParameter {
+      get { return (IValueLookupParameter<DoubleLimit>)Parameters[EstimationLimitsParameterName]; }
+    }
+    public IValueParameter<BoolValue> ApplyLinearScalingParameter {
+      get { return (IValueParameter<BoolValue>)Parameters[ApplyLinearScalingParameterName]; }
+    }
+    #endregion
+
+    #region properties
+    public BoolValue ApplyLinearScaling {
+      get { return ApplyLinearScalingParameter.Value; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private SymbolicRegressionSingleObjectiveValidationParetoBestSolutionAnalyzer(bool deserializing) : base(deserializing) { }
+    private SymbolicRegressionSingleObjectiveValidationParetoBestSolutionAnalyzer(SymbolicRegressionSingleObjectiveValidationParetoBestSolutionAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public SymbolicRegressionSingleObjectiveValidationParetoBestSolutionAnalyzer()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<DoubleLimit>(EstimationLimitsParameterName, "The lower and upper limit for the estimated values produced by the symbolic regression model."));
+      Parameters.Add(new ValueParameter<BoolValue>(ApplyLinearScalingParameterName, "Flag that indicates if the produced symbolic regression solution should be linearly scaled.", new BoolValue(true)));
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SymbolicRegressionSingleObjectiveValidationParetoBestSolutionAnalyzer(this, cloner);
+    }
+
+    protected override ISymbolicRegressionSolution CreateSolution(ISymbolicExpressionTree bestTree) {
+      var model = new SymbolicRegressionModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
+      if (ApplyLinearScaling.Value)
+        SymbolicRegressionModel.Scale(model, ProblemDataParameter.ActualValue);
+      return new SymbolicRegressionSolution(model, (IRegressionProblemData)ProblemDataParameter.ActualValue.Clone());
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveTrainingParetoBestSolutionAnalyzer.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveTrainingParetoBestSolutionAnalyzer.cs	(revision 7733)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveTrainingParetoBestSolutionAnalyzer.cs	(revision 7734)
@@ -36,5 +36,5 @@
   /// An operator that collects the Pareto-best symbolic data analysis solutions for single objective symbolic data analysis problems.
   /// </summary>
-  [Item("SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionAnalyzer", "An operator that analyzes the training best symbolic data analysis solution for multi objective symbolic data analysis problems.")]
+  [Item("SymbolicDataAnalysisSingleObjectiveTrainingParetoBestSolutionAnalyzer", "An operator that analyzes the Pareto-best symbolic data analysis solution for single objective symbolic data analysis problems.")]
   [StorableClass]
   public abstract class SymbolicDataAnalysisSingleObjectiveTrainingParetoBestSolutionAnalyzer<T> : SymbolicDataAnalysisSingleObjectiveAnalyzer
@@ -43,4 +43,8 @@
     private const string TrainingBestSolutionQualitiesParameterName = "Best training solution qualities";
     private const string ComplexityParameterName = "Complexity";
+
+    public override bool EnabledByDefault {
+      get { return false; }
+    }
 
     #region parameter properties
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveValidationParetoBestSolutionAnalyzer.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveValidationParetoBestSolutionAnalyzer.cs	(revision 7734)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveValidationParetoBestSolutionAnalyzer.cs	(revision 7734)
@@ -0,0 +1,214 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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 System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using System;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  /// <summary>
+  /// An operator that collects the Pareto-best symbolic data analysis solutions for single objective symbolic data analysis problems.
+  /// </summary>
+  [Item("SymbolicDataAnalysisSingleObjectiveValidationParetoBestSolutionAnalyzer", "An operator that analyzes the Pareto-best symbolic data analysis solution for single objective symbolic data analysis problems.")]
+  [StorableClass]
+  public abstract class SymbolicDataAnalysisSingleObjectiveValidationParetoBestSolutionAnalyzer<S, T, U> : SymbolicDataAnalysisSingleObjectiveValidationAnalyzer<T, U>
+    where S : class, ISymbolicDataAnalysisSolution
+    where T : class, ISymbolicDataAnalysisSingleObjectiveEvaluator<U>
+    where U : class, IDataAnalysisProblemData {
+    private const string ValidationBestSolutionsParameterName = "Best validation solutions";
+    private const string ValidationBestSolutionQualitiesParameterName = "Best validation solution qualities";
+    private const string ComplexityParameterName = "Complexity";
+
+    public override bool EnabledByDefault {
+      get { return false; }
+    }
+
+    #region parameter properties
+    public ILookupParameter<ItemList<S>> ValidationBestSolutionsParameter {
+      get { return (ILookupParameter<ItemList<S>>)Parameters[ValidationBestSolutionsParameterName]; }
+    }
+    public ILookupParameter<ItemList<DoubleArray>> ValidationBestSolutionQualitiesParameter {
+      get { return (ILookupParameter<ItemList<DoubleArray>>)Parameters[ValidationBestSolutionQualitiesParameterName]; }
+    }
+    public IScopeTreeLookupParameter<DoubleValue> ComplexityParameter {
+      get { return (IScopeTreeLookupParameter<DoubleValue>)Parameters[ComplexityParameterName]; }
+    }
+    #endregion
+    #region properties
+    public ItemList<S> ValidationBestSolutions {
+      get { return ValidationBestSolutionsParameter.ActualValue; }
+      set { ValidationBestSolutionsParameter.ActualValue = value; }
+    }
+    public ItemList<DoubleArray> ValidationBestSolutionQualities {
+      get { return ValidationBestSolutionQualitiesParameter.ActualValue; }
+      set { ValidationBestSolutionQualitiesParameter.ActualValue = value; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected SymbolicDataAnalysisSingleObjectiveValidationParetoBestSolutionAnalyzer(bool deserializing) : base(deserializing) { }
+    protected SymbolicDataAnalysisSingleObjectiveValidationParetoBestSolutionAnalyzer(SymbolicDataAnalysisSingleObjectiveValidationParetoBestSolutionAnalyzer<S, T, U> original, Cloner cloner) : base(original, cloner) { }
+    public SymbolicDataAnalysisSingleObjectiveValidationParetoBestSolutionAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<ItemList<S>>(ValidationBestSolutionsParameterName, "The validation best (Pareto-optimal) symbolic data analysis solutions."));
+      Parameters.Add(new LookupParameter<ItemList<DoubleArray>>(ValidationBestSolutionQualitiesParameterName, "The qualities of the validation best (Pareto-optimal) solutions."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>(ComplexityParameterName, "The complexity of each tree."));
+    }
+
+    public override IOperation Apply() {
+      IEnumerable<int> rows = GenerateRowsToEvaluate();
+      if (!rows.Any()) return base.Apply();
+
+      #region find best tree
+      var evaluator = EvaluatorParameter.ActualValue;
+      var problemData = ProblemDataParameter.ActualValue;
+      ISymbolicExpressionTree[] tree = SymbolicExpressionTree.ToArray();
+
+      // sort is ascending and we take the first n% => order so that best solutions are smallest
+      // sort order is determined by maximization parameter
+      double[] trainingQuality;
+      if (Maximization.Value) {
+        // largest values must be sorted first
+        trainingQuality = Quality.Select(x => -x.Value).ToArray();
+      } else {
+        // smallest values must be sorted first
+        trainingQuality = Quality.Select(x => x.Value).ToArray();
+      }
+
+      int[] treeIndexes = Enumerable.Range(0, tree.Length).ToArray();
+
+      // sort trees by training qualities
+      Array.Sort(trainingQuality, treeIndexes);
+
+      // number of best training solutions to validate (at least 1)
+      int topN = (int)Math.Max(tree.Length * PercentageOfBestSolutionsParameter.ActualValue.Value, 1);
+
+      IExecutionContext childContext = (IExecutionContext)ExecutionContext.CreateChildOperation(evaluator);
+      // evaluate best n training trees on validiation set
+      var qualities = treeIndexes
+        .Select(i => tree[i])
+        .Take(topN)
+        .AsParallel()
+        .Select(t => evaluator.Evaluate(childContext, t, problemData, rows))
+        .ToArray();
+      #endregion
+
+      var results = ResultCollection;
+      // create empty parameter and result values
+      if (ValidationBestSolutions == null) {
+        ValidationBestSolutions = new ItemList<S>();
+        ValidationBestSolutionQualities = new ItemList<DoubleArray>();
+        results.Add(new Result(ValidationBestSolutionQualitiesParameter.Name, ValidationBestSolutionQualitiesParameter.Description, ValidationBestSolutionQualities));
+        results.Add(new Result(ValidationBestSolutionsParameter.Name, ValidationBestSolutionsParameter.Description, ValidationBestSolutions));
+      }
+
+      IList<Tuple<double, double>> validationBestQualities = ValidationBestSolutionQualities
+        .Select(x => Tuple.Create(x[0], x[1]))
+        .ToList();
+
+      #region find best trees
+      IList<int> nonDominatedIndexes = new List<int>();
+
+      List<double> complexities;
+      if (ComplexityParameter.ActualValue != null) {
+        complexities = ComplexityParameter.ActualValue.Select(x => x.Value).ToList();
+      } else {
+        complexities = tree.Select(t => (double)t.Length).ToList();
+      }
+      List<Tuple<double, double>> fitness = new List<Tuple<double, double>>();
+      for (int i = 0; i < qualities.Length; i++)
+        fitness.Add(Tuple.Create(qualities[i], complexities[treeIndexes[i]]));
+
+      var maximization = Tuple.Create(Maximization.Value, false); // complexity must be minimized
+      List<Tuple<double, double>> newNonDominatedQualities = new List<Tuple<double, double>>();
+      for (int i = 0; i < fitness.Count; i++) {
+        if (IsNonDominated(fitness[i], validationBestQualities, maximization) &&
+          IsNonDominated(fitness[i], newNonDominatedQualities, maximization) &&
+          IsNonDominated(fitness[i], fitness.Skip(i + 1), maximization)) {
+          if (!newNonDominatedQualities.Contains(fitness[i])) {
+            newNonDominatedQualities.Add(fitness[i]);
+            nonDominatedIndexes.Add(i);
+          }
+        }
+      }
+      #endregion
+
+      #region update Pareto-optimal solution archive
+      if (nonDominatedIndexes.Count > 0) {
+        ItemList<DoubleArray> nonDominatedQualities = new ItemList<DoubleArray>();
+        ItemList<S> nonDominatedSolutions = new ItemList<S>();
+        // add all new non-dominated solutions to the archive
+        foreach (var index in nonDominatedIndexes) {
+          S solution = CreateSolution(tree[treeIndexes[index]]);
+          nonDominatedSolutions.Add(solution);
+          nonDominatedQualities.Add(new DoubleArray(new double[] { fitness[index].Item1, fitness[index].Item2 }));
+        }
+        // add old non-dominated solutions only if they are not dominated by one of the new solutions
+        for (int i = 0; i < validationBestQualities.Count; i++) {
+          if (IsNonDominated(validationBestQualities[i], newNonDominatedQualities, maximization)) {
+            if (!newNonDominatedQualities.Contains(validationBestQualities[i])) {
+              nonDominatedSolutions.Add(ValidationBestSolutions[i]);
+              nonDominatedQualities.Add(ValidationBestSolutionQualities[i]);
+            }
+          }
+        }
+
+        // make sure solutions and qualities are ordered in the results
+        var orderedIndexes =
+          nonDominatedSolutions.Select((s, i) => i).OrderBy(i => nonDominatedQualities[i][0]).ToArray();
+
+        var orderedNonDominatedSolutions = new ItemList<S>();
+        var orderedNonDominatedQualities = new ItemList<DoubleArray>();
+        foreach (var i in orderedIndexes) {
+          orderedNonDominatedQualities.Add(nonDominatedQualities[i]);
+          orderedNonDominatedSolutions.Add(nonDominatedSolutions[i]);
+        }
+
+        ValidationBestSolutions = orderedNonDominatedSolutions;
+        ValidationBestSolutionQualities = orderedNonDominatedQualities;
+
+        results[ValidationBestSolutionsParameter.Name].Value = orderedNonDominatedSolutions;
+        results[ValidationBestSolutionQualitiesParameter.Name].Value = orderedNonDominatedQualities;
+      }
+      #endregion
+      return base.Apply();
+    }
+
+    protected abstract S CreateSolution(ISymbolicExpressionTree bestTree);
+
+    private bool IsNonDominated(Tuple<double, double> point, IEnumerable<Tuple<double, double>> points, Tuple<bool, bool> maximization) {
+      return !points.Any(p => IsBetterOrEqual(p.Item1, point.Item1, maximization.Item1) &&
+                             IsBetterOrEqual(p.Item2, point.Item2, maximization.Item2));
+    }
+    private bool IsBetterOrEqual(double lhs, double rhs, bool maximization) {
+      if (maximization) return lhs >= rhs;
+      else return lhs <= rhs;
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 7733)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 7734)
@@ -111,4 +111,5 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="Analyzers\SymbolicDataAnalysisSingleObjectiveValidationParetoBestSolutionAnalyzer.cs" />
     <Compile Include="Analyzers\SymbolicDataAnalysisComplexityAnalyzer.cs" />
     <Compile Include="Analyzers\SymbolicDataAnalysisSingleObjectiveTrainingParetoBestSolutionAnalyzer.cs" />
