Index: /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Creators/ProbabilisticTreeCreator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Creators/ProbabilisticTreeCreator.cs	(revision 3218)
+++ /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Creators/ProbabilisticTreeCreator.cs	(revision 3218)
@@ -0,0 +1,82 @@
+#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 HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Random;
+using HeuristicLab.GP.Interfaces;
+using System;
+
+namespace HeuristicLab.GP.Operators {
+  public class ProbabilisticTreeCreator : OperatorBase {
+    private static int MAX_TRIES { get { return 100; } }
+
+    public override string Description {
+      get { return @"Generates a new random operator tree."; }
+    }
+
+    public ProbabilisticTreeCreator()
+      : base() {
+      AddVariableInfo(new VariableInfo("Random", "Uniform random number generator", typeof(MersenneTwister), VariableKind.In));
+      AddVariableInfo(new VariableInfo("FunctionLibrary", "The function library containing all available functions", typeof(FunctionLibrary), VariableKind.In));
+      AddVariableInfo(new VariableInfo("MinTreeSize", "The minimal allowed size of the tree", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("MaxTreeSize", "The maximal allowed size of the tree", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("MaxTreeHeight", "The maximal allowed height of the tree", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("FunctionTree", "The created tree", typeof(IGeneticProgrammingModel), VariableKind.New | VariableKind.Out));
+    }
+
+    public override IOperation Apply(IScope scope) {
+      IRandom random = GetVariableValue<IRandom>("Random", scope, true);
+      FunctionLibrary funLibrary = GetVariableValue<FunctionLibrary>("FunctionLibrary", scope, true);
+      int minTreeSize = GetVariableValue<IntData>("MinTreeSize", scope, true).Data;
+      int maxTreeSize = GetVariableValue<IntData>("MaxTreeSize", scope, true).Data;
+      int maxTreeHeight = GetVariableValue<IntData>("MaxTreeHeight", scope, true).Data;
+
+      IFunctionTree root = Create(random, funLibrary, minTreeSize, maxTreeSize, maxTreeHeight);
+      scope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("FunctionTree"), new GeneticProgrammingModel(root)));
+      return Util.CreateInitializationOperation(TreeGardener.GetAllSubTrees(root), scope);
+    }
+
+
+    public static IFunctionTree Create(IRandom random, FunctionLibrary funLib, int minSize, int maxSize, int maxHeight) {
+      int treeSize = random.Next(minSize, maxSize);
+      IFunctionTree root = null;
+      int tries = 0;
+      TreeGardener gardener = new TreeGardener(random, funLib);
+      do {
+        try {
+          root = gardener.PTC2(treeSize, maxHeight);
+        }
+        catch (ArgumentException) {
+          // try a different size
+          treeSize = random.Next(minSize, maxSize);
+          tries = 0;
+        }
+        if (tries++ >= MAX_TRIES) {
+          // try a different size
+          treeSize = random.Next(minSize, maxSize);
+          tries = 0;
+        }
+      } while (root == null || root.GetSize() > maxSize || root.GetHeight() > maxHeight);
+      return root;
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Creators/RampedTreeCreator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Creators/RampedTreeCreator.cs	(revision 3218)
+++ /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Creators/RampedTreeCreator.cs	(revision 3218)
@@ -0,0 +1,70 @@
+#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 HeuristicLab.Core;
+using HeuristicLab.Data;
+using System;
+using HeuristicLab.Random;
+using System.Diagnostics;
+using HeuristicLab.GP.Interfaces;
+
+namespace HeuristicLab.GP.Operators {
+  public class RampedTreeCreator : OperatorBase {
+    public override string Description {
+      get { return @"Generates a new random operator tree."; }
+    }
+
+    public RampedTreeCreator()
+      : base() {
+      AddVariableInfo(new VariableInfo("Random", "Uniform random number generator", typeof(MersenneTwister), VariableKind.In));
+      AddVariableInfo(new VariableInfo("FunctionLibrary", "The function library containing all available functions", typeof(FunctionLibrary), VariableKind.In));
+      AddVariableInfo(new VariableInfo("MinTreeHeight", "The minimal allowed height of the tree", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("MaxTreeHeight", "The maximal allowed height of the tree", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("BalancedTreesRate", "Determines how many trees should be balanced", typeof(DoubleData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("FunctionTree", "The created tree", typeof(IGeneticProgrammingModel), VariableKind.New | VariableKind.Out));
+      AddVariableInfo(new VariableInfo("TreeSize", "The size (number of nodes) of the tree", typeof(IntData), VariableKind.New | VariableKind.Out));
+      AddVariableInfo(new VariableInfo("TreeHeight", "The height of the tree", typeof(IntData), VariableKind.New | VariableKind.Out));
+    }
+
+    public override IOperation Apply(IScope scope) {
+      IRandom random = GetVariableValue<IRandom>("Random", scope, true);
+      FunctionLibrary opLibrary = GetVariableValue<FunctionLibrary>("FunctionLibrary", scope, true);
+      int minTreeHeight = GetVariableValue<IntData>("MinTreeHeight", scope, true).Data;
+      int maxTreeHeight = GetVariableValue<IntData>("MaxTreeHeight", scope, true).Data;
+      double balancedTreesRate = GetVariableValue<DoubleData>("BalancedTreesRate", scope, true).Data;
+
+      TreeGardener gardener = new TreeGardener(random, opLibrary);
+
+      int treeHeight = random.Next(minTreeHeight, maxTreeHeight + 1);
+      IFunctionTree root;
+      if(random.NextDouble() <= balancedTreesRate) {
+        root = gardener.CreateBalancedRandomTree(Int32.MaxValue, treeHeight);
+      } else {
+        root = gardener.CreateUnbalancedRandomTree(Int32.MaxValue, treeHeight);
+      }
+
+      Debug.Assert(gardener.IsValidTree(root) && root.GetHeight() <= maxTreeHeight);
+
+      scope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("FunctionTree"), new GeneticProgrammingModel(root)));
+      return Util.CreateInitializationOperation(TreeGardener.GetAllSubTrees(root), scope);
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Crossovers/GPCrossoverBase.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Crossovers/GPCrossoverBase.cs	(revision 3218)
+++ /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Crossovers/GPCrossoverBase.cs	(revision 3218)
@@ -0,0 +1,60 @@
+#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 HeuristicLab.Core;
+using System.Diagnostics;
+using HeuristicLab.Evolutionary;
+using HeuristicLab.GP.Interfaces;
+
+namespace HeuristicLab.GP.Operators {
+  public abstract class GPCrossoverBase : CrossoverBase {
+    public GPCrossoverBase()
+      : base() {
+      AddVariableInfo(new VariableInfo("FunctionLibrary", "The operator library containing all available operators", typeof(FunctionLibrary), VariableKind.In));
+      AddVariableInfo(new VariableInfo("FunctionTree", "The tree to crossover", typeof(IGeneticProgrammingModel), VariableKind.In | VariableKind.New));
+    }
+
+    internal abstract IFunctionTree Cross(IScope scope, TreeGardener gardener, IRandom random, IFunctionTree tree0, IFunctionTree tree1);
+
+    protected override void Cross(IScope scope, IRandom random) {
+      FunctionLibrary opLibrary = GetVariableValue<FunctionLibrary>("FunctionLibrary", scope, true);
+      TreeGardener gardener = new TreeGardener(random, opLibrary);
+
+      if (scope.SubScopes.Count != 2)
+        throw new InvalidOperationException("Number of parents must be exactly two.");
+
+      IGeneticProgrammingModel parent0 = GetVariableValue<IGeneticProgrammingModel>("FunctionTree", scope.SubScopes[0], false);
+      IGeneticProgrammingModel parent1 = GetVariableValue<IGeneticProgrammingModel>("FunctionTree", scope.SubScopes[1], false);
+
+      // randomly swap parents to remove a possible bias from selection (e.g. when using gender-specific selection)
+      if (random.NextDouble() < 0.5) {
+        IGeneticProgrammingModel tmp = parent0;
+        parent0 = parent1;
+        parent1 = tmp;
+      }
+
+      IFunctionTree child = Cross(scope, gardener, random, parent0.FunctionTree, parent1.FunctionTree);
+      Debug.Assert(gardener.IsValidTree(child));
+      scope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("FunctionTree"), new GeneticProgrammingModel(child)));
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Crossovers/LangdonHomologousCrossOver.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Crossovers/LangdonHomologousCrossOver.cs	(revision 3218)
+++ /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Crossovers/LangdonHomologousCrossOver.cs	(revision 3218)
@@ -0,0 +1,56 @@
+#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 HeuristicLab.Random;
+using HeuristicLab.GP.Interfaces;
+
+namespace HeuristicLab.GP.Operators {
+  /// <summary>
+  /// Implementation of a homologous crossover operator as described in: 
+  /// William B. Langdon 
+  /// Size Fair and Homologous Tree Genetic Programming Crossovers, 
+  /// Genetic Programming and Evolvable Machines, Vol. 1, Number 1/2, pp. 95-119, April 2000
+  /// </summary>
+  public class LangdonHomologousCrossOver : SizeFairCrossOver {
+    protected override IFunctionTree SelectReplacement(MersenneTwister random, List<int> replacedTrail, List<CrossoverPoint> crossoverPoints) {
+      List<CrossoverPoint> bestPoints = new List<CrossoverPoint> { crossoverPoints[0] };
+      int bestMatchLength = MatchingSteps(replacedTrail, crossoverPoints[0].trail);
+      for (int i = 1; i < crossoverPoints.Count; i++) {
+        int currentMatchLength = MatchingSteps(replacedTrail, crossoverPoints[i].trail);
+        if (currentMatchLength > bestMatchLength) {
+          bestMatchLength = currentMatchLength;
+          bestPoints.Clear();
+          bestPoints.Add(crossoverPoints[i]);
+        } else if (currentMatchLength == bestMatchLength) {
+          bestPoints.Add(crossoverPoints[i]);
+        }
+      }
+      return bestPoints[random.Next(bestPoints.Count)].tree;
+    }
+    private int MatchingSteps(List<int> t1, List<int> t2) {
+      int n = Math.Min(t1.Count, t2.Count);
+      for (int i = 0; i < n; i++) if (t1[i] != t2[i]) return i;
+      return n;
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Crossovers/OnePointCrossOver.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Crossovers/OnePointCrossOver.cs	(revision 3218)
+++ /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Crossovers/OnePointCrossOver.cs	(revision 3218)
@@ -0,0 +1,74 @@
+#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.Collections.Generic;
+using HeuristicLab.Core;
+using HeuristicLab.GP.Interfaces;
+
+namespace HeuristicLab.GP.Operators {
+  /// <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 : SizeConstrictedGPCrossoverBase {
+    // internal data structure to represent crossover points
+    private class CrossoverPoint {
+      public IFunctionTree parent0;
+      public IFunctionTree parent1;
+      public int childIndex;
+    }
+    public override string Description {
+      get {
+        return @"One point crossover for trees as described in W. B. Langdon and R. Poli. Foundations of Genetic Programming. Springer-Verlag, 2002.";
+      }
+    }
+
+    internal override IFunctionTree Cross(TreeGardener gardener, IRandom random, IFunctionTree tree0, IFunctionTree tree1, int maxTreeSize, int maxTreeHeight) {
+      List<CrossoverPoint> allowedCrossOverPoints = new List<CrossoverPoint>();
+      GetCrossOverPoints(gardener, tree0, tree1, maxTreeSize - tree0.GetSize(), allowedCrossOverPoints);
+      if (allowedCrossOverPoints.Count > 0) {
+        CrossoverPoint crossOverPoint = allowedCrossOverPoints[random.Next(allowedCrossOverPoints.Count)];
+        IFunctionTree parent0 = crossOverPoint.parent0;
+        IFunctionTree branch1 = crossOverPoint.parent1.SubTrees[crossOverPoint.childIndex];
+        parent0.RemoveSubTree(crossOverPoint.childIndex);
+        parent0.InsertSubTree(crossOverPoint.childIndex, branch1);
+      }
+      return tree0;
+    }
+
+    private void GetCrossOverPoints(TreeGardener gardener, IFunctionTree branch0, IFunctionTree branch1, int maxNewNodes, List<CrossoverPoint> crossoverPoints) {
+      if (branch0.SubTrees.Count != branch1.SubTrees.Count) return;
+
+      for (int i = 0; i < branch0.SubTrees.Count; i++) {
+        // if the current branch can be attached as a sub-tree to branch0
+        if (gardener.GetAllowedSubFunctions(branch0.Function, i).Contains(branch1.SubTrees[i].Function) &&
+           branch1.SubTrees[i].GetSize() - branch0.SubTrees[i].GetSize() <= maxNewNodes) {
+          CrossoverPoint p = new CrossoverPoint();
+          p.childIndex = i;
+          p.parent0 = branch0;
+          p.parent1 = branch1;
+          crossoverPoints.Add(p);
+        }
+        GetCrossOverPoints(gardener, branch0.SubTrees[i], branch1.SubTrees[i], maxNewNodes, crossoverPoints);
+      }
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Crossovers/SizeConstrictedGPCrossoverBase.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Crossovers/SizeConstrictedGPCrossoverBase.cs	(revision 3218)
+++ /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Crossovers/SizeConstrictedGPCrossoverBase.cs	(revision 3218)
@@ -0,0 +1,59 @@
+#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 HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.GP.Interfaces;
+
+namespace HeuristicLab.GP.Operators {
+  public abstract class SizeConstrictedGPCrossoverBase : GPCrossoverBase {
+
+    private int MaxRecombinationTries { get { return 20; } }
+
+    public SizeConstrictedGPCrossoverBase()
+      : base() {
+      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));
+    }
+
+    internal override IFunctionTree Cross(IScope scope, TreeGardener gardener, IRandom random, IFunctionTree tree0, IFunctionTree tree1) {
+      int maxTreeHeight = GetVariableValue<IntData>("MaxTreeHeight", scope, true).Data;
+      int maxTreeSize = GetVariableValue<IntData>("MaxTreeSize", scope, true).Data;
+
+      // when tree0 is terminal then try to cross into tree1, when tree1 is also terminal just return tree0 unchanged.
+      IFunctionTree newTree;
+      int tries = 0;
+      do {
+        if (tries++ > MaxRecombinationTries)
+          // if after so many tries it was not possible to create a solution within the given size constraints just return the tree without changes.
+          return tree0;
+        if (tree0.SubTrees.Count > 0) {
+          newTree = Cross(gardener, random, (IFunctionTree)tree0.Clone(), (IFunctionTree)tree1.Clone(), maxTreeSize, maxTreeHeight);
+        } else if (tree1.SubTrees.Count > 0) {
+          newTree = Cross(gardener, random, (IFunctionTree)tree1.Clone(), (IFunctionTree)tree0.Clone(), maxTreeSize, maxTreeHeight);
+        } else newTree = tree0;
+      } while (newTree.GetSize() > maxTreeSize || newTree.GetHeight() > maxTreeHeight);
+      return newTree;
+    }
+
+    internal abstract IFunctionTree Cross(TreeGardener gardener, IRandom random, IFunctionTree tree0, IFunctionTree tree1, int maxTreeSize, int maxTreeHeight);
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Crossovers/SizeFairCrossOver.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Crossovers/SizeFairCrossOver.cs	(revision 3218)
+++ /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Crossovers/SizeFairCrossOver.cs	(revision 3218)
@@ -0,0 +1,148 @@
+#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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Core;
+using HeuristicLab.GP.Interfaces;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.GP.Operators {
+  /// <summary>
+  /// Implementation of a size fair crossover operator as described in: 
+  /// William B. Langdon 
+  /// Size Fair and Homologous Tree Genetic Programming Crossovers, 
+  /// Genetic Programming and Evolvable Machines, Vol. 1, Number 1/2, pp. 95-119, April 2000
+  /// </summary>
+  public class SizeFairCrossOver : SizeConstrictedGPCrossoverBase {
+    private int MaxRecombinationTries { get { return 20; } }
+    // private data structure for crossover points
+    protected class CrossoverPoint {
+      public IFunctionTree tree;
+      public int branchSize;
+      public List<int> trail;
+    }
+
+    internal override IFunctionTree Cross(TreeGardener gardener, IRandom random, IFunctionTree tree0, IFunctionTree tree1, int maxTreeSize, int maxTreeHeight) {
+      int tries = 0;
+      IFunctionTree insertedBranch = null;
+      IFunctionTree parent = null;
+      int removedBranchIndex = 0;
+      do {
+        // select a random suboperator of the 'receiving' tree
+        while (parent == null) parent = gardener.GetRandomParentNode(tree0);
+        removedBranchIndex = random.Next(parent.SubTrees.Count);
+        insertedBranch = GetReplacementBranch((MersenneTwister)random, gardener, tree0, parent, removedBranchIndex, tree1, maxTreeSize, maxTreeHeight);
+      } while (insertedBranch == null && tries++ < MaxRecombinationTries);
+
+      if (insertedBranch != null) {
+        // replace the branch below the crossoverpoint with the selected branch from root1
+        parent.RemoveSubTree(removedBranchIndex);
+        parent.InsertSubTree(removedBranchIndex, insertedBranch);
+      }
+      return tree0;
+    }
+
+    private IFunctionTree GetReplacementBranch(MersenneTwister random, TreeGardener gardener, IFunctionTree intoTree, IFunctionTree parent, int replacedBranchIndex, IFunctionTree fromTree, int maxTreeSize, int maxTreeHeight) {
+      IList<IFunction> allowedFunctions = new List<IFunction>(gardener.GetAllowedSubFunctions(parent.Function, replacedBranchIndex));
+      int removedBranchSize = parent.SubTrees[replacedBranchIndex].GetSize();
+      int maxBranchSize = maxTreeSize - (intoTree.GetSize() - removedBranchSize);
+      int maxBranchHeight = maxTreeHeight - gardener.GetBranchLevel(intoTree, parent);  // returns 1 if intoTree==parent and 2 if parent is a child of intoTree
+      List<int> replacedTrail = GetTrail(intoTree, parent);
+      replacedTrail.Add(replacedBranchIndex);
+
+      List<CrossoverPoint> shorterBranches = new List<CrossoverPoint>();
+      List<CrossoverPoint> longerBranches = new List<CrossoverPoint>();
+      List<CrossoverPoint> equalLengthBranches = new List<CrossoverPoint>();
+
+      FindPossibleBranches(fromTree, allowedFunctions, maxBranchSize, maxBranchHeight, removedBranchSize, shorterBranches, equalLengthBranches, longerBranches, new List<int>());
+
+      if (shorterBranches.Count > 0 && longerBranches.Count > 0) {
+        double pEqualLength = equalLengthBranches.Count > 0 ? 1.0 / removedBranchSize : 0.0;
+        double pLonger;
+        if (parent.GetSize() == maxTreeSize) {
+          pLonger = 0.0;
+        } else {
+          pLonger = (1.0 - pEqualLength) / (longerBranches.Count * (1.0 + longerBranches.Average(p => p.branchSize) / shorterBranches.Average(p => p.branchSize)));
+        }
+        double pShorter = (1.0 - pEqualLength - pLonger);
+
+        double r = random.NextDouble();
+        if (r < pLonger) {
+          return SelectReplacement(random, replacedTrail, longerBranches);
+        } else if (r < pLonger + pShorter) {
+          return SelectReplacement(random, replacedTrail, shorterBranches);
+        } else {
+          return SelectReplacement(random, replacedTrail, equalLengthBranches);
+        }
+      } else if (equalLengthBranches.Count > 0) {
+        return SelectReplacement(random, replacedTrail, equalLengthBranches);
+      } else {
+        return null;
+      }
+    }
+
+    protected virtual IFunctionTree SelectReplacement(MersenneTwister random, List<int> replacedTrail, List<CrossoverPoint> crossoverPoints) {
+      return crossoverPoints[random.Next(crossoverPoints.Count)].tree;
+    }
+
+    private void FindPossibleBranches(IFunctionTree tree, IList<IFunction> allowedFunctions, int maxBranchSize, int maxBranchHeight, int removedBranchSize,
+      List<CrossoverPoint> shorterBranches, List<CrossoverPoint> equalLengthBranches, List<CrossoverPoint> longerBranches, List<int> trail) {
+      int treeSize = tree.GetSize();
+      if (allowedFunctions.Contains(tree.Function) && treeSize <= maxBranchSize && tree.GetHeight() <= maxBranchHeight) {
+        CrossoverPoint p = new CrossoverPoint();
+        p.branchSize = treeSize;
+        p.tree = tree;
+        p.trail = new List<int>(trail);
+        if (treeSize < removedBranchSize) shorterBranches.Add(p);
+        else if (treeSize > removedBranchSize) longerBranches.Add(p);
+        else equalLengthBranches.Add(p);
+      }
+      for (int i = 0; i < tree.SubTrees.Count; i++) {
+        trail.Add(i);
+        FindPossibleBranches(tree.SubTrees[i], allowedFunctions, maxBranchSize, maxBranchHeight, removedBranchSize, shorterBranches, equalLengthBranches, longerBranches, trail);
+        trail.RemoveAt(trail.Count - 1);
+      }
+    }
+
+    private List<int> GetTrail(IFunctionTree root, IFunctionTree branch) {
+      List<int> trail = new List<int>();
+      GetTrail(root, branch, trail);
+      trail.Reverse();
+      trail.RemoveAt(trail.Count - 1);
+      return trail;
+    }
+    private void GetTrail(IFunctionTree root, IFunctionTree branch, List<int> trail) {
+      if (root == branch) {
+        trail.Add(-1); // add flag that there was a match
+        return;
+      }
+
+      for (int i = 0; i < root.SubTrees.Count; i++) {
+        GetTrail(root.SubTrees[i], branch, trail);
+        if (trail.Count > 0) {
+          trail.Add(i);
+          return;
+        }
+      }
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Crossovers/StandardCrossOver.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Crossovers/StandardCrossOver.cs	(revision 3218)
+++ /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Crossovers/StandardCrossOver.cs	(revision 3218)
@@ -0,0 +1,78 @@
+#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.Collections.Generic;
+using HeuristicLab.Core;
+using HeuristicLab.GP.Interfaces;
+
+namespace HeuristicLab.GP.Operators {
+  public class StandardCrossOver : SizeConstrictedGPCrossoverBase {
+    private int MaxRecombinationTries { get { return 20; } }
+
+    public override string Description {
+      get {
+        return @"Takes two parent individuals P0 and P1 each. Selects a random node N0 of P0 and a random node N1 of P1.
+And replaces the branch with root0 N0 in P0 with N1 from P1 if the tree-size limits are not violated.
+When recombination with N0 and N1 would create a tree that is too large or invalid the operator randomly selects new N0 and N1 
+until a valid configuration is found.";
+      }
+    }
+
+    internal override IFunctionTree Cross(TreeGardener gardener, IRandom random, IFunctionTree tree0, IFunctionTree tree1, int maxTreeSize, int maxTreeHeight) {
+      int tries = 0;
+      List<IFunctionTree> allowedCrossoverPoints = null;
+      IFunctionTree parent0;
+      int replacedChildIndex;
+      do {
+        // select a random crossover point in the first parent tree0
+        parent0 = null;
+        while (parent0 == null) parent0 = gardener.GetRandomParentNode(tree0);
+        // select a random branch to replace
+        replacedChildIndex = random.Next(parent0.SubTrees.Count);
+
+        // calculate the max size and height that the inserted branch can have 
+        int maxInsertedBranchSize = maxTreeSize - (tree0.GetSize() - parent0.SubTrees[replacedChildIndex].GetSize());
+        int maxInsertedBranchHeight = maxTreeHeight - gardener.GetBranchLevel(tree0, parent0); // branchlevel is 1 if tree0==parent0
+
+        IList<IFunction> allowedFunctions = new List<IFunction>(gardener.GetAllowedSubFunctions(parent0.Function, replacedChildIndex));
+        allowedCrossoverPoints = GetPossibleCrossoverPoints(tree1, maxInsertedBranchSize, maxInsertedBranchHeight, allowedFunctions);
+      } while (allowedCrossoverPoints.Count == 0 && tries++ < MaxRecombinationTries);
+
+      if (allowedCrossoverPoints.Count > 0) {
+        IFunctionTree branch1 = allowedCrossoverPoints[random.Next(allowedCrossoverPoints.Count)];
+
+        // replace the branch in tree0 with the selected branch from tree1
+        parent0.RemoveSubTree(replacedChildIndex);
+        parent0.InsertSubTree(replacedChildIndex, branch1);
+      }
+      return tree0;
+    }
+
+    private List<IFunctionTree> GetPossibleCrossoverPoints(IFunctionTree tree, int maxInsertedBranchSize, int maxInsertedBranchHeight, IList<IFunction> allowedFunctions) {
+      List<IFunctionTree> crossoverPoints = new List<IFunctionTree>();
+      foreach (IFunctionTree possiblePoint in TreeGardener.GetAllSubTrees(tree)) {
+        if (allowedFunctions.Contains(possiblePoint.Function) && possiblePoint.GetSize() <= maxInsertedBranchSize && possiblePoint.GetHeight() <= maxInsertedBranchHeight)
+          crossoverPoints.Add(possiblePoint);
+      }
+      return crossoverPoints;
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Crossovers/UniformCrossover.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Crossovers/UniformCrossover.cs	(revision 3218)
+++ /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Crossovers/UniformCrossover.cs	(revision 3218)
@@ -0,0 +1,155 @@
+#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.Collections.Generic;
+using HeuristicLab.Core;
+using HeuristicLab.GP.Interfaces;
+
+namespace HeuristicLab.GP.Operators {
+  /// <summary>
+  /// Implementation of a homologous uniform crossover operator as described in: 
+  /// R. Poli and W. B. Langdon.  On the Search Properties of Different Crossover Operators in Genetic Programming.
+  /// In Proceedings of Genetic Programming '98, Madison, Wisconsin, 1998.
+  /// </summary>
+  public class UniformCrossover : SizeConstrictedGPCrossoverBase {
+    // internal datastructure to represent crossover points
+    private class CrossoverPoint {
+      public IFunctionTree Parent0;
+      public IFunctionTree Parent1;
+      public int ChildIndex;
+      public bool IsInternal;
+    }
+
+    public override string Description {
+      get {
+        return @"Uniform crossover as defined by Poli and Langdon";
+      }
+    }
+
+    internal override IFunctionTree Cross(TreeGardener gardener, IRandom random, IFunctionTree tree0, IFunctionTree tree1, int maxTreeSize, int maxTreeHeight) {
+      List<CrossoverPoint> allowedCrossOverPoints = new List<CrossoverPoint>();
+      GetCrossOverPoints(gardener, tree0, tree1, allowedCrossOverPoints);
+      // iterate through the list of crossover points and swap nodes with p=0.5
+      foreach (CrossoverPoint crossoverPoint in allowedCrossOverPoints) {
+        if (random.NextDouble() < 0.5) {
+          if (crossoverPoint.IsInternal) {
+            ExchangeNodes(crossoverPoint);
+          } else {
+            SwapSubtrees(crossoverPoint);
+          }
+        }
+      }
+      return tree0;
+    }
+
+    private void GetCrossOverPoints(TreeGardener gardener, IFunctionTree branch0, IFunctionTree branch1, List<CrossoverPoint> crossoverPoints) {
+      if (branch0.SubTrees.Count != branch1.SubTrees.Count) return; // branches have to have same number of sub-trees to be valid crossover points
+      // iterate over all sub-trees
+      for (int i = 0; i < branch0.SubTrees.Count; i++) {
+        IFunctionTree currentSubTree0 = branch0.SubTrees[i];
+        IFunctionTree currentSubTree1 = branch1.SubTrees[i];
+        // when the current sub-tree in branch1 can be attached as a child of branch0
+        // and the sub-tree of branch0 can be attached as child of branch1.
+        // note: we have to check both cases because either branch0 or branch1 can end up in the result tree
+        if (gardener.GetAllowedSubFunctions(branch0.Function, i).Contains(currentSubTree1.Function) &&
+          gardener.GetAllowedSubFunctions(branch1.Function, i).Contains(currentSubTree0.Function)) {
+          // and the sub-tree is at the border of the common region 
+          if (currentSubTree0.SubTrees.Count != currentSubTree1.SubTrees.Count) {
+            // then we have found a valid crossover point
+            CrossoverPoint p = new CrossoverPoint();
+            p.ChildIndex = i;
+            p.Parent0 = branch0;
+            p.Parent1 = branch1;
+            p.IsInternal = false;
+            crossoverPoints.Add(p);
+          } else {
+            // when the sub-trees are not on the border of the common region
+            // we also have to check if the children of the current sub-trees of branch0 and branch1 can be exchanged 
+            if (CanHaveSubTrees(gardener, currentSubTree0, currentSubTree1.SubTrees) &&
+              CanHaveSubTrees(gardener, currentSubTree1, currentSubTree0.SubTrees)) {
+              CrossoverPoint p = new CrossoverPoint();
+              p.ChildIndex = i;
+              p.Parent0 = branch0;
+              p.Parent1 = branch1;
+              p.IsInternal = true;
+              crossoverPoints.Add(p);
+            }
+          }
+        }
+        GetCrossOverPoints(gardener, currentSubTree0, currentSubTree1, crossoverPoints);
+      }
+    }
+
+    private bool CanHaveSubTrees(TreeGardener gardener, IFunctionTree parent, IList<IFunctionTree> subTrees) {
+      for (int i = 0; i < subTrees.Count; i++) {
+        if (!gardener.GetAllowedSubFunctions(parent.Function, i).Contains(subTrees[i].Function)) return false;
+      }
+      return true;
+    }
+
+    private void ExchangeNodes(CrossoverPoint crossoverPoint) {
+      IFunctionTree parent0 = crossoverPoint.Parent0;
+      IFunctionTree parent1 = crossoverPoint.Parent1;
+      int childIndex = crossoverPoint.ChildIndex;
+      IFunctionTree branch0 = crossoverPoint.Parent0.SubTrees[childIndex];
+      IFunctionTree branch1 = crossoverPoint.Parent1.SubTrees[childIndex];
+      // exchange the branches in the parent
+      parent0.RemoveSubTree(childIndex);
+      parent0.InsertSubTree(childIndex, branch1);
+      parent1.RemoveSubTree(childIndex);
+      parent1.InsertSubTree(childIndex, branch0);
+
+      ExchangeChildren(branch0, branch1);
+    }
+
+    private void SwapSubtrees(CrossoverPoint crossoverPoint) {
+      IFunctionTree parent0 = crossoverPoint.Parent0;
+      IFunctionTree parent1 = crossoverPoint.Parent1;
+      int childIndex = crossoverPoint.ChildIndex;
+      IFunctionTree branch0 = crossoverPoint.Parent0.SubTrees[childIndex];
+      IFunctionTree branch1 = crossoverPoint.Parent1.SubTrees[childIndex];
+      // insert branch1 into parent0 replacing branch0
+      parent0.RemoveSubTree(childIndex);
+      parent0.InsertSubTree(childIndex, branch1);
+      // insert branch0 into parent1 replacing branch1
+      parent1.RemoveSubTree(childIndex);
+      parent1.InsertSubTree(childIndex, branch0);
+    }
+
+    private void ExchangeChildren(IFunctionTree branch0, IFunctionTree branch1) {
+      List<IFunctionTree> branch0Children = new List<IFunctionTree>(branch0.SubTrees); // lists to backup subtrees
+      List<IFunctionTree> branch1Children = new List<IFunctionTree>(branch1.SubTrees);
+
+      // remove children of branch0 and branch1
+      while (branch1.SubTrees.Count > 0) branch1.RemoveSubTree(0);
+      while (branch0.SubTrees.Count > 0) branch0.RemoveSubTree(0);
+
+      // add original children of branch0 to branch1
+      foreach (IFunctionTree subTree in branch0Children) {
+        branch1.AddSubTree(subTree);
+      }
+      // add original children of branch1 to branch0
+      foreach (IFunctionTree subTree in branch1Children) {
+        branch0.AddSubTree(subTree);
+      }
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Function.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Function.cs	(revision 3218)
+++ /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Function.cs	(revision 3218)
@@ -0,0 +1,292 @@
+#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.Text;
+using HeuristicLab.Core;
+using System.Xml;
+using System.Diagnostics;
+using HeuristicLab.GP.Interfaces;
+using System.Linq;
+
+namespace HeuristicLab.GP {
+  public abstract class Function : ItemBase, IFunction {
+    private List<List<IFunction>> allowedSubFunctions = new List<List<IFunction>>();
+    private int minArity = -1;
+    private int maxArity = -1;
+    private double tickets = 1.0;
+    private IOperator initializer;
+    private IOperator manipulator;
+    private int minTreeHeight = -1;
+    private int minTreeSize = -1;
+
+    private string name;
+    public virtual string Name {
+      get { return name; }
+      set {
+        if (string.IsNullOrEmpty(value)) throw new ArgumentException();
+        if (value != name) {
+          name = value;
+          FireChanged();
+        }
+      }
+    }
+
+    protected Function() {
+      name = this.GetType().Name;
+    }
+
+    public virtual string Description {
+      get { return "Description for this function is missing (TODO)"; }
+    }
+
+    public int MinSubTrees {
+      get {
+        return minArity;
+      }
+      protected internal set {
+        if (value < 0) throw new ArgumentException();
+        if (minArity != value) {
+          minArity = value;
+          while (minArity > allowedSubFunctions.Count) allowedSubFunctions.Add(new List<IFunction>());
+          ResetCachedValues();
+          FireChanged();
+        }
+      }
+    }
+
+    public int MaxSubTrees {
+      get {
+        return maxArity;
+      }
+      protected internal set {
+        if (value < 0) throw new ArgumentException();
+        if (value < minArity) throw new ArgumentException();
+        if (value != maxArity) {
+          maxArity = value;
+          while (allowedSubFunctions.Count > maxArity) allowedSubFunctions.RemoveAt(allowedSubFunctions.Count - 1);
+          while (maxArity > allowedSubFunctions.Count) {
+            if (allowedSubFunctions.Count > 0) {
+              // copy the list of allowed sub-functions from the previous slot
+              allowedSubFunctions.Add(new List<IFunction>(allowedSubFunctions[allowedSubFunctions.Count - 1]));
+            } else {
+              // add empty list
+              allowedSubFunctions.Add(new List<IFunction>());
+            }
+          }
+          ResetCachedValues();
+          FireChanged();
+        }
+      }
+    }
+
+
+    public int MinTreeSize {
+      get {
+        if (minTreeSize <= 0) {
+          RecalculateMinimalTreeSize();
+          FireChanged();
+        }
+        Debug.Assert(minTreeSize > 0);
+        return minTreeSize;
+      }
+    }
+
+    public int MinTreeHeight {
+      get {
+        if (minTreeHeight <= 0) {
+          RecalculateMinimalTreeHeight();
+          FireChanged();
+        }
+        Debug.Assert(minTreeHeight > 0);
+        return minTreeHeight;
+      }
+    }
+
+    public double Tickets {
+      get { return tickets; }
+      set {
+        if (value < 0.0) throw new ArgumentException("Number of tickets must be positive");
+        if (value != tickets) {
+          tickets = value;
+          FireChanged();
+        }
+      }
+    }
+
+    public IOperator Initializer {
+      get { return initializer; }
+      set {
+        if (initializer != value) {
+          initializer = value;
+          FireChanged();
+        }
+      }
+    }
+
+    public IOperator Manipulator {
+      get { return manipulator; }
+      set {
+        if (manipulator != value) {
+          manipulator = value;
+          FireChanged();
+        }
+      }
+    }
+
+    public virtual IFunctionTree GetTreeNode() {
+      return new FunctionTree(this);
+    }
+
+    public ICollection<IFunction> GetAllowedSubFunctions(int index) {
+      if (index < 0 || index > MaxSubTrees) throw new ArgumentException("Index outside of allowed range. index = " + index);
+      return allowedSubFunctions[index];
+    }
+
+    public void AddAllowedSubFunction(IFunction function, int index) {
+      if (index < 0 || index > MaxSubTrees) throw new ArgumentException("Index outside of allowed range. index = " + index);
+      if (allowedSubFunctions[index] == null) {
+        allowedSubFunctions[index] = new List<IFunction>();
+      }
+      if (!allowedSubFunctions[index].Contains(function)) {
+        allowedSubFunctions[index].Add(function);
+      }
+      ResetCachedValues();
+      FireChanged();
+    }
+    public void RemoveAllowedSubFunction(IFunction function, int index) {
+      if (index < 0 || index > MaxSubTrees) throw new ArgumentException("Index outside of allowed range. index = " + index);
+      if (allowedSubFunctions[index].Contains(function)) {
+        allowedSubFunctions[index].Remove(function);
+        ResetCachedValues();
+        FireChanged();
+      }
+    }
+
+    private void ResetCachedValues() {
+      minTreeHeight = -1;
+      minTreeSize = -1;
+    }
+
+    public bool IsAllowedSubFunction(IFunction function, int index) {
+      return GetAllowedSubFunctions(index).Contains(function);
+    }
+
+    private void RecalculateMinimalTreeSize() {
+      if (MinSubTrees == 0) minTreeSize = 1;
+      else {
+        minTreeSize = int.MaxValue; // prevent infinite recursion        
+        minTreeSize = 1 + (from slot in Enumerable.Range(0, MinSubTrees)
+                           let minForSlot = (from function in GetAllowedSubFunctions(slot)
+                                             where function != this
+                                             select function.MinTreeSize).DefaultIfEmpty(0).Min()
+                           select minForSlot).Sum();
+      }
+    }
+
+    private void RecalculateMinimalTreeHeight() {
+      if (MinSubTrees == 0) minTreeHeight = 1;
+      else {
+        minTreeHeight = int.MaxValue;
+        minTreeHeight = 1 + (from slot in Enumerable.Range(0, MinSubTrees)
+                             let minForSlot = (from function in GetAllowedSubFunctions(slot)
+                                               where function != this
+                                               select function.MinTreeHeight).DefaultIfEmpty(0).Min()
+                             select minForSlot).Max();
+      }
+    }
+
+    public override IView CreateView() {
+      return new FunctionView(this);
+    }
+
+    public override string ToString() {
+      return name;
+    }
+
+    #region persistence
+    public override object Clone(IDictionary<Guid, object> clonedObjects) {
+      Function clone = (Function)base.Clone(clonedObjects);
+      if (initializer != null) clone.initializer = (IOperator)Auxiliary.Clone(initializer, clonedObjects);
+      else clone.initializer = null;
+      if (manipulator != null) clone.manipulator = (IOperator)Auxiliary.Clone(manipulator, clonedObjects);
+      else clone.manipulator = null;
+      clone.MaxSubTrees = maxArity;
+      clone.MinSubTrees = minArity;
+      clone.Tickets = tickets;
+      clone.allowedSubFunctions.Clear();
+      for (int i = 0; i < MaxSubTrees; i++) {
+        var allowedSubFunctionsForSlot = new List<IFunction>();
+        foreach (IFunction f in GetAllowedSubFunctions(i)) {
+          allowedSubFunctionsForSlot.Add((IFunction)Auxiliary.Clone(f, clonedObjects));
+        }
+        clone.allowedSubFunctions.Add(allowedSubFunctionsForSlot);
+      }
+      return clone;
+    }
+
+    public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary<Guid, IStorable> persistedObjects) {
+      XmlNode node = base.GetXmlNode(name, document, persistedObjects);
+      XmlAttribute minSubTreesAttr = document.CreateAttribute("MinSubTrees");
+      minSubTreesAttr.Value = XmlConvert.ToString(MinSubTrees);
+      XmlAttribute maxSubTreesAttr = document.CreateAttribute("MaxSubTrees");
+      maxSubTreesAttr.Value = XmlConvert.ToString(MaxSubTrees);
+      node.Attributes.Append(minSubTreesAttr);
+      node.Attributes.Append(maxSubTreesAttr);
+      if (initializer != null)
+        node.AppendChild(PersistenceManager.Persist("Initializer", initializer, document, persistedObjects));
+      if (manipulator != null)
+        node.AppendChild(PersistenceManager.Persist("Manipulator", manipulator, document, persistedObjects));
+      for (int i = 0; i < MaxSubTrees; i++) {
+        XmlNode slotNode = document.CreateElement("AllowedSubFunctions");
+        XmlAttribute slotAttr = document.CreateAttribute("Slot");
+        slotAttr.Value = XmlConvert.ToString(i);
+        slotNode.Attributes.Append(slotAttr);
+        node.AppendChild(slotNode);
+        foreach (IFunction f in GetAllowedSubFunctions(i)) {
+          slotNode.AppendChild(PersistenceManager.Persist(f, document, persistedObjects));
+        }
+      }
+      return node;
+    }
+
+    public override void Populate(XmlNode node, IDictionary<Guid, IStorable> restoredObjects) {
+      base.Populate(node, restoredObjects);
+      MinSubTrees = XmlConvert.ToInt32(node.Attributes["MinSubTrees"].Value);
+      MaxSubTrees = XmlConvert.ToInt32(node.Attributes["MaxSubTrees"].Value);
+      if (node.SelectSingleNode("Initializer") != null) {
+        initializer = (IOperator)PersistenceManager.Restore(node.SelectSingleNode("Initializer"), restoredObjects);
+      }
+      if (node.SelectSingleNode("Manipulator") != null) {
+        manipulator = (IOperator)PersistenceManager.Restore(node.SelectSingleNode("Manipulator"), restoredObjects);
+      }
+      foreach (var subFunctionsList in allowedSubFunctions) subFunctionsList.Clear();
+      foreach (XmlNode allowedSubFunctionsNode in node.SelectNodes("AllowedSubFunctions")) {
+        int slot = XmlConvert.ToInt32(allowedSubFunctionsNode.Attributes["Slot"].Value);
+        foreach (XmlNode fNode in allowedSubFunctionsNode.ChildNodes) {
+          AddAllowedSubFunction((IFunction)PersistenceManager.Restore(fNode, restoredObjects), slot);
+        }
+      }
+    }
+    #endregion
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/FunctionTree.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/FunctionTree.cs	(revision 3218)
+++ /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/FunctionTree.cs	(revision 3218)
@@ -0,0 +1,125 @@
+#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.Text;
+using HeuristicLab.Core;
+using HeuristicLab.GP.Interfaces;
+using System.Xml;
+
+namespace HeuristicLab.GP {
+  public class FunctionTree : IFunctionTree {
+    private List<IFunctionTree> subTrees;
+    private IFunction function;
+
+    public FunctionTree() {
+    }
+
+    public FunctionTree(IFunction function) {
+      subTrees = new List<IFunctionTree>();
+      this.function = function;
+    }
+
+    protected FunctionTree(FunctionTree original) {
+      this.function = original.Function;
+      this.subTrees = new List<IFunctionTree>(original.SubTrees.Count);
+      foreach (IFunctionTree originalSubTree in original.SubTrees) {
+        this.SubTrees.Add((IFunctionTree)originalSubTree.Clone());
+      }
+    }
+
+    #region IFunctionTree Members
+    public virtual bool HasLocalParameters {
+      get { return false; }
+    }
+
+    public virtual IList<IFunctionTree> SubTrees {
+      get { return subTrees; }
+    }
+
+    public IFunction Function {
+      get { return function; }
+      protected set { function = value; }
+    }
+
+    public int GetSize() {
+      int size = 1;
+      foreach (IFunctionTree tree in SubTrees) size += tree.GetSize();
+      return size;
+    }
+
+    public int GetHeight() {
+      int maxHeight = 0;
+      foreach (IFunctionTree tree in SubTrees) maxHeight = Math.Max(maxHeight, tree.GetHeight());
+      return maxHeight + 1;
+    }
+
+    public virtual IOperation CreateShakingOperation(IScope scope) {
+      return null;
+    }
+
+    public virtual IOperation CreateInitOperation(IScope scope) {
+      return null;
+    }
+
+    public void AddSubTree(IFunctionTree tree) {
+      SubTrees.Add(tree);
+    }
+
+    public virtual void InsertSubTree(int index, IFunctionTree tree) {
+      SubTrees.Insert(index, tree);
+    }
+
+    public virtual void RemoveSubTree(int index) {
+      SubTrees.RemoveAt(index);
+    }
+
+    public override string ToString() {
+      return Function.Name;
+    }
+
+    #endregion
+
+    #region IStorable Members
+
+    public Guid Guid {
+      get { throw new NotSupportedException(); }
+    }
+
+    public virtual object Clone() {
+      return new FunctionTree(this);
+    }
+
+    public object Clone(IDictionary<Guid, object> clonedObjects) {
+      throw new NotImplementedException();
+    }
+
+    public virtual XmlNode GetXmlNode(string name, XmlDocument document, IDictionary<Guid, IStorable> persistedObjects) {
+      return null;
+    }
+
+    public virtual void Populate(XmlNode node, IDictionary<Guid, IStorable> restoredObjects) {
+    }
+
+    #endregion
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/HeuristicLabEncodingsSymbolicExpressionTree.cs.frame
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/HeuristicLabEncodingsSymbolicExpressionTree.cs.frame	(revision 3218)
+++ /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/HeuristicLabEncodingsSymbolicExpressionTree.cs.frame	(revision 3218)
@@ -0,0 +1,40 @@
+#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.Text;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.GP.Operators {
+  [Plugin("HeuristicLab.GP.Operators", "3.3.0.$WCREV$")]
+  [PluginFile("HeuristicLab.GP.Operators-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.Core-3.2")]
+  [PluginDependency("HeuristicLab.Data-3.2")]
+  [PluginDependency("HeuristicLab.Evolutionary-3.2")]
+  [PluginDependency("HeuristicLab.GP", "3.3")]
+  [PluginDependency("HeuristicLab.GP.Interfaces", "3.3")]
+  [PluginDependency("HeuristicLab.Operators-3.2")]
+  [PluginDependency("HeuristicLab.Random-3.2")]
+  [PluginDependency("HeuristicLab.Selection-3.2")]
+  public class HeuristicLabGPOperatorsPlugin : PluginBase {
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Interfaces/IFunction.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Interfaces/IFunction.cs	(revision 3218)
+++ /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Interfaces/IFunction.cs	(revision 3218)
@@ -0,0 +1,43 @@
+#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.Text;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.GP.Interfaces {
+  public interface IFunction : IItem {
+    string Name { get; }
+    IFunctionTree GetTreeNode();
+    ICollection<IFunction> GetAllowedSubFunctions(int index);
+    void AddAllowedSubFunction(IFunction f, int index);
+    void RemoveAllowedSubFunction(IFunction f, int index);
+    bool IsAllowedSubFunction(IFunction f, int index);
+    int MinSubTrees { get; }
+    int MaxSubTrees { get; }
+    int MinTreeHeight { get; }
+    int MinTreeSize { get; }
+    double Tickets { get; }
+    IOperator Initializer { get; }
+    IOperator Manipulator { get; }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Interfaces/IFunctionTree.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Interfaces/IFunctionTree.cs	(revision 3218)
+++ /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Interfaces/IFunctionTree.cs	(revision 3218)
@@ -0,0 +1,41 @@
+#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.Text;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.GP.Interfaces {
+  public interface IFunctionTree : IStorable {
+    bool HasLocalParameters { get; }
+    IList<IFunctionTree> SubTrees { get; }
+    IFunction Function { get; }
+    IOperation CreateShakingOperation(IScope scope);
+    IOperation CreateInitOperation(IScope scope);
+    int GetSize();
+    int GetHeight();
+    void AddSubTree(IFunctionTree tree);
+    void InsertSubTree(int index, IFunctionTree tree);
+    void RemoveSubTree(int index);
+    string ToString();
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Manipulators/ChangeNodeTypeManipulation.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Manipulators/ChangeNodeTypeManipulation.cs	(revision 3218)
+++ /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Manipulators/ChangeNodeTypeManipulation.cs	(revision 3218)
@@ -0,0 +1,169 @@
+#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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Core;
+using HeuristicLab.Random;
+using System.Diagnostics;
+using HeuristicLab.GP.Interfaces;
+
+namespace HeuristicLab.GP.Operators {
+  public class ChangeNodeTypeManipulation : GPManipulatorBase {
+
+    public override string Description {
+      get {
+        return @"This manipulation operator selects a random tree-node and changes the function type.
+If this leads to a constraint-violation (wrong number or type of sub-trees) the sub-trees are repaired
+resulting in a valid tree again.";
+      }
+    }
+
+    public ChangeNodeTypeManipulation()
+      : base() {
+    }
+
+    internal override IOperation Manipulate(MersenneTwister random, IGeneticProgrammingModel gpModel, FunctionLibrary library, int maxTreeSize, int maxTreeHeight, IScope scope) {
+      TreeGardener gardener = new TreeGardener(random, library);
+      IFunctionTree parent = gardener.GetRandomParentNode(gpModel.FunctionTree);
+      IFunctionTree selectedChild;
+      int selectedChildIndex;
+      if (parent == null) {
+        selectedChildIndex = 0;
+        selectedChild = gpModel.FunctionTree;
+      } else {
+        selectedChildIndex = random.Next(parent.SubTrees.Count);
+        selectedChild = parent.SubTrees[selectedChildIndex];
+      }
+
+      if (selectedChild.SubTrees.Count == 0) {
+        IFunctionTree newTerminal = ChangeTerminalType(parent, selectedChild, selectedChildIndex, gardener, random);
+        if (parent == null) {
+          // no parent means the new child is the initial operator
+          gpModel.FunctionTree = newTerminal;
+        } else {
+          parent.RemoveSubTree(selectedChildIndex);
+          parent.InsertSubTree(selectedChildIndex, newTerminal);
+          // updating the variable is not necessary because it stays the same
+        }
+        Debug.Assert(gardener.IsValidTree(gpModel.FunctionTree));
+        // size and height stays the same when changing a terminal so no need to update the variables
+        // schedule an operation to initialize the new terminal
+        return Util.CreateInitializationOperation(TreeGardener.GetAllSubTrees(newTerminal), scope);
+      } else {
+        List<IFunctionTree> uninitializedBranches;
+        IFunctionTree newFunctionTree = ChangeFunctionType(parent, selectedChild, selectedChildIndex, gardener, random, out uninitializedBranches);
+        // in rare cases the function creates a tree that breaks the size limits
+        // calculate the height and size difference and 
+        // check if the size of the new tree is still in the allowed bounds
+        int oldChildSize = selectedChild.GetSize();
+        int oldChildHeight = selectedChild.GetHeight();
+        int newChildSize = newFunctionTree.GetSize();
+        int newChildHeight = newFunctionTree.GetHeight();
+        if ((gpModel.Height - oldChildHeight) + newChildHeight > maxTreeHeight ||
+          (gpModel.Size - oldChildSize) + newChildSize > maxTreeSize) {
+          // if size-constraints are violated don't change anything
+          return null;
+        }
+        if (parent == null) {
+          // no parent means the new function is the initial operator
+          gpModel.FunctionTree = newFunctionTree;
+        } else {
+          // remove the old child
+          parent.RemoveSubTree(selectedChildIndex);
+          // add the new child as sub-tree of parent
+          parent.InsertSubTree(selectedChildIndex, newFunctionTree);
+        }
+        // update size and height
+        gpModel.Size = gpModel.Size - oldChildSize + newChildSize;
+        gpModel.Height = gpModel.FunctionTree.GetHeight(); // must recalculate height because we can't know wether the manipulated branch was the deepest branch
+        // check if whole tree is ok
+        Debug.Assert(gardener.IsValidTree(gpModel.FunctionTree));
+        // return a composite operation that initializes all created sub-trees
+        return Util.CreateInitializationOperation(uninitializedBranches, scope);
+      }
+    }
+
+    private IFunctionTree ChangeTerminalType(IFunctionTree parent, IFunctionTree child, int childIndex, TreeGardener gardener, MersenneTwister random) {
+      IList<IFunction> allowedTerminals;
+      if (parent == null) {
+        allowedTerminals = gardener.Terminals;
+      } else {
+        allowedTerminals = new List<IFunction>();
+        var allAllowedChildren = gardener.GetAllowedSubFunctions(parent.Function, childIndex);
+        foreach (IFunction c in allAllowedChildren) {
+          if (TreeGardener.IsTerminal(c)) allowedTerminals.Add(c);
+        }
+      }
+      // selecting from the terminals should always work since the current child was also a terminal
+      // so in the worst case we will just create a new terminal of the same type again.
+      return gardener.CreateRandomTree(allowedTerminals, 1, 1);
+    }
+
+    private IFunctionTree ChangeFunctionType(IFunctionTree parent, IFunctionTree child, int childIndex, TreeGardener gardener, MersenneTwister random,
+      out List<IFunctionTree> uninitializedBranches) {
+      // since there are subtrees, we have to check which 
+      // and how many of the existing subtrees we can reuse.
+      // first let's choose the function we want to use instead of the old child. For this we have to determine the
+      // pool of allowed functions based on constraints of the parent if there is one.
+      List<IFunction> allowedFunctions = new List<IFunction>(gardener.GetAllowedSubFunctions(parent != null ? parent.Function : null, childIndex));
+      // try to make a tree with the same arity as the old child.
+      int actualArity = child.SubTrees.Count;
+      // create a new tree-node for a randomly selected function
+      IFunction selectedFunction = allowedFunctions[random.Next(allowedFunctions.Count)];
+      // arity of the selected operator
+      int minArity = selectedFunction.MinSubTrees;
+      int maxArity = selectedFunction.MaxSubTrees;
+      // if the old child had too many sub-trees then the new child should keep as many sub-trees as possible
+      if (actualArity > maxArity)
+        actualArity = maxArity;
+      if (actualArity < minArity)
+        actualArity = minArity;
+      // create a list that holds old sub-trees that we can reuse in the new tree
+      List<IFunctionTree> availableSubTrees = new List<IFunctionTree>(child.SubTrees);
+      List<IFunctionTree> freshSubTrees = new List<IFunctionTree>();
+      IFunctionTree newTree = selectedFunction.GetTreeNode();
+      // randomly select the sub-trees that we keep
+      for (int i = 0; i < actualArity; i++) {
+        // fill all sub-tree slots of the new tree
+        // if for a given slot i there are multiple existing sub-trees that can be used in that slot
+        // then use a random existing sub-tree. When there are no existing sub-trees
+        // that fit in the given slot then create a new random tree and use it for the slot
+        ICollection<IFunction> allowedSubFunctions = gardener.GetAllowedSubFunctions(selectedFunction, i);
+        var matchingSubTrees = availableSubTrees.Where(subTree => allowedSubFunctions.Contains(subTree.Function));
+        if (matchingSubTrees.Count() > 0) {
+          IFunctionTree selectedSubTree = matchingSubTrees.ElementAt(random.Next(matchingSubTrees.Count()));
+          // we can just add it as subtree
+          newTree.InsertSubTree(i, selectedSubTree);
+          availableSubTrees.Remove(selectedSubTree); // the branch shouldn't be available for the following slots
+        } else {
+          // no existing matching tree found => create a new tree of minimal size
+          IFunctionTree freshTree = gardener.CreateRandomTree(allowedSubFunctions, 1, 1);
+          freshSubTrees.AddRange(TreeGardener.GetAllSubTrees(freshTree));
+          newTree.InsertSubTree(i, freshTree);
+        }
+      }
+      freshSubTrees.Add(newTree);
+      uninitializedBranches = freshSubTrees;
+      return newTree;
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Manipulators/CutOutNodeManipulation.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Manipulators/CutOutNodeManipulation.cs	(revision 3218)
+++ /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Manipulators/CutOutNodeManipulation.cs	(revision 3218)
@@ -0,0 +1,111 @@
+#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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Core;
+using HeuristicLab.Random;
+using System.Diagnostics;
+using HeuristicLab.GP.Interfaces;
+
+namespace HeuristicLab.GP.Operators {
+  public class CutOutNodeManipulation : GPManipulatorBase {
+    public override string Description {
+      get {
+        return @"Takes a tree, selects a random node of the tree and then tries to replace a random sub-tree
+of that node with one of the childs of the selected child.
+
+               O                             O
+              / \                           / \
+             O   X                         O   2
+                / \    2 is selected =>       / \
+               1   2                         4   5
+              /   / \
+             3   4   5
+";
+      }
+    }
+
+    public CutOutNodeManipulation()
+      : base() {
+    }
+
+
+    internal override IOperation Manipulate(MersenneTwister random, IGeneticProgrammingModel gpModel, FunctionLibrary library, int maxTreeSize, int maxTreeHeight, IScope scope) {
+      TreeGardener gardener = new TreeGardener(random, library);
+      IFunctionTree parent = gardener.GetRandomParentNode(gpModel.FunctionTree);
+      // parent == null means we should cut out the root node
+      // => return a random sub-tree of the root
+      if (parent == null) {
+        // when there are sub-trees then replace the old tree with a random sub-tree
+        if (gpModel.FunctionTree.SubTrees.Count > 0) {
+          gpModel.FunctionTree = gpModel.FunctionTree.SubTrees[random.Next(gpModel.FunctionTree.SubTrees.Count)];
+          Debug.Assert(gardener.IsValidTree(gpModel.FunctionTree));
+          // we reused a sub-tree so we don't have to schedule initialization operations
+          return null;
+        } else {
+          // we want to cut the root node and there are no sub-trees => create a new random terminal
+          gpModel.FunctionTree = gardener.CreateRandomTree(gardener.Terminals, 1, 1);
+          Debug.Assert(gardener.IsValidTree(gpModel.FunctionTree));
+
+          // schedule an operation to initialize the whole tree
+          return Util.CreateInitializationOperation(TreeGardener.GetAllSubTrees(gpModel.FunctionTree), scope);
+        }
+      }
+
+      // select a child to cut away
+      int childIndex = random.Next(parent.SubTrees.Count);
+      IFunctionTree child = parent.SubTrees[childIndex];
+      // match the sub-trees of the child with the allowed sub-trees of the parent
+      ICollection<IFunction> allowedFunctions = gardener.GetAllowedSubFunctions(parent.Function, childIndex);
+      IFunctionTree[] possibleChilds = child.SubTrees.Where(t => allowedFunctions.Contains(t.Function)).ToArray();
+      if (possibleChilds.Length > 0) {
+        // replace child with a random child of that child
+        IFunctionTree selectedChild = possibleChilds[random.Next(possibleChilds.Length)];
+        parent.RemoveSubTree(childIndex);
+        parent.InsertSubTree(childIndex, selectedChild);
+        Debug.Assert(gardener.IsValidTree(gpModel.FunctionTree));
+        // recalculate the size and height of our tree
+        gpModel.Size = gpModel.FunctionTree.GetSize();
+        gpModel.Height = gpModel.FunctionTree.GetHeight();
+        // don't need to schedule initialization operations
+        return null;
+      } else {
+        // can't reuse an existing branch => create a new tree
+        // determine the level of the parent
+        int parentLevel = gardener.GetBranchLevel(gpModel.FunctionTree, parent);
+        // first remove the old child (first step essential!)
+        parent.RemoveSubTree(childIndex);
+        // then determine the number of nodes left over after the child has been removed!
+        int remainingNodes = gpModel.FunctionTree.GetSize();
+        allowedFunctions = gardener.GetAllowedSubFunctions(parent.Function, childIndex);
+        IFunctionTree newFunctionTree = gardener.CreateRandomTree(allowedFunctions, maxTreeSize - remainingNodes, maxTreeHeight - parentLevel);
+        parent.InsertSubTree(childIndex, newFunctionTree);
+        Debug.Assert(gardener.IsValidTree(gpModel.FunctionTree));
+        // recalculate size and height
+        gpModel.Size = gpModel.FunctionTree.GetSize();
+        gpModel.Height = gpModel.FunctionTree.GetHeight();
+        // schedule an initialization operation for the new function-tree
+        return Util.CreateInitializationOperation(TreeGardener.GetAllSubTrees(newFunctionTree), scope);
+      }
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Manipulators/DeleteSubTreeManipulation.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Manipulators/DeleteSubTreeManipulation.cs	(revision 3218)
+++ /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Manipulators/DeleteSubTreeManipulation.cs	(revision 3218)
@@ -0,0 +1,87 @@
+#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.Collections.Generic;
+using HeuristicLab.Core;
+using HeuristicLab.Random;
+using System.Diagnostics;
+using HeuristicLab.GP.Interfaces;
+
+namespace HeuristicLab.GP.Operators {
+  public class DeleteSubTreeManipulation : GPManipulatorBase {
+    public override string Description {
+      get {
+        return @"Deletes a random sub-tree of the input tree. If the remaining tree is not valid 
+the operator tries to fix the tree by generating random subtrees where necessary.";
+      }
+    }
+
+    public DeleteSubTreeManipulation()
+      : base() {
+    }
+
+    internal override IOperation Manipulate(MersenneTwister random, IGeneticProgrammingModel gpModel, FunctionLibrary library, int maxTreeSize, int maxTreeHeight, IScope scope) {
+      TreeGardener gardener = new TreeGardener(random, library);
+      IFunctionTree parent = gardener.GetRandomParentNode(gpModel.FunctionTree);
+
+      // parent==null means the whole tree should be deleted.
+      // => return a new minimal random tree
+      if (parent == null) {
+        IFunctionTree newTree = gardener.CreateBalancedRandomTree(1, 1);
+        // check if the tree is ok
+        Debug.Assert(gardener.IsValidTree(newTree));
+        gpModel.FunctionTree = newTree;
+        // schedule an operation to initialize the newly created operator
+        return Util.CreateInitializationOperation(TreeGardener.GetAllSubTrees(newTree), scope);
+      }
+
+      // select a branch to prune
+      int childIndex = random.Next(parent.SubTrees.Count);
+      if (parent.SubTrees.Count > parent.Function.MinSubTrees) {
+        parent.RemoveSubTree(childIndex);
+        // actually since the next sub-trees are shifted in the place of the removed branch
+        // it might be possible that these sub-trees are not allowed in the place of the old branch
+        // we ignore this problem for now.
+        // when this starts to become a problem a possible solution is to go through the shifted branches from the place of the shifted
+        // and find the first one that doesn't fit. At this position we insert a new randomly initialized subtree of matching type (gkronber 25.12.07)
+
+        Debug.Assert(gardener.IsValidTree(gpModel.FunctionTree));
+        // recalculate size and height
+        gpModel.Size = gpModel.FunctionTree.GetSize();
+        gpModel.Height = gpModel.FunctionTree.GetHeight();
+        // root hasn't changed so don't need to update 'FunctionTree' variable
+        return null;
+      } else {
+        // replace with a minimal random seedling
+        parent.RemoveSubTree(childIndex);
+        ICollection<IFunction> allowedFunctions = gardener.GetAllowedSubFunctions(parent.Function, childIndex);
+        IFunctionTree newFunctionTree = gardener.CreateRandomTree(allowedFunctions, 1, 1);
+        parent.InsertSubTree(childIndex, newFunctionTree);
+        Debug.Assert(gardener.IsValidTree(gpModel.FunctionTree));
+        // recalculate size and height
+        gpModel.Size = gpModel.FunctionTree.GetSize();
+        gpModel.Height = gpModel.FunctionTree.GetHeight();
+        // return an initialization operation for the newly created tree
+        return Util.CreateInitializationOperation(TreeGardener.GetAllSubTrees(newFunctionTree), scope);
+      }
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Manipulators/FullTreeShaker.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Manipulators/FullTreeShaker.cs	(revision 3218)
+++ /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Manipulators/FullTreeShaker.cs	(revision 3218)
@@ -0,0 +1,76 @@
+#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.Linq;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Random;
+using HeuristicLab.Data;
+using HeuristicLab.GP.Interfaces;
+using HeuristicLab.Selection;
+
+namespace HeuristicLab.GP.Operators {
+  public class FullTreeShaker : DelegatingOperator {
+    public override string Description {
+      get { return "Manipulates all tree nodes for which a manipulator is defined."; }
+    }
+
+    public FullTreeShaker()
+      : base() {
+      AddVariableInfo(new VariableInfo("Random", "A random generator (uniform)", typeof(MersenneTwister), VariableKind.In));
+      AddVariableInfo(new VariableInfo("FunctionLibrary", "Function library that defines function mutations", typeof(FunctionLibrary), VariableKind.In));
+      AddVariableInfo(new VariableInfo("ShakingFactor", "Variable that determines the force of the shaking operation", typeof(DoubleData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("FunctionTree", "The function tree that should be mutated", typeof(IGeneticProgrammingModel), VariableKind.In | VariableKind.Out));
+    }
+
+    public override IOperation Apply(IScope scope) {
+      FunctionLibrary library = GetVariableValue<FunctionLibrary>("FunctionLibrary", scope, true);
+      IGeneticProgrammingModel gpModel = GetVariableValue<IGeneticProgrammingModel>("FunctionTree", scope, false);
+      MersenneTwister mt = GetVariableValue<MersenneTwister>("Random", scope, true);
+
+      // save all existing sub-scopes in a backup scope
+      Scope backupScope = new Scope("backup");
+      foreach (Scope subScope in scope.SubScopes) {
+        backupScope.AddSubScope(subScope);
+      }
+
+      // create a scope for all shaking operations
+      Scope tempScope = new Scope("Temp. manipulation scope");
+      scope.AddSubScope(tempScope); // scope containing a subscope for each manipulation
+      scope.AddSubScope(backupScope); // scope containing the old subscopes
+
+      // create a composite operation for all shaking operations
+      CompositeOperation next = new CompositeOperation();
+      next.ExecuteInParallel = false;
+
+      // enqueue all shaking operations
+      foreach (IFunctionTree subTree in TreeGardener.GetAllSubTrees(gpModel.FunctionTree).Where(x=>x.HasLocalParameters)) {
+        IOperation shakingOperation = subTree.CreateShakingOperation(tempScope);
+        next.AddOperation(shakingOperation);
+      }
+
+      // schedule a reducer operation to delete all temporary scopes and restore
+      // the subscopes of the backup scope after all manipulations are finished.
+      next.AddOperation(new AtomicOperation(new RightReducer(), scope));
+      return next;
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Manipulators/GPManipulatorBase.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Manipulators/GPManipulatorBase.cs	(revision 3218)
+++ /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Manipulators/GPManipulatorBase.cs	(revision 3218)
@@ -0,0 +1,50 @@
+#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 HeuristicLab.Core;
+using HeuristicLab.Random;
+using HeuristicLab.Data;
+using HeuristicLab.GP.Interfaces;
+
+namespace HeuristicLab.GP.Operators {
+  public abstract class GPManipulatorBase : OperatorBase {
+    public GPManipulatorBase()
+      : base() {
+      AddVariableInfo(new VariableInfo("Random", "Uniform random number generator", typeof(MersenneTwister), VariableKind.In));
+      AddVariableInfo(new VariableInfo("FunctionLibrary", "The operator library containing all available operators", typeof(FunctionLibrary), 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 crossover", typeof(IGeneticProgrammingModel), VariableKind.In | VariableKind.New));
+    }
+
+    internal abstract IOperation Manipulate(MersenneTwister random, IGeneticProgrammingModel gpModel, FunctionLibrary library, int maxSize, int maxHeight, IScope scope);
+
+    public override IOperation Apply(IScope scope) {
+      FunctionLibrary funLibrary = GetVariableValue<FunctionLibrary>("FunctionLibrary", scope, true);
+      IGeneticProgrammingModel gpModel = GetVariableValue<IGeneticProgrammingModel>("FunctionTree", scope, false);
+      MersenneTwister random = GetVariableValue<MersenneTwister>("Random", scope, true);
+      int maxTreeSize = GetVariableValue<IntData>("MaxTreeSize", scope, true).Data;
+      int maxTreeHeight = GetVariableValue<IntData>("MaxTreeHeight", scope, true).Data;
+
+      return Manipulate(random, gpModel, funLibrary, maxTreeSize, maxTreeHeight, scope);
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Manipulators/OnePointShaker.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Manipulators/OnePointShaker.cs	(revision 3218)
+++ /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Manipulators/OnePointShaker.cs	(revision 3218)
@@ -0,0 +1,76 @@
+#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.Linq;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Random;
+using HeuristicLab.Data;
+using HeuristicLab.Selection;
+using HeuristicLab.GP.Interfaces;
+
+namespace HeuristicLab.GP.Operators {
+  public class OnePointShaker : DelegatingOperator {
+    public override string Description {
+      get { return "Selects a random node of all tree-nodes that have a manipulator defined and manipulates the selected node."; }
+    }
+
+    public OnePointShaker()
+      : base() {
+      AddVariableInfo(new VariableInfo("FunctionLibrary", "Function library that defines mutation operations for functions", typeof(FunctionLibrary), VariableKind.In));
+      AddVariableInfo(new VariableInfo("Random", "A random generator (uniform)", typeof(MersenneTwister), VariableKind.In));
+      AddVariableInfo(new VariableInfo("ShakingFactor", "Factor that determines the force of the shaking operation", typeof(DoubleData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("FunctionTree", "The function tree that should be mutated", typeof(IGeneticProgrammingModel), VariableKind.In | VariableKind.Out));
+    }
+
+    public override IOperation Apply(IScope scope) {
+      FunctionLibrary library = GetVariableValue<FunctionLibrary>("FunctionLibrary", scope, true);
+      IGeneticProgrammingModel gpModel = GetVariableValue<IGeneticProgrammingModel>("FunctionTree", scope, false);
+      MersenneTwister mt = GetVariableValue<MersenneTwister>("Random", scope, true);
+
+      // get all nodes with local parameters
+      var parametricBranches = TreeGardener.GetAllSubTrees(gpModel.FunctionTree).Where(branch => branch.HasLocalParameters);
+      if (parametricBranches.Count() == 0) return null; // don't manipulate anything if there are no nodes with a manipulation operator
+      IFunctionTree selectedBranch = parametricBranches.ElementAt(mt.Next(parametricBranches.Count()));
+
+      // save the exising sub-scopes in a backup scope
+      Scope backupScope = new Scope("backup");
+      foreach (Scope subScope in scope.SubScopes) {
+        backupScope.AddSubScope(subScope);
+      }
+
+      // create a scope for all shaking operations
+      Scope tempScope = new Scope("Temp. manipulation scope");
+      
+      // add the new sub-scopes
+      scope.AddSubScope(tempScope);
+      scope.AddSubScope(backupScope);
+
+      CompositeOperation next = new CompositeOperation();
+      next.ExecuteInParallel = false;
+      // the next operation should first manipulate and then restore the sub-scopes from the backup scope
+      next.AddOperation(selectedBranch.CreateShakingOperation(tempScope));
+      next.AddOperation(new AtomicOperation(new RightReducer(), scope));
+
+      return next;
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Manipulators/SubstituteSubTreeManipulation.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Manipulators/SubstituteSubTreeManipulation.cs	(revision 3218)
+++ /trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTree/3.3/Manipulators/SubstituteSubTreeManipulation.cs	(revision 3218)
@@ -0,0 +1,84 @@
+#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 HeuristicLab.Core;
+using HeuristicLab.Random;
+using System.Diagnostics;
+using HeuristicLab.GP.Interfaces;
+
+namespace HeuristicLab.GP.Operators {
+  public class SubstituteSubTreeManipulation : GPManipulatorBase {
+
+    public override string Description {
+      get { return "Selects a random node of the tree and replaces it with randomly initialized subtree."; }
+    }
+
+    public SubstituteSubTreeManipulation()
+      : base() {
+    }
+
+    internal override IOperation Manipulate(MersenneTwister random, IGeneticProgrammingModel gpModel, FunctionLibrary library, int maxTreeSize, int maxTreeHeight, IScope scope) {
+      TreeGardener gardener = new TreeGardener(random, library);
+      IFunctionTree parent = gardener.GetRandomParentNode(gpModel.FunctionTree);
+      if (parent == null) {
+        // parent == null means we should subsitute the whole tree
+        // => create a new random tree
+        IFunctionTree newTree = gardener.CreateRandomTree(gardener.AllFunctions, maxTreeSize, maxTreeHeight);
+        Debug.Assert(gardener.IsValidTree(newTree));
+
+        gpModel.FunctionTree = newTree;
+        // return a CompositeOperation that randomly initializes the new tree
+        return Util.CreateInitializationOperation(TreeGardener.GetAllSubTrees(newTree), scope);
+      } else {
+        // determine a random child of the parent to be replaced
+        int childIndex = random.Next(parent.SubTrees.Count);
+        // get the list of allowed functions for the new sub-tree
+        ICollection<IFunction> allowedFunctions = gardener.GetAllowedSubFunctions(parent.Function, childIndex);
+        if (allowedFunctions.Count == 0) {
+          // don't change anything
+          // this shouldn't happen
+          throw new InvalidProgramException();
+        }
+
+        // calculate the maximum size and height of the new sub-tree based on the location where
+        // it will be inserted
+        int parentLevel = gardener.GetBranchLevel(gpModel.FunctionTree, parent);
+        int maxSubTreeHeight = maxTreeHeight - parentLevel;
+        int maxSubTreeSize = maxTreeSize - (gpModel.Size - parent.SubTrees[childIndex].GetSize());
+
+        // create a random function tree
+        IFunctionTree newTree = gardener.CreateRandomTree(allowedFunctions, maxSubTreeSize, maxSubTreeHeight);
+        parent.RemoveSubTree(childIndex);
+        parent.InsertSubTree(childIndex, newTree);
+
+        Debug.Assert(gardener.IsValidTree(gpModel.FunctionTree));
+        // update the values of treeSize and treeHeight
+        gpModel.Size = gpModel.FunctionTree.GetSize();
+        gpModel.Height = gpModel.FunctionTree.GetHeight();
+        // the root hasn't changed so we don't need to update 
+        // return a CompositeOperation that randomly initializes all nodes of the new subtree
+        return Util.CreateInitializationOperation(TreeGardener.GetAllSubTrees(newTree), scope);
+      }
+    }
+  }
+}
