Index: stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification.Views/3.4/InteractiveSymbolicClassificationSolutionSimplifierViewBase.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification.Views/3.4/InteractiveSymbolicClassificationSolutionSimplifierViewBase.cs	(revision 12742)
+++ stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification.Views/3.4/InteractiveSymbolicClassificationSolutionSimplifierViewBase.cs	(revision 12745)
@@ -74,6 +74,6 @@
       var impactAndReplacementValues = new Dictionary<ISymbolicExpressionTreeNode, Tuple<double, double>>();
       foreach (var node in tree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPrefix()) {
-        double impactValue, replacementValue;
-        calculator.CalculateImpactAndReplacementValues(Content.Model, node, Content.ProblemData, Content.ProblemData.TrainingIndices, out impactValue, out replacementValue);
+        double impactValue, replacementValue, newQualityForImpactsCalculation;
+        calculator.CalculateImpactAndReplacementValues(Content.Model, node, Content.ProblemData, Content.ProblemData.TrainingIndices, out impactValue, out replacementValue, out newQualityForImpactsCalculation);
         impactAndReplacementValues.Add(node, new Tuple<double, double>(impactValue, replacementValue));
       }
Index: stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationPruningAnalyzer.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationPruningAnalyzer.cs	(revision 12742)
+++ stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationPruningAnalyzer.cs	(revision 12745)
@@ -22,4 +22,5 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
+using HeuristicLab.Data;
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
@@ -29,12 +30,15 @@
   [StorableClass]
   public sealed class SymbolicClassificationPruningAnalyzer : SymbolicDataAnalysisSingleObjectivePruningAnalyzer {
-    private const string ImpactValuesCalculatorParameterName = "ImpactValuesCalculator";
     private const string PruningOperatorParameterName = "PruningOperator";
-    private SymbolicClassificationPruningAnalyzer(SymbolicClassificationPruningAnalyzer original, Cloner cloner)
-      : base(original, cloner) {
+    public IValueParameter<SymbolicClassificationPruningOperator> PruningOperatorParameter {
+      get { return (IValueParameter<SymbolicClassificationPruningOperator>)Parameters[PruningOperatorParameterName]; }
     }
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new SymbolicClassificationPruningAnalyzer(this, cloner);
+
+    protected override SymbolicDataAnalysisExpressionPruningOperator PruningOperator {
+      get { return PruningOperatorParameter.Value; }
     }
+
+    private SymbolicClassificationPruningAnalyzer(SymbolicClassificationPruningAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) { return new SymbolicClassificationPruningAnalyzer(this, cloner); }
 
     [StorableConstructor]
@@ -42,6 +46,36 @@
 
     public SymbolicClassificationPruningAnalyzer() {
-      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()));
+      Parameters.Add(new ValueParameter<SymbolicClassificationPruningOperator>(PruningOperatorParameterName, "The operator used to prune trees", new SymbolicClassificationPruningOperator(new SymbolicClassificationSolutionImpactValuesCalculator())));
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+
+      #region Backwards compatible code, remove with 3.4
+      if (Parameters.ContainsKey(PruningOperatorParameterName)) {
+        var oldParam = Parameters[PruningOperatorParameterName] as ValueParameter<SymbolicDataAnalysisExpressionPruningOperator>;
+        if (oldParam != null) {
+          Parameters.Remove(oldParam);
+          Parameters.Add(new ValueParameter<SymbolicClassificationPruningOperator>(PruningOperatorParameterName, "The operator used to prune trees", new SymbolicClassificationPruningOperator(new SymbolicClassificationSolutionImpactValuesCalculator())));
+        }
+      } else {
+        // not yet contained
+        Parameters.Add(new ValueParameter<SymbolicClassificationPruningOperator>(PruningOperatorParameterName, "The operator used to prune trees", new SymbolicClassificationPruningOperator(new SymbolicClassificationSolutionImpactValuesCalculator())));
+      }
+
+      if (Parameters.ContainsKey("PruneOnlyZeroImpactNodes")) {
+        PruningOperator.PruneOnlyZeroImpactNodes = ((IFixedValueParameter<BoolValue>)Parameters["PruneOnlyZeroImpactNodes"]).Value.Value;
+        Parameters.Remove(Parameters["PruneOnlyZeroImpactNodes"]);
+      }
+      if (Parameters.ContainsKey("ImpactThreshold")) {
+        PruningOperator.NodeImpactThreshold = ((IFixedValueParameter<DoubleValue>)Parameters["ImpactThreshold"]).Value.Value;
+        Parameters.Remove(Parameters["ImpactThreshold"]);
+      }
+      if (Parameters.ContainsKey("ImpactValuesCalculator")) {
+        PruningOperator.ImpactValuesCalculator = ((ValueParameter<SymbolicDataAnalysisSolutionImpactValuesCalculator>)Parameters["ImpactValuesCalculator"]).Value;
+        Parameters.Remove(Parameters["ImpactValuesCalculator"]);
+      }
+      #endregion
     }
   }
Index: stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationPruningOperator.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationPruningOperator.cs	(revision 12742)
+++ stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationPruningOperator.cs	(revision 12745)
@@ -22,7 +22,9 @@
 #endregion
 
+using System.Collections.Generic;
 using System.Linq;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
@@ -32,6 +34,6 @@
   [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 EvaluatorParameterName = "Evaluator";
 
     #region parameter properties
@@ -39,40 +41,80 @@
       get { return (ILookupParameter<ISymbolicClassificationModelCreator>)Parameters[ModelCreatorParameterName]; }
     }
+
+    public ILookupParameter<ISymbolicClassificationSingleObjectiveEvaluator> EvaluatorParameter {
+      get {
+        return (ILookupParameter<ISymbolicClassificationSingleObjectiveEvaluator>)Parameters[EvaluatorParameterName];
+      }
+    }
     #endregion
 
-    protected SymbolicClassificationPruningOperator(SymbolicClassificationPruningOperator original, Cloner cloner)
-      : base(original, cloner) {
-    }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new SymbolicClassificationPruningOperator(this, cloner);
-    }
+    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()));
+    public SymbolicClassificationPruningOperator(ISymbolicDataAnalysisSolutionImpactValuesCalculator impactValuesCalculator)
+      : base(impactValuesCalculator) {
       Parameters.Add(new LookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName));
+      Parameters.Add(new LookupParameter<ISymbolicClassificationSingleObjectiveEvaluator>(EvaluatorParameterName));
     }
 
-    protected override ISymbolicDataAnalysisModel CreateModel() {
-      var model = ModelCreatorParameter.ActualValue.CreateSymbolicClassificationModel(SymbolicExpressionTree, Interpreter, EstimationLimits.Lower, EstimationLimits.Upper);
-      var problemData = (IClassificationProblemData)ProblemData;
-      var rows = problemData.TrainingIndices;
-      model.RecalculateModelParameters(problemData, rows);
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      base.ImpactValuesCalculator = new SymbolicClassificationSolutionImpactValuesCalculator();
+      if (!Parameters.ContainsKey(EvaluatorParameterName)) {
+        Parameters.Add(new LookupParameter<ISymbolicClassificationSingleObjectiveEvaluator>(EvaluatorParameterName));
+      }
+      #endregion
+    }
+
+    protected override ISymbolicDataAnalysisModel CreateModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IDataAnalysisProblemData problemData, DoubleLimit estimationLimits) {
+      var model = ModelCreatorParameter.ActualValue.CreateSymbolicClassificationModel(tree, interpreter, estimationLimits.Lower, estimationLimits.Upper);
+      var classificationProblemData = (IClassificationProblemData)problemData;
+      var rows = classificationProblemData.TrainingIndices;
+      model.RecalculateModelParameters(classificationProblemData, rows);
       return model;
     }
 
     protected override double Evaluate(IDataAnalysisModel model) {
-      var classificationModel = (IClassificationModel)model;
-      var classificationProblemData = (IClassificationProblemData)ProblemData;
-      var trainingIndices = Enumerable.Range(FitnessCalculationPartition.Start, FitnessCalculationPartition.Size);
-      var estimatedValues = classificationModel.GetEstimatedClassValues(ProblemData.Dataset, trainingIndices);
-      var targetValues = ProblemData.Dataset.GetDoubleValues(classificationProblemData.TargetVariable, trainingIndices);
-      OnlineCalculatorError errorState;
-      var quality = OnlineAccuracyCalculator.Calculate(targetValues, estimatedValues, out errorState);
-      if (errorState != OnlineCalculatorError.None) return double.NaN;
-      return quality;
+      var evaluator = EvaluatorParameter.ActualValue;
+      var classificationModel = (ISymbolicClassificationModel)model;
+      var classificationProblemData = (IClassificationProblemData)ProblemDataParameter.ActualValue;
+      var rows = Enumerable.Range(FitnessCalculationPartitionParameter.ActualValue.Start, FitnessCalculationPartitionParameter.ActualValue.Size);
+      return evaluator.Evaluate(this.ExecutionContext, classificationModel.SymbolicExpressionTree, classificationProblemData, rows);
+    }
+
+    public static ISymbolicExpressionTree Prune(ISymbolicExpressionTree tree, ISymbolicClassificationModelCreator modelCreator,
+      SymbolicClassificationSolutionImpactValuesCalculator impactValuesCalculator, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
+      IClassificationProblemData problemData, DoubleLimit estimationLimits, IEnumerable<int> rows,
+      double nodeImpactThreshold = 0.0, bool pruneOnlyZeroImpactNodes = false) {
+      var clonedTree = (ISymbolicExpressionTree)tree.Clone();
+      var model = modelCreator.CreateSymbolicClassificationModel(clonedTree, interpreter, estimationLimits.Lower, estimationLimits.Upper);
+
+      var nodes = clonedTree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPrefix().ToList();
+      double qualityForImpactsCalculation = double.NaN;
+
+      for (int i = 0; i < nodes.Count; ++i) {
+        var node = nodes[i];
+        if (node is ConstantTreeNode) continue;
+
+        double impactValue, replacementValue, newQualityForImpactsCalculation;
+        impactValuesCalculator.CalculateImpactAndReplacementValues(model, node, problemData, rows, out impactValue, out replacementValue, out newQualityForImpactsCalculation, qualityForImpactsCalculation);
+
+        if (pruneOnlyZeroImpactNodes && !impactValue.IsAlmost(0.0)) continue;
+        if (!pruneOnlyZeroImpactNodes && impactValue > nodeImpactThreshold) continue;
+
+        var constantNode = (ConstantTreeNode)node.Grammar.GetSymbol("Constant").CreateTreeNode();
+        constantNode.Value = replacementValue;
+
+        ReplaceWithConstant(node, constantNode);
+        i += node.GetLength() - 1; // skip subtrees under the node that was folded
+
+        qualityForImpactsCalculation = newQualityForImpactsCalculation;
+      }
+      return model.SymbolicExpressionTree;
     }
   }
Index: stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationSolutionImpactValuesCalculator.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationSolutionImpactValuesCalculator.cs	(revision 12742)
+++ stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationSolutionImpactValuesCalculator.cs	(revision 12745)
@@ -47,25 +47,19 @@
     }
 
-    public override double CalculateImpactValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, double originalQuality = double.NaN) {
+    public override double CalculateImpactValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, double qualityForImpactsCalculation = double.NaN) {
       double impactValue, replacementValue;
-      CalculateImpactAndReplacementValues(model, node, problemData, rows, out impactValue, out replacementValue, originalQuality);
+      double newQualityForImpactsCalculation;
+      CalculateImpactAndReplacementValues(model, node, problemData, rows, out impactValue, out replacementValue, out newQualityForImpactsCalculation, qualityForImpactsCalculation);
       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) {
+      IDataAnalysisProblemData problemData, IEnumerable<int> rows, out double impactValue, out double replacementValue, out double newQualityForImpactsCalculation,
+      double qualityForImpactsCalculation = Double.NaN) {
       var classificationModel = (ISymbolicClassificationModel)model;
       var classificationProblemData = (IClassificationProblemData)problemData;
 
-      var dataset = classificationProblemData.Dataset;
-      var targetClassValues = dataset.GetDoubleValues(classificationProblemData.TargetVariable, rows);
-
-      OnlineCalculatorError errorState;
-      if (double.IsNaN(originalQuality)) {
-        var originalClassValues = classificationModel.GetEstimatedClassValues(dataset, rows);
-        originalQuality = OnlineAccuracyCalculator.Calculate(targetClassValues, originalClassValues, out errorState);
-        if (errorState != OnlineCalculatorError.None) originalQuality = 0.0;
-      }
+      if (double.IsNaN(qualityForImpactsCalculation))
+        qualityForImpactsCalculation = CalculateQualityForImpacts(classificationModel, classificationProblemData, rows);
 
       replacementValue = CalculateReplacementValue(classificationModel, node, classificationProblemData, rows);
@@ -81,9 +75,23 @@
       tempModelParentNode.InsertSubtree(i, constantNode);
 
+      OnlineCalculatorError errorState;
+      var dataset = classificationProblemData.Dataset;
+      var targetClassValues = dataset.GetDoubleValues(classificationProblemData.TargetVariable, rows);
       var estimatedClassValues = tempModel.GetEstimatedClassValues(dataset, rows);
-      double newQuality = OnlineAccuracyCalculator.Calculate(targetClassValues, estimatedClassValues, out errorState);
-      if (errorState != OnlineCalculatorError.None) newQuality = 0.0;
+      newQualityForImpactsCalculation = OnlineAccuracyCalculator.Calculate(targetClassValues, estimatedClassValues, out errorState);
+      if (errorState != OnlineCalculatorError.None) newQualityForImpactsCalculation = 0.0;
 
-      impactValue = originalQuality - newQuality;
+      impactValue = qualityForImpactsCalculation - newQualityForImpactsCalculation;
+    }
+
+    public static double CalculateQualityForImpacts(ISymbolicClassificationModel model, IClassificationProblemData problemData, IEnumerable<int> rows) {
+      OnlineCalculatorError errorState;
+      var dataset = problemData.Dataset;
+      var targetClassValues = dataset.GetDoubleValues(problemData.TargetVariable, rows);
+      var originalClassValues = model.GetEstimatedClassValues(dataset, rows);
+      var qualityForImpactsCalculation = OnlineAccuracyCalculator.Calculate(targetClassValues, originalClassValues, out errorState);
+      if (errorState != OnlineCalculatorError.None) qualityForImpactsCalculation = 0.0;
+
+      return qualityForImpactsCalculation;
     }
   }
Index: stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views/3.4/InteractiveSymbolicRegressionSolutionSimplifierView.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views/3.4/InteractiveSymbolicRegressionSolutionSimplifierView.cs	(revision 12742)
+++ stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views/3.4/InteractiveSymbolicRegressionSolutionSimplifierView.cs	(revision 12745)
@@ -63,6 +63,6 @@
       var impactAndReplacementValues = new Dictionary<ISymbolicExpressionTreeNode, Tuple<double, double>>();
       foreach (var node in tree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPrefix()) {
-        double impactValue, replacementValue;
-        calculator.CalculateImpactAndReplacementValues(Content.Model, node, Content.ProblemData, Content.ProblemData.TrainingIndices, out impactValue, out replacementValue);
+        double impactValue, replacementValue, newQualityForImpactsCalculation;
+        calculator.CalculateImpactAndReplacementValues(Content.Model, node, Content.ProblemData, Content.ProblemData.TrainingIndices, out impactValue, out replacementValue, out newQualityForImpactsCalculation);
         impactAndReplacementValues.Add(node, new Tuple<double, double>(impactValue, replacementValue));
       }
Index: stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionPruningAnalyzer.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionPruningAnalyzer.cs	(revision 12742)
+++ stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionPruningAnalyzer.cs	(revision 12745)
@@ -24,4 +24,5 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
+using HeuristicLab.Data;
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
@@ -31,12 +32,15 @@
   [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) {
+    public IValueParameter<SymbolicRegressionPruningOperator> PruningOperatorParameter {
+      get { return (IValueParameter<SymbolicRegressionPruningOperator>)Parameters[PruningOperatorParameterName]; }
     }
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new SymbolicRegressionPruningAnalyzer(this, cloner);
+
+    protected override SymbolicDataAnalysisExpressionPruningOperator PruningOperator {
+      get { return PruningOperatorParameter.Value; }
     }
+
+    private SymbolicRegressionPruningAnalyzer(SymbolicRegressionPruningAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) { return new SymbolicRegressionPruningAnalyzer(this, cloner); }
 
     [StorableConstructor]
@@ -44,6 +48,38 @@
 
     public SymbolicRegressionPruningAnalyzer() {
-      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()));
+      Parameters.Add(new ValueParameter<SymbolicRegressionPruningOperator>(PruningOperatorParameterName, "The operator used to prune trees", new SymbolicRegressionPruningOperator(new SymbolicRegressionSolutionImpactValuesCalculator())));
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+
+      #region Backwards compatible code, remove with 3.4
+      if (Parameters.ContainsKey(PruningOperatorParameterName)) {
+        var oldParam = Parameters[PruningOperatorParameterName] as ValueParameter<SymbolicDataAnalysisExpressionPruningOperator>;
+        if (oldParam != null) {
+          Parameters.Remove(oldParam);
+          Parameters.Add(new ValueParameter<SymbolicRegressionPruningOperator>(PruningOperatorParameterName, "The operator used to prune trees", new SymbolicRegressionPruningOperator(new SymbolicRegressionSolutionImpactValuesCalculator())));
+        }
+      } else {
+        // not yet contained
+        Parameters.Add(new ValueParameter<SymbolicRegressionPruningOperator>(PruningOperatorParameterName, "The operator used to prune trees", new SymbolicRegressionPruningOperator(new SymbolicRegressionSolutionImpactValuesCalculator())));
+      }
+
+
+      if (Parameters.ContainsKey("PruneOnlyZeroImpactNodes")) {
+        PruningOperator.PruneOnlyZeroImpactNodes = ((IFixedValueParameter<BoolValue>)Parameters["PruneOnlyZeroImpactNodes"]).Value.Value;
+        Parameters.Remove(Parameters["PruneOnlyZeroImpactNodes"]);
+      }
+      if (Parameters.ContainsKey("ImpactThreshold")) {
+        PruningOperator.NodeImpactThreshold = ((IFixedValueParameter<DoubleValue>)Parameters["ImpactThreshold"]).Value.Value;
+        Parameters.Remove(Parameters["ImpactThreshold"]);
+      }
+      if (Parameters.ContainsKey("ImpactValuesCalculator")) {
+        PruningOperator.ImpactValuesCalculator = ((ValueParameter<SymbolicDataAnalysisSolutionImpactValuesCalculator>)Parameters["ImpactValuesCalculator"]).Value;
+        Parameters.Remove(Parameters["ImpactValuesCalculator"]);
+      }
+
+      #endregion
     }
   }
Index: stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionPruningOperator.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionPruningOperator.cs	(revision 12742)
+++ stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionPruningOperator.cs	(revision 12745)
@@ -22,7 +22,9 @@
 #endregion
 
+using System.Collections.Generic;
 using System.Linq;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
@@ -32,5 +34,11 @@
   [Item("SymbolicRegressionPruningOperator", "An operator which prunes symbolic regression trees.")]
   public class SymbolicRegressionPruningOperator : SymbolicDataAnalysisExpressionPruningOperator {
-    private const string ImpactValuesCalculatorParameterName = "ImpactValuesCalculator";
+    private const string EvaluatorParameterName = "Evaluator";
+
+    #region parameter properties
+    public ILookupParameter<ISymbolicRegressionSingleObjectiveEvaluator> EvaluatorParameter {
+      get { return (ILookupParameter<ISymbolicRegressionSingleObjectiveEvaluator>)Parameters[EvaluatorParameterName]; }
+    }
+    #endregion
 
     protected SymbolicRegressionPruningOperator(SymbolicRegressionPruningOperator original, Cloner cloner)
@@ -44,23 +52,60 @@
     protected SymbolicRegressionPruningOperator(bool deserializing) : base(deserializing) { }
 
-    public SymbolicRegressionPruningOperator() {
-      var impactValuesCalculator = new SymbolicRegressionSolutionImpactValuesCalculator();
-      Parameters.Add(new ValueParameter<ISymbolicDataAnalysisSolutionImpactValuesCalculator>(ImpactValuesCalculatorParameterName, "The impact values calculator to be used for figuring out the node impacts.", impactValuesCalculator));
+    public SymbolicRegressionPruningOperator(ISymbolicDataAnalysisSolutionImpactValuesCalculator impactValuesCalculator)
+      : base(impactValuesCalculator) {
+      Parameters.Add(new LookupParameter<ISymbolicRegressionSingleObjectiveEvaluator>(EvaluatorParameterName));
     }
 
-    protected override ISymbolicDataAnalysisModel CreateModel() {
-      return new SymbolicRegressionModel(SymbolicExpressionTree, Interpreter, EstimationLimits.Lower, EstimationLimits.Upper);
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      base.ImpactValuesCalculator = new SymbolicRegressionSolutionImpactValuesCalculator();
+      if (!Parameters.ContainsKey(EvaluatorParameterName)) {
+        Parameters.Add(new LookupParameter<ISymbolicRegressionSingleObjectiveEvaluator>(EvaluatorParameterName));
+      }
+      #endregion
+    }
+
+    protected override ISymbolicDataAnalysisModel CreateModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IDataAnalysisProblemData problemData, DoubleLimit estimationLimits) {
+      return new SymbolicRegressionModel(tree, interpreter, estimationLimits.Lower, estimationLimits.Upper);
     }
 
     protected override double Evaluate(IDataAnalysisModel model) {
-      var regressionModel = (IRegressionModel)model;
-      var regressionProblemData = (IRegressionProblemData)ProblemData;
-      var trainingIndices = Enumerable.Range(FitnessCalculationPartition.Start, FitnessCalculationPartition.Size);
-      var estimatedValues = regressionModel.GetEstimatedValues(ProblemData.Dataset, trainingIndices); // also bounds the values
-      var targetValues = ProblemData.Dataset.GetDoubleValues(regressionProblemData.TargetVariable, trainingIndices);
-      OnlineCalculatorError errorState;
-      var quality = OnlinePearsonsRCalculator.Calculate(targetValues, estimatedValues, out errorState);
-      if (errorState != OnlineCalculatorError.None) return double.NaN;
-      return quality*quality;
+      var regressionModel = (ISymbolicRegressionModel)model;
+      var regressionProblemData = (IRegressionProblemData)ProblemDataParameter.ActualValue;
+      var evaluator = EvaluatorParameter.ActualValue;
+      var fitnessEvaluationPartition = FitnessCalculationPartitionParameter.ActualValue;
+      var rows = Enumerable.Range(fitnessEvaluationPartition.Start, fitnessEvaluationPartition.Size);
+      return evaluator.Evaluate(this.ExecutionContext, regressionModel.SymbolicExpressionTree, regressionProblemData, rows);
+    }
+
+    public static ISymbolicExpressionTree Prune(ISymbolicExpressionTree tree, SymbolicRegressionSolutionImpactValuesCalculator impactValuesCalculator, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IRegressionProblemData problemData, DoubleLimit estimationLimits, IEnumerable<int> rows, double nodeImpactThreshold = 0.0, bool pruneOnlyZeroImpactNodes = false) {
+      var clonedTree = (ISymbolicExpressionTree)tree.Clone();
+      var model = new SymbolicRegressionModel(clonedTree, interpreter, estimationLimits.Lower, estimationLimits.Upper);
+      var nodes = clonedTree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPrefix().ToList(); // skip the nodes corresponding to the ProgramRootSymbol and the StartSymbol
+
+      double qualityForImpactsCalculation = double.NaN; // pass a NaN value initially so the impact calculator will calculate the quality
+
+      for (int i = 0; i < nodes.Count; ++i) {
+        var node = nodes[i];
+        if (node is ConstantTreeNode) continue;
+
+        double impactValue, replacementValue;
+        double newQualityForImpactsCalculation;
+        impactValuesCalculator.CalculateImpactAndReplacementValues(model, node, problemData, rows, out impactValue, out replacementValue, out newQualityForImpactsCalculation, qualityForImpactsCalculation);
+
+        if (pruneOnlyZeroImpactNodes && !impactValue.IsAlmost(0.0)) continue;
+        if (!pruneOnlyZeroImpactNodes && impactValue > nodeImpactThreshold) continue;
+
+        var constantNode = (ConstantTreeNode)node.Grammar.GetSymbol("Constant").CreateTreeNode();
+        constantNode.Value = replacementValue;
+
+        ReplaceWithConstant(node, constantNode);
+        i += node.GetLength() - 1; // skip subtrees under the node that was folded
+
+        qualityForImpactsCalculation = newQualityForImpactsCalculation;
+      }
+      return model.SymbolicExpressionTree;
     }
   }
Index: stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionSolutionImpactValuesCalculator.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionSolutionImpactValuesCalculator.cs	(revision 12742)
+++ stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionSolutionImpactValuesCalculator.cs	(revision 12745)
@@ -48,13 +48,13 @@
     }
 
-    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);
+    public override double CalculateImpactValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, double qualityForImpactsCalculation = double.NaN) {
+      double impactValue, replacementValue, newQualityForImpactsCalculation;
+      CalculateImpactAndReplacementValues(model, node, problemData, rows, out impactValue, out replacementValue, out newQualityForImpactsCalculation, qualityForImpactsCalculation);
       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) {
+      IDataAnalysisProblemData problemData, IEnumerable<int> rows, out double impactValue, out double replacementValue, out double newQualityForImpactsCalculation,
+      double qualityForImpactsCalculation = Double.NaN) {
       var regressionModel = (ISymbolicRegressionModel)model;
       var regressionProblemData = (IRegressionProblemData)problemData;
@@ -64,9 +64,6 @@
 
       OnlineCalculatorError errorState;
-      if (double.IsNaN(originalQuality)) {
-        var originalValues = regressionModel.GetEstimatedValues(dataset, rows);
-        originalQuality = OnlinePearsonsRCalculator.Calculate(targetValues, originalValues, out errorState);
-        if (errorState != OnlineCalculatorError.None) originalQuality = 0.0;
-      }
+      if (double.IsNaN(qualityForImpactsCalculation))
+        qualityForImpactsCalculation = CalculateQualityForImpacts(regressionModel, regressionProblemData, rows);
 
       replacementValue = CalculateReplacementValue(regressionModel, node, regressionProblemData, rows);
@@ -83,8 +80,19 @@
 
       var estimatedValues = tempModel.GetEstimatedValues(dataset, rows);
-      double newQuality = OnlinePearsonsRCalculator.Calculate(targetValues, estimatedValues, out errorState);
-      if (errorState != OnlineCalculatorError.None) newQuality = 0.0;
+      double r = OnlinePearsonsRCalculator.Calculate(targetValues, estimatedValues, out errorState);
+      if (errorState != OnlineCalculatorError.None) r = 0.0;
+      newQualityForImpactsCalculation = r * r;
 
-      impactValue = (originalQuality*originalQuality) - (newQuality*newQuality);
+      impactValue = qualityForImpactsCalculation - newQualityForImpactsCalculation;
+    }
+
+    public static double CalculateQualityForImpacts(ISymbolicRegressionModel model, IRegressionProblemData problemData, IEnumerable<int> rows) {
+      var estimatedValues = model.GetEstimatedValues(problemData.Dataset, rows); // also bounds the values
+      var targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
+      OnlineCalculatorError errorState;
+      var r = OnlinePearsonsRCalculator.Calculate(targetValues, estimatedValues, out errorState);
+      var quality = r * r;
+      if (errorState != OnlineCalculatorError.None) return double.NaN;
+      return quality;
     }
   }
Index: stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectivePruningAnalyzer.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectivePruningAnalyzer.cs	(revision 12742)
+++ stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectivePruningAnalyzer.cs	(revision 12745)
@@ -45,8 +45,6 @@
     private const string TotalNumberOfPrunedSubtreesParameterName = "Number of pruned subtrees";
     private const string TotalNumberOfPrunedTreesParameterName = "Number of pruned trees";
+    private const string TotalNumberOfPrunedNodesParameterName = "Number of pruned nodes";
     private const string RandomParameterName = "Random";
-    private const string PruneOnlyZeroImpactNodesParameterName = "PruneOnlyZeroImpactNodes";
-    private const string NodeImpactThresholdParameterName = "ImpactThreshold";
-    private const string PruningOperatorParameterName = "PruningOperator";
     private const string ResultsParameterName = "Results";
     private const string PopulationSizeParameterName = "PopulationSize";
@@ -54,4 +52,5 @@
 
     #region private members
+    private DataReducer prunedNodesReducer;
     private DataReducer prunedSubtreesReducer;
     private DataReducer prunedTreesReducer;
@@ -61,13 +60,4 @@
 
     #region parameter properties
-    public IValueParameter<SymbolicDataAnalysisExpressionPruningOperator> PruningOperatorParameter {
-      get { return (IValueParameter<SymbolicDataAnalysisExpressionPruningOperator>)Parameters[PruningOperatorParameterName]; }
-    }
-    public IFixedValueParameter<BoolValue> PruneOnlyZeroImpactNodesParameter {
-      get { return (IFixedValueParameter<BoolValue>)Parameters[PruneOnlyZeroImpactNodesParameterName]; }
-    }
-    public IFixedValueParameter<DoubleValue> NodeImpactThresholdParameter {
-      get { return (IFixedValueParameter<DoubleValue>)Parameters[NodeImpactThresholdParameterName]; }
-    }
     public ILookupParameter<IRandom> RandomParameter {
       get { return (ILookupParameter<IRandom>)Parameters[RandomParameterName]; }
@@ -91,5 +81,5 @@
 
     #region properties
-    protected SymbolicDataAnalysisExpressionPruningOperator PruningOperator { get { return PruningOperatorParameter.Value; } }
+    protected abstract SymbolicDataAnalysisExpressionPruningOperator PruningOperator { get; }
     protected int UpdateInterval { get { return UpdateIntervalParameter.Value.Value; } }
 
@@ -112,13 +102,4 @@
       get { return PruningProbabilityParameter.Value.Value; }
       set { PruningProbabilityParameter.Value.Value = value; }
-    }
-
-    protected bool PruneOnlyZeroImpactNodes {
-      get { return PruneOnlyZeroImpactNodesParameter.Value.Value; }
-      set { PruneOnlyZeroImpactNodesParameter.Value.Value = value; }
-    }
-    protected double NodeImpactThreshold {
-      get { return NodeImpactThresholdParameter.Value.Value; }
-      set { NodeImpactThresholdParameter.Value.Value = value; }
     }
     #endregion
@@ -140,4 +121,6 @@
     protected SymbolicDataAnalysisSingleObjectivePruningAnalyzer(SymbolicDataAnalysisSingleObjectivePruningAnalyzer original, Cloner cloner)
       : base(original, cloner) {
+      if (original.prunedNodesReducer != null)
+        this.prunedNodesReducer = (DataReducer)original.prunedNodesReducer.Clone();
       if (original.prunedSubtreesReducer != null)
         this.prunedSubtreesReducer = (DataReducer)original.prunedSubtreesReducer.Clone();
@@ -197,6 +180,4 @@
       Parameters.Add(new LookupParameter<IRandom>(RandomParameterName, "The random number generator."));
       Parameters.Add(new LookupParameter<IDataAnalysisProblemData>(ProblemDataParameterName, "The problem data."));
-      Parameters.Add(new FixedValueParameter<DoubleValue>(NodeImpactThresholdParameterName, "The impact threshold  below which an individual should be pruned.", new DoubleValue(0.0)));
-      Parameters.Add(new FixedValueParameter<BoolValue>(PruneOnlyZeroImpactNodesParameterName, "Switch to determine of only zero impact individuals should be pruned.", new BoolValue(false)));
       Parameters.Add(new LookupParameter<IntValue>(PopulationSizeParameterName, "The population of individuals."));
       #endregion
@@ -225,5 +206,6 @@
       var qualities = Quality.Select(x => x.Value).ToArray();
       var indices = Enumerable.Range(0, qualities.Length).ToArray();
-      Array.Sort(qualities, indices);
+      indices.StableSort((a, b) => qualities[a].CompareTo(qualities[b]));
+
       if (!Maximization.Value) Array.Reverse(indices);
 
@@ -233,5 +215,5 @@
       var empty = new EmptyOperator();
 
-      for (int i = 0; i < subscopes.Count; ++i) {
+      for (int i = 0; i < indices.Length; ++i) {
         IOperator @operator;
         if (range.Start <= i && i < range.End && random.NextDouble() <= PruningProbability)
@@ -250,7 +232,8 @@
       UpdateCounter = 0;
 
-      if (prunedSubtreesReducer == null || prunedTreesReducer == null || valuesCollector == null || resultsCollector == null) { InitializeOperators(); }
+      if (prunedNodesReducer == null || prunedSubtreesReducer == null || prunedTreesReducer == null || valuesCollector == null || resultsCollector == null) { InitializeOperators(); }
 
       var prune = CreatePruningOperation();
+      var reducePrunedNodes = ExecutionContext.CreateChildOperation(prunedNodesReducer);
       var reducePrunedSubtrees = ExecutionContext.CreateChildOperation(prunedSubtreesReducer);
       var reducePrunedTrees = ExecutionContext.CreateChildOperation(prunedTreesReducer);
@@ -258,8 +241,14 @@
       var collectResults = ExecutionContext.CreateChildOperation(resultsCollector);
 
-      return new OperationCollection { prune, reducePrunedSubtrees, reducePrunedTrees, collectValues, collectResults, base.Apply() };
+      return new OperationCollection { prune, reducePrunedNodes, reducePrunedSubtrees, reducePrunedTrees, collectValues, collectResults, base.Apply() };
     }
 
     private void InitializeOperators() {
+      prunedNodesReducer = new DataReducer();
+      prunedNodesReducer.ParameterToReduce.ActualName = PruningOperator.PrunedNodesParameter.ActualName;
+      prunedNodesReducer.ReductionOperation.Value = new ReductionOperation(ReductionOperations.Sum); // sum all the pruned subtrees parameter values
+      prunedNodesReducer.TargetOperation.Value = new ReductionOperation(ReductionOperations.Assign); // asign the sum to the target parameter
+      prunedNodesReducer.TargetParameter.ActualName = TotalNumberOfPrunedNodesParameterName;
+
       prunedSubtreesReducer = new DataReducer();
       prunedSubtreesReducer.ParameterToReduce.ActualName = PruningOperator.PrunedSubtreesParameter.ActualName;
@@ -275,4 +264,5 @@
 
       valuesCollector = new DataTableValuesCollector();
+      valuesCollector.CollectedValues.Add(new LookupParameter<IntValue>(TotalNumberOfPrunedNodesParameterName));
       valuesCollector.CollectedValues.Add(new LookupParameter<IntValue>(TotalNumberOfPrunedSubtreesParameterName));
       valuesCollector.CollectedValues.Add(new LookupParameter<IntValue>(TotalNumberOfPrunedTreesParameterName));
Index: stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisImpactValuesCalculator.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisImpactValuesCalculator.cs	(revision 12742)
+++ stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisImpactValuesCalculator.cs	(revision 12745)
@@ -6,7 +6,7 @@
   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);
+    double CalculateImpactValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, double qualityForImpactsCalculation = double.NaN);
     void CalculateImpactAndReplacementValues(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData,
-      IEnumerable<int> rows, out double impactValue, out double replacementValue, double originalQuality = double.NaN);
+      IEnumerable<int> rows, out double impactValue, out double replacementValue, out double newQualityForImpactsCalculation, double qualityForImpactsCalculation = double.NaN);
   }
 }
Index: stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionPruningOperator.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionPruningOperator.cs	(revision 12742)
+++ stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionPruningOperator.cs	(revision 12745)
@@ -34,5 +34,5 @@
   [StorableClass]
   [Item("SymbolicExpressionTreePruningOperator", "An operator that replaces introns with constant values in a symbolic expression tree.")]
-  public abstract class SymbolicDataAnalysisExpressionPruningOperator : SingleSuccessorOperator {
+  public abstract class SymbolicDataAnalysisExpressionPruningOperator : SingleSuccessorOperator, ISymbolicExpressionTreeOperator {
     #region parameter names
     private const string ProblemDataParameterName = "ProblemData";
@@ -41,4 +41,5 @@
     private const string PrunedSubtreesParameterName = "PrunedSubtrees";
     private const string PrunedTreesParameterName = "PrunedTrees";
+    private const string PrunedNodesParameterName = "PrunedNodes";
     private const string FitnessCalculationPartitionParameterName = "FitnessCalculationPartition";
     private const string NodeImpactThresholdParameterName = "ImpactThreshold";
@@ -48,4 +49,5 @@
     private const string EstimationLimitsParameterName = "EstimationLimits";
     private const string InterpreterParameterName = "SymbolicExpressionTreeInterpreter";
+    private const string ApplyLinearScalingParameterName = "ApplyLinearScaling";
     #endregion
 
@@ -72,4 +74,7 @@
       get { return (ILookupParameter<IntValue>)Parameters[PrunedTreesParameterName]; }
     }
+    public ILookupParameter<IntValue> PrunedNodesParameter {
+      get { return (ILookupParameter<IntValue>)Parameters[PrunedNodesParameterName]; }
+    }
     public IFixedValueParameter<DoubleValue> NodeImpactThresholdParameter {
       get { return (IFixedValueParameter<DoubleValue>)Parameters[NodeImpactThresholdParameterName]; }
@@ -84,22 +89,22 @@
       get { return (ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>)Parameters[InterpreterParameterName]; }
     }
+    public ILookupParameter<BoolValue> ApplyLinearScalingParameter {
+      get { return (ILookupParameter<BoolValue>)Parameters[ApplyLinearScalingParameterName]; }
+    }
     #endregion
 
     #region properties
-    protected IDataAnalysisProblemData ProblemData { get { return ProblemDataParameter.ActualValue; } }
-    protected ISymbolicDataAnalysisSolutionImpactValuesCalculator ImpactValuesCalculator { get { return ImpactValuesCalculatorParameter.Value; } }
-    protected IntRange FitnessCalculationPartition { get { return FitnessCalculationPartitionParameter.ActualValue; } }
-    protected bool PruneOnlyZeroImpactNodes {
+    public ISymbolicDataAnalysisSolutionImpactValuesCalculator ImpactValuesCalculator {
+      get { return ImpactValuesCalculatorParameter.Value; }
+      set { ImpactValuesCalculatorParameter.Value = value; }
+    }
+    public bool PruneOnlyZeroImpactNodes {
       get { return PruneOnlyZeroImpactNodesParameter.Value.Value; }
       set { PruneOnlyZeroImpactNodesParameter.Value.Value = value; }
     }
-    protected double NodeImpactThreshold {
+    public double NodeImpactThreshold {
       get { return NodeImpactThresholdParameter.Value.Value; }
       set { NodeImpactThresholdParameter.Value.Value = 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
 
@@ -109,9 +114,10 @@
       : base(original, cloner) { }
 
-    protected SymbolicDataAnalysisExpressionPruningOperator() {
+    protected SymbolicDataAnalysisExpressionPruningOperator(ISymbolicDataAnalysisSolutionImpactValuesCalculator impactValuesCalculator) {
       #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>(PrunedNodesParameterName, "A counter of how many nodes were pruned."));
       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."));
@@ -122,19 +128,45 @@
       Parameters.Add(new LookupParameter<ISymbolicExpressionTree>(SymbolicExpressionTreeParameterName));
       Parameters.Add(new LookupParameter<DoubleValue>(QualityParameterName));
+      Parameters.Add(new LookupParameter<BoolValue>(ApplyLinearScalingParameterName));
+      Parameters.Add(new ValueParameter<ISymbolicDataAnalysisSolutionImpactValuesCalculator>(ImpactValuesCalculatorParameterName, impactValuesCalculator));
       #endregion
     }
 
-    protected abstract ISymbolicDataAnalysisModel CreateModel();
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (!Parameters.ContainsKey(PrunedNodesParameterName)) {
+        Parameters.Add(new LookupParameter<IntValue>(PrunedNodesParameterName, "A counter of how many nodes were pruned."));
+      }
+      if (!Parameters.ContainsKey(ApplyLinearScalingParameterName)) {
+        Parameters.Add(new LookupParameter<BoolValue>(ApplyLinearScalingParameterName));
+      }
+      if (!Parameters.ContainsKey(ImpactValuesCalculatorParameterName)) {
+        // value must be set by derived operators (regression/classification)
+        Parameters.Add(new ValueParameter<ISymbolicDataAnalysisSolutionImpactValuesCalculator>(ImpactValuesCalculatorParameterName));
+      }
+      #endregion
+    }
+
+    protected abstract ISymbolicDataAnalysisModel CreateModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IDataAnalysisProblemData problemData, DoubleLimit estimationLimits);
 
     protected abstract double Evaluate(IDataAnalysisModel model);
 
     public override IOperation Apply() {
-      var model = CreateModel();
-      var nodes = SymbolicExpressionTree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPrefix().ToList();
-      var rows = Enumerable.Range(FitnessCalculationPartition.Start, FitnessCalculationPartition.Size);
+      var tree = SymbolicExpressionTreeParameter.ActualValue;
+      var problemData = ProblemDataParameter.ActualValue;
+      var fitnessCalculationPartition = FitnessCalculationPartitionParameter.ActualValue;
+      var estimationLimits = EstimationLimitsParameter.ActualValue;
+      var interpreter = InterpreterParameter.ActualValue;
+
+      var model = CreateModel(tree, interpreter, problemData, estimationLimits);
+      var nodes = tree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPrefix().ToList();
+      var rows = Enumerable.Range(fitnessCalculationPartition.Start, fitnessCalculationPartition.Size).ToList();
       var prunedSubtrees = 0;
       var prunedTrees = 0;
-
-      double quality = Evaluate(model);
+      var prunedNodes = 0;
+
+      double qualityForImpactsCalculation = double.NaN;
 
       for (int i = 0; i < nodes.Count; ++i) {
@@ -143,21 +175,21 @@
 
         double impactValue, replacementValue;
-        ImpactValuesCalculator.CalculateImpactAndReplacementValues(model, node, ProblemData, rows, out impactValue, out replacementValue, quality);
-
-        if (PruneOnlyZeroImpactNodes) {
-          if (!impactValue.IsAlmost(0.0)) continue;
-        } else if (NodeImpactThreshold < impactValue) {
-          continue;
-        }
+        double newQualityForImpacts;
+        ImpactValuesCalculator.CalculateImpactAndReplacementValues(model, node, problemData, rows, out impactValue, out replacementValue, out newQualityForImpacts, qualityForImpactsCalculation);
+
+        if (PruneOnlyZeroImpactNodes && !impactValue.IsAlmost(0.0)) continue;
+        if (!PruneOnlyZeroImpactNodes && impactValue > NodeImpactThreshold) continue;
 
         var constantNode = (ConstantTreeNode)node.Grammar.GetSymbol("Constant").CreateTreeNode();
         constantNode.Value = replacementValue;
 
+        var length = node.GetLength();
         ReplaceWithConstant(node, constantNode);
-        i += node.GetLength() - 1; // skip subtrees under the node that was folded
-
-        quality -= impactValue;
+        i += length - 1; // skip subtrees under the node that was folded
 
         prunedSubtrees++;
+        prunedNodes += length;
+
+        qualityForImpactsCalculation = newQualityForImpacts;
       }
 
@@ -165,9 +197,13 @@
       PrunedSubtreesParameter.ActualValue = new IntValue(prunedSubtrees);
       PrunedTreesParameter.ActualValue = new IntValue(prunedTrees);
+      PrunedNodesParameter.ActualValue = new IntValue(prunedNodes);
+
+      if (prunedSubtrees > 0) // if nothing was pruned then there's no need to re-evaluate the tree
+        QualityParameter.ActualValue.Value = Evaluate(model);
 
       return base.Apply();
     }
 
-    private static void ReplaceWithConstant(ISymbolicExpressionTreeNode original, ISymbolicExpressionTreeNode replacement) {
+    protected static void ReplaceWithConstant(ISymbolicExpressionTreeNode original, ISymbolicExpressionTreeNode replacement) {
       var parent = original.Parent;
       var i = parent.IndexOfSubtree(original);
Index: stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSolutionImpactValuesCalculator.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSolutionImpactValuesCalculator.cs	(revision 12742)
+++ stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSolutionImpactValuesCalculator.cs	(revision 12745)
@@ -37,6 +37,6 @@
     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);
+    public abstract double CalculateImpactValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, double qualityForImpactsCalculation = double.NaN);
+    public abstract void CalculateImpactAndReplacementValues(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, out double impactValue, out double replacementValue, out double newQualityForImpactsCalculation, double qualityForImpactsCalculation = double.NaN);
 
     protected static double CalculateReplacementValue(ISymbolicExpressionTreeNode node, ISymbolicExpressionTree sourceTree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
