Index: branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/MultiSymbolicDataAnalysisExpressionCrossover.cs
===================================================================
--- branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/MultiSymbolicDataAnalysisExpressionCrossover.cs	(revision 7476)
+++ branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/MultiSymbolicDataAnalysisExpressionCrossover.cs	(revision 7476)
@@ -0,0 +1,162 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Crossovers {
+  public class MultiSymbolicDataAnalysisExpressionCrossover<T> : StochasticMultiBranch<ISymbolicDataAnalysisExpressionCrossover<T>>,
+    ISymbolicDataAnalysisExpressionCrossover<T>,
+    ISymbolicExpressionTreeSizeConstraintOperator,
+    ISymbolicExpressionTreeGrammarBasedOperator where T : class, IDataAnalysisProblemData {
+    private const string MaximumSymbolicExpressionTreeLengthParameterName = "MaximumSymbolicExpressionTreeLength";
+    private const string MaximumSymbolicExpressionTreeDepthParameterName = "MaximumSymbolicExpressionTreeDepth";
+    private const string SymbolicExpressionTreeGrammarParameterName = "SymbolicExpressionTreeGrammar";
+    private const string ClonedSymbolicExpressionTreeGrammarParameterName = "ClonedSymbolicExpressionTreeGrammar";
+    private const string EvaluatorParameterName = "Evaluator";
+    private const string SymbolicDataAnalysisEvaluationPartitionParameterName = "EvaluationPartition";
+    private const string ParentsParameterName = "Parents";
+    private const string ChildParameterName = "Child";
+
+    public override bool CanChangeName {
+      get { return true; }
+    }
+    protected override bool CreateChildOperation {
+      get { return true; }
+    }
+
+    #region parameter properties
+    public ILookupParameter<ItemArray<ISymbolicExpressionTree>> ParentsParameter {
+      get { return (ScopeTreeLookupParameter<ISymbolicExpressionTree>)Parameters[ParentsParameterName]; }
+    }
+    public ILookupParameter<ISymbolicExpressionTree> ChildParameter {
+      get { return (ILookupParameter<ISymbolicExpressionTree>)Parameters[ChildParameterName]; }
+    }
+    public IValueLookupParameter<IntValue> MaximumSymbolicExpressionTreeLengthParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters[MaximumSymbolicExpressionTreeLengthParameterName]; }
+    }
+    public IValueLookupParameter<IntValue> MaximumSymbolicExpressionTreeDepthParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters[MaximumSymbolicExpressionTreeDepthParameterName]; }
+    }
+    public IValueLookupParameter<ISymbolicExpressionGrammar> SymbolicExpressionTreeGrammarParameter {
+      get { return (IValueLookupParameter<ISymbolicExpressionGrammar>)Parameters[SymbolicExpressionTreeGrammarParameterName]; }
+    }
+    public ILookupParameter<ISymbolicExpressionGrammar> ClonedSymbolicExpressionTreeGrammarParameter {
+      get { return (ILookupParameter<ISymbolicExpressionGrammar>)Parameters[ClonedSymbolicExpressionTreeGrammarParameterName]; }
+    }
+    public ILookupParameter<ISymbolicDataAnalysisSingleObjectiveEvaluator<T>> EvaluatorParameter {
+      get { return (ILookupParameter<ISymbolicDataAnalysisSingleObjectiveEvaluator<T>>)Parameters[EvaluatorParameterName]; }
+    }
+    public IValueLookupParameter<IntRange> SymbolicDataAnalysisEvaluationPartitionParameter {
+      get { return (IValueLookupParameter<IntRange>)Parameters[SymbolicDataAnalysisEvaluationPartitionParameterName]; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected MultiSymbolicDataAnalysisExpressionCrossover(bool deserializing) : base(deserializing) { }
+    protected MultiSymbolicDataAnalysisExpressionCrossover(MultiSymbolicDataAnalysisExpressionCrossover<T> original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) { return new MultiSymbolicDataAnalysisExpressionCrossover<T>(this, cloner); }
+    public MultiSymbolicDataAnalysisExpressionCrossover()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<IntValue>(MaximumSymbolicExpressionTreeLengthParameterName, "The maximal length (number of nodes) of the symbolic expression tree."));
+      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<ISymbolicExpressionGrammar>(SymbolicExpressionTreeGrammarParameterName, "The tree grammar that defines the correct syntax of symbolic expression trees that should be created."));
+      Parameters.Add(new LookupParameter<ISymbolicExpressionGrammar>(ClonedSymbolicExpressionTreeGrammarParameterName, "An immutable clone of the concrete grammar that is actually used to create and manipulate trees."));
+      Parameters.Add(new LookupParameter<ISymbolicDataAnalysisSingleObjectiveEvaluator<T>>(EvaluatorParameterName, "The single objective solution evaluator"));
+      Parameters.Add(new ValueLookupParameter<IntRange>(SymbolicDataAnalysisEvaluationPartitionParameterName, "The start index of the dataset partition on which the symbolic data analysis solution should be evaluated."));
+      Parameters.Add(new ScopeTreeLookupParameter<ISymbolicExpressionTree>(ParentsParameterName, "The parent symbolic expression trees which should be crossed."));
+      Parameters.Add(new LookupParameter<ISymbolicExpressionTree>(ChildParameterName, "The child symbolic expression tree resulting from the crossover."));
+
+      var list = (from type in ApplicationManager.Manager.GetTypes(typeof(ISymbolicDataAnalysisExpressionCrossover<T>))
+                  where this.GetType().Assembly == type.Assembly
+                  where !typeof(IMultiOperator<ISymbolicDataAnalysisExpressionCrossover<T>>).IsAssignableFrom(type)
+                  select (ISymbolicDataAnalysisExpressionCrossover<T>)Activator.CreateInstance(type)).ToList();
+
+      var checkedItemList = new CheckedItemList<ISymbolicDataAnalysisExpressionCrossover<T>>();
+      checkedItemList.AddRange(list.OrderBy(op => op.Name));
+      Operators = checkedItemList.AsReadOnly();
+      Operators_ItemsAdded(this, new CollectionItemsChangedEventArgs<IndexedItem<ISymbolicDataAnalysisExpressionCrossover<T>>>(Operators.CheckedItems));
+      Name = "MultiCrossover";
+    }
+
+    public override IOperation Apply() {
+      if (ClonedSymbolicExpressionTreeGrammarParameter.ActualValue == null) {
+        SymbolicExpressionTreeGrammarParameter.ActualValue.ReadOnly = true;
+        IScope globalScope = ExecutionContext.Scope;
+        while (globalScope.Parent != null)
+          globalScope = globalScope.Parent;
+
+        globalScope.Variables.Add(new Core.Variable(ClonedSymbolicExpressionTreeGrammarParameterName, (ISymbolicExpressionGrammar)SymbolicExpressionTreeGrammarParameter.ActualValue.Clone()));
+      }
+      return base.Apply();
+    }
+
+    public ISymbolicExpressionTree Crossover(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1) {
+      double sum = Operators.CheckedItems.Sum(o => Probabilities[o.Index]);
+      if (sum.IsAlmost(0)) throw new InvalidOperationException(Name + ": All selected operators have zero probability.");
+      double r = random.NextDouble() * sum;
+      sum = 0;
+      int index = -1;
+      foreach (var indexedItem in Operators.CheckedItems) {
+        sum += Probabilities[indexedItem.Index];
+        if (sum > r) {
+          index = indexedItem.Index;
+          break;
+        }
+      }
+      return Operators[index].Crossover(random, parent0, parent1);
+    }
+
+    protected override void Operators_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<ISymbolicDataAnalysisExpressionCrossover<T>>> e) {
+      base.Operators_ItemsReplaced(sender, e);
+      ParameterizeCrossovers();
+    }
+
+    protected override void Operators_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<ISymbolicDataAnalysisExpressionCrossover<T>>> e) {
+      base.Operators_ItemsAdded(sender, e);
+      ParameterizeCrossovers();
+    }
+
+    private void ParameterizeCrossovers() {
+      foreach (IStochasticOperator op in Operators.OfType<IStochasticOperator>()) {
+        op.RandomParameter.ActualName = RandomParameter.Name;
+      }
+      foreach (ISymbolicExpressionTreeSizeConstraintOperator op in Operators.OfType<ISymbolicExpressionTreeSizeConstraintOperator>()) {
+        op.MaximumSymbolicExpressionTreeDepthParameter.ActualName = MaximumSymbolicExpressionTreeDepthParameter.Name;
+        op.MaximumSymbolicExpressionTreeLengthParameter.ActualName = MaximumSymbolicExpressionTreeLengthParameter.Name;
+      }
+      foreach (ISymbolicExpressionTreeGrammarBasedOperator op in Operators.OfType<ISymbolicExpressionTreeGrammarBasedOperator>()) {
+        op.SymbolicExpressionTreeGrammarParameter.ActualName = SymbolicExpressionTreeGrammarParameter.Name;
+      }
+    }
+  }
+}
Index: branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionContextAwareCrossover.cs
===================================================================
--- branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionContextAwareCrossover.cs	(revision 7476)
+++ branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionContextAwareCrossover.cs	(revision 7476)
@@ -0,0 +1,127 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+
+  [Item("ContextAwareCrossover", "An operator which deterministically choses the best insertion point for a randomly selected node.")]
+  public sealed class SymbolicDataAnalysisExpressionContextAwareCrossover<T> : SymbolicDataAnalysisExpressionCrossover<T> where T : class, IDataAnalysisProblemData {
+    [StorableConstructor]
+    private SymbolicDataAnalysisExpressionContextAwareCrossover(bool deserializing) : base(deserializing) { }
+    private SymbolicDataAnalysisExpressionContextAwareCrossover(SymbolicDataAnalysisExpressionCrossover<T> original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public SymbolicDataAnalysisExpressionContextAwareCrossover()
+      : base() {
+      Name = "ContextAwareCrossover";
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SymbolicDataAnalysisExpressionContextAwareCrossover<T>(this, cloner);
+    }
+    protected override ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1) {
+      if (this.ExecutionContext == null)
+        throw new InvalidOperationException("ExecutionContext not set.");
+      List<int> rows = GenerateRowsToEvaluate().ToList();
+      T problemData = ProblemDataParameter.ActualValue;
+      ISymbolicDataAnalysisSingleObjectiveEvaluator<T> evaluator = EvaluatorParameter.ActualValue;
+
+      return Cross(random, parent0, parent1, this.ExecutionContext, evaluator, problemData, rows, MaximumSymbolicExpressionTreeDepth.Value, MaximumSymbolicExpressionTreeLength.Value);
+    }
+
+    public override ISymbolicExpressionTree Crossover(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1) {
+      return Cross(random, parent0, parent1);
+    }
+
+    /// <summary>
+    /// Takes two parent individuals P0 and P1. 
+    /// Randomly choose a node i from the second parent, then test all possible crossover points from the first parent to determine the best location for i to be inserted.
+    /// </summary>
+    public static ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1, IExecutionContext context,
+                                                ISymbolicDataAnalysisSingleObjectiveEvaluator<T> evaluator, T problemData, List<int> rows, int maxDepth, int maxLength) {
+      // randomly choose a node from the second parent
+      var possibleChildren = new List<ISymbolicExpressionTreeNode>();
+      parent1.Root.ForEachNodePostfix((n) => {
+        if (n.Subtrees.Any() && n != parent0.Root)
+          possibleChildren.AddRange(n.Subtrees);
+      });
+      var selectedChild = possibleChildren.SelectRandom(random);
+      var crossoverPoints = new List<CutPoint>();
+      var qualities = new List<Tuple<CutPoint, double>>();
+
+      parent0.Root.ForEachNodePostfix((n) => {
+        if (n.Subtrees.Any() && n != parent0.Root)
+          crossoverPoints.AddRange(from s in n.Subtrees
+                                   let crossoverPoint = new CutPoint(n, s)
+                                   let totalDepth = parent0.Root.GetBranchLevel(s) + selectedChild.GetDepth()
+                                   let totalLength = parent0.Root.GetLength() - s.GetLength() + selectedChild.GetLength()
+                                   where crossoverPoint.IsMatchingPointType(selectedChild) && totalDepth <= maxDepth && totalLength <= maxLength
+                                   select crossoverPoint);
+      });
+
+      if (crossoverPoints.Any()) {
+        // this loop will perform two swap operations per each crossover point
+        foreach (var crossoverPoint in crossoverPoints) {
+          // save the old parent so we can restore it later
+          var parent = selectedChild.Parent;
+          // perform a swap and check the quality of the solution
+          swap(crossoverPoint, selectedChild);
+          double quality = evaluator.Evaluate(context, parent0, problemData, rows);
+          qualities.Add(new Tuple<CutPoint, double>(crossoverPoint, quality));
+          // restore the correct parent
+          selectedChild.Parent = parent;
+          // swap the replaced subtree back into the tree so that the structure is preserved
+          swap(crossoverPoint, crossoverPoint.Child);
+        }
+
+        qualities.Sort((a, b) => a.Item2.CompareTo(b.Item2)); // assuming this sorts the list in ascending order
+        var crossoverPoint0 = evaluator.Maximization ? qualities.Last().Item1 : qualities.First().Item1;
+        // swap the node that would create the best offspring
+        // this last swap makes a total of (2 * crossoverPoints.Count() + 1) swap operations.
+        swap(crossoverPoint0, selectedChild);
+      }
+
+      return parent0;
+    }
+
+    private static void swap(CutPoint crossoverPoint, ISymbolicExpressionTreeNode selectedBranch) {
+      if (crossoverPoint.Child != null) {
+        // manipulate the tree of parent0 in place
+        // replace the branch in tree0 with the selected branch from tree1
+        crossoverPoint.Parent.RemoveSubtree(crossoverPoint.ChildIndex);
+        if (selectedBranch != null) {
+          crossoverPoint.Parent.InsertSubtree(crossoverPoint.ChildIndex, selectedBranch);
+        }
+      } else {
+        // child is null (additional child should be added under the parent)
+        if (selectedBranch != null) {
+          crossoverPoint.Parent.AddSubtree(selectedBranch);
+        }
+      }
+    }
+  }
+}
Index: branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionCrossover.cs
===================================================================
--- branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionCrossover.cs	(revision 7476)
+++ branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionCrossover.cs	(revision 7476)
@@ -0,0 +1,156 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  public abstract class SymbolicDataAnalysisExpressionCrossover<T> : SymbolicExpressionTreeCrossover, ISymbolicDataAnalysisExpressionCrossover<T> where T : class, IDataAnalysisProblemData {
+    private const string SymbolicDataAnalysisTreeInterpreterParameterName = "SymbolicExpressionTreeInterpreter";
+    private const string ProblemDataParameterName = "ProblemData";
+    private const string EstimationLimitsParameterName = "EstimationLimits";
+    private const string EvaluatorParameterName = "Evaluator";
+    private const string SymbolicDataAnalysisEvaluationPartitionParameterName = "EvaluationPartition";
+    private const string RelativeNumberOfEvaluatedSamplesParameterName = "RelativeNumberOfEvaluatedSamples";
+    private const string MaximumSymbolicExpressionTreeLengthParameterName = "MaximumSymbolicExpressionTreeLength";
+    private const string MaximumSymbolicExpressionTreeDepthParameterName = "MaximumSymbolicExpressionTreeDepth";
+
+    public override bool CanChangeName { get { return true; } }
+
+    #region Parameter properties
+    public ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter> SymbolicDataAnalysisTreeInterpreterParameter {
+      get { return (ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>)Parameters[SymbolicDataAnalysisTreeInterpreterParameterName]; }
+    }
+    public IValueLookupParameter<T> ProblemDataParameter {
+      get { return (IValueLookupParameter<T>)Parameters[ProblemDataParameterName]; }
+    }
+    public ILookupParameter<ISymbolicDataAnalysisSingleObjectiveEvaluator<T>> EvaluatorParameter {
+      get { return (ILookupParameter<ISymbolicDataAnalysisSingleObjectiveEvaluator<T>>)Parameters[EvaluatorParameterName]; }
+    }
+    public IValueLookupParameter<IntRange> SymbolicDataAnalysisEvaluationPartitionParameter {
+      get { return (IValueLookupParameter<IntRange>)Parameters[SymbolicDataAnalysisEvaluationPartitionParameterName]; }
+    }
+    public IValueLookupParameter<DoubleLimit> EstimationLimitsParameter {
+      get { return (IValueLookupParameter<DoubleLimit>)Parameters[EstimationLimitsParameterName]; }
+    }
+    public IValueLookupParameter<PercentValue> RelativeNumberOfEvaluatedSamplesParameter {
+      get { return (IValueLookupParameter<PercentValue>)Parameters[RelativeNumberOfEvaluatedSamplesParameterName]; }
+    }
+    public IValueLookupParameter<IntValue> MaximumSymbolicExpressionTreeLengthParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters[MaximumSymbolicExpressionTreeLengthParameterName]; }
+    }
+    public IValueLookupParameter<IntValue> MaximumSymbolicExpressionTreeDepthParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters[MaximumSymbolicExpressionTreeDepthParameterName]; }
+    }
+    #endregion
+
+    #region Properties
+    public IntValue MaximumSymbolicExpressionTreeLength {
+      get { return MaximumSymbolicExpressionTreeLengthParameter.ActualValue; }
+    }
+    public IntValue MaximumSymbolicExpressionTreeDepth {
+      get { return MaximumSymbolicExpressionTreeDepthParameter.ActualValue; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected SymbolicDataAnalysisExpressionCrossover(bool deserializing) : base(deserializing) { }
+    protected SymbolicDataAnalysisExpressionCrossover(SymbolicDataAnalysisExpressionCrossover<T> original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public SymbolicDataAnalysisExpressionCrossover()
+      : base() {
+      Parameters.Add(new LookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>(SymbolicDataAnalysisTreeInterpreterParameterName, "The interpreter that should be used to calculate the output values of the symbolic data analysis tree."));
+      Parameters.Add(new LookupParameter<ISymbolicDataAnalysisSingleObjectiveEvaluator<T>>(EvaluatorParameterName, "The single objective solution evaluator"));
+      Parameters.Add(new ValueLookupParameter<T>(ProblemDataParameterName, "The problem data on which the symbolic data analysis solution should be evaluated."));
+      Parameters.Add(new ValueLookupParameter<IntRange>(SymbolicDataAnalysisEvaluationPartitionParameterName, "The start index of the dataset partition on which the symbolic data analysis solution should be evaluated."));
+      Parameters.Add(new ValueLookupParameter<DoubleLimit>(EstimationLimitsParameterName, "The upper and lower limit that should be used as cut off value for the output values of symbolic data analysis trees."));
+      Parameters.Add(new ValueLookupParameter<PercentValue>(RelativeNumberOfEvaluatedSamplesParameterName, "The relative number of samples of the dataset partition, which should be randomly chosen for evaluation between the start and end index."));
+      Parameters.Add(new ValueLookupParameter<IntValue>(MaximumSymbolicExpressionTreeDepthParameterName, "The maximum tree depth."));
+      Parameters.Add(new ValueLookupParameter<IntValue>(MaximumSymbolicExpressionTreeLengthParameterName, "The maximum tree length."));
+
+      EvaluatorParameter.Hidden = true;
+      EstimationLimitsParameter.Hidden = true;
+      SymbolicDataAnalysisEvaluationPartitionParameter.Hidden = true;
+      SymbolicDataAnalysisTreeInterpreterParameter.Hidden = true;
+      ProblemDataParameter.Hidden = true;
+      RelativeNumberOfEvaluatedSamplesParameter.Hidden = true;
+    }
+
+    /// <summary>
+    /// Creates a SymbolicExpressionTreeNode reusing the root and start symbols (since they are expensive to create).
+    /// </summary>
+    /// <param name="random"></param>
+    /// <param name="node"></param>
+    /// <param name="rootSymbol"></param>
+    /// <param name="startSymbol"></param>
+    /// <returns></returns>
+    protected static ISymbolicExpressionTree CreateTreeFromNode(IRandom random, ISymbolicExpressionTreeNode node, ISymbol rootSymbol, ISymbol startSymbol) {
+      var rootNode = new SymbolicExpressionTreeTopLevelNode(rootSymbol);
+      if (rootNode.HasLocalParameters) rootNode.ResetLocalParameters(random);
+
+      var startNode = new SymbolicExpressionTreeTopLevelNode(startSymbol);
+      if (startNode.HasLocalParameters) startNode.ResetLocalParameters(random);
+
+      startNode.AddSubtree(node);
+      rootNode.AddSubtree(startNode);
+
+      return new SymbolicExpressionTree(rootNode);
+    }
+
+    protected IEnumerable<int> GenerateRowsToEvaluate() {
+      return GenerateRowsToEvaluate(RelativeNumberOfEvaluatedSamplesParameter.ActualValue.Value);
+    }
+
+    protected IEnumerable<int> GenerateRowsToEvaluate(double percentageOfRows) {
+      IEnumerable<int> rows;
+      int samplesStart = SymbolicDataAnalysisEvaluationPartitionParameter.ActualValue.Start;
+      int samplesEnd = SymbolicDataAnalysisEvaluationPartitionParameter.ActualValue.End;
+      int testPartitionStart = ProblemDataParameter.ActualValue.TestPartition.Start;
+      int testPartitionEnd = ProblemDataParameter.ActualValue.TestPartition.End;
+
+      if (samplesEnd < samplesStart) throw new ArgumentException("Start value is larger than end value.");
+
+      if (percentageOfRows.IsAlmost(1.0))
+        rows = Enumerable.Range(samplesStart, samplesEnd - samplesStart);
+      else {
+        int seed = RandomParameter.ActualValue.Next();
+        int count = (int)((samplesEnd - samplesStart) * percentageOfRows);
+        if (count == 0) count = 1;
+        rows = RandomEnumerable.SampleRandomNumbers(seed, samplesStart, samplesEnd, count);
+      }
+
+      return rows.Where(i => i < testPartitionStart || testPartitionEnd <= i);
+    }
+
+    protected abstract override ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1);
+    public abstract ISymbolicExpressionTree Crossover(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1);
+  }
+}
Index: branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDepthConstrainedCrossover.cs
===================================================================
--- branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDepthConstrainedCrossover.cs	(revision 7476)
+++ branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDepthConstrainedCrossover.cs	(revision 7476)
@@ -0,0 +1,173 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+
+  [Item("DepthConstrainedCrossover", "An operator which performs subtree swapping within a specific depth range.")]
+  public sealed class SymbolicDataAnalysisExpressionDepthConstrainedCrossover<T> :
+    SymbolicDataAnalysisExpressionCrossover<T> where T : class, IDataAnalysisProblemData {
+    private enum Ranges { HighLevel, Standard, LowLevel };
+    private const string DepthRangeParameterName = "DepthRange";
+    #region Parameter properties
+
+    public ConstrainedValueParameter<StringValue> DepthRangeParameter {
+      get { return (ConstrainedValueParameter<StringValue>)Parameters[DepthRangeParameterName]; }
+    }
+    #endregion
+
+    #region Properties
+    public StringValue DepthRange {
+      get { return (StringValue)DepthRangeParameter.ActualValue; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private SymbolicDataAnalysisExpressionDepthConstrainedCrossover(bool deserializing) : base(deserializing) { }
+    private SymbolicDataAnalysisExpressionDepthConstrainedCrossover(SymbolicDataAnalysisExpressionCrossover<T> original, Cloner cloner)
+      : base(original, cloner) { }
+    public SymbolicDataAnalysisExpressionDepthConstrainedCrossover()
+      : base() {
+      Parameters.Add(new ConstrainedValueParameter<StringValue>(DepthRangeParameterName, "Depth range specifier"));
+      DepthRangeParameter.ValidValues.Add(new StringValue(Enum.GetName(typeof(Ranges), Ranges.HighLevel)));
+      DepthRangeParameter.ValidValues.Add(new StringValue(Enum.GetName(typeof(Ranges), Ranges.Standard)));
+      DepthRangeParameter.ValidValues.Add(new StringValue(Enum.GetName(typeof(Ranges), Ranges.LowLevel)));
+      Name = "DepthConstrainedCrossover";
+    }
+    public override IDeepCloneable Clone(Cloner cloner) { return new SymbolicDataAnalysisExpressionDepthConstrainedCrossover<T>(this, cloner); }
+
+    protected override ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1) {
+      return Cross(random, parent0, parent1, MaximumSymbolicExpressionTreeDepth.Value, MaximumSymbolicExpressionTreeLength.Value, DepthRange.Value);
+    }
+
+    public override ISymbolicExpressionTree Crossover(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1) {
+      return Cross(random, parent0, parent1);
+    }
+
+    /// <summary>
+    /// Takes two parent individuals P0 and P1. 
+    /// Randomly choose nodes that fall within the specified depth range in both parents.
+    /// </summary>
+    /// <param name="random">Pseudo-random number generator.</param>
+    /// <param name="parent0">First parent.</param>
+    /// <param name="parent1">Second parent.</param>
+    /// <param name="maxDepth">Maximum allowed length depth.</param>
+    /// <param name="maxLength">Maximum allowed tree length.</param>
+    /// <param name="mode">Controls the crossover behavior: 
+    /// - HighLevel (upper 25% of the tree),
+    /// - Standard (mid 50%)
+    /// - LowLevel (low 25%)</param>
+    /// <returns></returns>
+    public static ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1, int maxDepth, int maxLength, string mode) {
+      int depth = parent0.Root.GetDepth() - 1; // subtract 1 because the tree levels are counted from 0 
+      var depthRange = new IntRange();
+      const int depthOffset = 2; // skip the first 2 levels (root + startNode)
+      switch ((int)Enum.Parse(typeof(Ranges), mode)) {
+        case (int)Ranges.HighLevel:
+          depthRange.Start = depthOffset; // skip the first 2 levels (root + startNode)
+          depthRange.End = depthRange.Start + (int)Math.Round(depth * 0.25);
+          break;
+        case (int)Ranges.Standard:
+          depthRange.Start = depthOffset + (int)Math.Round(depth * 0.25);
+          depthRange.End = depthRange.Start + (int)Math.Round(depth * 0.5);
+          break;
+        case (int)Ranges.LowLevel:
+          depthRange.Start = depthOffset + (int)Math.Round(depth * 0.75);
+          depthRange.End = Math.Max(depthRange.Start, depth);
+          break;
+      }
+
+      // make sure that the depth range does not exceeded the actual depth of parent0
+      if (depthRange.Start > depth)
+        depthRange.Start = depth;
+      if (depthRange.End < depthRange.Start)
+        depthRange.End = depthRange.Start;
+
+      var crossoverPoints0 = (from node in GetNodesAtDepth(parent0.Root, depthRange) select new CutPoint(node.Parent, node)).ToList();
+
+      if (crossoverPoints0.Count == 0)
+        throw new Exception("No crossover points available in the first parent");
+
+      var crossoverPoint0 = crossoverPoints0.SelectRandom(random);
+
+      int level = parent0.Root.GetBranchLevel(crossoverPoint0.Child);
+      int length = parent0.Root.GetLength() - crossoverPoint0.Child.GetLength();
+
+      var allowedBranches = (from s in GetNodesAtDepth(parent1.Root, depthRange)
+                             where
+                               crossoverPoint0.IsMatchingPointType(s) &&
+                               s.GetDepth() + level <= maxDepth &&
+                               s.GetLength() + length <= maxLength
+                             select s).ToList();
+      if (allowedBranches.Count == 0) return parent0;
+      var selectedBranch = allowedBranches.SelectRandom(random);
+      swap(crossoverPoint0, selectedBranch);
+      return parent0;
+    }
+
+    private static IEnumerable<ISymbolicExpressionTreeNode> GetNodesAtDepth(ISymbolicExpressionTreeNode root, IntRange range) {
+      var list = new List<Tuple<ISymbolicExpressionTreeNode, int>> { new Tuple<ISymbolicExpressionTreeNode, int>(root, 0) };
+      int offset = 0;
+      int level = 0;
+      while (level < range.End) {
+        ++level;
+        int count = list.Count;
+        for (int i = offset; i != count; ++i) {
+          if (list[i].Item1.Subtrees.Any())
+            list.AddRange(from s in list[i].Item1.Subtrees select new Tuple<ISymbolicExpressionTreeNode, int>(s, level));
+        }
+        offset = count;
+      }
+      // taking advantage of the fact that the list is already sorted by level
+      for (int i = list.Count - 1; i >= 0; --i) {
+        if (list[i].Item2 >= range.Start)
+          yield return list[i].Item1;
+        else break;
+      }
+    }
+
+    private static void swap(CutPoint crossoverPoint, ISymbolicExpressionTreeNode selectedBranch) {
+      // perform the actual swap
+      if (crossoverPoint.Child != null) {
+        // manipulate the tree of parent0 in place
+        // replace the branch in tree0 with the selected branch from tree1
+        crossoverPoint.Parent.RemoveSubtree(crossoverPoint.ChildIndex);
+        if (selectedBranch != null) {
+          crossoverPoint.Parent.InsertSubtree(crossoverPoint.ChildIndex, selectedBranch);
+        }
+      } else {
+        // child is null (additional child should be added under the parent)
+        if (selectedBranch != null) {
+          crossoverPoint.Parent.AddSubtree(selectedBranch);
+        }
+      }
+    }
+  }
+}
Index: branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDeterministicBestCrossover.cs
===================================================================
--- branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDeterministicBestCrossover.cs	(revision 7476)
+++ branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDeterministicBestCrossover.cs	(revision 7476)
@@ -0,0 +1,134 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+
+  [Item("DeterministicBestCrossover", "An operator which performs subtree swapping in a deterministic way, by choosing the best subtree to be swapped in a certain position.")]
+  public sealed class SymbolicDataAnalysisExpressionDeterministicBestCrossover<T> : SymbolicDataAnalysisExpressionCrossover<T> where T : class, IDataAnalysisProblemData {
+    [StorableConstructor]
+    private SymbolicDataAnalysisExpressionDeterministicBestCrossover(bool deserializing) : base(deserializing) { }
+    private SymbolicDataAnalysisExpressionDeterministicBestCrossover(SymbolicDataAnalysisExpressionCrossover<T> original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public SymbolicDataAnalysisExpressionDeterministicBestCrossover()
+      : base() {
+      Name = "DeterministicBestCrossover";
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SymbolicDataAnalysisExpressionDeterministicBestCrossover<T>(this, cloner);
+    }
+    protected override ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1) {
+      if (this.ExecutionContext == null)
+        throw new InvalidOperationException("ExecutionContext not set.");
+      List<int> rows = GenerateRowsToEvaluate().ToList();
+      T problemData = ProblemDataParameter.ActualValue;
+      ISymbolicDataAnalysisSingleObjectiveEvaluator<T> evaluator = EvaluatorParameter.ActualValue;
+
+      return Cross(random, parent0, parent1, this.ExecutionContext, evaluator, problemData, rows, MaximumSymbolicExpressionTreeDepth.Value, MaximumSymbolicExpressionTreeLength.Value);
+    }
+
+    public override ISymbolicExpressionTree Crossover(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1) {
+      return Cross(random, parent0, parent1);
+    }
+    /// <summary>
+    /// Takes two parent individuals P0 and P1. 
+    /// Randomly choose a node i from the first parent, then test all nodes j from the second parent to determine the best child that would be obtained by swapping i for j.
+    /// </summary>
+    public static ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1, IExecutionContext context,
+                                                ISymbolicDataAnalysisSingleObjectiveEvaluator<T> evaluator, T problemData, List<int> rows, int maxDepth, int maxLength) {
+      var crossoverPoints0 = new List<CutPoint>();
+      parent0.Root.ForEachNodePostfix((n) => {
+        if (n.Subtrees.Any() && n != parent0.Root)
+          crossoverPoints0.AddRange(from s in n.Subtrees select new CutPoint(n, s));
+      });
+      CutPoint crossoverPoint0 = crossoverPoints0.SelectRandom(random);
+      int level = parent0.Root.GetBranchLevel(crossoverPoint0.Child);
+      int length = parent0.Root.GetLength() - crossoverPoint0.Child.GetLength();
+
+      var allowedBranches = new List<ISymbolicExpressionTreeNode>();
+      parent1.Root.ForEachNodePostfix((n) => {
+        if (n.Subtrees.Any() && n != parent1.Root)
+          allowedBranches.AddRange(from s in n.Subtrees
+                                   where crossoverPoint0.IsMatchingPointType(s) && s.GetDepth() + level <= maxDepth && s.GetLength() + length <= maxLength
+                                   select s);
+      });
+
+      if (allowedBranches.Count == 0)
+        return parent0;
+
+      // create symbols in order to improvize an ad-hoc tree so that the child can be evaluated
+      ISymbolicExpressionTreeNode selectedBranch = null;
+
+      var nodeQualities = new List<Tuple<ISymbolicExpressionTreeNode, double>>();
+
+      var originalChild = crossoverPoint0.Child;
+
+      foreach (var node in allowedBranches) {
+        var parent = node.Parent;
+        swap(crossoverPoint0, node); // the swap will set the nodes parent to crossoverPoint0.Parent
+        double quality = evaluator.Evaluate(context, parent0, problemData, rows);
+        swap(crossoverPoint0, originalChild); // swap the child back (so that the next swap will not affect the currently swapped node from parent1)
+        nodeQualities.Add(new Tuple<ISymbolicExpressionTreeNode, double>(node, quality));
+        node.Parent = parent; // restore correct parent
+      }
+
+      nodeQualities.Sort((a, b) => a.Item2.CompareTo(b.Item2)); // assuming this sorts the list in ascending order
+      selectedBranch = evaluator.Maximization ? nodeQualities.Last().Item1 : nodeQualities.First().Item1;
+
+
+      if (selectedBranch == null)
+        throw new Exception("Selected branch is null");
+
+      if (selectedBranch.Parent == null)
+        throw new Exception("Parent is null");
+
+
+      // swap the node that would create the best offspring
+      swap(crossoverPoint0, selectedBranch);
+
+      return parent0;
+    }
+
+    private static void swap(CutPoint crossoverPoint, ISymbolicExpressionTreeNode selectedBranch) {
+      if (crossoverPoint.Child != null) {
+        // manipulate the tree of parent0 in place
+        // replace the branch in tree0 with the selected branch from tree1
+        crossoverPoint.Parent.RemoveSubtree(crossoverPoint.ChildIndex);
+        if (selectedBranch != null) {
+          crossoverPoint.Parent.InsertSubtree(crossoverPoint.ChildIndex, selectedBranch);
+        }
+      } else {
+        // child is null (additional child should be added under the parent)
+        if (selectedBranch != null) {
+          crossoverPoint.Parent.AddSubtree(selectedBranch);
+        }
+      }
+    }
+  }
+}
Index: branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover.cs
===================================================================
--- branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover.cs	(revision 7476)
+++ branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover.cs	(revision 7476)
@@ -0,0 +1,166 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+
+  [Item("ProbabilisticFunctionalCrossover", "An operator which performs subtree swapping based on the behavioral similarity between subtrees.")]
+  public sealed class SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover<T> : SymbolicDataAnalysisExpressionCrossover<T> where T : class, IDataAnalysisProblemData {
+    [StorableConstructor]
+    private SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover(bool deserializing) : base(deserializing) { }
+    private SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover(SymbolicDataAnalysisExpressionCrossover<T> original, Cloner cloner)
+      : base(original, cloner) { }
+    public SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover()
+      : base() {
+      Name = "ProbabilisticFunctionalCrossover";
+    }
+    public override IDeepCloneable Clone(Cloner cloner) { return new SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover<T>(this, cloner); }
+
+    protected override ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1) {
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter = SymbolicDataAnalysisTreeInterpreterParameter.ActualValue;
+      List<int> rows = GenerateRowsToEvaluate().ToList();
+      T problemData = ProblemDataParameter.ActualValue;
+      return Cross(random, parent0, parent1, interpreter, problemData,
+                   rows, MaximumSymbolicExpressionTreeDepth.Value, MaximumSymbolicExpressionTreeLength.Value);
+    }
+
+    public override ISymbolicExpressionTree Crossover(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1) {
+      return Cross(random, parent0, parent1);
+    }
+
+    /// <summary>
+    /// Takes two parent individuals P0 and P1. 
+    /// Randomly choose a node i from the first parent, then for each matching node j from the second parent, calculate the behavioral distance based on the range:
+    /// d(i,j) = 0.5 * ( abs(max(i) - max(j)) + abs(min(i) - min(j)) ).
+    /// Next, assign probabilities for the selection of the second cross point based on the inversed and normalized behavioral distance and
+    /// choose the second crosspoint via a random weighted selection procedure.
+    /// </summary>
+    public static ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1,
+                                                ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, T problemData, IList<int> rows, int maxDepth, int maxLength) {
+      var crossoverPoints0 = new List<CutPoint>();
+      parent0.Root.ForEachNodePostfix((n) => {
+        if (n.Subtrees.Any() && n != parent0.Root)
+          crossoverPoints0.AddRange(from s in n.Subtrees
+                                    select new CutPoint(n, s));
+      });
+      var crossoverPoint0 = crossoverPoints0.SelectRandom(random);
+      int level = parent0.Root.GetBranchLevel(crossoverPoint0.Child);
+      int length = parent0.Root.GetLength() - crossoverPoint0.Child.GetLength();
+
+      var allowedBranches = new List<ISymbolicExpressionTreeNode>();
+      parent1.Root.ForEachNodePostfix((n) => {
+        if (n.Subtrees.Any() && n != parent1.Root)
+          allowedBranches.AddRange(from s in n.Subtrees
+                                   where crossoverPoint0.IsMatchingPointType(s) && s.GetDepth() + level <= maxDepth && s.GetLength() + length <= maxLength
+                                   select s);
+      });
+
+      if (allowedBranches.Count == 0)
+        return parent0;
+
+      var dataset = problemData.Dataset;
+
+      // create symbols in order to improvize an ad-hoc tree so that the child can be evaluated
+      var rootSymbol = new ProgramRootSymbol();
+      var startSymbol = new StartSymbol();
+      var tree0 = CreateTreeFromNode(random, crossoverPoint0.Child, rootSymbol, startSymbol); // this will change crossoverPoint0.Child.Parent
+      double min0 = 0.0, max0 = 0.0;
+      foreach (double v in interpreter.GetSymbolicExpressionTreeValues(tree0, dataset, rows)) {
+        if (min0 > v) min0 = v;
+        if (max0 < v) max0 = v;
+      }
+      crossoverPoint0.Child.Parent = crossoverPoint0.Parent; // restore correct parent 
+
+      var weights = new List<double>();
+      foreach (var node in allowedBranches) {
+        var parent = node.Parent;
+        var tree1 = CreateTreeFromNode(random, node, rootSymbol, startSymbol);
+        double min1 = 0.0, max1 = 0.0;
+        foreach (double v in interpreter.GetSymbolicExpressionTreeValues(tree1, dataset, rows)) {
+          if (min1 > v) min1 = v;
+          if (max1 < v) max1 = v;
+        }
+        double behavioralDistance = (Math.Abs(min0 - min1) + Math.Abs(max0 - max1)) / 2; // this can be NaN of Infinity because some trees are crazy like exp(exp(exp(...))), we correct that below
+        weights.Add(behavioralDistance);
+        node.Parent = parent; // restore correct node parent
+      }
+
+      // remove branches with an infinite or NaN behavioral distance
+      int count = weights.Count, idx = 0;
+      while (idx < count) {
+        if (Double.IsNaN(weights[idx]) || Double.IsInfinity(weights[idx])) {
+          weights.RemoveAt(idx);
+          allowedBranches.RemoveAt(idx);
+          --count;
+        } else {
+          ++idx;
+        }
+      }
+
+      // check if there are any allowed branches left
+      if (allowedBranches.Count == 0)
+        return parent0;
+
+      ISymbolicExpressionTreeNode selectedBranch;
+      double sum = weights.Sum();
+
+      if (sum.IsAlmost(0.0) || weights.Count == 1) // if there is only one allowed branch, or if all weights are zero
+        selectedBranch = allowedBranches[0];
+      else {
+        for (int i = 0; i != weights.Count; ++i) // normalize and invert values
+          weights[i] = 1 - weights[i] / sum;
+
+        sum = weights.Sum(); // take new sum
+
+        // compute the probabilities (selection weights)
+        for (int i = 0; i != weights.Count; ++i)
+          weights[i] /= sum;
+
+        selectedBranch = allowedBranches.SelectRandom(weights, random);
+      }
+      swap(crossoverPoint0, selectedBranch);
+      return parent0;
+    }
+
+    private static void swap(CutPoint crossoverPoint, ISymbolicExpressionTreeNode selectedBranch) {
+      if (crossoverPoint.Child != null) {
+        // manipulate the tree of parent0 in place
+        // replace the branch in tree0 with the selected branch from tree1
+        crossoverPoint.Parent.RemoveSubtree(crossoverPoint.ChildIndex);
+        if (selectedBranch != null) {
+          crossoverPoint.Parent.InsertSubtree(crossoverPoint.ChildIndex, selectedBranch);
+        }
+      } else {
+        // child is null (additional child should be added under the parent)
+        if (selectedBranch != null) {
+          crossoverPoint.Parent.AddSubtree(selectedBranch);
+        }
+      }
+    }
+  }
+}
Index: branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionSemanticSimilarityCrossover.cs
===================================================================
--- branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionSemanticSimilarityCrossover.cs	(revision 7476)
+++ branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionSemanticSimilarityCrossover.cs	(revision 7476)
@@ -0,0 +1,146 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Data;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+
+  [Item("SemanticSimilarityCrossover", "An operator which performs subtree swapping based on the semantic similarity between subtrees.")]
+  public sealed class SymbolicDataAnalysisExpressionSemanticSimilarityCrossover<T> : SymbolicDataAnalysisExpressionCrossover<T> where T : class, IDataAnalysisProblemData {
+    private const string SemanticSimilarityRangeParameterName = "SemanticSimilarityRange";
+
+    #region Parameter properties
+    public IValueParameter<DoubleRange> SemanticSimilarityRangeParameter {
+      get { return (IValueParameter<DoubleRange>)Parameters[SemanticSimilarityRangeParameterName]; }
+    }
+    #endregion
+
+    #region Properties
+    public DoubleRange SemanticSimilarityRange {
+      get { return SemanticSimilarityRangeParameter.Value; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private SymbolicDataAnalysisExpressionSemanticSimilarityCrossover(bool deserializing) : base(deserializing) { }
+    private SymbolicDataAnalysisExpressionSemanticSimilarityCrossover(SymbolicDataAnalysisExpressionCrossover<T> original, Cloner cloner) : base(original, cloner) { }
+    public SymbolicDataAnalysisExpressionSemanticSimilarityCrossover()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<DoubleRange>(SemanticSimilarityRangeParameterName, "Semantic similarity interval.", new DoubleRange(0.0001, 10)));
+      Name = "SemanticSimilarityCrossover";
+    }
+    public override IDeepCloneable Clone(Cloner cloner) { return new SymbolicDataAnalysisExpressionSemanticSimilarityCrossover<T>(this, cloner); }
+
+    protected override ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1) {
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter = SymbolicDataAnalysisTreeInterpreterParameter.ActualValue;
+      List<int> rows = GenerateRowsToEvaluate().ToList();
+      T problemData = ProblemDataParameter.ActualValue;
+      return Cross(random, parent0, parent1, interpreter, problemData, rows, MaximumSymbolicExpressionTreeDepth.Value, MaximumSymbolicExpressionTreeLength.Value, SemanticSimilarityRange);
+    }
+
+    public override ISymbolicExpressionTree Crossover(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1) {
+      return Cross(random, parent0, parent1);
+    }
+
+    /// <summary>
+    /// Takes two parent individuals P0 and P1. 
+    /// Randomly choose a node i from the first parent, then get a node j from the second parent that matches the semantic similarity criteria.
+    /// </summary>
+    public static ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
+                                                T problemData, List<int> rows, int maxDepth, int maxLength, DoubleRange range) {
+      var crossoverPoints0 = new List<CutPoint>();
+      parent0.Root.ForEachNodePostfix((n) => {
+        if (n.Subtrees.Any() && n != parent0.Root)
+          foreach (var child in n.Subtrees)
+            crossoverPoints0.Add(new CutPoint(n, child));
+      });
+      var crossoverPoint0 = crossoverPoints0.SelectRandom(random);
+      int level = parent0.Root.GetBranchLevel(crossoverPoint0.Child);
+      int length = parent0.Root.GetLength() - crossoverPoint0.Child.GetLength();
+
+      var allowedBranches = new List<ISymbolicExpressionTreeNode>();
+      parent1.Root.ForEachNodePostfix((n) => {
+        if (n.Subtrees.Any() && n != parent1.Root)
+          allowedBranches.AddRange(n.Subtrees.Where(s => crossoverPoint0.IsMatchingPointType(s) && s.GetDepth() + level <= maxDepth && s.GetLength() + length <= maxLength));
+      });
+
+      if (allowedBranches.Count == 0)
+        return parent0;
+
+      var dataset = problemData.Dataset;
+
+      // create symbols in order to improvize an ad-hoc tree so that the child can be evaluated
+      var rootSymbol = new ProgramRootSymbol();
+      var startSymbol = new StartSymbol();
+      var tree0 = CreateTreeFromNode(random, crossoverPoint0.Child, rootSymbol, startSymbol);
+      List<double> estimatedValues0 = interpreter.GetSymbolicExpressionTreeValues(tree0, dataset, rows).ToList();
+      crossoverPoint0.Child.Parent = crossoverPoint0.Parent; // restore parent
+      ISymbolicExpressionTreeNode selectedBranch = null;
+
+      // pick the first node that fulfills the semantic similarity conditions
+      foreach (var node in allowedBranches) {
+        var parent = node.Parent;
+        var tree1 = CreateTreeFromNode(random, node, startSymbol, rootSymbol); // this will affect node.Parent 
+        List<double> estimatedValues1 = interpreter.GetSymbolicExpressionTreeValues(tree1, dataset, rows).ToList();
+        node.Parent = parent; // restore parent
+
+        OnlineCalculatorError errorState;
+        double ssd = OnlineMeanAbsoluteErrorCalculator.Calculate(estimatedValues0, estimatedValues1, out errorState);
+
+        if (range.Start > ssd || range.End < ssd)
+          continue;
+
+        selectedBranch = node;
+        break;
+      }
+
+      // perform the actual swap
+      if (selectedBranch != null)
+        swap(crossoverPoint0, selectedBranch);
+
+      return parent0;
+    }
+
+    private static void swap(CutPoint crossoverPoint, ISymbolicExpressionTreeNode selectedBranch) {
+      // perform the actual swap
+      if (crossoverPoint.Child != null) {
+        // manipulate the tree of parent0 in place
+        // replace the branch in tree0 with the selected branch from tree1
+        crossoverPoint.Parent.RemoveSubtree(crossoverPoint.ChildIndex);
+        if (selectedBranch != null) {
+          crossoverPoint.Parent.InsertSubtree(crossoverPoint.ChildIndex, selectedBranch);
+        }
+      } else {
+        // child is null (additional child should be added under the parent)
+        if (selectedBranch != null) {
+          crossoverPoint.Parent.AddSubtree(selectedBranch);
+        }
+      }
+    }
+  }
+}
Index: branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionSizefairCrossover.cs
===================================================================
--- branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionSizefairCrossover.cs	(revision 7476)
+++ branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionSizefairCrossover.cs	(revision 7476)
@@ -0,0 +1,45 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Crossovers {
+  [Item("SizeFairCrossover", "An operator which performs subtree swapping crossover.")]
+  class SymbolicDataAnalysisExpressionSizefairCrossover<T> : SubtreeCrossover, ISymbolicDataAnalysisExpressionCrossover<T> {
+    [StorableConstructor]
+    protected SymbolicDataAnalysisExpressionSizefairCrossover(bool deserializing) : base(deserializing) { }
+    protected SymbolicDataAnalysisExpressionSizefairCrossover(SubtreeCrossover original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) { return new SymbolicDataAnalysisExpressionSizefairCrossover<T>(this, cloner); }
+
+    public override bool CanChangeName {
+      get { return true; }
+    }
+
+    public SymbolicDataAnalysisExpressionSizefairCrossover()
+      : base() {
+      SymbolicDataAnalysisEvaluationPartitionParameter.Hidden = true;
+      Name = "SizeFairCrossover";
+    }
+  }
+}
