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 10468)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification-3.4.csproj	(revision 10469)
@@ -150,4 +150,5 @@
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="SymbolicClassificationPruningOperator.cs" />
     <None Include="HeuristicLab.snk" />
     <None Include="Plugin.cs.frame" />
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationPruningAnalyzer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationPruningAnalyzer.cs	(revision 10468)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationPruningAnalyzer.cs	(revision 10469)
@@ -20,8 +20,6 @@
 #endregion
 
-using System;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
@@ -31,17 +29,6 @@
   [StorableClass]
   public sealed class SymbolicClassificationPruningAnalyzer : SymbolicDataAnalysisSingleObjectivePruningAnalyzer {
-    private const string ModelCreatorParameterName = "ModelCreator";
-    #region parameter properties
-    public ILookupParameter<ISymbolicClassificationModelCreator> ModelCreatorParameter {
-      get { return (ILookupParameter<ISymbolicClassificationModelCreator>)Parameters[ModelCreatorParameterName]; }
-    }
-    #endregion
-    #region properties
-    private ISymbolicClassificationModelCreator ModelCreator {
-      get { return ModelCreatorParameter.ActualValue; }
-      set { ModelCreatorParameter.ActualValue = value; }
-    }
-    #endregion
-
+    private const string ImpactValuesCalculatorParameterName = "ImpactValuesCalculator";
+    private const string PruningOperatorParameterName = "PruningOperator";
     private SymbolicClassificationPruningAnalyzer(SymbolicClassificationPruningAnalyzer original, Cloner cloner)
       : base(original, cloner) {
@@ -55,15 +42,6 @@
 
     public SymbolicClassificationPruningAnalyzer() {
-      // pruning parameters
-      Parameters.Add(new LookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName));
-      impactValuesCalculator = new SymbolicClassificationSolutionImpactValuesCalculator();
-    }
-
-    protected override ISymbolicDataAnalysisModel CreateModel(ISymbolicExpressionTree tree,
-      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, double lowerEstimationLimit = Double.MinValue,
-      double upperEstimationLimit = Double.MaxValue) {
-      var model = ModelCreator.CreateSymbolicClassificationModel(tree, Interpreter, lowerEstimationLimit, upperEstimationLimit);
-      model.RecalculateModelParameters((IClassificationProblemData)ProblemData, ProblemData.TrainingIndices);
-      return model;
+      Parameters.Add(new ValueParameter<SymbolicDataAnalysisSolutionImpactValuesCalculator>(ImpactValuesCalculatorParameterName, "The impact values calculator", new SymbolicClassificationSolutionImpactValuesCalculator()));
+      Parameters.Add(new ValueParameter<SymbolicDataAnalysisExpressionPruningOperator>(PruningOperatorParameterName, "The operator used to prune trees", new SymbolicClassificationPruningOperator()));
     }
   }
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationPruningOperator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationPruningOperator.cs	(revision 10469)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationPruningOperator.cs	(revision 10469)
@@ -0,0 +1,65 @@
+﻿using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Classification {
+  [StorableClass]
+  [Item("SymbolicClassificationPruningOperator", "An operator which prunes symbolic classificaton trees.")]
+  public class SymbolicClassificationPruningOperator : SymbolicDataAnalysisExpressionPruningOperator {
+    private const string ImpactValuesCalculatorParameterName = "ImpactValuesCalculator";
+    private const string ModelCreatorParameterName = "ModelCreator";
+    private const string ApplyLinearScalingParmameterName = "ApplyLinearScaling";
+
+    #region parameter properties
+    public ILookupParameter<ISymbolicClassificationModelCreator> ModelCreatorParameter {
+      get { return (ILookupParameter<ISymbolicClassificationModelCreator>)Parameters[ModelCreatorParameterName]; }
+    }
+
+    public ILookupParameter<BoolValue> ApplyLinearScalingParameter {
+      get { return (ILookupParameter<BoolValue>)Parameters[ApplyLinearScalingParmameterName]; }
+    }
+    #endregion
+    #region properties
+    private ISymbolicClassificationModelCreator ModelCreator { get { return ModelCreatorParameter.ActualValue; } }
+    private BoolValue ApplyLinearScaling { get { return ApplyLinearScalingParameter.ActualValue; } }
+    #endregion
+
+    protected SymbolicClassificationPruningOperator(SymbolicClassificationPruningOperator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SymbolicClassificationPruningOperator(this, cloner);
+    }
+
+    [StorableConstructor]
+    protected SymbolicClassificationPruningOperator(bool deserializing) : base(deserializing) { }
+
+    public SymbolicClassificationPruningOperator() {
+      Parameters.Add(new ValueParameter<ISymbolicDataAnalysisSolutionImpactValuesCalculator>(ImpactValuesCalculatorParameterName, new SymbolicClassificationSolutionImpactValuesCalculator()));
+      Parameters.Add(new LookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName));
+    }
+
+    protected override ISymbolicDataAnalysisModel CreateModel() {
+      var model = ModelCreator.CreateSymbolicClassificationModel(SymbolicExpressionTree, Interpreter, EstimationLimits.Lower, EstimationLimits.Upper);
+      var rows = Enumerable.Range(FitnessCalculationPartition.Start, FitnessCalculationPartition.Size);
+      var problemData = (IClassificationProblemData)ProblemData;
+      model.RecalculateModelParameters(problemData, rows);
+      return model;
+    }
+
+    protected override double Evaluate(IDataAnalysisModel model) {
+      var classificationModel = (IClassificationModel)model;
+      var classificationProblemData = (IClassificationProblemData)ProblemData;
+      var trainingIndices = ProblemData.TrainingIndices.ToList();
+      var estimatedValues = classificationModel.GetEstimatedClassValues(ProblemData.Dataset, trainingIndices);
+      var targetValues = ProblemData.Dataset.GetDoubleValues(classificationProblemData.TargetVariable, trainingIndices);
+      OnlineCalculatorError errorState;
+      var quality = OnlinePearsonsRSquaredCalculator.Calculate(targetValues, estimatedValues, out errorState);
+      if (errorState != OnlineCalculatorError.None) return double.NaN;
+      return quality;
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationSolutionImpactValuesCalculator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationSolutionImpactValuesCalculator.cs	(revision 10468)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationSolutionImpactValuesCalculator.cs	(revision 10469)
@@ -20,10 +20,24 @@
 #endregion
 
+using System;
 using System.Collections.Generic;
 using HeuristicLab.Common;
+using HeuristicLab.Core;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Classification {
+  [StorableClass]
+  [Item("SymbolicClassificationSolutionImpactValuesCalculator", "Calculate symbolic expression tree node impact values for classification problems.")]
   public class SymbolicClassificationSolutionImpactValuesCalculator : SymbolicDataAnalysisSolutionImpactValuesCalculator {
+    public SymbolicClassificationSolutionImpactValuesCalculator() { }
+    protected SymbolicClassificationSolutionImpactValuesCalculator(SymbolicClassificationSolutionImpactValuesCalculator original, Cloner cloner)
+      : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SymbolicClassificationSolutionImpactValuesCalculator(this, cloner);
+    }
+    [StorableConstructor]
+    protected SymbolicClassificationSolutionImpactValuesCalculator(bool deserializing) : base(deserializing) { }
+
     public override double CalculateReplacementValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows) {
       var classificationModel = (ISymbolicClassificationModel)model;
@@ -34,4 +48,12 @@
 
     public override double CalculateImpactValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, double originalQuality = double.NaN) {
+      double impactValue, replacementValue;
+      CalculateImpactAndReplacementValues(model, node, problemData, rows, out impactValue, out replacementValue, originalQuality);
+      return impactValue;
+    }
+
+    public override void CalculateImpactAndReplacementValues(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node,
+      IDataAnalysisProblemData problemData, IEnumerable<int> rows, out double impactValue, out double replacementValue,
+      double originalQuality = Double.NaN) {
       var classificationModel = (ISymbolicClassificationModel)model;
       var classificationProblemData = (IClassificationProblemData)problemData;
@@ -47,5 +69,5 @@
       }
 
-      var replacementValue = CalculateReplacementValue(classificationModel, node, classificationProblemData, rows);
+      replacementValue = CalculateReplacementValue(classificationModel, node, classificationProblemData, rows);
       var constantNode = new ConstantTreeNode(new Constant()) { Value = replacementValue };
 
@@ -63,7 +85,6 @@
       if (errorState != OnlineCalculatorError.None) newQuality = 0.0;
 
-      return originalQuality - newQuality;
+      impactValue = originalQuality - newQuality;
     }
-
   }
 }
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 10468)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4.csproj	(revision 10469)
@@ -120,7 +120,7 @@
     <Compile Include="Plugin.cs" />
     <Compile Include="SingleObjective\ConstantOptimizationAnalyzer.cs" />
-    <Compile Include="SingleObjective\Evaluators\SymbolicRegressionMeanRelativeErrorEvaluator.cs" />    
-	<Compile Include="SymbolicRegressionPruningAnalyzer.cs" />    
-	<Compile Include="SingleObjective\SymbolicRegressionSingleObjectiveValidationParetoBestSolutionAnalyzer.cs" />
+    <Compile Include="SingleObjective\Evaluators\SymbolicRegressionMeanRelativeErrorEvaluator.cs" />
+    <Compile Include="SymbolicRegressionPruningAnalyzer.cs" />
+    <Compile Include="SingleObjective\SymbolicRegressionSingleObjectiveValidationParetoBestSolutionAnalyzer.cs" />
     <Compile Include="SingleObjective\SymbolicRegressionSingleObjectiveTrainingParetoBestSolutionAnalyzer.cs" />
     <Compile Include="SingleObjective\Evaluators\SymbolicRegressionSingleObjectiveMaxAbsoluteErrorEvaluator.cs" />
@@ -145,4 +145,5 @@
     <Compile Include="SingleObjective\Evaluators\SymbolicRegressionSingleObjectiveMeanSquaredErrorEvaluator.cs" />
     <Compile Include="SingleObjective\Evaluators\SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.cs" />
+    <Compile Include="SymbolicRegressionPruningOperator.cs" />
     <Compile Include="SymbolicRegressionSolution.cs" />
     <Compile Include="SymbolicRegressionSolutionImpactValuesCalculator.cs" />
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionPruningAnalyzer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionPruningAnalyzer.cs	(revision 10468)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionPruningAnalyzer.cs	(revision 10469)
@@ -1,6 +1,28 @@
-﻿using System;
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) 2002-2014 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.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
@@ -9,4 +31,6 @@
   [StorableClass]
   public sealed class SymbolicRegressionPruningAnalyzer : SymbolicDataAnalysisSingleObjectivePruningAnalyzer {
+    private const string ImpactValuesCalculatorParameterName = "ImpactValuesCalculator";
+    private const string PruningOperatorParameterName = "PruningOperator";
     private SymbolicRegressionPruningAnalyzer(SymbolicRegressionPruningAnalyzer original, Cloner cloner)
       : base(original, cloner) {
@@ -20,11 +44,6 @@
 
     public SymbolicRegressionPruningAnalyzer() {
-      impactValuesCalculator = new SymbolicRegressionSolutionImpactValuesCalculator();
-    }
-
-    protected override ISymbolicDataAnalysisModel CreateModel(ISymbolicExpressionTree tree,
-      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, double lowerEstimationLimit = Double.MinValue,
-      double upperEstimationLimit = Double.MaxValue) {
-      return new SymbolicRegressionModel(tree, interpreter, lowerEstimationLimit, upperEstimationLimit);
+      Parameters.Add(new ValueParameter<SymbolicDataAnalysisSolutionImpactValuesCalculator>(ImpactValuesCalculatorParameterName, "The impact values calculator", new SymbolicRegressionSolutionImpactValuesCalculator()));
+      Parameters.Add(new ValueParameter<SymbolicDataAnalysisExpressionPruningOperator>(PruningOperatorParameterName, "The operator used to prune trees", new SymbolicRegressionPruningOperator()));
     }
   }
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionPruningOperator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionPruningOperator.cs	(revision 10469)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionPruningOperator.cs	(revision 10469)
@@ -0,0 +1,52 @@
+﻿using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
+  [StorableClass]
+  [Item("SymbolicRegressionPruningOperator", "An operator which prunes symbolic regression trees.")]
+  public class SymbolicRegressionPruningOperator : SymbolicDataAnalysisExpressionPruningOperator {
+    private const string ImpactValuesCalculatorParameterName = "ImpactValuesCalculator";
+    private const string ImpactValuesCalculatorParameterDescription = "The impact values calculator to be used for figuring out the node impacts.";
+
+    private const string EvaluatorParameterName = "Evaluator";
+
+    public ILookupParameter<ISymbolicRegressionSingleObjectiveEvaluator> EvaluatorParameter {
+      get { return (ILookupParameter<ISymbolicRegressionSingleObjectiveEvaluator>)Parameters[EvaluatorParameterName]; }
+    }
+
+    protected SymbolicRegressionPruningOperator(SymbolicRegressionPruningOperator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SymbolicRegressionPruningOperator(this, cloner);
+    }
+
+    [StorableConstructor]
+    protected SymbolicRegressionPruningOperator(bool deserializing) : base(deserializing) { }
+
+    public SymbolicRegressionPruningOperator() {
+      var impactValuesCalculator = new SymbolicRegressionSolutionImpactValuesCalculator();
+      Parameters.Add(new ValueParameter<ISymbolicDataAnalysisSolutionImpactValuesCalculator>(ImpactValuesCalculatorParameterName, ImpactValuesCalculatorParameterDescription, impactValuesCalculator));
+      Parameters.Add(new LookupParameter<ISymbolicRegressionSingleObjectiveEvaluator>(EvaluatorParameterName));
+    }
+
+    protected override ISymbolicDataAnalysisModel CreateModel() {
+      return new SymbolicRegressionModel(SymbolicExpressionTree, Interpreter, EstimationLimits.Lower, EstimationLimits.Upper);
+    }
+
+    protected override double Evaluate(IDataAnalysisModel model) {
+      var regressionModel = (IRegressionModel)model;
+      var regressionProblemData = (IRegressionProblemData)ProblemData;
+      var trainingIndices = ProblemData.TrainingIndices.ToList();
+      var estimatedValues = regressionModel.GetEstimatedValues(ProblemData.Dataset, trainingIndices); // also bounds the values
+      var targetValues = ProblemData.Dataset.GetDoubleValues(regressionProblemData.TargetVariable, trainingIndices);
+      OnlineCalculatorError errorState;
+      var quality = OnlinePearsonsRSquaredCalculator.Calculate(targetValues, estimatedValues, out errorState);
+      if (errorState != OnlineCalculatorError.None) return double.NaN;
+      return quality;
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionSolutionImpactValuesCalculator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionSolutionImpactValuesCalculator.cs	(revision 10468)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionSolutionImpactValuesCalculator.cs	(revision 10469)
@@ -20,10 +20,25 @@
 #endregion
 
+using System;
 using System.Collections.Generic;
 using HeuristicLab.Common;
+using HeuristicLab.Core;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
+  [StorableClass]
+  [Item("SymbolicRegressionSolutionImpactValuesCalculator", "Calculate symbolic expression tree node impact values for regression problems.")]
   public class SymbolicRegressionSolutionImpactValuesCalculator : SymbolicDataAnalysisSolutionImpactValuesCalculator {
+    public SymbolicRegressionSolutionImpactValuesCalculator() { }
+
+    protected SymbolicRegressionSolutionImpactValuesCalculator(SymbolicRegressionSolutionImpactValuesCalculator original, Cloner cloner)
+      : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SymbolicRegressionSolutionImpactValuesCalculator(this, cloner);
+    }
+
+    [StorableConstructor]
+    protected SymbolicRegressionSolutionImpactValuesCalculator(bool deserializing) : base(deserializing) { }
     public override double CalculateReplacementValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows) {
       var regressionModel = (ISymbolicRegressionModel)model;
@@ -34,4 +49,12 @@
 
     public override double CalculateImpactValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, double originalQuality = double.NaN) {
+      double impactValue, replacementValue;
+      CalculateImpactAndReplacementValues(model, node, problemData, rows, out impactValue, out replacementValue, originalQuality);
+      return impactValue;
+    }
+
+    public override void CalculateImpactAndReplacementValues(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node,
+      IDataAnalysisProblemData problemData, IEnumerable<int> rows, out double impactValue, out double replacementValue,
+      double originalQuality = Double.NaN) {
       var regressionModel = (ISymbolicRegressionModel)model;
       var regressionProblemData = (IRegressionProblemData)problemData;
@@ -47,5 +70,5 @@
       }
 
-      var replacementValue = CalculateReplacementValue(regressionModel, node, regressionProblemData, rows);
+      replacementValue = CalculateReplacementValue(regressionModel, node, regressionProblemData, rows);
       var constantNode = new ConstantTreeNode(new Constant()) { Value = replacementValue };
 
@@ -63,7 +86,6 @@
       if (errorState != OnlineCalculatorError.None) newQuality = 0.0;
 
-      return originalQuality - newQuality;
+      impactValue = originalQuality - newQuality;
     }
-
   }
 }
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectivePruningAnalyzer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectivePruningAnalyzer.cs	(revision 10468)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectivePruningAnalyzer.cs	(revision 10469)
@@ -5,6 +5,6 @@
 using HeuristicLab.Core;
 using HeuristicLab.Data;
-using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
-using HeuristicLab.Optimization;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization.Operators;
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
@@ -14,29 +14,29 @@
   [Item("SymbolicDataAnalysisSingleObjectivePruningAnalyzer", "An analyzer that prunes introns from trees in single objective symbolic data analysis problems.")]
   public abstract class SymbolicDataAnalysisSingleObjectivePruningAnalyzer : SymbolicDataAnalysisSingleObjectiveAnalyzer {
+    #region parameter names
     private const string ProblemDataParameterName = "ProblemData";
-    private const string InterpreterParameterName = "SymbolicExpressionTreeInterpreter";
-
     private const string UpdateIntervalParameterName = "UpdateInverval";
     private const string UpdateCounterParameterName = "UpdateCounter";
-
     private const string PopulationSliceParameterName = "PopulationSlice";
     private const string PruningProbabilityParameterName = "PruningProbability";
-
-    private const string NumberOfPrunedSubtreesParameterName = "PrunedSubtrees";
-    private const string NumberOfPrunedTreesParameterName = "PrunedTrees";
-
+    private const string TotalNumberOfPrunedSubtreesParameterName = "Number of pruned subtrees";
+    private const string TotalNumberOfPrunedTreesParameterName = "Number of pruned trees";
     private const string RandomParameterName = "Random";
-    private const string EstimationLimitsParameterName = "EstimationLimits";
-
     private const string PruneOnlyZeroImpactNodesParameterName = "PruneOnlyZeroImpactNodes";
     private const string NodeImpactThresholdParameterName = "ImpactThreshold";
-
-    private const string FitnessCalculationPartitionParameterName = "FitnessCalculationPartition";
-
-    private bool reentry;
-    [Storable]
-    protected ISymbolicDataAnalysisSolutionImpactValuesCalculator impactValuesCalculator;
-
+    private const string PruningOperatorParameterName = "PruningOperator";
+    private const string ResultsParameterName = "Results";
+    #endregion
+    #region private members
+    private DataReducer prunedSubtreesReducer;
+    private DataReducer prunedTreesReducer;
+    private DataTableValuesCollector valuesCollector;
+    private ResultsCollector resultsCollector;
+    private EmptyOperator emptyOp;
+    #endregion
     #region parameter properties
+    public IValueParameter<SymbolicDataAnalysisExpressionPruningOperator> PruningOperatorParameter {
+      get { return (IValueParameter<SymbolicDataAnalysisExpressionPruningOperator>)Parameters[PruningOperatorParameterName]; }
+    }
     public IFixedValueParameter<BoolValue> PruneOnlyZeroImpactNodesParameter {
       get { return (IFixedValueParameter<BoolValue>)Parameters[PruneOnlyZeroImpactNodesParameterName]; }
@@ -45,7 +45,4 @@
       get { return (IFixedValueParameter<DoubleValue>)Parameters[NodeImpactThresholdParameterName]; }
     }
-    public ILookupParameter<DoubleLimit> EstimationLimitsParameter {
-      get { return (ILookupParameter<DoubleLimit>)Parameters[EstimationLimitsParameterName]; }
-    }
     public ILookupParameter<IRandom> RandomParameter {
       get { return (ILookupParameter<IRandom>)Parameters[RandomParameterName]; }
@@ -53,10 +50,4 @@
     private ILookupParameter<IDataAnalysisProblemData> ProblemDataParameter {
       get { return (ILookupParameter<IDataAnalysisProblemData>)Parameters[ProblemDataParameterName]; }
-    }
-    public ILookupParameter<IntRange> FitnessCalculationPartitionParameter {
-      get { return (ILookupParameter<IntRange>)Parameters[FitnessCalculationPartitionParameterName]; }
-    }
-    private ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter> InterpreterParameter {
-      get { return (ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>)Parameters[InterpreterParameterName]; }
     }
     public IValueParameter<IntValue> UpdateIntervalParameter {
@@ -72,39 +63,24 @@
       get { return (IValueParameter<DoubleValue>)Parameters[PruningProbabilityParameterName]; }
     }
-    public IFixedValueParameter<DoubleValue> NumberOfPrunedSubtreesParameter {
-      get { return (IFixedValueParameter<DoubleValue>)Parameters[NumberOfPrunedSubtreesParameterName]; }
-    }
-    public IFixedValueParameter<DoubleValue> NumberOfPrunedTreesParameter {
-      get { return (IFixedValueParameter<DoubleValue>)Parameters[NumberOfPrunedTreesParameterName]; }
-    }
     #endregion
     #region properties
+    protected SymbolicDataAnalysisExpressionPruningOperator PruningOperator { get { return PruningOperatorParameter.Value; } }
     protected IDataAnalysisProblemData ProblemData { get { return ProblemDataParameter.ActualValue; } }
-    protected IntRange FitnessCalculationPartition { get { return FitnessCalculationPartitionParameter.ActualValue; } }
-    protected ISymbolicDataAnalysisExpressionTreeInterpreter Interpreter { get { return InterpreterParameter.ActualValue; } }
     protected IntValue UpdateInterval { get { return UpdateIntervalParameter.Value; } }
     protected IntValue UpdateCounter { get { return UpdateCounterParameter.Value; } }
     protected DoubleRange PopulationSlice { get { return PopulationSliceParameter.Value; } }
     protected DoubleValue PruningProbability { get { return PruningProbabilityParameter.Value; } }
-    protected DoubleValue PrunedSubtrees { get { return NumberOfPrunedSubtreesParameter.Value; } }
-    protected DoubleValue PrunedTrees { get { return NumberOfPrunedTreesParameter.Value; } }
-    protected DoubleLimit EstimationLimits { get { return EstimationLimitsParameter.ActualValue; } }
     protected IRandom Random { get { return RandomParameter.ActualValue; } }
     protected DoubleValue NodeImpactThreshold { get { return NodeImpactThresholdParameter.Value; } }
     protected BoolValue PruneOnlyZeroImpactNodes { get { return PruneOnlyZeroImpactNodesParameter.Value; } }
     #endregion
-
     #region IStatefulItem members
     public override void InitializeState() {
       base.InitializeState();
       UpdateCounter.Value = 0;
-      PrunedSubtrees.Value = 0;
-      PrunedTrees.Value = 0;
     }
     public override void ClearState() {
       base.ClearState();
       UpdateCounter.Value = 0;
-      PrunedSubtrees.Value = 0;
-      PrunedTrees.Value = 0;
     }
     #endregion
@@ -112,95 +88,101 @@
     [StorableConstructor]
     protected SymbolicDataAnalysisSingleObjectivePruningAnalyzer(bool deserializing) : base(deserializing) { }
-    [StorableHook(HookType.AfterDeserialization)]
-    private void AfterDeserialization() {
-      if (!Parameters.ContainsKey(FitnessCalculationPartitionParameterName))
-        Parameters.Add(new LookupParameter<IntRange>(FitnessCalculationPartitionParameterName, ""));
-    }
     protected SymbolicDataAnalysisSingleObjectivePruningAnalyzer(SymbolicDataAnalysisSingleObjectivePruningAnalyzer original, Cloner cloner)
       : base(original, cloner) {
-      impactValuesCalculator = original.impactValuesCalculator;
+      this.prunedSubtreesReducer = (DataReducer)original.prunedSubtreesReducer.Clone();
+      this.prunedTreesReducer = (DataReducer)original.prunedTreesReducer.Clone();
+      this.valuesCollector = (DataTableValuesCollector)original.valuesCollector.Clone();
+      this.resultsCollector = (ResultsCollector)original.resultsCollector.Clone();
     }
     protected SymbolicDataAnalysisSingleObjectivePruningAnalyzer() {
+      #region add parameters
       Parameters.Add(new ValueParameter<DoubleRange>(PopulationSliceParameterName, new DoubleRange(0.75, 1)));
       Parameters.Add(new ValueParameter<DoubleValue>(PruningProbabilityParameterName, new DoubleValue(0.5)));
-      // analyzer parameters
       Parameters.Add(new ValueParameter<IntValue>(UpdateIntervalParameterName, "The interval in which the tree length analysis should be applied.", new IntValue(1)));
       Parameters.Add(new ValueParameter<IntValue>(UpdateCounterParameterName, "The value which counts how many times the operator was called", new IntValue(0)));
       Parameters.Add(new LookupParameter<IRandom>(RandomParameterName));
       Parameters.Add(new LookupParameter<IDataAnalysisProblemData>(ProblemDataParameterName));
-      Parameters.Add(new LookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>(InterpreterParameterName));
-
-      Parameters.Add(new FixedValueParameter<DoubleValue>(NumberOfPrunedSubtreesParameterName, new DoubleValue(0)));
-      Parameters.Add(new FixedValueParameter<DoubleValue>(NumberOfPrunedTreesParameterName, new DoubleValue(0)));
-      Parameters.Add(new LookupParameter<DoubleLimit>(EstimationLimitsParameterName));
       Parameters.Add(new FixedValueParameter<DoubleValue>(NodeImpactThresholdParameterName, new DoubleValue(0.0)));
       Parameters.Add(new FixedValueParameter<BoolValue>(PruneOnlyZeroImpactNodesParameterName, new BoolValue(false)));
-      Parameters.Add(new LookupParameter<IntRange>(FitnessCalculationPartitionParameterName, ""));
+      #endregion
+    }
+
+    private void InitializeOperators() {
+      prunedSubtreesReducer = new DataReducer();
+      prunedSubtreesReducer.ParameterToReduce.ActualName = PruningOperator.PrunedSubtreesParameter.ActualName;
+      prunedSubtreesReducer.ReductionOperation.Value = new ReductionOperation(ReductionOperations.Sum); // sum all the pruned subtrees parameter values
+      prunedSubtreesReducer.TargetOperation.Value = new ReductionOperation(ReductionOperations.Assign); // asign the sum to the target parameter
+      prunedSubtreesReducer.TargetParameter.ActualName = TotalNumberOfPrunedSubtreesParameterName;
+
+      prunedTreesReducer = new DataReducer();
+      prunedTreesReducer.ParameterToReduce.ActualName = PruningOperator.PrunedTreesParameter.ActualName;
+      prunedTreesReducer.ReductionOperation.Value = new ReductionOperation(ReductionOperations.Sum);
+      prunedTreesReducer.TargetOperation.Value = new ReductionOperation(ReductionOperations.Assign);
+      prunedTreesReducer.TargetParameter.ActualName = TotalNumberOfPrunedTreesParameterName;
+
+      valuesCollector = new DataTableValuesCollector();
+      valuesCollector.CollectedValues.Add(new LookupParameter<IntValue>(TotalNumberOfPrunedSubtreesParameterName));
+      valuesCollector.CollectedValues.Add(new LookupParameter<IntValue>(TotalNumberOfPrunedTreesParameterName));
+      valuesCollector.DataTableParameter.ActualName = "Population pruning";
+
+      resultsCollector = new ResultsCollector();
+      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>("Population pruning"));
+      resultsCollector.ResultsParameter.ActualName = ResultsParameterName;
+
+      emptyOp = new EmptyOperator();
+    }
+
+    // 
+    /// <summary>
+    /// Computes the closed interval bounding the portion of the population that is to be pruned. 
+    /// </summary>
+    /// <returns>Returns an int range [start, end]</returns>
+    private IntRange GetSliceBounds() {
+      var count = ExecutionContext.Scope.SubScopes.Count;
+      var start = (int)Math.Round(PopulationSlice.Start * count);
+      var end = (int)Math.Round(PopulationSlice.End * count);
+      if (end > count) end = count;
+
+      if (start >= end) throw new ArgumentOutOfRangeException("Invalid PopulationSlice bounds.");
+      return new IntRange(start, end);
+    }
+
+    private IOperation CreatePruningOperation() {
+      var oc = new OperationCollection { Parallel = true };
+      var range = GetSliceBounds();
+      var qualities = Quality.Select(x => x.Value).ToArray();
+      var indices = Enumerable.Range(0, qualities.Length).ToArray();
+      Array.Sort(qualities, indices);
+      if (!Maximization.Value) Array.Reverse(indices);
+
+      var subscopes = ExecutionContext.Scope.SubScopes;
+
+      for (int i = 0; i < subscopes.Count; ++i) {
+        IOperator op;
+        if (range.Start <= i && i < range.End && Random.NextDouble() <= PruningProbability.Value)
+          op = PruningOperator;
+        else op = emptyOp;
+        var index = indices[i];
+        var subscope = subscopes[index];
+        oc.Add(ExecutionContext.CreateChildOperation(op, subscope));
+      }
+      return oc;
     }
 
     public override IOperation Apply() {
-      if (reentry) {
-        UpdateCounter.Value++;
+      UpdateCounter.Value++;
+      if (UpdateCounter.Value != UpdateInterval.Value) return base.Apply();
+      UpdateCounter.Value = 0;
 
-        if (UpdateCounter.Value != UpdateInterval.Value) return base.Apply();
-        UpdateCounter.Value = 0;
+      if (prunedSubtreesReducer == null || prunedTreesReducer == null || valuesCollector == null || resultsCollector == null) { InitializeOperators(); }
 
-        var trees = SymbolicExpressionTreeParameter.ActualValue.ToList();
-        var qualities = QualityParameter.ActualValue.ToList();
+      var prune = CreatePruningOperation();
+      var reducePrunedSubtrees = ExecutionContext.CreateChildOperation(prunedSubtreesReducer);
+      var reducePrunedTrees = ExecutionContext.CreateChildOperation(prunedTreesReducer);
+      var collectValues = ExecutionContext.CreateChildOperation(valuesCollector);
+      var collectResults = ExecutionContext.CreateChildOperation(resultsCollector);
 
-        var population = trees.Zip(qualities, (tree, quality) => new { Tree = tree, Quality = quality }).ToList();
-        Func<double, double, int> compare = (a, b) => Maximization.Value ? a.CompareTo(b) : b.CompareTo(a);
-        population.Sort((a, b) => compare(a.Quality.Value, b.Quality.Value));
-
-        var start = (int)Math.Round(PopulationSlice.Start * trees.Count);
-        var end = (int)Math.Round(PopulationSlice.End * trees.Count);
-
-        if (end == population.Count) end--;
-
-        if (start >= end || end >= population.Count) throw new Exception("Invalid PopulationSlice bounds.");
-
-        PrunedSubtrees.Value = 0;
-        PrunedTrees.Value = 0;
-
-        reentry = false;
-
-        var operations = new OperationCollection { Parallel = true };
-        foreach (var p in population.Skip(start).Take(end)) {
-          if (Random.NextDouble() > PruningProbability.Value) continue;
-          var op = new SymbolicDataAnalysisExpressionPruningOperator {
-            Model = CreateModel(p.Tree, Interpreter, EstimationLimits.Lower, EstimationLimits.Upper),
-            ImpactsCalculator = impactValuesCalculator,
-            ProblemData = ProblemData,
-            Random = Random,
-            PruneOnlyZeroImpactNodes = PruneOnlyZeroImpactNodes.Value,
-            NodeImpactThreshold = NodeImpactThreshold.Value,
-            FitnessCalculationPartition = FitnessCalculationPartition
-          };
-          operations.Add(ExecutionContext.CreateChildOperation(op, ExecutionContext.Scope));
-        }
-        return new OperationCollection { operations, ExecutionContext.CreateOperation(this) };
-      }
-
-      DataTable table;
-
-      if (ResultCollection.ContainsKey("Population Pruning")) {
-        table = (DataTable)ResultCollection["Population Pruning"].Value;
-      } else {
-        table = new DataTable("Population Pruning");
-        table.Rows.Add(new DataRow("Pruned Trees") { VisualProperties = { StartIndexZero = true } });
-        table.Rows.Add(new DataRow("Pruned Subtrees") { VisualProperties = { StartIndexZero = true } });
-        ResultCollection.Add(new Result("Population Pruning", table));
-      }
-
-      table.Rows["Pruned Trees"].Values.Add(PrunedTrees.Value);
-      table.Rows["Pruned Subtrees"].Values.Add(PrunedSubtrees.Value);
-
-      reentry = true;
-
-      return base.Apply();
+      return new OperationCollection { prune, reducePrunedSubtrees, reducePrunedTrees, collectValues, collectResults, base.Apply() };
     }
-
-    protected abstract ISymbolicDataAnalysisModel CreateModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
-      double lowerEstimationLimit = double.MinValue, double upperEstimationLimit = double.MaxValue);
   }
 }
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisImpactValuesCalculator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisImpactValuesCalculator.cs	(revision 10468)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisImpactValuesCalculator.cs	(revision 10469)
@@ -1,9 +1,12 @@
 ﻿using System.Collections.Generic;
+using HeuristicLab.Core;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
-  public interface ISymbolicDataAnalysisSolutionImpactValuesCalculator {
+  public interface ISymbolicDataAnalysisSolutionImpactValuesCalculator : IItem {
     double CalculateReplacementValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows);
     double CalculateImpactValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, double originalQuality = double.NaN);
+    void CalculateImpactAndReplacementValues(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData,
+      IEnumerable<int> rows, out double impactValue, out double replacementValue, double originalQuality = double.NaN);
   }
 }
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionPruningOperator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionPruningOperator.cs	(revision 10468)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionPruningOperator.cs	(revision 10469)
@@ -34,74 +34,120 @@
   [StorableClass]
   [Item("SymbolicExpressionTreePruningOperator", "An operator that replaces introns with constant values in a symbolic expression tree.")]
-  public class SymbolicDataAnalysisExpressionPruningOperator : SingleSuccessorOperator {
-    private const string NumberOfPrunedSubtreesParameterName = "PrunedSubtrees";
-    private const string NumberOfPrunedTreesParameterName = "PrunedTrees";
+  public abstract class SymbolicDataAnalysisExpressionPruningOperator : SingleSuccessorOperator {
+    #region parameter names
+    private const string ProblemDataParameterName = "ProblemData";
+    private const string SymbolicDataAnalysisModelParameterName = "SymbolicDataAnalysisModel";
+    private const string ImpactValuesCalculatorParameterName = "ImpactValuesCalculator";
+    private const string PrunedSubtreesParameterName = "PrunedSubtrees";
+    private const string PrunedTreesParameterName = "PrunedTrees";
+    private const string FitnessCalculationPartitionParameterName = "FitnessCalculationPartition";
+    private const string NodeImpactThresholdParameterName = "ImpactThreshold";
+    private const string PruneOnlyZeroImpactNodesParameterName = "PruneOnlyZeroImpactNodes";
+    private const string SymbolicExpressionTreeParameterName = "SymbolicExpressionTree"; // the tree to be pruned
+    private const string QualityParameterName = "Quality"; // the quality 
+    private const string EstimationLimitsParameterName = "EstimationLimits";
+    private const string InterpreterParameterName = "SymbolicExpressionTreeInterpreter";
+    #endregion
+
     #region parameter properties
-    public ILookupParameter<DoubleValue> NumberOfPrunedSubtreesParameter {
-      get { return (ILookupParameter<DoubleValue>)Parameters[NumberOfPrunedSubtreesParameterName]; }
+    public ILookupParameter<ISymbolicExpressionTree> SymbolicExpressionTreeParameter {
+      get { return (ILookupParameter<ISymbolicExpressionTree>)Parameters[SymbolicExpressionTreeParameterName]; }
     }
-    public ILookupParameter<DoubleValue> NumberOfPrunedTreesParameter {
-      get { return (ILookupParameter<DoubleValue>)Parameters[NumberOfPrunedTreesParameterName]; }
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters[QualityParameterName]; }
+    }
+    public ILookupParameter<IDataAnalysisProblemData> ProblemDataParameter {
+      get { return (ILookupParameter<IDataAnalysisProblemData>)Parameters[ProblemDataParameterName]; }
+    }
+    public IValueParameter<ISymbolicDataAnalysisSolutionImpactValuesCalculator> ImpactValuesCalculatorParameter {
+      get { return (IValueParameter<ISymbolicDataAnalysisSolutionImpactValuesCalculator>)Parameters[ImpactValuesCalculatorParameterName]; }
+    }
+    public ILookupParameter<IntRange> FitnessCalculationPartitionParameter {
+      get { return (ILookupParameter<IntRange>)Parameters[FitnessCalculationPartitionParameterName]; }
+    }
+    public ILookupParameter<IntValue> PrunedSubtreesParameter {
+      get { return (ILookupParameter<IntValue>)Parameters[PrunedSubtreesParameterName]; }
+    }
+    public ILookupParameter<IntValue> PrunedTreesParameter {
+      get { return (ILookupParameter<IntValue>)Parameters[PrunedTreesParameterName]; }
+    }
+    public IFixedValueParameter<DoubleValue> NodeImpactThresholdParameter {
+      get { return (IFixedValueParameter<DoubleValue>)Parameters[NodeImpactThresholdParameterName]; }
+    }
+    public IFixedValueParameter<BoolValue> PruneOnlyZeroImpactNodesParameter {
+      get { return (IFixedValueParameter<BoolValue>)Parameters[PruneOnlyZeroImpactNodesParameterName]; }
+    }
+    public ILookupParameter<DoubleLimit> EstimationLimitsParameter {
+      get { return (ILookupParameter<DoubleLimit>)Parameters[EstimationLimitsParameterName]; }
+    }
+    public ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter> InterpreterParameter {
+      get { return (ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>)Parameters[InterpreterParameterName]; }
     }
     #endregion
     #region properties
-    private DoubleValue PrunedSubtrees { get { return NumberOfPrunedSubtreesParameter.ActualValue; } }
-    private DoubleValue PrunedTrees { get { return NumberOfPrunedTreesParameter.ActualValue; } }
+    protected IDataAnalysisProblemData ProblemData { get { return ProblemDataParameter.ActualValue; } }
+    protected ISymbolicDataAnalysisSolutionImpactValuesCalculator ImpactValuesCalculator { get { return ImpactValuesCalculatorParameter.Value; } }
+    protected IntRange FitnessCalculationPartition { get { return FitnessCalculationPartitionParameter.ActualValue; } }
+    protected BoolValue PruneOnlyZeroImpactNodes { get { return PruneOnlyZeroImpactNodesParameter.Value; } }
+    protected DoubleValue NodeImpactThreshold { get { return NodeImpactThresholdParameter.Value; } }
+    protected ISymbolicExpressionTree SymbolicExpressionTree { get { return SymbolicExpressionTreeParameter.ActualValue; } }
+    protected DoubleValue Quality { get { return QualityParameter.ActualValue; } }
+    protected DoubleLimit EstimationLimits { get { return EstimationLimitsParameter.ActualValue; } }
+    protected ISymbolicDataAnalysisExpressionTreeInterpreter Interpreter { get { return InterpreterParameter.ActualValue; } }
     #endregion
 
     [StorableConstructor]
     protected SymbolicDataAnalysisExpressionPruningOperator(bool deserializing) : base(deserializing) { }
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new SymbolicDataAnalysisExpressionPruningOperator(this, cloner);
+    protected SymbolicDataAnalysisExpressionPruningOperator(SymbolicDataAnalysisExpressionPruningOperator original, Cloner cloner)
+      : base(original, cloner) { }
+
+    protected SymbolicDataAnalysisExpressionPruningOperator() {
+      #region add parameters
+      Parameters.Add(new LookupParameter<IDataAnalysisProblemData>(ProblemDataParameterName));
+      Parameters.Add(new LookupParameter<ISymbolicDataAnalysisModel>(SymbolicDataAnalysisModelParameterName));
+      Parameters.Add(new LookupParameter<IntRange>(FitnessCalculationPartitionParameterName));
+      Parameters.Add(new LookupParameter<IntValue>(PrunedSubtreesParameterName, "A counter of how many subtrees were replaced."));
+      Parameters.Add(new LookupParameter<IntValue>(PrunedTreesParameterName, "A counter of how many trees were pruned."));
+      Parameters.Add(new FixedValueParameter<BoolValue>(PruneOnlyZeroImpactNodesParameterName, "Specify whether or not only zero impact nodes should be pruned."));
+      Parameters.Add(new FixedValueParameter<DoubleValue>(NodeImpactThresholdParameterName, "Specifies an impact value threshold below which nodes should be pruned."));
+      Parameters.Add(new LookupParameter<DoubleLimit>(EstimationLimitsParameterName));
+      Parameters.Add(new LookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>(InterpreterParameterName));
+      Parameters.Add(new LookupParameter<ISymbolicExpressionTree>(SymbolicExpressionTreeParameterName));
+      Parameters.Add(new LookupParameter<DoubleValue>(QualityParameterName));
+      #endregion
     }
-    protected SymbolicDataAnalysisExpressionPruningOperator(SymbolicDataAnalysisExpressionPruningOperator original, Cloner cloner)
-      : base(original, cloner) {
-    }
-
-    public SymbolicDataAnalysisExpressionPruningOperator() {
-      Parameters.Add(new LookupParameter<DoubleValue>(NumberOfPrunedSubtreesParameterName));
-      Parameters.Add(new LookupParameter<DoubleValue>(NumberOfPrunedTreesParameterName));
-    }
-
-    public ISymbolicDataAnalysisModel Model { get; set; }
-    public IDataAnalysisProblemData ProblemData { get; set; }
-    public ISymbolicDataAnalysisSolutionImpactValuesCalculator ImpactsCalculator { get; set; }
-
-    public IntRange FitnessCalculationPartition { get; set; }
-    public IRandom Random { get; set; }
-
-    public bool PruneOnlyZeroImpactNodes { get; set; }
-    public double NodeImpactThreshold { get; set; }
-
     public override IOperation Apply() {
-      int prunedSubtrees = 0;
-
-      var nodes = Model.SymbolicExpressionTree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPrefix().ToList();
+      var model = CreateModel();
+      var nodes = SymbolicExpressionTree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPrefix().ToList();
       var rows = Enumerable.Range(FitnessCalculationPartition.Start, FitnessCalculationPartition.Size).ToList();
 
-      for (int j = 0; j < nodes.Count; ++j) {
-        var node = nodes[j];
+      var prunedSubtrees = 0;
+      var prunedTrees = 0;
+
+      double quality = Evaluate(model);
+
+      for (int i = 0; i < nodes.Count; ++i) {
+        var node = nodes[i];
         if (node is ConstantTreeNode) continue;
 
-        var impact = ImpactsCalculator.CalculateImpactValue(Model, node, ProblemData, rows);
+        double impactValue, replacementValue;
+        ImpactValuesCalculator.CalculateImpactAndReplacementValues(model, node, ProblemData, rows, out impactValue, out replacementValue, quality);
 
-        if (PruneOnlyZeroImpactNodes) {
-          if (!impact.IsAlmost(0.0)) continue;
-        } else {
-          if (NodeImpactThreshold < impact) continue;
-        }
+        if (PruneOnlyZeroImpactNodes.Value && (!impactValue.IsAlmost(0.0))) continue;
+        else if (NodeImpactThreshold.Value < impactValue) continue;
 
-        var replacementValue = ImpactsCalculator.CalculateReplacementValue(Model, node, ProblemData, rows);
         var constantNode = new ConstantTreeNode(new Constant()) { Value = replacementValue };
         ReplaceWithConstant(node, constantNode);
-        j += node.GetLength() - 1; // skip subtrees under the node that was folded
+        i += node.GetLength() - 1; // skip subtrees under the node that was folded
+
+        quality -= impactValue;
 
         prunedSubtrees++;
       }
 
-      if (prunedSubtrees > 0) {
-        lock (PrunedSubtrees) { PrunedSubtrees.Value += prunedSubtrees; }
-        lock (PrunedTrees) { PrunedTrees.Value += 1; }
-      }
+      if (prunedSubtrees > 0) prunedTrees = 1;
+      PrunedSubtreesParameter.ActualValue = new IntValue(prunedSubtrees);
+      PrunedTreesParameter.ActualValue = new IntValue(prunedTrees);
+
       return base.Apply();
     }
@@ -112,4 +158,6 @@
       parent.InsertSubtree(i, replacement);
     }
+    protected abstract ISymbolicDataAnalysisModel CreateModel();
+    protected abstract double Evaluate(IDataAnalysisModel model);
   }
 }
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSolutionImpactValuesCalculator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSolutionImpactValuesCalculator.cs	(revision 10468)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSolutionImpactValuesCalculator.cs	(revision 10469)
@@ -22,10 +22,21 @@
 using System.Collections.Generic;
 using HeuristicLab.Common;
+using HeuristicLab.Core;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
-  public abstract class SymbolicDataAnalysisSolutionImpactValuesCalculator : ISymbolicDataAnalysisSolutionImpactValuesCalculator {
+  [StorableClass]
+  [Item("SymbolicDataAnalysisSolutionImpactValuesCalculator", "Calculates the impact values and replacements values for symbolic expression tree nodes.")]
+  public abstract class SymbolicDataAnalysisSolutionImpactValuesCalculator : Item, ISymbolicDataAnalysisSolutionImpactValuesCalculator {
+    protected SymbolicDataAnalysisSolutionImpactValuesCalculator() { }
+
+    protected SymbolicDataAnalysisSolutionImpactValuesCalculator(SymbolicDataAnalysisSolutionImpactValuesCalculator original, Cloner cloner)
+      : base(original, cloner) { }
+    [StorableConstructor]
+    protected SymbolicDataAnalysisSolutionImpactValuesCalculator(bool deserializing) : base(deserializing) { }
     public abstract double CalculateReplacementValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows);
     public abstract double CalculateImpactValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, double originalQuality = double.NaN);
+    public abstract void CalculateImpactAndReplacementValues(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, out double impactValue, out double replacementValue, double originalQuality = double.NaN);
 
     protected static double CalculateReplacementValue(ISymbolicExpressionTreeNode node, ISymbolicExpressionTree sourceTree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
