Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationPruningAnalyzer.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationPruningAnalyzer.cs	(revision 12188)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationPruningAnalyzer.cs	(revision 12189)
@@ -43,5 +43,5 @@
     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<SymbolicDataAnalysisExpressionPruningOperator>(PruningOperatorParameterName, "The operator used to prune trees", new SymbolicClassificationPruningOperator(new SymbolicClassificationSolutionImpactValuesCalculator())));
     }
   }
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationPruningOperator.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationPruningOperator.cs	(revision 12188)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationPruningOperator.cs	(revision 12189)
@@ -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,4 @@
   [Item("SymbolicClassificationPruningOperator", "An operator which prunes symbolic classificaton trees.")]
   public class SymbolicClassificationPruningOperator : SymbolicDataAnalysisExpressionPruningOperator {
-    private const string ImpactValuesCalculatorParameterName = "ImpactValuesCalculator";
     private const string ModelCreatorParameterName = "ModelCreator";
 
@@ -52,14 +53,14 @@
     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));
     }
 
-    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);
+    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;
     }
@@ -69,6 +70,11 @@
       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);
+
+      return Evaluate(classificationModel, classificationProblemData, trainingIndices);
+    }
+
+    private static double Evaluate(IClassificationModel model, IClassificationProblemData problemData, IEnumerable<int> rows) {
+      var estimatedValues = model.GetEstimatedClassValues(problemData.Dataset, rows);
+      var targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
       OnlineCalculatorError errorState;
       var quality = OnlineAccuracyCalculator.Calculate(targetValues, estimatedValues, out errorState);
@@ -76,4 +82,38 @@
       return quality;
     }
+
+    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.IterateNodesPrefix().ToList();
+      double quality = Evaluate(model, problemData, rows);
+
+      for (int i = 0; i < nodes.Count; ++i) {
+        var node = nodes[i];
+        if (node is ConstantTreeNode) continue;
+
+        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;
+        }
+
+        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
+
+        quality -= impactValue;
+      }
+      return model.SymbolicExpressionTree;
+    }
   }
 }
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionPruningAnalyzer.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionPruningAnalyzer.cs	(revision 12188)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionPruningAnalyzer.cs	(revision 12189)
@@ -45,5 +45,5 @@
     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<SymbolicDataAnalysisExpressionPruningOperator>(PruningOperatorParameterName, "The operator used to prune trees", new SymbolicRegressionPruningOperator(new SymbolicRegressionSolutionImpactValuesCalculator())));
     }
   }
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionPruningOperator.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionPruningOperator.cs	(revision 12188)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionPruningOperator.cs	(revision 12189)
@@ -22,8 +22,9 @@
 #endregion
 
+using System.Collections.Generic;
 using System.Linq;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HeuristicLab.Parameters;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
@@ -32,6 +33,4 @@
   [Item("SymbolicRegressionPruningOperator", "An operator which prunes symbolic regression trees.")]
   public class SymbolicRegressionPruningOperator : SymbolicDataAnalysisExpressionPruningOperator {
-    private const string ImpactValuesCalculatorParameterName = "ImpactValuesCalculator";
-
     protected SymbolicRegressionPruningOperator(SymbolicRegressionPruningOperator original, Cloner cloner)
       : base(original, cloner) {
@@ -44,11 +43,10 @@
     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) {
     }
 
-    protected override ISymbolicDataAnalysisModel CreateModel() {
-      return new SymbolicRegressionModel(SymbolicExpressionTree, Interpreter, EstimationLimits.Lower, EstimationLimits.Upper);
+    protected override ISymbolicDataAnalysisModel CreateModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IDataAnalysisProblemData problemData, DoubleLimit estimationLimits) {
+      return new SymbolicRegressionModel(tree, interpreter, estimationLimits.Lower, estimationLimits.Upper);
     }
 
@@ -56,7 +54,12 @@
       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);
+      var rows = Enumerable.Range(FitnessCalculationPartition.Start, FitnessCalculationPartition.Size);
+      return Evaluate(regressionModel, regressionProblemData, rows);
+    }
+
+    private static double Evaluate(IRegressionModel 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 quality = OnlinePearsonsRSquaredCalculator.Calculate(targetValues, estimatedValues, out errorState);
@@ -64,4 +67,34 @@
       return quality;
     }
+
+    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.IterateNodesPrefix().ToList();
+      double quality = Evaluate(model, problemData, rows);
+
+      for (int i = 0; i < nodes.Count; ++i) {
+        var node = nodes[i];
+        if (node is ConstantTreeNode) continue;
+
+        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;
+        }
+
+        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
+
+        quality -= impactValue;
+      }
+      return model.SymbolicExpressionTree;
+    }
   }
 }
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionPruningOperator.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionPruningOperator.cs	(revision 12188)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionPruningOperator.cs	(revision 12189)
@@ -109,5 +109,5 @@
       : base(original, cloner) { }
 
-    protected SymbolicDataAnalysisExpressionPruningOperator() {
+    protected SymbolicDataAnalysisExpressionPruningOperator(ISymbolicDataAnalysisSolutionImpactValuesCalculator impactValuesCalculator) {
       #region add parameters
       Parameters.Add(new LookupParameter<IDataAnalysisProblemData>(ProblemDataParameterName));
@@ -122,13 +122,14 @@
       Parameters.Add(new LookupParameter<ISymbolicExpressionTree>(SymbolicExpressionTreeParameterName));
       Parameters.Add(new LookupParameter<DoubleValue>(QualityParameterName));
+      Parameters.Add(new ValueParameter<ISymbolicDataAnalysisSolutionImpactValuesCalculator>(ImpactValuesCalculatorParameterName, impactValuesCalculator));
       #endregion
     }
 
-    protected abstract ISymbolicDataAnalysisModel CreateModel();
+    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 model = CreateModel(SymbolicExpressionTree, Interpreter, ProblemData, EstimationLimits);
       var nodes = SymbolicExpressionTree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPrefix().ToList();
       var rows = Enumerable.Range(FitnessCalculationPartition.Start, FitnessCalculationPartition.Size);
@@ -169,5 +170,36 @@
     }
 
-    private static void ReplaceWithConstant(ISymbolicExpressionTreeNode original, ISymbolicExpressionTreeNode replacement) {
+    public ISymbolicExpressionTree Prune(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IDataAnalysisProblemData problemData, DoubleLimit estimationLimits) {
+      var model = CreateModel((ISymbolicExpressionTree)tree.Clone(), Interpreter, ProblemData, EstimationLimits);
+      var nodes = SymbolicExpressionTree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPrefix().ToList();
+      var rows = Enumerable.Range(FitnessCalculationPartition.Start, FitnessCalculationPartition.Size);
+
+      double quality = Evaluate(model);
+
+      for (int i = 0; i < nodes.Count; ++i) {
+        var node = nodes[i];
+        if (node is ConstantTreeNode) continue;
+
+        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;
+        }
+
+        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
+
+        quality -= impactValue;
+      }
+      return model.SymbolicExpressionTree;
+    }
+
+    protected static void ReplaceWithConstant(ISymbolicExpressionTreeNode original, ISymbolicExpressionTreeNode replacement) {
       var parent = original.Parent;
       var i = parent.IndexOfSubtree(original);
