Index: trunk/sources/HeuristicLab.StructureIdentification/HeuristicLab.StructureIdentification.csproj
===================================================================
--- trunk/sources/HeuristicLab.StructureIdentification/HeuristicLab.StructureIdentification.csproj	(revision 617)
+++ trunk/sources/HeuristicLab.StructureIdentification/HeuristicLab.StructureIdentification.csproj	(revision 618)
@@ -101,4 +101,5 @@
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="RampedTreeCreator.cs" />
+    <Compile Include="Recombination\OnePointCrossOver.cs" />
     <Compile Include="Recombination\StandardCrossOver.cs" />
     <Compile Include="Recombination\SizeFairCrossOver.cs" />
Index: trunk/sources/HeuristicLab.StructureIdentification/Recombination/OnePointCrossOver.cs
===================================================================
--- trunk/sources/HeuristicLab.StructureIdentification/Recombination/OnePointCrossOver.cs	(revision 618)
+++ trunk/sources/HeuristicLab.StructureIdentification/Recombination/OnePointCrossOver.cs	(revision 618)
@@ -0,0 +1,156 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 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.Operators;
+using HeuristicLab.Random;
+using HeuristicLab.Data;
+using HeuristicLab.Constraints;
+using HeuristicLab.Functions;
+using System.Diagnostics;
+
+namespace HeuristicLab.StructureIdentification {
+  /// <summary>
+  /// Implementation of a homologous one point crossover operator as described in: 
+  /// W. B. Langdon and R. Poli.  Foundations of Genetic Programming. Springer-Verlag, 2002.
+  /// </summary>
+  public class OnePointCrossOver : OperatorBase {
+    public override string Description {
+      get {
+        return @"";
+      }
+    }
+    public OnePointCrossOver()
+      : base() {
+      AddVariableInfo(new VariableInfo("Random", "Pseudo random number generator", typeof(MersenneTwister), VariableKind.In));
+      AddVariableInfo(new VariableInfo("OperatorLibrary", "The operator library containing all available operators", typeof(GPOperatorLibrary), VariableKind.In));
+      AddVariableInfo(new VariableInfo("MaxTreeHeight", "The maximal allowed height of the tree", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("MaxTreeSize", "The maximal allowed size (number of nodes) of the tree", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("FunctionTree", "The tree to mutate", typeof(IFunctionTree), VariableKind.In | VariableKind.New));
+      AddVariableInfo(new VariableInfo("TreeSize", "The size (number of nodes) of the tree", typeof(IntData), VariableKind.New));
+      AddVariableInfo(new VariableInfo("TreeHeight", "The height of the tree", typeof(IntData), VariableKind.New));
+    }
+
+    public override IOperation Apply(IScope scope) {
+      MersenneTwister random = GetVariableValue<MersenneTwister>("Random", scope, true);
+      GPOperatorLibrary opLibrary = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", scope, true);
+      int maxTreeHeight = GetVariableValue<IntData>("MaxTreeHeight", scope, true).Data;
+      int maxTreeSize = GetVariableValue<IntData>("MaxTreeSize", scope, true).Data;
+
+      TreeGardener gardener = new TreeGardener(random, opLibrary);
+
+      if((scope.SubScopes.Count % 2) != 0)
+        throw new InvalidOperationException("Number of parents is not even");
+
+      CompositeOperation initOperations = new CompositeOperation();
+
+      int children = scope.SubScopes.Count / 2;
+      for(int i = 0; i < children; i++) {
+        IScope parent1 = scope.SubScopes[0];
+        scope.RemoveSubScope(parent1);
+        IScope parent2 = scope.SubScopes[0];
+        scope.RemoveSubScope(parent2);
+        IScope child = new Scope(i.ToString());
+        IOperation childInitOperation = Cross(gardener, maxTreeSize, maxTreeHeight, scope, random, parent1, parent2, child);
+        initOperations.AddOperation(childInitOperation);
+        scope.AddSubScope(child);
+      }
+
+      return initOperations;
+    }
+
+    private IOperation Cross(TreeGardener gardener, int maxTreeSize, int maxTreeHeight,
+      IScope scope, MersenneTwister random, IScope parent1, IScope parent2, IScope child) {
+      IFunctionTree newTree = Cross(gardener, parent1, parent2,
+        random, maxTreeSize, maxTreeHeight);
+
+      int newTreeSize = newTree.Size;
+      int newTreeHeight = newTree.Height;
+      child.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("FunctionTree"), newTree));
+      child.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeSize"), new IntData(newTreeSize)));
+      child.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeHeight"), new IntData(newTreeHeight)));
+
+      // check if the new tree is valid and if the height of is still in the allowed bounds (we are not so strict for the max-size)
+      Debug.Assert(gardener.IsValidTree(newTree) && newTreeHeight <= maxTreeHeight && newTreeSize <= maxTreeSize);
+      return null;
+    }
+
+
+    private IFunctionTree Cross(TreeGardener gardener, IScope f, IScope g, MersenneTwister random, int maxTreeSize, int maxTreeHeight) {
+      IFunctionTree tree0 = f.GetVariableValue<IFunctionTree>("FunctionTree", false);
+      int tree0Height = f.GetVariableValue<IntData>("TreeHeight", false).Data;
+      int tree0Size = f.GetVariableValue<IntData>("TreeSize", false).Data;
+
+      IFunctionTree tree1 = g.GetVariableValue<IFunctionTree>("FunctionTree", false);
+      int tree1Height = g.GetVariableValue<IntData>("TreeHeight", false).Data;
+      int tree1Size = g.GetVariableValue<IntData>("TreeSize", false).Data;
+
+      if(tree0Size == 1 && tree1Size == 1) {
+        return CombineTerminals(gardener, tree0, tree1, random);
+      } else {
+        // we are going to insert tree1 into tree0 at a random place so we have to make sure that tree0 is not a terminal
+        // in case both trees are higher than 1 we swap the trees with probability 50%
+        if(tree0Height == 1 || (tree1Height > 1 && random.Next(2) == 0)) {
+          IFunctionTree tmp = tree0; tree0 = tree1; tree1 = tmp;
+          int tmpHeight = tree0Height; tree0Height = tree1Height; tree1Height = tmpHeight;
+          int tmpSize = tree0Size; tree0Size = tree1Size; tree1Size = tmpSize;
+        }
+
+        List<IFunctionTree[]> allowedCrossOverPoints = GetCrossOverPoints(null, tree0, tree1);
+        if(allowedCrossOverPoints.Count == 0) {
+          if(random.NextDouble() < 0.5) return tree0; else return tree1;
+        }
+        IFunctionTree[] crossOverPoints = allowedCrossOverPoints[random.Next(allowedCrossOverPoints.Count)];
+        IFunctionTree parent = crossOverPoints[0];
+        IFunctionTree replacedBranch = crossOverPoints[1];
+        IFunctionTree insertedBranch = crossOverPoints[2];
+        if(parent == null) return insertedBranch;
+        else {
+          int i = 0;
+          while(parent.SubTrees[i] != replacedBranch) i++;
+          parent.RemoveSubTree(i);
+          parent.InsertSubTree(i, insertedBranch);
+          return tree0;
+        }
+      }
+    }
+
+    private List<IFunctionTree[]> GetCrossOverPoints(IFunctionTree parent, IFunctionTree tree0, IFunctionTree tree1) {
+      List<IFunctionTree[]> results = new List<IFunctionTree[]>();
+      if(tree0.Function != tree1.Function) return results;
+
+      int maxArity = Math.Min(tree0.SubTrees.Count, tree1.SubTrees.Count);
+      for(int i = 0; i < maxArity; i++) {
+        results.AddRange(GetCrossOverPoints(tree0, tree0.SubTrees[i], tree1.SubTrees[i]));
+      }
+      if(results.Count == 0) results.Add(new IFunctionTree[] { parent, tree0, tree1 });
+      return results;
+    }
+
+    private IFunctionTree CombineTerminals(TreeGardener gardener, IFunctionTree f, IFunctionTree g, MersenneTwister random) {
+      if(random.NextDouble() < 0.5) return f; else return g;
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.StructureIdentification/Recombination/SizeFairCrossOver.cs
===================================================================
--- trunk/sources/HeuristicLab.StructureIdentification/Recombination/SizeFairCrossOver.cs	(revision 617)
+++ trunk/sources/HeuristicLab.StructureIdentification/Recombination/SizeFairCrossOver.cs	(revision 618)
@@ -126,13 +126,6 @@
         }
 
-        // save the roots because later on we change tree0 and tree1 while searching a valid tree configuration
-        IFunctionTree root0 = tree0;
-        IFunctionTree root1 = tree1;
-        int root0Height = tree0Height;
-        int root1Height = tree1Height;
-        int rootSize = tree0Size;
-
         // select a random suboperator of the 'receiving' tree
-        IFunctionTree crossoverPoint = gardener.GetRandomParentNode(root0);
+        IFunctionTree crossoverPoint = gardener.GetRandomParentNode(tree0);
         int removedBranchIndex;
         IFunctionTree removedBranch;
@@ -140,5 +133,5 @@
         if(crossoverPoint == null) {
           removedBranchIndex = 0;
-          removedBranch = root0;
+          removedBranch = tree0;
           allowedFunctions = gardener.GetAllowedSubFunctions(null, 0);
         } else {
@@ -148,20 +141,20 @@
         }
         int removedBranchSize = removedBranch.Size;
-        int maxBranchSize = maxTreeSize - (root0.Size - removedBranchSize);
-        int maxBranchHeight = maxTreeHeight - gardener.GetBranchLevel(root0, removedBranch);
-        IFunctionTree insertedBranch = GetReplacementBranch(random, gardener, allowedFunctions, root1, removedBranchSize, maxBranchSize, maxBranchHeight);
+        int maxBranchSize = maxTreeSize - (tree0.Size - removedBranchSize);
+        int maxBranchHeight = maxTreeHeight - gardener.GetBranchLevel(tree0, removedBranch);
+        IFunctionTree insertedBranch = GetReplacementBranch(random, gardener, allowedFunctions, tree1, removedBranchSize, maxBranchSize, maxBranchHeight);
 
         int tries = 0;
         while(insertedBranch == null) {
           if(tries++ > MAX_RECOMBINATION_TRIES) {
-            if(random.Next() > 0.5) return root1;
-            else return root0;
+            if(random.Next() > 0.5) return tree1;
+            else return tree0;
           }
 
           // retry with a different crossoverPoint        
-          crossoverPoint = gardener.GetRandomParentNode(root0);
+          crossoverPoint = gardener.GetRandomParentNode(tree0);
           if(crossoverPoint == null) {
             removedBranchIndex = 0;
-            removedBranch = root0;
+            removedBranch = tree0;
             allowedFunctions = gardener.GetAllowedSubFunctions(null, 0);
           } else {
@@ -171,7 +164,7 @@
           }
           removedBranchSize = removedBranch.Size;
-          maxBranchSize = maxTreeSize - (root0.Size - removedBranchSize);
-          maxBranchHeight = maxTreeHeight - gardener.GetBranchLevel(root0, removedBranch) + 1;
-          insertedBranch = GetReplacementBranch(random, gardener, allowedFunctions, root1, removedBranchSize, maxBranchSize, maxBranchHeight);
+          maxBranchSize = maxTreeSize - (tree0.Size - removedBranchSize);
+          maxBranchHeight = maxTreeHeight - gardener.GetBranchLevel(tree0, removedBranch) + 1;
+          insertedBranch = GetReplacementBranch(random, gardener, allowedFunctions, tree1, removedBranchSize, maxBranchSize, maxBranchHeight);
         }
         if(crossoverPoint != null) {
@@ -179,5 +172,5 @@
           crossoverPoint.RemoveSubTree(removedBranchIndex);
           crossoverPoint.InsertSubTree(removedBranchIndex, insertedBranch);
-          return root0;
+          return tree0;
         } else {
           return insertedBranch;
