Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectivePruningAnalyzer.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectivePruningAnalyzer.cs	(revision 10457)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectivePruningAnalyzer.cs	(revision 10459)
@@ -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: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 10457)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 10459)
@@ -173,5 +173,5 @@
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="Analyzers\SymbolicDataAnalysisSingleObjectivePruningAnalyzer.cs" /> 
+    <Compile Include="Analyzers\SymbolicDataAnalysisSingleObjectivePruningAnalyzer.cs" />
     <Compile Include="Analyzers\SymbolicDataAnalysisGenealogyAnalyzer.cs" />
     <Compile Include="Analyzers\SymbolicDataAnalysisPopulationDiversityAnalyzer.cs" />
@@ -295,6 +295,6 @@
     <Compile Include="Symbols\VariableConditionTreeNode.cs" />
     <Compile Include="Symbols\VariableTreeNode.cs" />
-    <Compile Include="Tracking\SymbolicDataAnalysExpressionAfterCrossoverOperator.cs" />
-    <Compile Include="Tracking\SymbolicDataAnalysExpressionBeforeCrossoverOperator.cs" />
+    <Compile Include="Tracking\SymbolicDataAnalysisExpressionAfterCrossoverOperator.cs" />
+    <Compile Include="Tracking\SymbolicDataAnalysisExpressionBeforeCrossoverOperator.cs" />
     <Compile Include="Tracking\SymbolicDataAnalysisExpressionAfterManipulatorOperator.cs" />
     <Compile Include="Tracking\SymbolicDataAnalysisExpressionBeforeManipulatorOperator.cs" />
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisImpactValuesCalculator.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisImpactValuesCalculator.cs	(revision 10457)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisImpactValuesCalculator.cs	(revision 10459)
@@ -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: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionPruningOperator.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionPruningOperator.cs	(revision 10457)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionPruningOperator.cs	(revision 10459)
@@ -34,74 +34,121 @@
   [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((IRegressionModel)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; }
-      }
+      //      Quality.Value = quality; // update quality according to what has been pruned
+
+      if (prunedSubtrees > 0) prunedTrees = 1;
+      PrunedSubtreesParameter.ActualValue = new IntValue(prunedSubtrees);
+      PrunedTreesParameter.ActualValue = new IntValue(prunedTrees);
+
       return base.Apply();
     }
@@ -112,4 +159,7 @@
       parent.InsertSubtree(i, replacement);
     }
+    protected abstract ISymbolicDataAnalysisModel CreateModel();
+    protected abstract double Evaluate();
+    protected abstract double Evaluate(IDataAnalysisModel model);
   }
 }
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs	(revision 10457)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs	(revision 10459)
@@ -356,6 +356,6 @@
       // add tracking analyzer
       foreach (var op in operators.OfType<SymbolicDataAnalysisGenealogyAnalyzer>()) {
-        //        op.BeforeCrossoverOperator = new SymbolicDataAnalysExpressionBeforeCrossoverOperator();
-        //        op.AfterCrossoverOperator = new SymbolicDataAnalysExpressionAfterCrossoverOperator();
+        //        op.BeforeCrossoverOperator = new SymbolicDataAnalysisExpressionBeforeCrossoverOperator();
+        //        op.AfterCrossoverOperator = new SymbolicDataAnalysisExpressionAfterCrossoverOperator();
         op.BeforeCrossoverOperator = new BeforeCrossoverOperator<ISymbolicExpressionTree>();
         op.AfterCrossoverOperator = new AfterCrossoverOperator<ISymbolicExpressionTree>();
@@ -373,4 +373,5 @@
           op.ManipulatorChildParameterName = manipulator.SymbolicExpressionTreeParameter.Name;
         }
+        op.PopulationParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
       }
     }
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSolutionImpactValuesCalculator.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSolutionImpactValuesCalculator.cs	(revision 10457)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSolutionImpactValuesCalculator.cs	(revision 10459)
@@ -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,
@@ -47,4 +58,6 @@
       return interpreter.GetSymbolicExpressionTreeValues(tempTree, dataset, rows).Median();
     }
+
+
   }
 }
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/SymbolicDataAnalysExpressionAfterCrossoverOperator.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/SymbolicDataAnalysExpressionAfterCrossoverOperator.cs	(revision 10457)
+++ 	(revision )
@@ -1,39 +1,0 @@
-﻿using System;
-using System.Collections.Generic;
-using System.Linq;
-using HeuristicLab.Core;
-using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
-using HeuristicLab.EvolutionTracking;
-
-namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
-  public class SymbolicDataAnalysExpressionAfterCrossoverOperator : AfterCrossoverOperator<ISymbolicExpressionTree> {
-    public override IOperation Apply() {
-      var childVertex = GenealogyGraph[ChildParameter.ActualValue].Last();
-      var arc0 = (IGenealogyGraphArc)childVertex.InArcs[0];
-      var arc1 = (IGenealogyGraphArc)childVertex.InArcs[1];
-      var nodes0 = (List<ISymbolicExpressionTreeNode>)arc0.Data;
-      var nodes1 = (List<ISymbolicExpressionTreeNode>)arc1.Data;
-      var childNodes = ChildParameter.ActualValue.IterateNodesBreadth().ToList();
-      IFragment<ISymbolicExpressionTreeNode> fragment = null;
-
-      for (int i = 0; i < Math.Min(nodes0.Count, childNodes.Count); ++i) {
-        if (nodes0[i] == childNodes[i]) continue;
-        fragment = new Fragment<ISymbolicExpressionTreeNode> {
-          Root = childNodes[i],
-          NewPos = i
-        };
-      }
-      if (fragment == null) throw new Exception("Could not determine fragment!");
-
-      for (int i = 0; i < nodes1.Count; ++i) {
-        if (nodes1[i] != fragment.Root) continue;
-        fragment.OldPos = i;
-      }
-
-      arc0.Data = null;
-      arc1.Data = fragment;
-
-      return base.Apply();
-    }
-  }
-}
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/SymbolicDataAnalysExpressionBeforeCrossoverOperator.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/SymbolicDataAnalysExpressionBeforeCrossoverOperator.cs	(revision 10457)
+++ 	(revision )
@@ -1,23 +1,0 @@
-﻿using System.Linq;
-using HeuristicLab.Core;
-using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
-using HeuristicLab.EvolutionTracking;
-
-namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
-  public class SymbolicDataAnalysExpressionBeforeCrossoverOperator : BeforeCrossoverOperator<ISymbolicExpressionTree> {
-    public override IOperation Apply() {
-      var result = base.Apply();
-      var parents = ParentsParameter.ActualValue.ToList();
-      var childVertex = GenealogyGraph[parents[0]].Last(); // use the parent since it is actually the child before crossover (and the ChildParameter doesn't have a value yet)
-      //      var parentVertices = ExecutionContext.Scope.SubScopes.Select(s => CurrentGeneration[int.Parse(s.Name)]).ToList();
-
-      for (int i = 0; i < parents.Count; ++i) {
-        var nodes = parents[i].IterateNodesBreadth().ToList();
-        var arc = (IGenealogyGraphArc)childVertex.InArcs[i];
-        arc.Data = nodes;
-      }
-
-      return result;
-    }
-  }
-}
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/SymbolicDataAnalysisExpressionAfterCrossoverOperator.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/SymbolicDataAnalysisExpressionAfterCrossoverOperator.cs	(revision 10459)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/SymbolicDataAnalysisExpressionAfterCrossoverOperator.cs	(revision 10459)
@@ -0,0 +1,39 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.EvolutionTracking;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  public class SymbolicDataAnalysisExpressionAfterCrossoverOperator : AfterCrossoverOperator<ISymbolicExpressionTree> {
+    public override IOperation Apply() {
+      var childVertex = GenealogyGraph[ChildParameter.ActualValue].Last();
+      var arc0 = (IGenealogyGraphArc)childVertex.InArcs[0];
+      var arc1 = (IGenealogyGraphArc)childVertex.InArcs[1];
+      var nodes0 = (List<ISymbolicExpressionTreeNode>)arc0.Data;
+      var nodes1 = (List<ISymbolicExpressionTreeNode>)arc1.Data;
+      var childNodes = ChildParameter.ActualValue.IterateNodesBreadth().ToList();
+      IFragment<ISymbolicExpressionTreeNode> fragment = null;
+
+      for (int i = 0; i < Math.Min(nodes0.Count, childNodes.Count); ++i) {
+        if (nodes0[i] == childNodes[i]) continue;
+        fragment = new Fragment<ISymbolicExpressionTreeNode> {
+          Root = childNodes[i],
+          NewPos = i
+        };
+      }
+      if (fragment == null) throw new Exception("Could not determine fragment!");
+
+      for (int i = 0; i < nodes1.Count; ++i) {
+        if (nodes1[i] != fragment.Root) continue;
+        fragment.OldPos = i;
+      }
+
+      arc0.Data = null;
+      arc1.Data = fragment;
+
+      return base.Apply();
+    }
+  }
+}
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/SymbolicDataAnalysisExpressionBeforeCrossoverOperator.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/SymbolicDataAnalysisExpressionBeforeCrossoverOperator.cs	(revision 10459)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/SymbolicDataAnalysisExpressionBeforeCrossoverOperator.cs	(revision 10459)
@@ -0,0 +1,23 @@
+﻿using System.Linq;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.EvolutionTracking;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  public class SymbolicDataAnalysisExpressionBeforeCrossoverOperator : BeforeCrossoverOperator<ISymbolicExpressionTree> {
+    public override IOperation Apply() {
+      var result = base.Apply();
+      var parents = ParentsParameter.ActualValue.ToList();
+      var childVertex = GenealogyGraph[parents[0]].Last(); // use the parent since it is actually the child before crossover (and the ChildParameter doesn't have a value yet)
+      //      var parentVertices = ExecutionContext.Scope.SubScopes.Select(s => CurrentGeneration[int.Parse(s.Name)]).ToList();
+
+      for (int i = 0; i < parents.Count; ++i) {
+        var nodes = parents[i].IterateNodesBreadth().ToList();
+        var arc = (IGenealogyGraphArc)childVertex.InArcs[i];
+        arc.Data = nodes;
+      }
+
+      return result;
+    }
+  }
+}
