Index: branches/HeuristicLab.Crossovers/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Crossovers/SubtreeCrossover.cs
===================================================================
--- branches/HeuristicLab.Crossovers/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Crossovers/SubtreeCrossover.cs	(revision 7343)
+++ branches/HeuristicLab.Crossovers/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Crossovers/SubtreeCrossover.cs	(revision 7477)
@@ -28,4 +28,5 @@
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
 
 namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding {
@@ -37,9 +38,12 @@
   /// </summary>  
   [Item("SubtreeCrossover", "An operator which performs subtree swapping crossover.")]
+  [NonDiscoverableType]
   [StorableClass]
-  public sealed class SubtreeCrossover : SymbolicExpressionTreeCrossover, ISymbolicExpressionTreeSizeConstraintOperator {
+  public class SubtreeCrossover : SymbolicExpressionTreeCrossover, ISymbolicExpressionTreeSizeConstraintOperator {
     private const string InternalCrossoverPointProbabilityParameterName = "InternalCrossoverPointProbability";
     private const string MaximumSymbolicExpressionTreeLengthParameterName = "MaximumSymbolicExpressionTreeLength";
     private const string MaximumSymbolicExpressionTreeDepthParameterName = "MaximumSymbolicExpressionTreeDepth";
+    private const string SymbolicDataAnalysisEvaluationPartitionParameterName = "EvaluationPartition";
+
     #region Parameter Properties
     public IValueLookupParameter<PercentValue> InternalCrossoverPointProbabilityParameter {
@@ -51,4 +55,7 @@
     public IValueLookupParameter<IntValue> MaximumSymbolicExpressionTreeDepthParameter {
       get { return (IValueLookupParameter<IntValue>)Parameters[MaximumSymbolicExpressionTreeDepthParameterName]; }
+    }
+    public IValueLookupParameter<IntRange> SymbolicDataAnalysisEvaluationPartitionParameter {
+      get { return (IValueLookupParameter<IntRange>)Parameters[SymbolicDataAnalysisEvaluationPartitionParameterName]; }
     }
     #endregion
@@ -65,6 +72,6 @@
     #endregion
     [StorableConstructor]
-    private SubtreeCrossover(bool deserializing) : base(deserializing) { }
-    private SubtreeCrossover(SubtreeCrossover original, Cloner cloner) : base(original, cloner) { }
+    protected SubtreeCrossover(bool deserializing) : base(deserializing) { }
+    protected SubtreeCrossover(SubtreeCrossover original, Cloner cloner) : base(original, cloner) { }
     public SubtreeCrossover()
       : base() {
@@ -72,4 +79,5 @@
       Parameters.Add(new ValueLookupParameter<IntValue>(MaximumSymbolicExpressionTreeDepthParameterName, "The maximal depth of the symbolic expression tree (a tree with one node has depth = 0)."));
       Parameters.Add(new ValueLookupParameter<PercentValue>(InternalCrossoverPointProbabilityParameterName, "The probability to select an internal crossover point (instead of a leaf node).", new PercentValue(0.9)));
+      Parameters.Add(new ValueLookupParameter<IntRange>(SymbolicDataAnalysisEvaluationPartitionParameterName, "The start index of the dataset partition on which the symbolic data analysis solution should be evaluated."));
     }
 
@@ -82,4 +90,8 @@
       return Cross(random, parent0, parent1, InternalCrossoverPointProbability.Value,
         MaximumSymbolicExpressionTreeLength.Value, MaximumSymbolicExpressionTreeDepth.Value);
+    }
+
+    public ISymbolicExpressionTree Crossover(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1) {
+      return Cross(random, parent0, parent1);
     }
 
@@ -94,15 +106,14 @@
       // calculate the max length and depth that the inserted branch can have 
       int maxInsertedBranchLength = maxTreeLength - (parent0.Length - childLength);
-      int maxInsertedBranchDepth = maxTreeDepth - GetBranchLevel(parent0.Root, crossoverPoint0.Parent);
+      int maxInsertedBranchDepth = maxTreeDepth - parent0.Root.GetBranchLevel(crossoverPoint0.Parent);
 
       List<ISymbolicExpressionTreeNode> allowedBranches = new List<ISymbolicExpressionTreeNode>();
       parent1.Root.ForEachNodePostfix((n) => {
         if (n.GetLength() <= maxInsertedBranchLength &&
-            n.GetDepth() <= maxInsertedBranchDepth &&
-            IsMatchingPointType(crossoverPoint0, n))
+            n.GetDepth() <= maxInsertedBranchDepth && crossoverPoint0.IsMatchingPointType(n))
           allowedBranches.Add(n);
       });
       // empty branch
-      if (IsMatchingPointType(crossoverPoint0, null)) allowedBranches.Add(null);
+      if (crossoverPoint0.IsMatchingPointType(null)) allowedBranches.Add(null);
 
       if (allowedBranches.Count == 0) {
@@ -125,28 +136,4 @@
         }
         return parent0;
-      }
-    }
-
-    private static bool IsMatchingPointType(CutPoint cutPoint, ISymbolicExpressionTreeNode newChild) {
-      var parent = cutPoint.Parent;
-      if (newChild == null) {
-        // make sure that one subtree can be removed and that only the last subtree is removed 
-        return parent.Grammar.GetMinimumSubtreeCount(parent.Symbol) < parent.SubtreeCount &&
-          cutPoint.ChildIndex == parent.SubtreeCount - 1;
-      } else {
-        // check syntax constraints of direct parent - child relation
-        if (!parent.Grammar.ContainsSymbol(newChild.Symbol) ||
-            !parent.Grammar.IsAllowedChildSymbol(parent.Symbol, newChild.Symbol, cutPoint.ChildIndex)) return false;
-
-        bool result = true;
-        // check point type for the whole branch
-        newChild.ForEachNodePostfix((n) => {
-          result =
-            result &&
-            parent.Grammar.ContainsSymbol(n.Symbol) &&
-            n.SubtreeCount >= parent.Grammar.GetMinimumSubtreeCount(n.Symbol) &&
-            n.SubtreeCount <= parent.Grammar.GetMaximumSubtreeCount(n.Symbol);
-        });
-        return result;
       }
     }
@@ -226,13 +213,4 @@
       }
     }
-
-    private static int GetBranchLevel(ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode point) {
-      if (root == point) return 0;
-      foreach (var subtree in root.Subtrees) {
-        int branchLevel = GetBranchLevel(subtree, point);
-        if (branchLevel < int.MaxValue) return 1 + branchLevel;
-      }
-      return int.MaxValue;
-    }
   }
 }
