Index: /branches/HeuristicLab.Crossovers/HeuristicLab.Crossovers.sln
===================================================================
--- /branches/HeuristicLab.Crossovers/HeuristicLab.Crossovers.sln	(revision 7476)
+++ /branches/HeuristicLab.Crossovers/HeuristicLab.Crossovers.sln	(revision 7477)
@@ -7,10 +7,18 @@
 	ProjectSection(SolutionItems) = preProject
 		Build.cmd = Build.cmd
+		HeuristicLab.Crossovers.vsmdi = HeuristicLab.Crossovers.vsmdi
+		Local.testsettings = Local.testsettings
 		PreBuildEvent.cmd = PreBuildEvent.cmd
+		TraceAndTestImpact.testsettings = TraceAndTestImpact.testsettings
 	EndProjectSection
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.4", "HeuristicLab.Encodings.SymbolicExpressionTreeEncoding\3.4\HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.4.csproj", "{06D4A186-9319-48A0-BADE-A2058D462EEA}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Tests", "HeuristicLab.Tests\HeuristicLab.Tests.csproj", "{A878E2D8-C909-4108-8A0F-06CB3E3609D6}"
+EndProject
 Global
+	GlobalSection(TestCaseManagementSettings) = postSolution
+		CategoryFile = HeuristicLab.Crossovers.vsmdi
+	EndGlobalSection
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -46,4 +54,12 @@
 		{06D4A186-9319-48A0-BADE-A2058D462EEA}.Release|x86.ActiveCfg = Release|x86
 		{06D4A186-9319-48A0-BADE-A2058D462EEA}.Release|x86.Build.0 = Release|x86
+		{A878E2D8-C909-4108-8A0F-06CB3E3609D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{A878E2D8-C909-4108-8A0F-06CB3E3609D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{A878E2D8-C909-4108-8A0F-06CB3E3609D6}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{A878E2D8-C909-4108-8A0F-06CB3E3609D6}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{A878E2D8-C909-4108-8A0F-06CB3E3609D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{A878E2D8-C909-4108-8A0F-06CB3E3609D6}.Release|Any CPU.Build.0 = Release|Any CPU
+		{A878E2D8-C909-4108-8A0F-06CB3E3609D6}.Release|x64.ActiveCfg = Release|Any CPU
+		{A878E2D8-C909-4108-8A0F-06CB3E3609D6}.Release|x86.ActiveCfg = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
Index: /branches/HeuristicLab.Crossovers/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Crossovers/SubtreeCrossover.cs
===================================================================
--- /branches/HeuristicLab.Crossovers/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Crossovers/SubtreeCrossover.cs	(revision 7476)
+++ /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;
-    }
   }
 }
Index: /branches/HeuristicLab.Crossovers/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/CutPoint.cs
===================================================================
--- /branches/HeuristicLab.Crossovers/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/CutPoint.cs	(revision 7476)
+++ /branches/HeuristicLab.Crossovers/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/CutPoint.cs	(revision 7477)
@@ -22,5 +22,5 @@
 
 namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding {
-  internal class CutPoint {
+  public class CutPoint {
     public ISymbolicExpressionTreeNode Parent { get; set; }
     public ISymbolicExpressionTreeNode Child { get; set; }
@@ -39,4 +39,29 @@
       this.Child = null;
     }
+
+    public bool IsMatchingPointType(ISymbolicExpressionTreeNode newChild) {
+      var parent = this.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 &&
+          this.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, this.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;
+      }
+    }
   }
 }
Index: /branches/HeuristicLab.Crossovers/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.4.csproj
===================================================================
--- /branches/HeuristicLab.Crossovers/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.4.csproj	(revision 7476)
+++ /branches/HeuristicLab.Crossovers/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.4.csproj	(revision 7477)
@@ -41,5 +41,5 @@
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
-    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <OutputPath>..\..\..\..\trunk\sources\bin\</OutputPath>
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
@@ -51,5 +51,5 @@
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
-    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <OutputPath>..\..\..\..\trunk\sources\bin\</OutputPath>
     <DefineConstants>TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
Index: /branches/HeuristicLab.Crossovers/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Interfaces/ISymbolicExpressionTreeNode.cs
===================================================================
--- /branches/HeuristicLab.Crossovers/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Interfaces/ISymbolicExpressionTreeNode.cs	(revision 7476)
+++ /branches/HeuristicLab.Crossovers/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Interfaces/ISymbolicExpressionTreeNode.cs	(revision 7477)
@@ -32,4 +32,5 @@
     int GetDepth();
     int GetLength();
+    int GetBranchLevel(ISymbolicExpressionTreeNode child);
 
     IEnumerable<ISymbolicExpressionTreeNode> IterateNodesPostfix();
Index: /branches/HeuristicLab.Crossovers/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/SymbolicExpressionTreeNode.cs
===================================================================
--- /branches/HeuristicLab.Crossovers/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/SymbolicExpressionTreeNode.cs	(revision 7476)
+++ /branches/HeuristicLab.Crossovers/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/SymbolicExpressionTreeNode.cs	(revision 7477)
@@ -125,4 +125,19 @@
     }
 
+    public int GetBranchLevel(ISymbolicExpressionTreeNode child) {
+      return GetBranchLevel(this, child);
+    }
+
+    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;
+    }
+
     public virtual void ResetLocalParameters(IRandom random) { }
     public virtual void ShakeLocalParameters(IRandom random, double shakingFactor) { }
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 7477)
@@ -20,4 +20,5 @@
 #endregion
 
+using HeuristicLab.Data;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
Index: /branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
===================================================================
--- /branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 7476)
+++ /branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 7477)
@@ -41,5 +41,5 @@
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
-    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <OutputPath>..\..\..\..\trunk\sources\bin\</OutputPath>
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
@@ -50,5 +50,5 @@
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
-    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <OutputPath>..\..\..\..\trunk\sources\bin\</OutputPath>
     <DefineConstants>TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
@@ -168,4 +168,13 @@
     <Compile Include="Creators\SymbolicDataAnalysisExpressionRampedHalfAndHalfTreeCreator.cs" />
     <Compile Include="Creators\SymbolicDataAnalysisExpressionTreeCreator.cs" />
+    <Compile Include="Crossovers\MultiSymbolicDataAnalysisExpressionCrossover.cs" />
+    <Compile Include="Crossovers\SymbolicDataAnalysisExpressionContextAwareCrossover.cs" />
+    <Compile Include="Crossovers\SymbolicDataAnalysisExpressionCrossover.cs" />
+    <Compile Include="Crossovers\SymbolicDataAnalysisExpressionDepthConstrainedCrossover.cs" />
+    <Compile Include="Crossovers\SymbolicDataAnalysisExpressionDeterministicBestCrossover.cs" />
+    <Compile Include="Crossovers\SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover.cs" />
+    <Compile Include="Crossovers\SymbolicDataAnalysisExpressionSemanticSimilarityCrossover.cs" />
+    <Compile Include="Crossovers\SymbolicDataAnalysisExpressionSizefairCrossover.cs" />
+    <Compile Include="Interfaces\ISymbolicDataAnalysisExpressionCrossover.cs" />
     <Compile Include="Plugin.cs" />
     <Compile Include="SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs" />
Index: /branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionCrossover.cs
===================================================================
--- /branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionCrossover.cs	(revision 7477)
+++ /branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionCrossover.cs	(revision 7477)
@@ -0,0 +1,33 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Data;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  public interface ISymbolicDataAnalysisExpressionCrossover<T> : ISymbolicExpressionTreeCrossover {
+    IValueLookupParameter<IntRange> SymbolicDataAnalysisEvaluationPartitionParameter { get; }
+    ISymbolicExpressionTree Crossover(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1);
+  }
+}
Index: /branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionTreeInterpreter.cs
===================================================================
--- /branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 7476)
+++ /branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 7477)
@@ -22,9 +22,11 @@
 using System.Collections.Generic;
 using HeuristicLab.Core;
+using HeuristicLab.Data;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
-  public interface ISymbolicDataAnalysisExpressionTreeInterpreter : INamedItem {
+  public interface ISymbolicDataAnalysisExpressionTreeInterpreter : INamedItem, IStatefulItem {
     IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, IEnumerable<int> rows);
+    IntValue EvaluatedSolutions { get; set; }
   }
 }
Index: /branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionCrossover.cs
===================================================================
--- /branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionCrossover.cs	(revision 7477)
+++ /branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionCrossover.cs	(revision 7477)
@@ -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/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs
===================================================================
--- /branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs	(revision 7476)
+++ /branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs	(revision 7477)
@@ -48,4 +48,5 @@
     internal delegate double CompiledFunction(int sampleIndex, IList<double>[] columns);
     private const string CheckExpressionsWithIntervalArithmeticParameterName = "CheckExpressionsWithIntervalArithmetic";
+    private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
     #region private classes
     private class InterpreterState {
@@ -156,4 +157,8 @@
       get { return (IValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; }
     }
+
+    public IValueParameter<IntValue> EvaluatedSolutionsParameter {
+      get { return (IValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
+    }
     #endregion
 
@@ -162,4 +167,9 @@
       get { return CheckExpressionsWithIntervalArithmeticParameter.Value; }
       set { CheckExpressionsWithIntervalArithmeticParameter.Value = value; }
+    }
+
+    public IntValue EvaluatedSolutions {
+      get { return EvaluatedSolutionsParameter.Value; }
+      set { EvaluatedSolutionsParameter.Value = value; }
     }
     #endregion
@@ -176,5 +186,16 @@
       : base("SymbolicDataAnalysisExpressionTreeILEmittingInterpreter", "Interpreter for symbolic expression trees.") {
       Parameters.Add(new ValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.", new BoolValue(false)));
-    }
+      Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
+    }
+
+    #region state
+    public void InitializeState() {
+      EvaluatedSolutions.Value = 0;
+    }
+
+    public void ClearState() {
+      EvaluatedSolutions.Value = 0;
+    }
+    #endregion
 
     public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, IEnumerable<int> rows) {
Index: /branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeInterpreter.cs
===================================================================
--- /branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 7476)
+++ /branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 7477)
@@ -34,4 +34,5 @@
   public sealed class SymbolicDataAnalysisExpressionTreeInterpreter : ParameterizedNamedItem, ISymbolicDataAnalysisExpressionTreeInterpreter {
     private const string CheckExpressionsWithIntervalArithmeticParameterName = "CheckExpressionsWithIntervalArithmetic";
+    private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
     #region private classes
     private class InterpreterState {
@@ -176,4 +177,8 @@
       get { return (IValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; }
     }
+
+    public IValueParameter<IntValue> EvaluatedSolutionsParameter {
+      get { return (IValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
+    }
     #endregion
 
@@ -183,6 +188,10 @@
       set { CheckExpressionsWithIntervalArithmeticParameter.Value = value; }
     }
+
+    public IntValue EvaluatedSolutions {
+      get { return EvaluatedSolutionsParameter.Value; }
+      set { EvaluatedSolutionsParameter.Value = value; }
+    }
     #endregion
-
 
     [StorableConstructor]
@@ -196,7 +205,18 @@
       : base("SymbolicDataAnalysisExpressionTreeInterpreter", "Interpreter for symbolic expression trees including automatically defined functions.") {
       Parameters.Add(new ValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.", new BoolValue(false)));
-    }
+      Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
+    }
+
+    #region state
+    public void InitializeState() {
+      EvaluatedSolutions.Value = 0;
+    }
+
+    public void ClearState() {
+    }
+    #endregion
 
     public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, IEnumerable<int> rows) {
+      EvaluatedSolutions.Value++; // increment the evaluated solutions counter
       if (CheckExpressionsWithIntervalArithmetic.Value)
         throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
Index: /branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs
===================================================================
--- /branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs	(revision 7476)
+++ /branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs	(revision 7477)
@@ -32,4 +32,5 @@
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 using HeuristicLab.PluginInfrastructure;
+using HeuristicLab.Problems.DataAnalysis.Symbolic.Crossovers;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
@@ -198,4 +199,5 @@
     private void InitializeOperators() {
       Operators.AddRange(ApplicationManager.Manager.GetInstances<ISymbolicExpressionTreeOperator>());
+      Operators.AddRange(ApplicationManager.Manager.GetInstances<ISymbolicDataAnalysisExpressionCrossover<T>>());
       Operators.Add(new SymbolicExpressionSymbolFrequencyAnalyzer());
       Operators.Add(new SymbolicDataAnalysisVariableFrequencyAnalyzer());
@@ -307,4 +309,7 @@
         op.SymbolicDataAnalysisTreeInterpreterParameter.ActualName = SymbolicExpressionTreeInterpreterParameterName;
       }
+      foreach (var op in operators.OfType<ISymbolicDataAnalysisExpressionCrossover<T>>()) {
+        op.SymbolicDataAnalysisEvaluationPartitionParameter.ActualName = FitnessCalculationPartitionParameterName;
+      }
     }
 
Index: /branches/HeuristicLab.Crossovers/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionCrossoverTest.cs
===================================================================
--- /branches/HeuristicLab.Crossovers/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionCrossoverTest.cs	(revision 7477)
+++ /branches/HeuristicLab.Crossovers/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionCrossoverTest.cs	(revision 7477)
@@ -0,0 +1,345 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 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.Diagnostics;
+using System.Linq;
+using System.Threading;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Random;
+using HeuristicLab.Core;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using ExecutionContext = HeuristicLab.Core.ExecutionContext;
+using HeuristicLab.Problems.DataAnalysis.Symbolic.Regression;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Tests {
+  [TestClass()]
+  public class SymbolicDataAnalysisExpressionCrossoverTest {
+    private const int PopulationSize = 10000;
+    private const int MaxTreeDepth = 10;
+    private const int MaxTreeLength = 100;
+    private const int Rows = 1000;
+    private const int Columns = 50;
+
+    /// <summary>
+    ///Gets or sets the test context which provides
+    ///information about and functionality for the current test run.
+    ///</summary>
+    public TestContext TestContext { get; set; }
+
+    [TestMethod]
+    public void SymbolicDataAnalysisExpressionSemanticSimilarityCrossoverPerformanceTest() {
+      SemanticSimilarityCrossoverPerformanceTest();
+    }
+
+    [TestMethod]
+    public void SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossoverPerformanceTest() {
+      ProbabilisticFunctionalCrossoverPerformanceTest();
+    }
+
+    [TestMethod]
+    public void SymbolicDataAnalysisExpressionDeterministicBestCrossoverPerformanceTest() {
+      DeterministicBestCrossoverPerformanceTest();
+    }
+
+    [TestMethod]
+    public void SymbolicDataAnalysisExpressionContextAwareCrossoverPerformanceTest() {
+      ContextAwareCrossoverPerformanceTest();
+    }
+
+    [TestMethod]
+    public void SymbolicDataAnalysisExpressionDepthConstrainedCrossoverPerformanceTest() {
+      DepthConstrainedCrossoverPerformanceTest();
+    }
+
+    private static void DepthConstrainedCrossoverPerformanceTest() {
+      var twister = new MersenneTwister(31415);
+      var dataset = Util.CreateRandomDataset(twister, Rows, Columns);
+      var grammar = new FullFunctionalExpressionGrammar();
+      var stopwatch = new Stopwatch();
+
+      grammar.MaximumFunctionArguments = 0;
+      grammar.MaximumFunctionDefinitions = 0;
+      grammar.MinimumFunctionArguments = 0;
+      grammar.MinimumFunctionDefinitions = 0;
+
+      var trees = Util.CreateRandomTrees(twister, dataset, grammar, PopulationSize, 1, MaxTreeLength, 0, 0);
+      foreach (ISymbolicExpressionTree tree in trees) {
+        Util.InitTree(tree, twister, new List<string>(dataset.VariableNames));
+      }
+      var problemData = new RegressionProblemData(dataset, dataset.VariableNames, dataset.VariableNames.Last());
+      var problem = new SymbolicRegressionSingleObjectiveProblem();
+      problem.ProblemData = problemData;
+
+      var crossover = problem.OperatorsParameter.Value.OfType<SymbolicDataAnalysisExpressionDepthConstrainedCrossover<IRegressionProblemData>>().First();
+      //crossover.DepthRange.Value = "HighLevel";
+      //crossover.DepthRange.Value = "Standard";
+      crossover.DepthRange.Value = "LowLevel";
+
+      var globalScope = new Scope("Global Scope");
+      globalScope.Variables.Add(new Core.Variable("Random", twister));
+      var context = new ExecutionContext(null, problem, globalScope);
+      context = new ExecutionContext(context, crossover, globalScope);
+
+      stopwatch.Start();
+      for (int i = 0; i != PopulationSize; ++i) {
+        var parent0 = (ISymbolicExpressionTree)trees.SelectRandom(twister).Clone();
+        var scopeParent0 = new Scope();
+        scopeParent0.Variables.Add(new Core.Variable(crossover.ParentsParameter.ActualName, parent0));
+        context.Scope.SubScopes.Add(scopeParent0);
+
+        var parent1 = (ISymbolicExpressionTree)trees.SelectRandom(twister).Clone();
+        var scopeParent1 = new Scope();
+        scopeParent1.Variables.Add(new Core.Variable(crossover.ParentsParameter.ActualName, parent1));
+        context.Scope.SubScopes.Add(scopeParent1);
+
+        crossover.Execute(context, new CancellationToken());
+
+        context.Scope.SubScopes.Remove(scopeParent0); // clean the scope in preparation for the next iteration
+        context.Scope.SubScopes.Remove(scopeParent1); // clean the scope in preparation for the next iteration
+      }
+      stopwatch.Stop();
+      double msPerCrossover = 2 * stopwatch.ElapsedMilliseconds / (double)PopulationSize;
+      Console.WriteLine("DepthConstrainedCrossover: " + Environment.NewLine +
+                        msPerCrossover + " ms per crossover (~" + Math.Round(1000.0 / (msPerCrossover)) + " crossover operations / s)");
+
+      foreach (var tree in trees)
+        Util.IsValid(tree);
+    }
+
+    private static void SemanticSimilarityCrossoverPerformanceTest() {
+      var twister = new MersenneTwister(31415);
+      var dataset = Util.CreateRandomDataset(twister, Rows, Columns);
+      var grammar = new FullFunctionalExpressionGrammar();
+      var stopwatch = new Stopwatch();
+
+      grammar.MaximumFunctionArguments = 0;
+      grammar.MaximumFunctionDefinitions = 0;
+      grammar.MinimumFunctionArguments = 0;
+      grammar.MinimumFunctionDefinitions = 0;
+
+      var trees = Util.CreateRandomTrees(twister, dataset, grammar, PopulationSize, 1, MaxTreeLength, 0, 0);
+      foreach (ISymbolicExpressionTree tree in trees) {
+        Util.InitTree(tree, twister, new List<string>(dataset.VariableNames));
+      }
+      var problemData = new RegressionProblemData(dataset, dataset.VariableNames, dataset.VariableNames.Last());
+      var problem = new SymbolicRegressionSingleObjectiveProblem();
+      problem.ProblemData = problemData;
+
+      var interpreter = problem.SymbolicExpressionTreeInterpreter;
+      var crossover = problem.OperatorsParameter.Value.OfType<SymbolicDataAnalysisExpressionSemanticSimilarityCrossover<IRegressionProblemData>>().First();
+
+      var globalScope = new Scope("Global Scope");
+      globalScope.Variables.Add(new Core.Variable("Random", twister));
+      var context = new ExecutionContext(null, problem, globalScope);
+      context = new ExecutionContext(context, crossover, globalScope);
+
+      stopwatch.Start();
+      for (int i = 0; i != PopulationSize; ++i) {
+        var parent0 = (ISymbolicExpressionTree)trees.SelectRandom(twister).Clone();
+        var scopeParent0 = new Scope();
+        scopeParent0.Variables.Add(new Core.Variable(crossover.ParentsParameter.ActualName, parent0));
+        context.Scope.SubScopes.Add(scopeParent0);
+
+        var parent1 = (ISymbolicExpressionTree)trees.SelectRandom(twister).Clone();
+        var scopeParent1 = new Scope();
+        scopeParent1.Variables.Add(new Core.Variable(crossover.ParentsParameter.ActualName, parent1));
+        context.Scope.SubScopes.Add(scopeParent1);
+
+        crossover.Execute(context, new CancellationToken());
+
+        context.Scope.SubScopes.Remove(scopeParent0); // clean the scope in preparation for the next iteration
+        context.Scope.SubScopes.Remove(scopeParent1); // clean the scope in preparation for the next iteration
+      }
+      stopwatch.Stop();
+      double msPerCrossover = 2 * stopwatch.ElapsedMilliseconds / (double)PopulationSize;
+      Console.WriteLine("SemanticSimilarityCrossover: " + Environment.NewLine +
+                        interpreter.EvaluatedSolutions + " evaluations" + Environment.NewLine +
+                        msPerCrossover + " ms per crossover (~" + Math.Round(1000.0 / (msPerCrossover)) + " crossover operations / s)");
+
+      foreach (var tree in trees)
+        Util.IsValid(tree);
+    }
+
+    private static void ProbabilisticFunctionalCrossoverPerformanceTest() {
+      var twister = new MersenneTwister(31415);
+      var dataset = Util.CreateRandomDataset(twister, Rows, Columns);
+      var grammar = new FullFunctionalExpressionGrammar();
+      var stopwatch = new Stopwatch();
+
+      grammar.MaximumFunctionArguments = 0;
+      grammar.MaximumFunctionDefinitions = 0;
+      grammar.MinimumFunctionArguments = 0;
+      grammar.MinimumFunctionDefinitions = 0;
+
+      var trees = Util.CreateRandomTrees(twister, dataset, grammar, PopulationSize, 1, MaxTreeLength, 0, 0);
+      foreach (ISymbolicExpressionTree tree in trees) {
+        Util.InitTree(tree, twister, new List<string>(dataset.VariableNames));
+      }
+      var problemData = new RegressionProblemData(dataset, dataset.VariableNames, dataset.VariableNames.Last());
+      var problem = new SymbolicRegressionSingleObjectiveProblem();
+      problem.ProblemData = problemData;
+      var interpreter = problem.SymbolicExpressionTreeInterpreter;
+
+      var crossover = problem.OperatorsParameter.Value.OfType<SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover<IRegressionProblemData>>().First();
+
+      var globalScope = new Scope("Global Scope");
+      globalScope.Variables.Add(new Core.Variable("Random", twister));
+      var context = new ExecutionContext(null, problem, globalScope);
+      context = new ExecutionContext(context, crossover, globalScope);
+
+      stopwatch.Start();
+      for (int i = 0; i != PopulationSize; ++i) {
+        var parent0 = (ISymbolicExpressionTree)trees.SelectRandom(twister).Clone();
+        var scopeParent0 = new Scope();
+        scopeParent0.Variables.Add(new Core.Variable(crossover.ParentsParameter.ActualName, parent0));
+        context.Scope.SubScopes.Add(scopeParent0);
+
+        var parent1 = (ISymbolicExpressionTree)trees.SelectRandom(twister).Clone();
+        var scopeParent1 = new Scope();
+        scopeParent1.Variables.Add(new Core.Variable(crossover.ParentsParameter.ActualName, parent1));
+        context.Scope.SubScopes.Add(scopeParent1);
+
+        crossover.Execute(context, new CancellationToken());
+
+        context.Scope.SubScopes.Remove(scopeParent0); // clean the scope in preparation for the next iteration
+        context.Scope.SubScopes.Remove(scopeParent1); // clean the scope in preparation for the next iteration
+      }
+      stopwatch.Stop();
+
+      double msPerCrossover = 2 * stopwatch.ElapsedMilliseconds / (double)PopulationSize;
+      Console.WriteLine("ProbabilisticFunctionalCrossover: " + Environment.NewLine +
+                        interpreter.EvaluatedSolutions + " evaluations" + Environment.NewLine +
+                        msPerCrossover + " ms per crossover (~" + Math.Round(1000.0 / (msPerCrossover)) + " crossover operations / s)");
+      foreach (var tree in trees)
+        Util.IsValid(tree);
+    }
+
+    private static void DeterministicBestCrossoverPerformanceTest() {
+      var twister = new MersenneTwister(31415);
+      var dataset = Util.CreateRandomDataset(twister, Rows, Columns);
+      var grammar = new FullFunctionalExpressionGrammar();
+      var stopwatch = new Stopwatch();
+
+      grammar.MaximumFunctionArguments = 0;
+      grammar.MaximumFunctionDefinitions = 0;
+      grammar.MinimumFunctionArguments = 0;
+      grammar.MinimumFunctionDefinitions = 0;
+
+      var trees = Util.CreateRandomTrees(twister, dataset, grammar, PopulationSize, 1, MaxTreeLength, 0, 0);
+      foreach (ISymbolicExpressionTree tree in trees) {
+        Util.InitTree(tree, twister, new List<string>(dataset.VariableNames));
+      }
+      var problemData = new RegressionProblemData(dataset, dataset.VariableNames, dataset.VariableNames.Last());
+      var problem = new SymbolicRegressionSingleObjectiveProblem();
+      problem.ProblemData = problemData;
+
+      var interpreter = problem.SymbolicExpressionTreeInterpreter;
+      var crossover = problem.OperatorsParameter.Value.OfType<SymbolicDataAnalysisExpressionDeterministicBestCrossover<IRegressionProblemData>>().First();
+
+      var globalScope = new Scope("Global Scope");
+      globalScope.Variables.Add(new Core.Variable("Random", twister));
+      var context = new ExecutionContext(null, problem, globalScope);
+      context = new ExecutionContext(context, crossover, globalScope);
+
+      stopwatch.Start();
+      for (int i = 0; i != PopulationSize; ++i) {
+        var parent0 = (ISymbolicExpressionTree)trees.SelectRandom(twister).Clone();
+        var scopeParent0 = new Scope();
+        scopeParent0.Variables.Add(new Core.Variable(crossover.ParentsParameter.ActualName, parent0));
+        context.Scope.SubScopes.Add(scopeParent0);
+
+        var parent1 = (ISymbolicExpressionTree)trees.SelectRandom(twister).Clone();
+        var scopeParent1 = new Scope();
+        scopeParent1.Variables.Add(new Core.Variable(crossover.ParentsParameter.ActualName, parent1));
+        context.Scope.SubScopes.Add(scopeParent1);
+
+        crossover.Execute(context, new CancellationToken());
+
+        context.Scope.SubScopes.Remove(scopeParent0); // clean the scope in preparation for the next iteration
+        context.Scope.SubScopes.Remove(scopeParent1); // clean the scope in preparation for the next iteration
+      }
+      stopwatch.Stop();
+      double msPerCrossover = 2 * stopwatch.ElapsedMilliseconds / (double)PopulationSize;
+      Console.WriteLine("DeterministicBestCrossover: " + Environment.NewLine +
+                        interpreter.EvaluatedSolutions + " evaluations" + Environment.NewLine +
+                        msPerCrossover + " ms per crossover (~" + Math.Round(1000.0 / (msPerCrossover)) + " crossover operations / s)");
+
+      foreach (var tree in trees)
+        Util.IsValid(tree);
+    }
+
+    private static void ContextAwareCrossoverPerformanceTest() {
+      var twister = new MersenneTwister(31415);
+      var dataset = Util.CreateRandomDataset(twister, Rows, Columns);
+      var grammar = new FullFunctionalExpressionGrammar();
+      var stopwatch = new Stopwatch();
+
+      grammar.MaximumFunctionArguments = 0;
+      grammar.MaximumFunctionDefinitions = 0;
+      grammar.MinimumFunctionArguments = 0;
+      grammar.MinimumFunctionDefinitions = 0;
+
+      var trees = Util.CreateRandomTrees(twister, dataset, grammar, PopulationSize, 1, MaxTreeLength, 0, 0);
+      foreach (ISymbolicExpressionTree tree in trees) {
+        Util.InitTree(tree, twister, new List<string>(dataset.VariableNames));
+      }
+      var problemData = new RegressionProblemData(dataset, dataset.VariableNames, dataset.VariableNames.Last());
+      var problem = new SymbolicRegressionSingleObjectiveProblem();
+      problem.ProblemData = problemData;
+
+      var interpreter = problem.SymbolicExpressionTreeInterpreter;
+      var crossover = problem.OperatorsParameter.Value.OfType<SymbolicDataAnalysisExpressionContextAwareCrossover<IRegressionProblemData>>().First();
+
+      var globalScope = new Scope("Global Scope");
+      globalScope.Variables.Add(new Core.Variable("Random", twister));
+      var context = new ExecutionContext(null, problem, globalScope);
+      context = new ExecutionContext(context, crossover, globalScope);
+
+      stopwatch.Start();
+      for (int i = 0; i != PopulationSize; ++i) {
+        var parent0 = (ISymbolicExpressionTree)trees.SelectRandom(twister).Clone();
+        var scopeParent0 = new Scope();
+        scopeParent0.Variables.Add(new Core.Variable(crossover.ParentsParameter.ActualName, parent0));
+        context.Scope.SubScopes.Add(scopeParent0);
+
+        var parent1 = (ISymbolicExpressionTree)trees.SelectRandom(twister).Clone();
+        var scopeParent1 = new Scope();
+        scopeParent1.Variables.Add(new Core.Variable(crossover.ParentsParameter.ActualName, parent1));
+        context.Scope.SubScopes.Add(scopeParent1);
+
+        crossover.Execute(context, new CancellationToken());
+
+        context.Scope.SubScopes.Remove(scopeParent0); // clean the scope in preparation for the next iteration
+        context.Scope.SubScopes.Remove(scopeParent1); // clean the scope in preparation for the next iteration
+      }
+      stopwatch.Stop();
+      double msPerCrossover = 2 * stopwatch.ElapsedMilliseconds / (double)PopulationSize;
+      Console.WriteLine("ContextAwareCrossover: " + Environment.NewLine +
+                        interpreter.EvaluatedSolutions + " evaluations" + Environment.NewLine +
+                        msPerCrossover + " ms per crossover (~" + Math.Round(1000.0 / (msPerCrossover)) + " crossover operations / s)");
+
+      foreach (var tree in trees)
+        Util.IsValid(tree);
+    }
+  }
+}
Index: /branches/HeuristicLab.Crossovers/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/Util.cs
===================================================================
--- /branches/HeuristicLab.Crossovers/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/Util.cs	(revision 7477)
+++ /branches/HeuristicLab.Crossovers/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/Util.cs	(revision 7477)
@@ -0,0 +1,177 @@
+#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.Diagnostics;
+using System.Linq;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Problems.DataAnalysis.Symbolic;
+using HeuristicLab.Random;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Tests {
+  internal class Util {
+
+    public static void InitTree(ISymbolicExpressionTree tree, MersenneTwister twister, List<string> varNames) {
+      foreach (var node in tree.IterateNodesPostfix()) {
+        if (node is VariableTreeNode) {
+          var varNode = node as VariableTreeNode;
+          varNode.Weight = twister.NextDouble() * 20.0 - 10.0;
+          varNode.VariableName = varNames[twister.Next(varNames.Count)];
+        } else if (node is ConstantTreeNode) {
+          var constantNode = node as ConstantTreeNode;
+          constantNode.Value = twister.NextDouble() * 20.0 - 10.0;
+        }
+      }
+    }
+
+
+    public static ISymbolicExpressionTree[] CreateRandomTrees(MersenneTwister twister, Dataset dataset, ISymbolicExpressionGrammar grammar, int popSize) {
+      return CreateRandomTrees(twister, dataset, grammar, popSize, 1, 200, 3, 3);
+    }
+
+    public static ISymbolicExpressionTree[] CreateRandomTrees(MersenneTwister twister, Dataset dataset, ISymbolicExpressionGrammar grammar,
+      int popSize, int minSize, int maxSize,
+      int maxFunctionDefinitions, int maxFunctionArguments) {
+      foreach (Variable variableSymbol in grammar.Symbols.OfType<Variable>()) {
+        variableSymbol.VariableNames = dataset.VariableNames.Skip(1);
+      }
+      ISymbolicExpressionTree[] randomTrees = new ISymbolicExpressionTree[popSize];
+      for (int i = 0; i < randomTrees.Length; i++) {
+        randomTrees[i] = ProbabilisticTreeCreator.Create(twister, grammar, maxSize, 10);
+      }
+      return randomTrees;
+    }
+
+
+    public static Dataset CreateRandomDataset(MersenneTwister twister, int rows, int columns) {
+      double[,] data = new double[rows, columns];
+      for (int i = 0; i < rows; i++) {
+        for (int j = 0; j < columns; j++) {
+          data[i, j] = twister.NextDouble() * 2.0 - 1.0;
+        }
+      }
+      IEnumerable<string> variableNames = new string[] { "y" }.Concat(Enumerable.Range(0, columns - 1).Select(x => "x" + x.ToString()));
+      Dataset ds = new Dataset(variableNames, data);
+      return ds;
+    }
+
+    public static double NodesPerSecond(long nNodes, Stopwatch watch) {
+      return nNodes / (watch.ElapsedMilliseconds / 1000.0);
+    }
+
+    public static double CalculateEvaluatedNodesPerSec(ISymbolicExpressionTree[] trees, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, Dataset dataset, int repetitions) {
+      // warm up
+      IEnumerable<int> rows = Enumerable.Range(0, dataset.Rows);
+      long nNodes = 0;
+      double c = 0;
+      for (int i = 0; i < trees.Length; i++) {
+        nNodes += trees[i].Length * (dataset.Rows - 1);
+        c = interpreter.GetSymbolicExpressionTreeValues(trees[i], dataset, rows).Count(); // count needs to evaluate all rows
+      }
+
+      Stopwatch watch = new Stopwatch();
+      for (int rep = 0; rep < repetitions; rep++) {
+        watch.Start();
+        c = 0;
+        for (int i = 0; i < trees.Length; i++) {
+          interpreter.GetSymbolicExpressionTreeValues(trees[i], dataset, rows).Count(); // count needs to evaluate all rows
+        }
+        watch.Stop();
+      }
+      Console.WriteLine("Random tree evaluation performance of " + interpreter.GetType() + ": " +
+        watch.ElapsedMilliseconds + "ms " +
+        Util.NodesPerSecond(nNodes * repetitions, watch) + " nodes/sec");
+      return Util.NodesPerSecond(nNodes * repetitions, watch);
+    }
+
+    public static void IsValid(ISymbolicExpressionTree tree) {
+      int reportedSize = tree.Length;
+      int actualSize = tree.IterateNodesPostfix().Count();
+      Assert.AreEqual(actualSize, reportedSize);
+
+      foreach (var defunTreeNode in tree.Root.Subtrees.OfType<DefunTreeNode>()) {
+        int arity = defunTreeNode.NumberOfArguments;
+
+        foreach (var argTreenode in defunTreeNode.IterateNodesPrefix().OfType<ArgumentTreeNode>()) {
+          Assert.IsTrue(argTreenode.SubtreeCount == 0);
+          Assert.IsTrue(((Argument)argTreenode.Symbol).ArgumentIndex < arity);
+        }
+
+        foreach (var argSymbol in Enumerable.Range(0, defunTreeNode.NumberOfArguments).Select(x => new Argument(x))) {
+          Assert.IsTrue(defunTreeNode.Grammar.ContainsSymbol(argSymbol));
+          Assert.IsTrue(defunTreeNode.Grammar.GetMaximumSubtreeCount(argSymbol) == 0);
+          Assert.IsTrue(defunTreeNode.Grammar.GetMinimumSubtreeCount(argSymbol) == 0);
+        }
+
+        var invoke = new InvokeFunction(defunTreeNode.FunctionName);
+        foreach (var otherRootNode in tree.Root.Subtrees) {
+          if (otherRootNode.Grammar.ContainsSymbol(invoke)) {
+            Assert.IsTrue(otherRootNode.Grammar.GetMinimumSubtreeCount(invoke) == arity);
+            Assert.IsTrue(otherRootNode.Grammar.GetMaximumSubtreeCount(invoke) == arity);
+            Assert.IsFalse(otherRootNode.Grammar.IsAllowedChildSymbol(invoke, invoke));
+            for (int i = 0; i < arity; i++) {
+              Assert.IsFalse(otherRootNode.Grammar.IsAllowedChildSymbol(invoke, invoke, i));
+            }
+          }
+        }
+
+      }
+
+      foreach (var subtree in tree.Root.Subtrees) {
+        Assert.AreNotSame(subtree.Grammar, tree.Root.Grammar);
+        IsValid(subtree.Grammar);
+      }
+
+      IsValid(tree.Root.Grammar);
+      IsValid(tree.Root);
+    }
+
+    public static void IsValid(ISymbolicExpressionTreeGrammar grammar) {
+      Assert.IsTrue(grammar.Symbols.Count() == grammar.Symbols.Distinct().Count());
+      foreach (ISymbol symbol in grammar.AllowedSymbols) {
+        Assert.IsTrue(grammar.GetAllowedChildSymbols(symbol).Count() == grammar.GetAllowedChildSymbols(symbol).Distinct().Count());
+        for (int i = 0; i < grammar.GetMaximumSubtreeCount(symbol); i++) {
+          Assert.IsTrue(grammar.GetAllowedChildSymbols(symbol, i).Count() == grammar.GetAllowedChildSymbols(symbol, i).Distinct().Count());
+        }
+      }
+
+      foreach (var symbol in grammar.ModifyableSymbols) {
+        //check if ever symbol has at least one allowed child
+        for (int i = 0; i < grammar.GetMaximumSubtreeCount(symbol); i++)
+          Assert.IsTrue(grammar.GetAllowedChildSymbols(symbol, i).Any());
+      }
+    }
+
+    public static void IsValid(ISymbolicExpressionTreeNode treeNode) {
+      var matchingSymbol = (from symb in treeNode.Grammar.Symbols
+                            where symb.Name == treeNode.Symbol.Name
+                            select symb).SingleOrDefault();
+      Assert.IsTrue(treeNode.Subtrees.Count() >= treeNode.Grammar.GetMinimumSubtreeCount(matchingSymbol));
+      Assert.IsTrue(treeNode.Subtrees.Count() <= treeNode.Grammar.GetMaximumSubtreeCount(matchingSymbol));
+      Assert.AreNotEqual(0.0, matchingSymbol.InitialFrequency); // check that no deactivated symbols occur in the tree
+      for (int i = 0; i < treeNode.Subtrees.Count(); i++) {
+        Assert.IsTrue(treeNode.Grammar.GetAllowedChildSymbols(treeNode.Symbol, i).Select(x => x.Name).Contains(treeNode.GetSubtree(i).Symbol.Name));
+        IsValid(treeNode.GetSubtree(i));
+      }
+    }
+  }
+}
Index: /branches/HeuristicLab.Crossovers/HeuristicLab.Tests/HeuristicLab.Tests.csproj
===================================================================
--- /branches/HeuristicLab.Crossovers/HeuristicLab.Tests/HeuristicLab.Tests.csproj	(revision 7477)
+++ /branches/HeuristicLab.Crossovers/HeuristicLab.Tests/HeuristicLab.Tests.csproj	(revision 7477)
@@ -0,0 +1,93 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>
+    </ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{A878E2D8-C909-4108-8A0F-06CB3E3609D6}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.Tests</RootNamespace>
+    <AssemblyName>HeuristicLab.Tests</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\..\..\..\trunk\sources\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>..\..\..\..\trunk\sources\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="HeuristicLab.Collections-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Collections-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Common-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Common-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Core-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Core-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Data-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Data-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.4, Version=3.4.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.4.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Operators-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Operators-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Optimization-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Optimization-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Problems.DataAnalysis-3.4, Version=3.4.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Problems.DataAnalysis-3.4.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Problems.DataAnalysis.Symbolic-3.4, Version=3.4.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4, Version=3.4.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Random-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Random-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="HeuristicLab.Problems.DataAnalysis.Symbolic-3.4\SymbolicDataAnalysisExpressionCrossoverTest.cs" />
+    <Compile Include="HeuristicLab.Problems.DataAnalysis.Symbolic-3.4\Util.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
Index: /branches/HeuristicLab.Crossovers/HeuristicLab.Tests/HeuristicLab.Tests.csproj.user
===================================================================
--- /branches/HeuristicLab.Crossovers/HeuristicLab.Tests/HeuristicLab.Tests.csproj.user	(revision 7477)
+++ /branches/HeuristicLab.Crossovers/HeuristicLab.Tests/HeuristicLab.Tests.csproj.user	(revision 7477)
@@ -0,0 +1,6 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <ProjectView>ShowAllFiles</ProjectView>
+  </PropertyGroup>
+</Project>
Index: /branches/HeuristicLab.Crossovers/HeuristicLab.Tests/Properties/AssemblyInfo.cs
===================================================================
--- /branches/HeuristicLab.Crossovers/HeuristicLab.Tests/Properties/AssemblyInfo.cs	(revision 7477)
+++ /branches/HeuristicLab.Crossovers/HeuristicLab.Tests/Properties/AssemblyInfo.cs	(revision 7477)
@@ -0,0 +1,35 @@
+﻿using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("HeuristicLab.Tests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("HeuristicLab.Tests")]
+[assembly: AssemblyCopyright("Copyright ©  2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("8e776743-5a6c-4df9-a7c0-59b9bb1e9d03")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
