Index: /branches/plugins/HeuristicLab.GP/3.2/BakedFunctionTree.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/BakedFunctionTree.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/BakedFunctionTree.cs	(revision 1295)
@@ -0,0 +1,347 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using System.Xml;
+using System.Globalization;
+
+namespace HeuristicLab.GP {
+
+  public class LightWeightFunction {
+    public byte arity = 0;
+    public IFunction functionType;
+    public List<double> data = new List<double>();
+
+    public LightWeightFunction Clone() {
+      LightWeightFunction clone = new LightWeightFunction();
+      clone.arity = arity;
+      clone.functionType = functionType;
+      clone.data.AddRange(data);
+      return clone;
+    }
+  }
+
+  public class BakedFunctionTree : ItemBase, IFunctionTree {
+    private List<LightWeightFunction> linearRepresentation;
+    public List<LightWeightFunction> LinearRepresentation {
+      get {
+        FlattenVariables();
+        FlattenTrees(); 
+        return linearRepresentation;
+      }
+    }
+    private bool treesExpanded = false;
+    private List<IFunctionTree> subTrees;
+    private bool variablesExpanded = false;
+    private List<IVariable> variables;
+
+    public BakedFunctionTree() {
+      linearRepresentation = new List<LightWeightFunction>();
+    }
+
+    internal BakedFunctionTree(IFunction function)
+      : this() {
+      LightWeightFunction fun = new LightWeightFunction();
+      fun.functionType = function;
+      linearRepresentation.Add(fun);
+      treesExpanded = true;
+      subTrees = new List<IFunctionTree>();
+      variables = new List<IVariable>();
+      variablesExpanded = true;
+      foreach(IVariableInfo variableInfo in function.VariableInfos) {
+        if(variableInfo.Local) {
+          variables.Add((IVariable)function.GetVariable(variableInfo.FormalName).Clone());
+        }
+      }
+    }
+
+    internal BakedFunctionTree(IFunctionTree tree)
+      : this() {
+      LightWeightFunction fun = new LightWeightFunction();
+      fun.functionType = tree.Function;
+      linearRepresentation.Add(fun);
+      foreach(IVariable variable in tree.LocalVariables) {
+        IItem value = variable.Value;
+        fun.data.Add(GetDoubleValue(value));
+      }
+      foreach(IFunctionTree subTree in tree.SubTrees) {
+        AddSubTree(new BakedFunctionTree(subTree));
+      }
+    }
+
+    private double GetDoubleValue(IItem value) {
+      if(value is DoubleData) {
+        return ((DoubleData)value).Data;
+      } else if(value is ConstrainedDoubleData) {
+        return ((ConstrainedDoubleData)value).Data;
+      } else if(value is IntData) {
+        return ((IntData)value).Data;
+      } else if(value is ConstrainedIntData) {
+        return ((ConstrainedIntData)value).Data;
+      } else throw new NotSupportedException("Invalid datatype of local variable for GP");
+    }
+
+    private int BranchLength(int branchRoot) {
+      int arity = linearRepresentation[branchRoot].arity;
+      int length = 1;
+      for(int i = 0; i < arity; i++) {
+        length += BranchLength(branchRoot + length);
+      }
+      return length;
+    }
+
+    private void FlattenTrees() {
+      if(treesExpanded) {
+        linearRepresentation[0].arity = (byte)subTrees.Count;
+        foreach(BakedFunctionTree subTree in subTrees) {
+          subTree.FlattenVariables();
+          subTree.FlattenTrees();
+          linearRepresentation.AddRange(subTree.linearRepresentation);
+        }
+        treesExpanded = false;
+        subTrees = null;
+      }
+    }
+
+    private void FlattenVariables() {
+      if(variablesExpanded) {
+        linearRepresentation[0].data.Clear();
+        foreach(IVariable variable in variables) {
+          linearRepresentation[0].data.Add(GetDoubleValue(variable.Value));
+        }
+        variablesExpanded = false;
+        variables = null;
+      }
+    }
+
+    public int Size {
+      get {
+        if(treesExpanded) {
+          int size = 1;
+          foreach(BakedFunctionTree tree in subTrees) {
+            size += tree.Size;
+          }
+          return size;
+        } else 
+        return linearRepresentation.Count;
+      }
+    }
+
+    public int Height {
+      get {
+        if(treesExpanded) {
+          int height = 0;
+          foreach(IFunctionTree subTree in subTrees) {
+            int curHeight = subTree.Height;
+            if(curHeight > height) height = curHeight;
+          }
+          return height+1;
+        } else {
+          int nextBranchStart;
+          return BranchHeight(0, out nextBranchStart);
+        }
+      }
+    }
+
+    private int BranchHeight(int branchStart, out int nextBranchStart) {
+      LightWeightFunction f = linearRepresentation[branchStart];
+      int height = 0;
+      branchStart++;
+      for(int i = 0; i < f.arity; i++) {
+        int curHeight = BranchHeight(branchStart, out nextBranchStart);
+        if(curHeight > height) height = curHeight;
+        branchStart = nextBranchStart;
+      }
+      nextBranchStart = branchStart;
+      return height + 1;
+    }
+
+    public IList<IFunctionTree> SubTrees {
+      get {
+        if(!treesExpanded) {
+          subTrees = new List<IFunctionTree>();
+          int arity = linearRepresentation[0].arity;
+          int branchIndex = 1;
+          for(int i = 0; i < arity; i++) {
+            BakedFunctionTree subTree = new BakedFunctionTree();
+            int length = BranchLength(branchIndex);
+            for(int j = branchIndex; j < branchIndex + length; j++) {
+              subTree.linearRepresentation.Add(linearRepresentation[j]);
+            }
+            branchIndex += length;
+            subTrees.Add(subTree);
+          }
+          treesExpanded = true;
+          linearRepresentation.RemoveRange(1, linearRepresentation.Count - 1);
+          linearRepresentation[0].arity = 0;
+        }
+        return subTrees;
+      }
+    }
+
+    public ICollection<IVariable> LocalVariables {
+      get {
+        if(!variablesExpanded) {
+          variables = new List<IVariable>();
+          IFunction function = Function;
+          int localVariableIndex = 0;
+          foreach(IVariableInfo variableInfo in function.VariableInfos) {
+            if(variableInfo.Local) {
+              IVariable clone = (IVariable)function.GetVariable(variableInfo.FormalName).Clone();
+              IItem value = clone.Value;
+              if(value is ConstrainedDoubleData) {
+                ((ConstrainedDoubleData)value).Data = linearRepresentation[0].data[localVariableIndex];
+              } else if(value is ConstrainedIntData) {
+                ((ConstrainedIntData)value).Data = (int)linearRepresentation[0].data[localVariableIndex];
+              } else if(value is DoubleData) {
+                ((DoubleData)value).Data = linearRepresentation[0].data[localVariableIndex];
+              } else if(value is IntData) {
+                ((IntData)value).Data = (int)linearRepresentation[0].data[localVariableIndex];
+              } else throw new NotSupportedException("Invalid local variable type for GP.");
+              variables.Add(clone);
+              localVariableIndex++;
+            }
+          }
+          variablesExpanded = true;
+          linearRepresentation[0].data.Clear();
+        }
+        return variables;
+      }
+    }
+
+    public IFunction Function {
+      get { return linearRepresentation[0].functionType; }
+    }
+
+    public IVariable GetLocalVariable(string name) {
+      foreach(IVariable var in LocalVariables) {
+        if(var.Name == name) return var;
+      }
+      return null;
+    }
+
+    public void AddVariable(IVariable variable) {
+      throw new NotSupportedException();
+    }
+
+    public void RemoveVariable(string name) {
+      throw new NotSupportedException();
+    }
+
+    public void AddSubTree(IFunctionTree tree) {
+      if(!treesExpanded) throw new InvalidOperationException();
+      subTrees.Add(tree);
+    }
+
+    public void InsertSubTree(int index, IFunctionTree tree) {
+      if(!treesExpanded) throw new InvalidOperationException();
+      subTrees.Insert(index, tree);
+    }
+
+    public void RemoveSubTree(int index) {
+      // sanity check
+      if(!treesExpanded) throw new InvalidOperationException();
+      subTrees.RemoveAt(index);
+    }
+
+    public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary<Guid, IStorable> persistedObjects) {
+      FlattenVariables();
+      FlattenTrees();
+      XmlNode node = base.GetXmlNode(name, document, persistedObjects);
+      XmlNode linearRepresentationNode = document.CreateElement("LinearRepresentation");
+      foreach(LightWeightFunction f in linearRepresentation) {
+        XmlNode entryNode = PersistenceManager.Persist("FunctionType", f.functionType, document, persistedObjects);
+        XmlAttribute arityAttribute = document.CreateAttribute("Arity");
+        arityAttribute.Value = f.arity+"";
+        entryNode.Attributes.Append(arityAttribute);
+        if(f.data.Count > 0) {
+          XmlAttribute dataAttribute = document.CreateAttribute("Data");
+          dataAttribute.Value = GetString(f.data);
+          entryNode.Attributes.Append(dataAttribute);
+        }
+        linearRepresentationNode.AppendChild(entryNode);
+      }
+
+      node.AppendChild(linearRepresentationNode);
+      return node;
+    }
+
+    public override void Populate(XmlNode node, IDictionary<Guid, IStorable> restoredObjects) {
+      base.Populate(node, restoredObjects);
+      XmlNode linearRepresentationNode = node.SelectSingleNode("LinearRepresentation");
+      foreach(XmlNode entryNode in linearRepresentationNode.ChildNodes) {
+        LightWeightFunction f = new LightWeightFunction();
+        f.arity = byte.Parse(entryNode.Attributes["Arity"].Value, CultureInfo.InvariantCulture);
+        if(entryNode.Attributes["Data"]!=null) 
+          f.data = GetList<double>(entryNode.Attributes["Data"].Value, s => double.Parse(s, CultureInfo.InvariantCulture));
+        f.functionType = (IFunction)PersistenceManager.Restore(entryNode, restoredObjects);
+        linearRepresentation.Add(f);
+      }
+      treesExpanded = false;
+      variablesExpanded = false;
+    }
+
+    private string GetString(IEnumerable<double> xs) {
+      StringBuilder builder = new StringBuilder();
+      foreach(double x in xs) {
+        builder.Append(x.ToString("r", CultureInfo.InvariantCulture) + "; ");
+      }
+      if(builder.Length > 0) builder.Remove(builder.Length - 2, 2);
+      return builder.ToString();
+    }
+
+    private List<T> GetList<T>(string s, Converter<string, T> converter) {
+      List<T> result = new List<T>();
+      string[] tokens = s.Split(new char[] { ';', ' ' }, StringSplitOptions.RemoveEmptyEntries);
+      foreach(string token in tokens) {
+        T x = converter(token.Trim());
+        result.Add(x);
+      }
+      return result;
+    }
+
+    public override object Clone(IDictionary<Guid, object> clonedObjects) {
+      BakedFunctionTree clone = new BakedFunctionTree();
+      // in case the user (de)serialized the tree between evaluation and selection we have to flatten the tree again.
+      if(treesExpanded) FlattenTrees();
+      if(variablesExpanded) FlattenVariables();
+      foreach(LightWeightFunction f in linearRepresentation) {
+        clone.linearRepresentation.Add(f.Clone());
+      }
+      return clone;
+    }
+
+    public override IView CreateView() {
+      return new FunctionTreeView(this);
+    }
+
+    //public override string ToString() {
+    //  SymbolicExpressionExporter exporter = new SymbolicExpressionExporter();
+    //  exporter.Visit(this);
+    //  return exporter.GetStringRepresentation();
+    //}
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/DefaultFunctionTreeNameGenerator.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/DefaultFunctionTreeNameGenerator.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/DefaultFunctionTreeNameGenerator.cs	(revision 1295)
@@ -0,0 +1,39 @@
+#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 {
+  public class DefaultFunctionTreeNameGenerator : IFunctionTreeNameGenerator {
+    #region IFunctionTreeNameGenerator Members
+    string IFunctionTreeNameGenerator.Name {
+      get { return "Default Representation"; }
+    }
+
+    string IFunctionTreeNameGenerator.GetName(IFunctionTree tree) {
+      return tree.Function.Name;
+    }
+    #endregion
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/EqualiserController.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/EqualiserController.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/EqualiserController.cs	(revision 1295)
@@ -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 System.Collections.Generic;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.GP {
+  public class EqualiserController : OperatorBase {
+    public override string Description {
+      get { return @"TODO\r\nOperator description still missing ..."; }
+    }
+
+    public EqualiserController() {
+      AddVariableInfo(new VariableInfo("EqualiserHistogram", "Histogram of the target distribution", typeof(DoubleArrayData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("AcceptanceProbabilities", "Acceptance probabilities of individuals falling into bins", typeof(DoubleArrayData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("Histogram", "The histogram of the actual distribution", typeof(IntArrayData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("Rate", "Parameter that controls the convergence rate of the population to the equalised distribution", typeof(DoubleData), VariableKind.In));
+    }
+
+    public override IOperation Apply(IScope scope) {
+      DoubleArrayData equaliserHistogram = GetVariableValue<DoubleArrayData>("EqualiserHistogram", scope, true);
+      DoubleArrayData acceptanceProbabilities = GetVariableValue<DoubleArrayData>("AcceptanceProbabilities", scope, false, false);
+      IntArrayData currentHistogram = GetVariableValue<IntArrayData>("Histogram", scope, false, false);
+      double rate = GetVariableValue<DoubleData>("Rate", scope, false, false).Data;
+
+      double sum = 0.0;
+      Array.ForEach(currentHistogram.Data, delegate(int i) { sum += i; });
+      for(int i = 0; i < acceptanceProbabilities.Data.Length; i++) {
+        double normalizedDiff = (equaliserHistogram.Data[i] - (currentHistogram.Data[i] / sum)) / equaliserHistogram.Data[i];
+        acceptanceProbabilities.Data[i] = acceptanceProbabilities.Data[i] + normalizedDiff * rate;
+        currentHistogram.Data[i] = 0;
+      }
+      currentHistogram.FireChanged();
+      acceptanceProbabilities.FireChanged();
+      return null;
+    }
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/FunctionBase.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/FunctionBase.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/FunctionBase.cs	(revision 1295)
@@ -0,0 +1,157 @@
+#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.Data;
+using HeuristicLab.Core;
+using System.Xml;
+using HeuristicLab.Constraints;
+using System.Diagnostics;
+
+namespace HeuristicLab.GP {
+  /// <summary>
+  /// Functions are like operators except that they do not allow sub-operators and the normal form of evaluation
+  /// is to evaluate all children first.
+  /// </summary>
+  public abstract class FunctionBase : OperatorBase, IFunction {
+    public const string INITIALIZATION = "Initialization";
+    public const string MANIPULATION = "Manipulation";
+    private List<IFunction>[] allowedSubFunctions;
+    private int minArity = -1;
+    private int maxArity = -1;
+
+    public virtual double Apply() {
+      throw new NotImplementedException();
+    }
+
+    public virtual IFunctionTree GetTreeNode() {
+      return new BakedFunctionTree(this);
+    }
+
+    public int MinArity {
+      get {
+        if(minArity < 0) RefreshArity();
+        return minArity;
+      }
+    }
+
+    public int MaxArity {
+      get {
+        if(maxArity < 0) RefreshArity();
+        return maxArity;
+      }
+    }
+
+    private void RefreshArity() {
+      minArity = 2; maxArity = 2; // default arity is 2
+      foreach(IConstraint constraint in Constraints) {
+        NumberOfSubOperatorsConstraint theConstraint = constraint as NumberOfSubOperatorsConstraint;
+        if(theConstraint != null) {
+          minArity = theConstraint.MinOperators.Data;
+          maxArity = theConstraint.MaxOperators.Data;
+        }
+      }
+    }
+
+    public IList<IFunction> AllowedSubFunctions(int index) {
+      if(allowedSubFunctions == null) {
+        // first time: analyze the constraint and create a cached copy of the allowed sub-functions
+        allowedSubFunctions = new List<IFunction>[MaxArity];
+        for(int i = 0; i < MaxArity; i++) {
+          allowedSubFunctions[i] = GetAllowedSubFunctions(i);
+        }
+      }
+      return allowedSubFunctions[index];
+    }
+
+    private List<IFunction> GetAllowedSubFunctions(int index) {
+      List<IFunction> allowedSubFunctions = new List<IFunction>();
+      foreach(IConstraint constraint in Constraints) {
+        if(constraint is SubOperatorTypeConstraint) {
+          SubOperatorTypeConstraint subOpConstraint = constraint as SubOperatorTypeConstraint;
+          if(subOpConstraint.SubOperatorIndex.Data == index) {
+            foreach(IFunction f in subOpConstraint.AllowedSubOperators) allowedSubFunctions.Add(f);
+            subOpConstraint.Changed += new EventHandler(subOpConstraint_Changed); // register an event-handler to invalidate the cache on constraing changes
+            return allowedSubFunctions;
+          }
+        } else if(constraint is AllSubOperatorsTypeConstraint) {
+          AllSubOperatorsTypeConstraint subOpConstraint = constraint as AllSubOperatorsTypeConstraint;
+          foreach(IFunction f in subOpConstraint.AllowedSubOperators) allowedSubFunctions.Add(f);
+          subOpConstraint.Changed += new EventHandler(subOpConstraint_Changed); // register an event-handler to invalidate the cache on constraint changes
+          return allowedSubFunctions;
+        }
+      }
+      return allowedSubFunctions;
+    }
+
+    private void subOpConstraint_Changed(object sender, EventArgs e) {
+      allowedSubFunctions = null;
+    }
+
+    // operator-tree style evaluation is not supported for functions.
+    public override IOperation Apply(IScope scope) {
+      throw new NotSupportedException();
+    }
+
+    private static readonly List<IOperator> emptySubOperatorList = new List<IOperator>();
+    public override IList<IOperator> SubOperators {
+      get { return emptySubOperatorList; }
+    }
+
+    public override void AddSubOperator(IOperator subOperator) {
+      throw new NotSupportedException();
+    }
+
+    public override bool TryAddSubOperator(IOperator subOperator) {
+      throw new NotSupportedException();
+    }
+
+    public override bool TryAddSubOperator(IOperator subOperator, int index) {
+      throw new NotSupportedException();
+    }
+
+    public override bool TryAddSubOperator(IOperator subOperator, int index, out ICollection<IConstraint> violatedConstraints) {
+      throw new NotSupportedException();
+    }
+
+    public override bool TryAddSubOperator(IOperator subOperator, out ICollection<IConstraint> violatedConstraints) {
+      throw new NotSupportedException();
+    }
+
+    public override void AddSubOperator(IOperator subOperator, int index) {
+      throw new NotSupportedException();
+    }
+
+    public override void RemoveSubOperator(int index) {
+      throw new NotSupportedException();
+    }
+
+    public override bool TryRemoveSubOperator(int index) {
+      throw new NotSupportedException();
+    }
+
+    public override bool TryRemoveSubOperator(int index, out ICollection<IConstraint> violatedConstraints) {
+      throw new NotSupportedException();
+    }
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/FunctionView.Designer.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/FunctionView.Designer.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/FunctionView.Designer.cs	(revision 1295)
@@ -0,0 +1,198 @@
+#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;
+namespace HeuristicLab.GP {
+  partial class FunctionTreeView {
+    /// <summary> 
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary> 
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      if(selectedVariable != null) {
+        selectedVariable.Value.Changed -= new EventHandler(selectedVariable_ValueChanged);
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      this.components = new System.ComponentModel.Container();
+      this.funTreeView = new System.Windows.Forms.TreeView();
+      this.splitContainer = new System.Windows.Forms.SplitContainer();
+      this.variablesGroupBox = new System.Windows.Forms.GroupBox();
+      this.variablesSplitContainer = new System.Windows.Forms.SplitContainer();
+      this.variablesListBox = new System.Windows.Forms.ListBox();
+      this.label1 = new System.Windows.Forms.Label();
+      this.templateTextBox = new System.Windows.Forms.TextBox();
+      this.editButton = new System.Windows.Forms.Button();
+      this.treeNodeContextMenu = new System.Windows.Forms.ContextMenu();
+      this.splitContainer.Panel1.SuspendLayout();
+      this.splitContainer.Panel2.SuspendLayout();
+      this.splitContainer.SuspendLayout();
+      this.variablesGroupBox.SuspendLayout();
+      this.variablesSplitContainer.Panel1.SuspendLayout();
+      this.variablesSplitContainer.SuspendLayout();
+      this.SuspendLayout();
+      // 
+      // funTreeView
+      // 
+      this.funTreeView.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.funTreeView.HideSelection = false;
+      this.funTreeView.Location = new System.Drawing.Point(0, 0);
+      this.funTreeView.Name = "funTreeView";
+      this.funTreeView.Size = new System.Drawing.Size(182, 532);
+      this.funTreeView.TabIndex = 0;
+      this.funTreeView.MouseUp += new System.Windows.Forms.MouseEventHandler(this.funTreeView_MouseUp);
+      this.funTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.functionTreeView_AfterSelect);
+      // 
+      // splitContainer
+      // 
+      this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.splitContainer.Location = new System.Drawing.Point(0, 0);
+      this.splitContainer.Name = "splitContainer";
+      // 
+      // splitContainer.Panel1
+      // 
+      this.splitContainer.Panel1.Controls.Add(this.funTreeView);
+      // 
+      // splitContainer.Panel2
+      // 
+      this.splitContainer.Panel2.Controls.Add(this.variablesGroupBox);
+      this.splitContainer.Panel2.Controls.Add(this.label1);
+      this.splitContainer.Panel2.Controls.Add(this.templateTextBox);
+      this.splitContainer.Panel2.Controls.Add(this.editButton);
+      this.splitContainer.Size = new System.Drawing.Size(735, 532);
+      this.splitContainer.SplitterDistance = 182;
+      this.splitContainer.TabIndex = 1;
+      // 
+      // variablesGroupBox
+      // 
+      this.variablesGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                  | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.variablesGroupBox.Controls.Add(this.variablesSplitContainer);
+      this.variablesGroupBox.Location = new System.Drawing.Point(3, 31);
+      this.variablesGroupBox.Name = "variablesGroupBox";
+      this.variablesGroupBox.Size = new System.Drawing.Size(543, 498);
+      this.variablesGroupBox.TabIndex = 5;
+      this.variablesGroupBox.TabStop = false;
+      this.variablesGroupBox.Text = "Local variables";
+      // 
+      // variablesSplitContainer
+      // 
+      this.variablesSplitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.variablesSplitContainer.Location = new System.Drawing.Point(3, 16);
+      this.variablesSplitContainer.Name = "variablesSplitContainer";
+      // 
+      // variablesSplitContainer.Panel1
+      // 
+      this.variablesSplitContainer.Panel1.Controls.Add(this.variablesListBox);
+      this.variablesSplitContainer.Size = new System.Drawing.Size(537, 479);
+      this.variablesSplitContainer.SplitterDistance = 179;
+      this.variablesSplitContainer.TabIndex = 0;
+      // 
+      // variablesListBox
+      // 
+      this.variablesListBox.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.variablesListBox.FormattingEnabled = true;
+      this.variablesListBox.Location = new System.Drawing.Point(0, 0);
+      this.variablesListBox.Name = "variablesListBox";
+      this.variablesListBox.Size = new System.Drawing.Size(179, 472);
+      this.variablesListBox.TabIndex = 0;
+      this.variablesListBox.SelectedIndexChanged += new System.EventHandler(this.variablesListBox_SelectedIndexChanged);
+      // 
+      // label1
+      // 
+      this.label1.AutoSize = true;
+      this.label1.Location = new System.Drawing.Point(3, 10);
+      this.label1.Name = "label1";
+      this.label1.Size = new System.Drawing.Size(96, 13);
+      this.label1.TabIndex = 3;
+      this.label1.Text = "Function definition:";
+      // 
+      // templateTextBox
+      // 
+      this.templateTextBox.Location = new System.Drawing.Point(105, 7);
+      this.templateTextBox.Name = "templateTextBox";
+      this.templateTextBox.ReadOnly = true;
+      this.templateTextBox.Size = new System.Drawing.Size(190, 20);
+      this.templateTextBox.TabIndex = 2;
+      // 
+      // editButton
+      // 
+      this.editButton.Enabled = false;
+      this.editButton.Location = new System.Drawing.Point(301, 5);
+      this.editButton.Name = "editButton";
+      this.editButton.Size = new System.Drawing.Size(49, 23);
+      this.editButton.TabIndex = 1;
+      this.editButton.Text = "Edit...";
+      this.editButton.UseVisualStyleBackColor = true;
+      this.editButton.Click += new System.EventHandler(this.editButton_Click);
+      // 
+      // treeNodeContextMenu
+      // 
+      this.treeNodeContextMenu.Name = "treeNodeContextMenu";
+      // 
+      // FunctionTreeView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.splitContainer);
+      this.Name = "FunctionTreeView";
+      this.Size = new System.Drawing.Size(735, 532);
+      this.splitContainer.Panel1.ResumeLayout(false);
+      this.splitContainer.Panel2.ResumeLayout(false);
+      this.splitContainer.Panel2.PerformLayout();
+      this.splitContainer.ResumeLayout(false);
+      this.variablesGroupBox.ResumeLayout(false);
+      this.variablesSplitContainer.Panel1.ResumeLayout(false);
+      this.variablesSplitContainer.ResumeLayout(false);
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.TreeView funTreeView;
+    private System.Windows.Forms.SplitContainer splitContainer;
+    private System.Windows.Forms.TextBox templateTextBox;
+    private System.Windows.Forms.Button editButton;
+    private System.Windows.Forms.GroupBox variablesGroupBox;
+    private System.Windows.Forms.SplitContainer variablesSplitContainer;
+    private System.Windows.Forms.ListBox variablesListBox;
+    private System.Windows.Forms.Label label1;
+    private System.Windows.Forms.ContextMenu treeNodeContextMenu;
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/FunctionView.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/FunctionView.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/FunctionView.cs	(revision 1295)
@@ -0,0 +1,181 @@
+#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.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using HeuristicLab.Core;
+using HeuristicLab.PluginInfrastructure;
+using HeuristicLab.Data;
+
+namespace HeuristicLab.GP {
+  public partial class FunctionTreeView : ViewBase {
+    private IFunctionTree functionTree;
+
+    private IFunctionTree selectedBranch;
+    private IVariable selectedVariable;
+    private IFunctionTreeNameGenerator nameGenerator;
+    private IFunctionTreeNameGenerator[] allNameGenerators;
+    private MenuItem representationsMenu;
+
+    public FunctionTreeView() {
+      nameGenerator = new DefaultFunctionTreeNameGenerator();
+      InitializeComponent();
+
+      DiscoveryService discoveryService = new DiscoveryService();
+      allNameGenerators = discoveryService.GetInstances<IFunctionTreeNameGenerator>();
+      representationsMenu = new MenuItem();
+      representationsMenu.Text = "Tree representation";
+      representationsMenu.Name = "Tree representation";
+      foreach(IFunctionTreeNameGenerator generator in allNameGenerators) {
+        MenuItem mi = new MenuItem(generator.Name, 
+          delegate(object source, EventArgs args) {
+            IFunctionTreeNameGenerator g = (IFunctionTreeNameGenerator)((MenuItem)source).Tag;
+            this.nameGenerator = g;
+            foreach(MenuItem otherMenuItem in representationsMenu.MenuItems) otherMenuItem.Checked = false;
+            ((MenuItem)source).Checked = true;
+            UpdateControls();
+          }, Shortcut.None);
+        if(generator is DefaultFunctionTreeNameGenerator) mi.Checked = true;
+        else mi.Checked = false;
+        mi.Tag = generator;
+        representationsMenu.MenuItems.Add(mi);
+      }
+    }
+
+    public FunctionTreeView(IFunctionTree functionTree)
+      : this() {
+      this.functionTree = functionTree;
+      Refresh();
+    }
+
+    protected override void UpdateControls() {
+      funTreeView.Nodes.Clear();
+      TreeNode rootNode = new TreeNode();
+      rootNode.Name = functionTree.Function.Name;
+      rootNode.Text = nameGenerator.GetName(functionTree);
+      rootNode.Tag = functionTree;
+      treeNodeContextMenu.MenuItems.Clear();
+      treeNodeContextMenu.MenuItems.Add(representationsMenu);
+      DiscoveryService discoveryService = new DiscoveryService();
+      IFunctionTreeExporter[] exporters = discoveryService.GetInstances<IFunctionTreeExporter>();
+      foreach(IFunctionTreeExporter exporter in exporters) {
+        string result;
+        // register a menu item for the exporter
+        MenuItem item = new MenuItem("Copy to clip-board (" + exporter.Name + ")", 
+          delegate(object source, EventArgs args) {
+            TreeNode node = funTreeView.SelectedNode;
+            if(node == null || node.Tag == null) return;
+            Clipboard.SetText(exporter.Export((IFunctionTree)node.Tag));
+          }, Shortcut.None);
+        // try to export the whole tree 
+        if(exporter.TryExport(functionTree, out result)) {
+          // if it worked enable the context-menu item
+          item.Enabled = true;
+        } else {
+          item.Enabled = false;
+        }
+        treeNodeContextMenu.MenuItems.Add(item);
+      }
+      rootNode.ContextMenu = treeNodeContextMenu;
+      funTreeView.Nodes.Add(rootNode);
+
+      foreach(IFunctionTree subTree in functionTree.SubTrees) {
+        CreateTree(rootNode, subTree);
+      }
+      funTreeView.ExpandAll();
+    }
+
+    private void CreateTree(TreeNode rootNode, IFunctionTree functionTree) {
+      TreeNode node = new TreeNode();
+      node.Name = functionTree.Function.Name;
+      node.Text = nameGenerator.GetName(functionTree);
+      node.Tag = functionTree;
+      node.ContextMenu = treeNodeContextMenu;
+      rootNode.Nodes.Add(node);
+      foreach(IFunctionTree subTree in functionTree.SubTrees) {
+        CreateTree(node, subTree);
+      }
+    }
+
+    private void functionTreeView_AfterSelect(object sender, TreeViewEventArgs e) {
+      variablesListBox.Items.Clear();
+      variablesSplitContainer.Panel2.Controls.Clear();
+      templateTextBox.Clear();
+      editButton.Enabled = false;
+      if(funTreeView.SelectedNode != null && funTreeView.SelectedNode.Tag != null) {
+        IFunctionTree selectedBranch = (IFunctionTree)funTreeView.SelectedNode.Tag;
+        UpdateVariablesList(selectedBranch);
+        templateTextBox.Text = nameGenerator.GetName(selectedBranch);
+        this.selectedBranch = selectedBranch;
+        editButton.Enabled = true;
+      }
+    }
+
+    private void UpdateVariablesList(IFunctionTree functionTree) {
+      foreach(IVariable variable in functionTree.LocalVariables) {
+        variablesListBox.Items.Add(variable.Name);
+      }
+    }
+
+    private void variablesListBox_SelectedIndexChanged(object sender, EventArgs e) {
+      // in case we had an event-handler registered for a different variable => unregister the event-handler
+      if(selectedVariable != null) {
+        selectedVariable.Value.Changed -= new EventHandler(selectedVariable_ValueChanged);
+      }
+      if(variablesListBox.SelectedItem != null) {
+        string selectedVariableName = (string)variablesListBox.SelectedItem;
+        selectedVariable = selectedBranch.GetLocalVariable(selectedVariableName);
+        variablesSplitContainer.Panel2.Controls.Clear();
+        Control editor = (Control)selectedVariable.CreateView();
+        variablesSplitContainer.Panel2.Controls.Add(editor);
+        editor.Dock = DockStyle.Fill;
+        // register an event handler that updates the treenode when the value of the variable is changed by the user
+        selectedVariable.Value.Changed += new EventHandler(selectedVariable_ValueChanged);
+      } else {
+        variablesSplitContainer.Panel2.Controls.Clear();
+      }
+    }
+
+    void selectedVariable_ValueChanged(object sender, EventArgs e) {
+      if(funTreeView.SelectedNode != null && funTreeView.SelectedNode.Tag != null) {
+        TreeNode node = funTreeView.SelectedNode;
+        node.Text = nameGenerator.GetName(functionTree);
+      }
+    }
+
+    protected virtual void editButton_Click(object sender, EventArgs e) {
+      PluginManager.ControlManager.ShowControl(selectedBranch.Function.CreateView());
+    }
+
+    private void funTreeView_MouseUp(object sender, MouseEventArgs e) {
+      if(e.Button == MouseButtons.Right) {
+        // Select the clicked node
+        funTreeView.SelectedNode = funTreeView.GetNodeAt(e.X, e.Y);
+      }
+    }
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/FunctionView.resx
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/FunctionView.resx	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/FunctionView.resx	(revision 1295)
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="representationContextMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>180, 17</value>
+  </metadata>
+  <metadata name="treeNodeContextMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+</root>
Index: /branches/plugins/HeuristicLab.GP/3.2/GPOperatorGroup.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/GPOperatorGroup.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/GPOperatorGroup.cs	(revision 1295)
@@ -0,0 +1,228 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Data;
+using HeuristicLab.Random;
+using HeuristicLab.Constraints;
+
+namespace HeuristicLab.GP {
+  public class GPOperatorGroup : OperatorGroup {
+    private Dictionary<IOperator, int> minTreeHeight = new Dictionary<IOperator, int>();
+    private Dictionary<IOperator, int> minTreeSize = new Dictionary<IOperator, int>();
+    private SubOperatorsConstraintAnalyser constraintAnalyser = new SubOperatorsConstraintAnalyser();
+
+    public GPOperatorGroup()
+      : base() {
+    }
+
+    public override void AddOperator(IOperator op) {
+      base.AddOperator(op);
+      var localVariableInfos = op.VariableInfos.Where(f => f.Local);
+
+      if(op.GetVariable(GPOperatorLibrary.MIN_TREE_HEIGHT) == null) {
+        op.AddVariable(new Variable(GPOperatorLibrary.MIN_TREE_HEIGHT, new IntData(-1)));
+      }
+      if(op.GetVariable(GPOperatorLibrary.MIN_TREE_SIZE) == null) {
+        op.AddVariable(new Variable(GPOperatorLibrary.MIN_TREE_SIZE, new IntData(-1)));
+      }
+      if(op.GetVariable(GPOperatorLibrary.TICKETS) == null) {
+        op.AddVariable(new Variable(GPOperatorLibrary.TICKETS, new DoubleData(1.0)));
+      }
+      foreach(IConstraint c in op.Constraints) {
+        if(c is SubOperatorTypeConstraint || c is AllSubOperatorsTypeConstraint) c.Changed += new EventHandler(UpdateTreeBounds);
+      }
+      RecalculateMinimalTreeBounds();
+      OnOperatorAdded(op);
+    }
+
+    void UpdateTreeBounds(object sender, EventArgs e) {
+      RecalculateMinimalTreeBounds();
+    }
+
+    private void RecalculateMinimalTreeBounds() {
+      minTreeHeight.Clear();
+      minTreeSize.Clear();
+      constraintAnalyser.AllPossibleOperators = Operators;
+
+      foreach(IOperator op in Operators) {
+        ((IntData)op.GetVariable(GPOperatorLibrary.MIN_TREE_HEIGHT).Value).Data = RecalculateMinimalTreeHeight(op);
+        ((IntData)op.GetVariable(GPOperatorLibrary.MIN_TREE_SIZE).Value).Data = RecalculateMinimalTreeSize(op);
+      }
+    }
+
+    private int RecalculateMinimalTreeSize(IOperator op) {
+      // check for memoized value
+      if(minTreeSize.ContainsKey(op)) {
+        return minTreeSize[op];
+      }
+
+      int minArity;
+      int maxArity;
+      GetMinMaxArity(op, out minArity, out maxArity);
+      // no suboperators possible => minimalTreeSize == 1 (the current node)
+      if(minArity == 0 && maxArity == 0) {
+        minTreeSize[op] = 1;
+        return 1;
+      }
+
+      // when suboperators are necessary we have to find the smallest possible tree (recursively)
+      // the minimal size of the parent is 1 + the sum of the minimal sizes of all subtrees
+      int subTreeSizeSum = 0;
+
+      // mark the currently processed operator to prevent infinite recursions and stack overflow
+      minTreeSize[op] = 9999;
+      for(int i = 0; i < minArity; i++) {
+        // calculate the minTreeSize of all allowed sub-operators 
+        // if the list of allowed suboperators is empty because the operator needs suboperators 
+        // but there are no valid suboperators defined in the current group then we just use an impossible 
+        // tree size here to indicate that there was a problem.
+        // usually as more operators are added to the group the problem will be corrected (by adding the missing operator).
+        // however if the missing operator is never added the high min tree size here has the effect that this operator
+        // will not be included in generated subtrees because the resulting size would always be higher than a reasonably set 
+        // maximal tree size.
+        int minSubTreeSize = constraintAnalyser.GetAllowedOperators(op, i).Select(subOp => RecalculateMinimalTreeSize(subOp))
+          .Concat(Enumerable.Repeat(9999, 1)).Min();
+        subTreeSizeSum += minSubTreeSize;
+      }
+
+      minTreeSize[op] = subTreeSizeSum + 1;
+      return subTreeSizeSum + 1;
+    }
+
+    private int RecalculateMinimalTreeHeight(IOperator op) {
+      // check for memoized value
+      if(minTreeHeight.ContainsKey(op)) {
+        return minTreeHeight[op];
+      }
+
+      int minArity;
+      int maxArity;
+      GetMinMaxArity(op, out minArity, out maxArity);
+      // no suboperators possible => minimalTreeHeight == 1
+      if(minArity == 0 && maxArity == 0) {
+        minTreeHeight[op] = 1;
+        return 1;
+      }
+
+      // when suboperators are necessary we have to find the smallest possible tree (recursively)
+      // the minimal height of the parent is 1 + the height of the largest subtree
+      int maxSubTreeHeight = 0;
+
+      // mark the currently processed operator to prevent infinite recursions leading to stack overflow
+      minTreeHeight[op] = 9999;
+      for(int i = 0; i < minArity; i++) {
+        // calculate the minTreeHeight of all possible sub-operators.
+        // use the smallest possible subTree as lower bound for the subTreeHeight.
+        // if the list of allowed suboperators is empty because the operator needs suboperators 
+        // but there are no valid suboperators defined in the current group then we use an impossible tree height
+        // to indicate that there was a problem.
+        // usually as more operators are added to the group the problem will be corrected (by adding the missing operator).
+        // however if the missing operator is never added the high min tree height here has the effect that this operator
+        // will not be included in generated subtrees because the resulting (virtual) height would always be higher than a reasonably set 
+        // maximal tree height.
+        int minSubTreeHeight = constraintAnalyser.GetAllowedOperators(op, i).Select(subOp => RecalculateMinimalTreeHeight(subOp))
+          .Concat(Enumerable.Repeat(9999, 1)).Min();
+
+        // if the smallest height of this subtree is larger than all other subtrees before we have to update the min height of the parent
+        if(minSubTreeHeight > maxSubTreeHeight) {
+          maxSubTreeHeight = minSubTreeHeight;
+        }
+      }
+
+      minTreeHeight[op] = maxSubTreeHeight + 1;
+      return maxSubTreeHeight + 1;
+    }
+
+    private void GetMinMaxArity(IOperator op, out int minArity, out int maxArity) {
+      foreach(IConstraint constraint in op.Constraints) {
+        NumberOfSubOperatorsConstraint theConstraint = constraint as NumberOfSubOperatorsConstraint;
+        if(theConstraint != null) {
+          minArity = theConstraint.MinOperators.Data;
+          maxArity = theConstraint.MaxOperators.Data;
+          return;
+        }
+      }
+      // the default arity is 2
+      minArity = 2;
+      maxArity = 2;
+    }
+
+    public override void AddSubGroup(IOperatorGroup group) {
+      throw new NotSupportedException();
+    }
+
+    public override void RemoveOperator(IOperator op) {
+      base.RemoveOperator(op);
+      op.RemoveVariable(GPOperatorLibrary.MIN_TREE_SIZE);
+      op.RemoveVariable(GPOperatorLibrary.MIN_TREE_HEIGHT);
+      op.RemoveVariable(GPOperatorLibrary.TICKETS);
+      foreach(IConstraint c in op.Constraints) {
+        if(c is SubOperatorTypeConstraint || c is AllSubOperatorsTypeConstraint) c.Changed -= new EventHandler(UpdateTreeBounds);
+      }
+
+      // remove the operator from the allowed sub-functions of the remaining operators
+      foreach(IOperator o in Operators) {
+        if(o != op) {
+          foreach(IConstraint c in o.Constraints) {
+            if(c is SubOperatorTypeConstraint) {
+              ((SubOperatorTypeConstraint)c).RemoveOperator(op);
+            } else if(c is AllSubOperatorsTypeConstraint) {
+              ((AllSubOperatorsTypeConstraint)c).RemoveOperator(op);
+            }
+          }
+        }
+      }
+      OnOperatorRemoved(op);
+    }
+
+    public override void RemoveSubGroup(IOperatorGroup group) {
+      throw new NotSupportedException();
+    }
+
+    public event EventHandler OperatorAdded;
+    public event EventHandler OperatorRemoved;
+
+    protected virtual void OnOperatorAdded(IOperator op) {
+      if(OperatorAdded != null) {
+        OperatorAdded(this, new OperatorEventArgs(op));
+      }
+    }
+    protected virtual void OnOperatorRemoved(IOperator op) {
+      if(OperatorRemoved != null) {
+        OperatorRemoved(this, new OperatorEventArgs(op));
+      }
+    }
+  }
+
+  internal class OperatorEventArgs : EventArgs {
+    public IOperator op;
+
+    public OperatorEventArgs(IOperator op) {
+      this.op = op;
+    }
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/GPOperatorLibrary.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/GPOperatorLibrary.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/GPOperatorLibrary.cs	(revision 1295)
@@ -0,0 +1,86 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using System.Xml;
+
+namespace HeuristicLab.GP {
+  public class GPOperatorLibrary : ItemBase, IOperatorLibrary, IEditable  {
+    // constants for variable names
+    internal const string MIN_TREE_HEIGHT = "MinTreeHeight";
+    internal const string MIN_TREE_SIZE = "MinTreeSize";
+    internal const string TICKETS = "Tickets";
+
+    private GPOperatorGroup group;
+
+    public GPOperatorGroup GPOperatorGroup {
+      get { return group; }
+    }
+    #region IOperatorLibrary Members
+
+    public IOperatorGroup Group {
+      get { return group; }
+    }
+
+    #endregion
+
+
+    public GPOperatorLibrary()
+      : base() {
+      group = new GPOperatorGroup();
+    }
+
+    public override IView CreateView() {
+      return new GPOperatorLibraryEditor(this);
+    }
+
+    public override object Clone(IDictionary<Guid, object> clonedObjects) {
+      GPOperatorLibrary clone = (GPOperatorLibrary)base.Clone(clonedObjects);
+      clone.group = (GPOperatorGroup)group.Clone(clonedObjects);
+      return clone;
+    }
+
+    #region persistence
+    public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary<Guid, IStorable> persistedObjects) {
+      XmlNode node = base.GetXmlNode(name, document, persistedObjects);
+      node.AppendChild(PersistenceManager.Persist("Group", group, document, persistedObjects));
+      return node;
+    }
+
+    public override void Populate(System.Xml.XmlNode node, IDictionary<Guid, IStorable> restoredObjects) {
+      base.Populate(node, restoredObjects);
+      group = (GPOperatorGroup) PersistenceManager.Restore(node.SelectSingleNode("Group"), restoredObjects);
+    }
+    #endregion
+
+    #region IEditable Members
+
+    public IEditor CreateEditor() {
+      return new GPOperatorLibraryEditor(this);
+    }
+
+    #endregion
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/GPOperatorLibraryEditor.Designer.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/GPOperatorLibraryEditor.Designer.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/GPOperatorLibraryEditor.Designer.cs	(revision 1295)
@@ -0,0 +1,238 @@
+#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
+
+namespace HeuristicLab.GP {
+  partial class GPOperatorLibraryEditor {
+    /// <summary> 
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary> 
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if(disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      this.operatorLibraryEditor = new HeuristicLab.Core.OperatorLibraryEditor();
+      this.tabControl = new System.Windows.Forms.TabControl();
+      this.operatorLibraryTabPage = new System.Windows.Forms.TabPage();
+      this.initializationTabPage = new System.Windows.Forms.TabPage();
+      this.initSplitContainer = new System.Windows.Forms.SplitContainer();
+      this.initListView = new System.Windows.Forms.ListView();
+      this.initVariableView = new HeuristicLab.Core.VariableView();
+      this.mutationTabPage = new System.Windows.Forms.TabPage();
+      this.mutationSplitContainer = new System.Windows.Forms.SplitContainer();
+      this.mutationListView = new System.Windows.Forms.ListView();
+      this.mutationVariableView = new HeuristicLab.Core.VariableView();
+      this.tabControl.SuspendLayout();
+      this.operatorLibraryTabPage.SuspendLayout();
+      this.initializationTabPage.SuspendLayout();
+      this.initSplitContainer.Panel1.SuspendLayout();
+      this.initSplitContainer.Panel2.SuspendLayout();
+      this.initSplitContainer.SuspendLayout();
+      this.mutationTabPage.SuspendLayout();
+      this.mutationSplitContainer.Panel1.SuspendLayout();
+      this.mutationSplitContainer.Panel2.SuspendLayout();
+      this.mutationSplitContainer.SuspendLayout();
+      this.SuspendLayout();
+      // 
+      // operatorLibraryEditor
+      // 
+      this.operatorLibraryEditor.Caption = "Operator Library";
+      this.operatorLibraryEditor.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.operatorLibraryEditor.Filename = null;
+      this.operatorLibraryEditor.Location = new System.Drawing.Point(3, 3);
+      this.operatorLibraryEditor.Name = "operatorLibraryEditor";
+      this.operatorLibraryEditor.OperatorLibrary = null;
+      this.operatorLibraryEditor.Size = new System.Drawing.Size(663, 529);
+      this.operatorLibraryEditor.TabIndex = 0;
+      // 
+      // tabControl
+      // 
+      this.tabControl.Controls.Add(this.operatorLibraryTabPage);
+      this.tabControl.Controls.Add(this.initializationTabPage);
+      this.tabControl.Controls.Add(this.mutationTabPage);
+      this.tabControl.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.tabControl.Location = new System.Drawing.Point(0, 0);
+      this.tabControl.Name = "tabControl";
+      this.tabControl.SelectedIndex = 0;
+      this.tabControl.Size = new System.Drawing.Size(677, 561);
+      this.tabControl.TabIndex = 1;
+      // 
+      // operatorLibraryTabPage
+      // 
+      this.operatorLibraryTabPage.Controls.Add(this.operatorLibraryEditor);
+      this.operatorLibraryTabPage.Location = new System.Drawing.Point(4, 22);
+      this.operatorLibraryTabPage.Name = "operatorLibraryTabPage";
+      this.operatorLibraryTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.operatorLibraryTabPage.Size = new System.Drawing.Size(669, 535);
+      this.operatorLibraryTabPage.TabIndex = 0;
+      this.operatorLibraryTabPage.Text = "Operator Library";
+      this.operatorLibraryTabPage.UseVisualStyleBackColor = true;
+      // 
+      // initializationTabPage
+      // 
+      this.initializationTabPage.Controls.Add(this.initSplitContainer);
+      this.initializationTabPage.Location = new System.Drawing.Point(4, 22);
+      this.initializationTabPage.Name = "initializationTabPage";
+      this.initializationTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.initializationTabPage.Size = new System.Drawing.Size(669, 535);
+      this.initializationTabPage.TabIndex = 1;
+      this.initializationTabPage.Text = "Initialization";
+      this.initializationTabPage.UseVisualStyleBackColor = true;
+      // 
+      // initSplitContainer
+      // 
+      this.initSplitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.initSplitContainer.Location = new System.Drawing.Point(3, 3);
+      this.initSplitContainer.Name = "initSplitContainer";
+      // 
+      // initSplitContainer.Panel1
+      // 
+      this.initSplitContainer.Panel1.Controls.Add(this.initListView);
+      // 
+      // initSplitContainer.Panel2
+      // 
+      this.initSplitContainer.Panel2.Controls.Add(this.initVariableView);
+      this.initSplitContainer.Size = new System.Drawing.Size(663, 529);
+      this.initSplitContainer.SplitterDistance = 221;
+      this.initSplitContainer.TabIndex = 0;
+      // 
+      // initListView
+      // 
+      this.initListView.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.initListView.Location = new System.Drawing.Point(0, 0);
+      this.initListView.Name = "initListView";
+      this.initListView.Size = new System.Drawing.Size(221, 529);
+      this.initListView.TabIndex = 0;
+      this.initListView.UseCompatibleStateImageBehavior = false;
+      this.initListView.View = System.Windows.Forms.View.List;
+      this.initListView.SelectedIndexChanged += new System.EventHandler(this.initListView_SelectedIndexChanged);
+      // 
+      // initVariableView
+      // 
+      this.initVariableView.Caption = "Variable";
+      this.initVariableView.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.initVariableView.Location = new System.Drawing.Point(0, 0);
+      this.initVariableView.Name = "initVariableView";
+      this.initVariableView.Size = new System.Drawing.Size(438, 529);
+      this.initVariableView.TabIndex = 0;
+      this.initVariableView.Variable = null;
+      // 
+      // mutationTabPage
+      // 
+      this.mutationTabPage.Controls.Add(this.mutationSplitContainer);
+      this.mutationTabPage.Location = new System.Drawing.Point(4, 22);
+      this.mutationTabPage.Name = "mutationTabPage";
+      this.mutationTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.mutationTabPage.Size = new System.Drawing.Size(669, 535);
+      this.mutationTabPage.TabIndex = 2;
+      this.mutationTabPage.Text = "Mutation";
+      this.mutationTabPage.UseVisualStyleBackColor = true;
+      // 
+      // mutationSplitContainer
+      // 
+      this.mutationSplitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.mutationSplitContainer.Location = new System.Drawing.Point(3, 3);
+      this.mutationSplitContainer.Name = "mutationSplitContainer";
+      // 
+      // mutationSplitContainer.Panel1
+      // 
+      this.mutationSplitContainer.Panel1.Controls.Add(this.mutationListView);
+      // 
+      // mutationSplitContainer.Panel2
+      // 
+      this.mutationSplitContainer.Panel2.Controls.Add(this.mutationVariableView);
+      this.mutationSplitContainer.Size = new System.Drawing.Size(663, 529);
+      this.mutationSplitContainer.SplitterDistance = 221;
+      this.mutationSplitContainer.TabIndex = 0;
+      // 
+      // mutationListView
+      // 
+      this.mutationListView.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.mutationListView.Location = new System.Drawing.Point(0, 0);
+      this.mutationListView.MultiSelect = false;
+      this.mutationListView.Name = "mutationListView";
+      this.mutationListView.Size = new System.Drawing.Size(221, 529);
+      this.mutationListView.TabIndex = 0;
+      this.mutationListView.UseCompatibleStateImageBehavior = false;
+      this.mutationListView.View = System.Windows.Forms.View.List;
+      this.mutationListView.SelectedIndexChanged += new System.EventHandler(this.mutationListView_SelectedIndexChanged);
+      // 
+      // mutationVariableView
+      // 
+      this.mutationVariableView.Caption = "Variable";
+      this.mutationVariableView.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.mutationVariableView.Location = new System.Drawing.Point(0, 0);
+      this.mutationVariableView.Name = "mutationVariableView";
+      this.mutationVariableView.Size = new System.Drawing.Size(438, 529);
+      this.mutationVariableView.TabIndex = 0;
+      this.mutationVariableView.Variable = null;
+      // 
+      // GPOperatorLibraryEditor
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.tabControl);
+      this.Name = "GPOperatorLibraryEditor";
+      this.Size = new System.Drawing.Size(677, 561);
+      this.tabControl.ResumeLayout(false);
+      this.operatorLibraryTabPage.ResumeLayout(false);
+      this.initializationTabPage.ResumeLayout(false);
+      this.initSplitContainer.Panel1.ResumeLayout(false);
+      this.initSplitContainer.Panel2.ResumeLayout(false);
+      this.initSplitContainer.ResumeLayout(false);
+      this.mutationTabPage.ResumeLayout(false);
+      this.mutationSplitContainer.Panel1.ResumeLayout(false);
+      this.mutationSplitContainer.Panel2.ResumeLayout(false);
+      this.mutationSplitContainer.ResumeLayout(false);
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+
+    private HeuristicLab.Core.OperatorLibraryEditor operatorLibraryEditor;
+    private System.Windows.Forms.TabControl tabControl;
+    private System.Windows.Forms.TabPage operatorLibraryTabPage;
+    private System.Windows.Forms.TabPage initializationTabPage;
+    private System.Windows.Forms.TabPage mutationTabPage;
+    private System.Windows.Forms.SplitContainer initSplitContainer;
+    private System.Windows.Forms.SplitContainer mutationSplitContainer;
+    private HeuristicLab.Core.VariableView initVariableView;
+    private HeuristicLab.Core.VariableView mutationVariableView;
+    private System.Windows.Forms.ListView initListView;
+    private System.Windows.Forms.ListView mutationListView;
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/GPOperatorLibraryEditor.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/GPOperatorLibraryEditor.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/GPOperatorLibraryEditor.cs	(revision 1295)
@@ -0,0 +1,153 @@
+#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.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using HeuristicLab.Core;
+using System.Diagnostics;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.GP {
+  public partial class GPOperatorLibraryEditor : EditorBase {
+    public IOperatorLibrary OperatorLibrary {
+      get { return (IOperatorLibrary)Item; }
+      set { base.Item = value; }
+    }
+
+    public GPOperatorLibraryEditor(GPOperatorLibrary library)
+      : base() {
+      InitializeComponent();
+      OperatorLibrary = library;
+      operatorLibraryEditor.OperatorLibrary = library;
+
+      library.GPOperatorGroup.OperatorAdded += new EventHandler(GPOperatorLibraryView_OperatorAdded);
+      library.GPOperatorGroup.OperatorRemoved += new EventHandler(GPOperatorGroup_OperatorRemoved);
+
+      mutationVariableView.Enabled = false;
+      initVariableView.Enabled = false;
+
+      foreach(IOperator op in library.Group.Operators) {
+        if(op.GetVariable(FunctionBase.MANIPULATION) != null) {
+          ListViewItem item = new ListViewItem();
+          item.Text = op.Name;
+          item.Name = op.Name;
+          item.Tag = op;
+          mutationListView.Items.Add(item);
+        }
+        if(op.GetVariable(FunctionBase.INITIALIZATION) != null) {
+          ListViewItem item = new ListViewItem();
+          item.Name = op.Name;
+          item.Text = op.Name;
+          item.Tag = op;
+          initListView.Items.Add(item);
+        }
+      }
+    }
+
+
+    private void GPOperatorLibraryView_OperatorAdded(object sender, EventArgs e) {
+      IOperator op = ((OperatorEventArgs)e).op;
+      if(op.GetVariable(FunctionBase.MANIPULATION) != null) {
+        ListViewItem operatorMutationItem = new ListViewItem();
+        operatorMutationItem.Name = op.Name;
+        operatorMutationItem.Text = op.Name;
+        operatorMutationItem.Tag = op;
+        mutationListView.Items.Add(operatorMutationItem);
+      }
+
+      if(op.GetVariable(FunctionBase.INITIALIZATION) != null) {
+        ListViewItem operatorInitItem = new ListViewItem();
+        operatorInitItem.Name = op.Name;
+        operatorInitItem.Text = op.Name;
+        operatorInitItem.Tag = op;
+        initListView.Items.Add(operatorInitItem);
+      }
+
+      op.NameChanged += new EventHandler(op_NameChanged);
+      Refresh();
+    }
+
+    private void op_NameChanged(object sender, EventArgs e) {
+      IOperator srcOp = (IOperator)sender;
+      foreach(ListViewItem item in mutationListView.Items) {
+        if(item.Tag == srcOp) {
+          item.Name = srcOp.Name;
+          item.Text = srcOp.Name;
+          break;
+        }
+      }
+      foreach(ListViewItem item in initListView.Items) {
+        if(item.Tag == srcOp) {
+          item.Name = srcOp.Name;
+          item.Text = srcOp.Name;
+          break;
+        }
+      }
+    }
+
+
+    private void GPOperatorGroup_OperatorRemoved(object sender, EventArgs e) {
+      IOperator op = ((OperatorEventArgs)e).op;
+
+      foreach(ListViewItem item in mutationListView.Items) {
+        if(item.Tag == op) {
+          mutationListView.Items.Remove(item);
+          break;
+        }
+      }
+
+      foreach(ListViewItem item in initListView.Items) {
+        if(item.Tag == op) {
+          initListView.Items.Remove(item);
+          break;
+        }
+      }
+    }
+
+    private void mutationListView_SelectedIndexChanged(object sender, EventArgs e) {
+      if(mutationListView.SelectedItems.Count>0 && mutationListView.SelectedItems[0].Tag != null) {
+        IVariable variable = ((IOperator)mutationListView.SelectedItems[0].Tag).GetVariable(FunctionBase.MANIPULATION);
+        mutationVariableView.Enabled = true;
+        mutationVariableView.Variable = variable;
+      } else {
+        mutationVariableView.Enabled = false;
+      }
+    }
+
+    private void initListView_SelectedIndexChanged(object sender, EventArgs e) {
+      if(initListView.SelectedItems.Count>0 && initListView.SelectedItems[0].Tag != null) {
+        IVariable variable = ((IOperator)initListView.SelectedItems[0].Tag).GetVariable(FunctionBase.INITIALIZATION);
+        initVariableView.Enabled = true;
+        initVariableView.Variable = variable;
+      } else {
+        initVariableView.Enabled = false;
+      }
+    }
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/GPOperatorLibraryEditor.resx
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/GPOperatorLibraryEditor.resx	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/GPOperatorLibraryEditor.resx	(revision 1295)
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
Index: /branches/plugins/HeuristicLab.GP/3.2/HeuristicLab.GP.csproj
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/HeuristicLab.GP.csproj	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/HeuristicLab.GP.csproj	(revision 1295)
@@ -0,0 +1,172 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{1F1CF3ED-374C-4288-995B-93F6B872F571}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.GP</RootNamespace>
+    <AssemblyName>HeuristicLab.GP-3.2</AssemblyName>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <SignAssembly>true</SignAssembly>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x86\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+    <OutputPath>bin\x86\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml.Linq">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data.DataSetExtensions">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="BakedFunctionTree.cs" />
+    <Compile Include="DefaultFunctionTreeNameGenerator.cs" />
+    <Compile Include="EqualiserController.cs" />
+    <Compile Include="Logging\TreeArityAnalyser.cs" />
+    <Compile Include="OffspringEqualiser.cs" />
+    <Compile Include="Recombination\SizeConstrictedGPCrossoverBase.cs" />
+    <Compile Include="Recombination\GPCrossoverBase.cs" />
+    <Compile Include="Recombination\UniformCrossover.cs" />
+    <Compile Include="UnknownFunctionException.cs" />
+    <Compile Include="IFunctionTreeNameGenerator.cs" />
+    <Compile Include="IFunctionTreeExporter.cs" />
+    <Compile Include="FunctionBase.cs" />
+    <Compile Include="FunctionView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="FunctionView.Designer.cs">
+      <DependentUpon>FunctionView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="GPOperatorGroup.cs" />
+    <Compile Include="GPOperatorLibrary.cs" />
+    <Compile Include="GPOperatorLibraryEditor.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="GPOperatorLibraryEditor.Designer.cs">
+      <DependentUpon>GPOperatorLibraryEditor.cs</DependentUpon>
+    </Compile>
+    <Compile Include="HeuristicLabGPPlugin.cs" />
+    <Compile Include="IFunction.cs" />
+    <Compile Include="IFunctionTree.cs" />
+    <Compile Include="Manipulation\ChangeNodeTypeManipulation.cs" />
+    <Compile Include="Manipulation\CutOutNodeManipulation.cs" />
+    <Compile Include="Manipulation\DeleteSubTreeManipulation.cs" />
+    <Compile Include="Manipulation\FullTreeShaker.cs" />
+    <Compile Include="Manipulation\OnePointShaker.cs" />
+    <Compile Include="Manipulation\SubstituteSubTreeManipulation.cs" />
+    <Compile Include="ProbabilisticTreeCreator.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="RampedTreeCreator.cs" />
+    <Compile Include="Recombination\LangdonHomologousCrossOver.cs" />
+    <Compile Include="Recombination\OnePointCrossOver.cs" />
+    <Compile Include="Recombination\SizeFairCrossOver.cs" />
+    <Compile Include="Recombination\StandardCrossOver.cs" />
+    <Compile Include="TreeGardener.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\HeuristicLab.Constraints\HeuristicLab.Constraints.csproj">
+      <Project>{FCD62C6F-4793-4593-AE9A-0BDCA256EE99}</Project>
+      <Name>HeuristicLab.Constraints</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\HeuristicLab.Core\HeuristicLab.Core.csproj">
+      <Project>{F43B59AB-2B8C-4570-BC1E-15592086517C}</Project>
+      <Name>HeuristicLab.Core</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\HeuristicLab.Data\HeuristicLab.Data.csproj">
+      <Project>{F473D9AF-3F09-4296-9F28-3C65118DAFFA}</Project>
+      <Name>HeuristicLab.Data</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\HeuristicLab.Operators\HeuristicLab.Operators.csproj">
+      <Project>{A9983BA2-B3B2-475E-8E2C-62050B71D1C5}</Project>
+      <Name>HeuristicLab.Operators</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\HeuristicLab.PluginInfrastructure\HeuristicLab.PluginInfrastructure.csproj">
+      <Project>{94186A6A-5176-4402-AE83-886557B53CCA}</Project>
+      <Name>HeuristicLab.PluginInfrastructure</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\HeuristicLab.Random\HeuristicLab.Random.csproj">
+      <Project>{47019A74-F7F7-482E-83AA-D3F4F777E879}</Project>
+      <Name>HeuristicLab.Random</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\HeuristicLab.Selection\HeuristicLab.Selection.csproj">
+      <Project>{F7CF0571-25CB-43D5-8443-0843A1E2861A}</Project>
+      <Name>HeuristicLab.Selection</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="FunctionView.resx">
+      <DependentUpon>FunctionView.cs</DependentUpon>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+    <EmbeddedResource Include="GPOperatorLibraryEditor.resx">
+      <DependentUpon>GPOperatorLibraryEditor.cs</DependentUpon>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="HeuristicLab.snk" />
+    <None Include="Properties\AssemblyInfo.frame" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+  <PropertyGroup>
+    <PreBuildEvent>set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+set ProjectDir=$(ProjectDir)
+set SolutionDir=$(SolutionDir)
+set Outdir=$(Outdir)
+
+call PreBuildEvent.cmd</PreBuildEvent>
+  </PropertyGroup>
+</Project>
Index: /branches/plugins/HeuristicLab.GP/3.2/HeuristicLabGPPlugin.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/HeuristicLabGPPlugin.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/HeuristicLabGPPlugin.cs	(revision 1295)
@@ -0,0 +1,38 @@
+#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 {
+  [ClassInfo(Name = "HeuristicLab.GP-3.2")]
+  [PluginFile(Filename = "HeuristicLab.GP-3.2.dll", Filetype = PluginFileType.Assembly)]
+  [Dependency(Dependency = "HeuristicLab.Constraints-3.2")]
+  [Dependency(Dependency = "HeuristicLab.Core-3.2")]
+  [Dependency(Dependency = "HeuristicLab.Data-3.2")]
+  [Dependency(Dependency = "HeuristicLab.Operators-3.2")]
+  [Dependency(Dependency = "HeuristicLab.Random-3.2")]
+  [Dependency(Dependency = "HeuristicLab.Selection-3.2")]
+  public class HeuristicLabGPPlugin : PluginBase {
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/IFunction.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/IFunction.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/IFunction.cs	(revision 1295)
@@ -0,0 +1,35 @@
+#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 {
+  public interface IFunction : IOperator {
+    IFunctionTree GetTreeNode();
+    double Apply();
+    IList<IFunction> AllowedSubFunctions(int index);
+    int MinArity { get; }
+    int MaxArity { get; }
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/IFunctionTree.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/IFunctionTree.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/IFunctionTree.cs	(revision 1295)
@@ -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 {
+  public interface IFunctionTree : IItem {
+    int Size { get; }
+    int Height { get; }
+    IList<IFunctionTree> SubTrees { get; }
+    ICollection<IVariable> LocalVariables { get; }
+    IFunction Function { get; }
+    IVariable GetLocalVariable(string name);
+    void AddVariable(IVariable variable);
+    void RemoveVariable(string name);
+    void AddSubTree(IFunctionTree tree);
+    void InsertSubTree(int index, IFunctionTree tree);
+    void RemoveSubTree(int index);
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/IFunctionTreeExporter.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/IFunctionTreeExporter.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/IFunctionTreeExporter.cs	(revision 1295)
@@ -0,0 +1,33 @@
+#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 {
+  public interface IFunctionTreeExporter {
+    string Name { get; }
+    string Export(IFunctionTree tree);
+    bool TryExport(IFunctionTree tree, out string exported);
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/IFunctionTreeNameGenerator.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/IFunctionTreeNameGenerator.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/IFunctionTreeNameGenerator.cs	(revision 1295)
@@ -0,0 +1,32 @@
+#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 {
+  public interface IFunctionTreeNameGenerator {
+    string Name { get; }
+    string GetName(IFunctionTree tree);
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/Logging/TreeArityAnalyser.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/Logging/TreeArityAnalyser.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/Logging/TreeArityAnalyser.cs	(revision 1295)
@@ -0,0 +1,120 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Random;
+using HeuristicLab.Data;
+using HeuristicLab.Constraints;
+using System.Diagnostics;
+
+namespace HeuristicLab.GP {
+  /// <summary>
+  /// Creates a histogram of the arities of functions used in the whole GP population.
+  /// </summary>
+  public class TreeArityAnalyser : OperatorBase {
+    public override string Description {
+      get {
+        return @"Creates a histogram of the arities of functions used in the whole GP population.";
+      }
+    }
+    public TreeArityAnalyser()
+      : base() {
+      AddVariableInfo(new VariableInfo("FunctionTree", "The tree to mutate", typeof(IFunctionTree), VariableKind.In));
+      AddVariableInfo(new VariableInfo("Histogram", "The histogram of arities over all functions in all functiontrees", typeof(ItemList<ItemList<IntData>>), VariableKind.New | VariableKind.Out));
+    }
+
+    public override IOperation Apply(IScope scope) {
+      ItemList<ItemList<IntData>> histogram = GetVariableValue<ItemList<ItemList<IntData>>>("Histogram", scope, false, false);
+      if(histogram == null) {
+        histogram = new ItemList<ItemList<IntData>>();
+        IVariableInfo info = GetVariableInfo("Histogram");
+        if(info.Local)
+          AddVariable(new HeuristicLab.Core.Variable(info.ActualName, histogram));
+        else
+          scope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName(info.FormalName), histogram));
+      } else {
+        histogram.Clear();
+      }
+
+      foreach(IScope subScope in scope.SubScopes) {
+        ItemList<ItemList<IntData>> subHistogram = GetArityHistogram(subScope);
+        MergeHistogram(subHistogram, histogram);
+      }
+
+      return null;
+    }
+
+    private ItemList<ItemList<IntData>> GetArityHistogram(IScope subScope) {
+      IFunctionTree tree = GetVariableValue<IFunctionTree>("FunctionTree", subScope, false);
+      List<int> arities = new List<int>();
+      Arities(tree, arities);
+      var histogram = arities.GroupBy(x => x, (g, xs) => new { Group = g, Count = xs.Count() }).OrderBy(g=>g.Group); // count number of distinct arities
+      ItemList<ItemList<IntData>> result = new ItemList<ItemList<IntData>>();
+      
+      // translate enumerable to itemlist
+      histogram.Aggregate(result, (r, g) => { 
+        ItemList<IntData> entry = new ItemList<IntData>(); 
+        entry.Add(new IntData(g.Group));
+        entry.Add(new IntData(g.Count));
+        r.Add(entry); return r; 
+      });
+      return result;
+    }
+
+    private void Arities(IFunctionTree tree, List<int> arities) {
+      arities.Add(tree.SubTrees.Count);
+      foreach(IFunctionTree subTree in tree.SubTrees) {
+        Arities(subTree, arities);
+      }
+    }
+
+    private void MergeHistogram(ItemList<ItemList<IntData>> srcHistogram, ItemList<ItemList<IntData>> dstHistogram) {
+      int j = 0;
+      for(int i = 0; i < srcHistogram.Count; i++) {
+        int g = srcHistogram[i][0].Data;
+        int c = srcHistogram[i][1].Data;
+        int dstG, dstC;
+        if(j < dstHistogram.Count) {
+          dstG = dstHistogram[j][0].Data;
+          dstC = dstHistogram[j][1].Data;
+        } else {
+          dstG = int.MaxValue;
+          dstC = 0;
+        }
+        if(g < dstG) {
+          // new group before the current group
+          if(j < dstHistogram.Count)
+            dstHistogram.Insert(j, srcHistogram[i]);
+          else
+            dstHistogram.Add(srcHistogram[i]);
+        } else if(g == dstG) {
+          dstHistogram[j][1] = new IntData(c + dstC);
+        }
+        j++;
+      }
+    }
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/Manipulation/ChangeNodeTypeManipulation.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/Manipulation/ChangeNodeTypeManipulation.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/Manipulation/ChangeNodeTypeManipulation.cs	(revision 1295)
@@ -0,0 +1,192 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Random;
+using HeuristicLab.Data;
+using HeuristicLab.Constraints;
+using System.Diagnostics;
+
+namespace HeuristicLab.GP {
+  public class ChangeNodeTypeManipulation : OperatorBase {
+
+    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() {
+      AddVariableInfo(new VariableInfo("Random", "Uniform random number generator", typeof(MersenneTwister), VariableKind.In));
+      AddVariableInfo(new VariableInfo("OperatorLibrary", "The operator library containing all available operators", typeof(GPOperatorLibrary), VariableKind.In));
+      AddVariableInfo(new VariableInfo("MaxTreeHeight", "The maximal allowed height of the tree", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("MaxTreeSize", "The maximal allowed size (number of nodes) of the tree", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("FunctionTree", "The tree to mutate", typeof(IFunctionTree), VariableKind.In | VariableKind.Out));
+      AddVariableInfo(new VariableInfo("TreeSize", "The size (number of nodes) of the tree", typeof(IntData), VariableKind.In | VariableKind.Out));
+      AddVariableInfo(new VariableInfo("TreeHeight", "The height of the tree", typeof(IntData), VariableKind.In | VariableKind.Out));
+    }
+
+
+    public override IOperation Apply(IScope scope) {
+      IFunctionTree root = GetVariableValue<IFunctionTree>("FunctionTree", scope, false);
+      MersenneTwister random = GetVariableValue<MersenneTwister>("Random", scope, true);
+      GPOperatorLibrary library = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", scope, true);
+      IntData treeSize = GetVariableValue<IntData>("TreeSize", scope, false);
+      IntData treeHeight = GetVariableValue<IntData>("TreeHeight", scope, false);
+      int maxTreeSize = GetVariableValue<IntData>("MaxTreeSize", scope, true).Data;
+      int maxTreeHeight = GetVariableValue<IntData>("MaxTreeHeight", scope, true).Data;
+      TreeGardener gardener = new TreeGardener(random, library);
+      IFunctionTree parent = gardener.GetRandomParentNode(root);
+      IFunctionTree selectedChild;
+      int selectedChildIndex;
+      if(parent == null) {
+        selectedChildIndex = 0;
+        selectedChild = root;
+      } 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
+          // and we have to update the value in the variable
+          scope.GetVariable(scope.TranslateName("FunctionTree")).Value = newTerminal;
+        } else {
+          parent.RemoveSubTree(selectedChildIndex);
+          parent.InsertSubTree(selectedChildIndex, newTerminal);
+          // updating the variable is not necessary because it stays the same
+        }
+        Debug.Assert(gardener.IsValidTree(root));
+        // 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 gardener.CreateInitializationOperation(gardener.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.Size;
+        int oldChildHeight = selectedChild.Height;
+        int newChildSize = newFunctionTree.Size;
+        int newChildHeight = newFunctionTree.Height;
+        if((treeHeight.Data - oldChildHeight) + newChildHeight > maxTreeHeight ||
+          (treeSize.Data - 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
+          // and we have to update the value in the variable
+          scope.GetVariable(scope.TranslateName("FunctionTree")).Value = newFunctionTree;
+          root = 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
+        treeSize.Data = (treeSize.Data - oldChildSize) + newChildSize;
+        treeHeight.Data = root.Height; // 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(root));
+        // return a composite operation that initializes all created sub-trees
+        return gardener.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(gardener.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.
+      IList<IFunction> allowedFunctions = 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.MinArity;
+      int maxArity = selectedFunction.MaxArity;
+      // 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(gardener.GetAllSubTrees(freshTree));
+          newTree.InsertSubTree(i, freshTree);
+        }
+      }
+      freshSubTrees.Add(newTree);
+      uninitializedBranches = freshSubTrees;
+      return newTree;
+    }
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/Manipulation/CutOutNodeManipulation.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/Manipulation/CutOutNodeManipulation.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/Manipulation/CutOutNodeManipulation.cs	(revision 1295)
@@ -0,0 +1,131 @@
+#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.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Random;
+using System;
+using System.Diagnostics;
+
+namespace HeuristicLab.GP {
+  public class CutOutNodeManipulation : OperatorBase {
+    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() {
+      AddVariableInfo(new VariableInfo("Random", "Uniform random number generator", typeof(MersenneTwister), VariableKind.In));
+      AddVariableInfo(new VariableInfo("OperatorLibrary", "The operator library containing all available operators", typeof(GPOperatorLibrary), VariableKind.In));
+      AddVariableInfo(new VariableInfo("MaxTreeHeight", "The maximal allowed height of the tree", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("MaxTreeSize", "The maximal allowed size (number of nodes) of the tree", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("FunctionTree", "The tree to mutate", typeof(IFunctionTree), VariableKind.In | VariableKind.Out));
+      AddVariableInfo(new VariableInfo("TreeSize", "The size (number of nodes) of the tree", typeof(IntData), VariableKind.In | VariableKind.Out));
+      AddVariableInfo(new VariableInfo("TreeHeight", "The height of the tree", typeof(IntData), VariableKind.In | VariableKind.Out));
+    }
+
+
+    public override IOperation Apply(IScope scope) {
+      IFunctionTree root = GetVariableValue<IFunctionTree>("FunctionTree", scope, true);
+      MersenneTwister random = GetVariableValue<MersenneTwister>("Random", scope, true);
+      GPOperatorLibrary library = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", scope, true);
+      int maxTreeHeight = GetVariableValue<IntData>("MaxTreeHeight", scope, true).Data;
+      int maxTreeSize = GetVariableValue<IntData>("MaxTreeSize", scope, true).Data;
+      TreeGardener gardener = new TreeGardener(random, library);
+      IFunctionTree parent = gardener.GetRandomParentNode(root);
+      // 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 (root.SubTrees.Count > 0) {
+          root = root.SubTrees[random.Next(root.SubTrees.Count)];
+          GetVariableValue<IntData>("TreeSize", scope, true).Data = root.Size;
+          GetVariableValue<IntData>("TreeHeight", scope, true).Data = root.Height;
+          // update the variable
+          scope.GetVariable(scope.TranslateName("FunctionTree")).Value = root;
+          Debug.Assert(gardener.IsValidTree(root));
+          // 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
+          IFunctionTree newTree;
+          newTree = gardener.CreateRandomTree(gardener.Terminals, 1, 1);
+          GetVariableValue<IntData>("TreeSize", scope, true).Data = newTree.Size;
+          GetVariableValue<IntData>("TreeHeight", scope, true).Data = newTree.Height;
+          // update the variable
+          scope.GetVariable(scope.TranslateName("FunctionTree")).Value = newTree;
+          Debug.Assert(gardener.IsValidTree(newTree));
+          // schedule an operation to initialize the whole tree
+          return gardener.CreateInitializationOperation(gardener.GetAllSubTrees(newTree), 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(root));
+        // update the size and height of our tree
+        GetVariableValue<IntData>("TreeSize", scope, true).Data = root.Size;
+        GetVariableValue<IntData>("TreeHeight", scope, true).Data = root.Height;
+        // 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(root, 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 = root.Size;
+        allowedFunctions = gardener.GetAllowedSubFunctions(parent.Function, childIndex);
+        IFunctionTree newFunctionTree = gardener.CreateRandomTree(allowedFunctions, maxTreeSize - remainingNodes, maxTreeHeight - parentLevel);
+        parent.InsertSubTree(childIndex, newFunctionTree);
+        GetVariableValue<IntData>("TreeSize", scope, true).Data = root.Size;
+        GetVariableValue<IntData>("TreeHeight", scope, true).Data = root.Height;
+        Debug.Assert(gardener.IsValidTree(root));
+        // schedule an initialization operation for the new function-tree
+        return gardener.CreateInitializationOperation(gardener.GetAllSubTrees(newFunctionTree), scope);
+      }
+    }
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/Manipulation/DeleteSubTreeManipulation.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/Manipulation/DeleteSubTreeManipulation.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/Manipulation/DeleteSubTreeManipulation.cs	(revision 1295)
@@ -0,0 +1,103 @@
+#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.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Random;
+using System.Diagnostics;
+
+namespace HeuristicLab.GP {
+  public class DeleteSubTreeManipulation : OperatorBase {
+    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() {
+      AddVariableInfo(new VariableInfo("Random", "Uniform random number generator", typeof(MersenneTwister), VariableKind.In));
+      AddVariableInfo(new VariableInfo("OperatorLibrary", "The operator library containing all available operators", typeof(GPOperatorLibrary), VariableKind.In));
+      AddVariableInfo(new VariableInfo("MaxTreeHeight", "The maximal allowed height of the tree", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("MaxTreeSize", "The maximal allowed size (number of nodes) of the tree", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("FunctionTree", "The tree to mutate", typeof(IFunctionTree), VariableKind.In | VariableKind.Out));
+      AddVariableInfo(new VariableInfo("TreeSize", "The size (number of nodes) of the tree", typeof(IntData), VariableKind.In | VariableKind.Out));
+      AddVariableInfo(new VariableInfo("TreeHeight", "The height of the tree", typeof(IntData), VariableKind.In | VariableKind.Out));
+    }
+
+
+    public override IOperation Apply(IScope scope) {
+      IFunctionTree root = GetVariableValue<IFunctionTree>("FunctionTree", scope, true);
+      MersenneTwister random = GetVariableValue<MersenneTwister>("Random", scope, true);
+      GPOperatorLibrary library = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", scope, true);
+      TreeGardener gardener = new TreeGardener(random, library);
+      IFunctionTree parent = gardener.GetRandomParentNode(root);
+
+      // 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));
+        // update sizes to match the new tree
+        GetVariableValue<IntData>("TreeSize", scope, true).Data = newTree.Size;
+        GetVariableValue<IntData>("TreeHeight", scope, true).Data = newTree.Height;
+        scope.GetVariable(scope.TranslateName("FunctionTree")).Value = newTree;
+
+        // schedule an operation to initialize the newly created operator
+        return gardener.CreateInitializationOperation(gardener.GetAllSubTrees(newTree), scope);
+      }
+
+      // select a branch to prune
+      int childIndex = random.Next(parent.SubTrees.Count);
+      if(parent.SubTrees.Count > parent.Function.MinArity) {
+        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(root));
+        GetVariableValue<IntData>("TreeSize", scope, true).Data = root.Size;
+        GetVariableValue<IntData>("TreeHeight", scope, true).Data = root.Height;
+        // 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(root));
+        GetVariableValue<IntData>("TreeSize", scope, true).Data = root.Size;
+        GetVariableValue<IntData>("TreeHeight", scope, true).Data = root.Height;
+        // again the root hasn't changed so we don't need to update the 'FunctionTree' variable
+        // but we have to return an initialization operation for the newly created tree
+        return gardener.CreateInitializationOperation(gardener.GetAllSubTrees(newFunctionTree), scope);
+      }
+    }
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/Manipulation/FullTreeShaker.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/Manipulation/FullTreeShaker.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/Manipulation/FullTreeShaker.cs	(revision 1295)
@@ -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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Random;
+using HeuristicLab.Data;
+using HeuristicLab.Selection;
+
+namespace HeuristicLab.GP {
+  public class FullTreeShaker : DelegatingOperator {
+    public override string Description {
+      get { return "Manipulates all tree nodes for which a '" + FunctionBase.MANIPULATION + "' variable is defined."; }
+    }
+
+    public FullTreeShaker()
+      : base() {
+      AddVariableInfo(new VariableInfo("Random", "A random generator (uniform)", typeof(MersenneTwister), VariableKind.In));
+      AddVariableInfo(new VariableInfo("OperatorLibrary", "Operator library that defines operator mutations", typeof(GPOperatorLibrary), 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(IFunctionTree), VariableKind.In | VariableKind.Out));
+    }
+
+    public override IOperation Apply(IScope scope) {
+      GPOperatorLibrary library = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", scope, true);
+      IFunctionTree tree = GetVariableValue<IFunctionTree>("FunctionTree", scope, false);
+      MersenneTwister mt = GetVariableValue<MersenneTwister>("Random", scope, true);
+
+      // enqueue all mutation operations as parallel operations
+      CompositeOperation next = new CompositeOperation();
+      next.ExecuteInParallel = false;
+
+      Scope tempScope = new Scope("Temp. manipulation scope");
+
+      TreeGardener gardener = new TreeGardener(mt, library);
+      var parametricBranches = gardener.GetAllSubTrees(tree).Where(branch => branch.Function.GetVariable(FunctionBase.MANIPULATION) != null);
+      foreach(IFunctionTree subTree in parametricBranches) {
+        IOperator mutation = (IOperator)subTree.Function.GetVariable(FunctionBase.MANIPULATION).Value;
+
+        // store all local variables into a temporary scope
+        Scope mutationScope = new Scope();
+        foreach(IVariable variable in subTree.LocalVariables) {
+          mutationScope.AddVariable(variable);
+        }
+
+        tempScope.AddSubScope(mutationScope);
+        next.AddOperation(new AtomicOperation(mutation, mutationScope));
+      }
+
+      // save all existing sub-scopes in a backup scope
+      Scope backupScope = new Scope("backup");
+      foreach(Scope subScope in scope.SubScopes) {
+        backupScope.AddSubScope(subScope);
+      }
+
+      scope.AddSubScope(tempScope); // scope containing a subscope for each manipulation
+      scope.AddSubScope(backupScope); // scope containing the old subscopes
+
+      // 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: /branches/plugins/HeuristicLab.GP/3.2/Manipulation/OnePointShaker.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/Manipulation/OnePointShaker.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/Manipulation/OnePointShaker.cs	(revision 1295)
@@ -0,0 +1,81 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Random;
+using HeuristicLab.Data;
+using HeuristicLab.Selection;
+
+namespace HeuristicLab.GP {
+  public class OnePointShaker : DelegatingOperator {
+    public override string Description {
+      get { return "Selects a random node of all tree-nodes that have a '"+FunctionBase.MANIPULATION+"' variable defined and manipulates the selected node."; }
+    }
+
+    public OnePointShaker()
+      : base() {
+      AddVariableInfo(new VariableInfo("OperatorLibrary", "Operator library that defines mutation operations for operators", typeof(GPOperatorLibrary), 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(IFunctionTree), VariableKind.In | VariableKind.Out));
+    }
+
+    public override IOperation Apply(IScope scope) {
+      GPOperatorLibrary library = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", scope, true);
+      IFunctionTree tree = GetVariableValue<IFunctionTree>("FunctionTree", scope, false);
+      MersenneTwister mt = GetVariableValue<MersenneTwister>("Random", scope, true);
+      TreeGardener gardener = new TreeGardener(mt, library);
+
+      // get all nodes for which a manipulation is defined
+      var parametricBranches = gardener.GetAllSubTrees(tree).Where(branch => branch.Function.GetVariable(FunctionBase.MANIPULATION) != null);
+      IFunctionTree selectedBranch = parametricBranches.ElementAt(mt.Next(parametricBranches.Count()));
+      IOperator mutation = (IOperator)selectedBranch.Function.GetVariable(FunctionBase.MANIPULATION).Value;
+      CompositeOperation next = new CompositeOperation();
+
+      // store all local variables into a temporary scope
+      Scope tempScope = new Scope("Temp. manipulation scope");
+      foreach(IVariable variable in selectedBranch.LocalVariables) {
+        tempScope.AddVariable(variable);
+      }
+
+      // save the exising sub-scops in a backup scope
+      Scope backupScope = new Scope("backup");
+      foreach (Scope subScope in scope.SubScopes) {
+        backupScope.AddSubScope(subScope);
+      }
+
+      // add the new sub-scopes
+      scope.AddSubScope(tempScope);
+      scope.AddSubScope(backupScope);
+
+      // the next operation should first manipulate and then restore the sub-scopes from the backup scope
+      next.AddOperation(new AtomicOperation(mutation, tempScope));
+      next.AddOperation(new AtomicOperation(new RightReducer(), scope));
+
+      return next;
+    }
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/Manipulation/SubstituteSubTreeManipulation.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/Manipulation/SubstituteSubTreeManipulation.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/Manipulation/SubstituteSubTreeManipulation.cs	(revision 1295)
@@ -0,0 +1,104 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Random;
+using System.Diagnostics;
+
+namespace HeuristicLab.GP {
+  public class SubstituteSubTreeManipulation : OperatorBase {
+
+    public override string Description {
+      get { return "Selects a random node of the tree and replaces it with randomly initialized subtree."; }
+    }
+
+    public SubstituteSubTreeManipulation()
+      : base() {
+      AddVariableInfo(new VariableInfo("Random", "Uniform random number generator", typeof(MersenneTwister), VariableKind.In));
+      AddVariableInfo(new VariableInfo("OperatorLibrary", "The operator library containing all available operators", typeof(GPOperatorLibrary), VariableKind.In));
+      AddVariableInfo(new VariableInfo("MaxTreeHeight", "The maximal allowed height of the tree", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("MaxTreeSize", "The maximal allowed size (number of nodes) of the tree", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("FunctionTree", "The tree to manipulate", typeof(IFunctionTree), VariableKind.In | VariableKind.Out));
+      AddVariableInfo(new VariableInfo("TreeSize", "The size (number of nodes) of the tree", typeof(IntData), VariableKind.In | VariableKind.Out));
+      AddVariableInfo(new VariableInfo("TreeHeight", "The height of the tree", typeof(IntData), VariableKind.In | VariableKind.Out));
+    }
+
+    public override IOperation Apply(IScope scope) {
+      IFunctionTree root = GetVariableValue<IFunctionTree>("FunctionTree", scope, true);
+      MersenneTwister random = GetVariableValue<MersenneTwister>("Random", scope, true);
+      GPOperatorLibrary library = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", scope, true);
+      int maxTreeHeight = GetVariableValue<IntData>("MaxTreeHeight", scope, true).Data;
+      int maxTreeSize = GetVariableValue<IntData>("MaxTreeSize", scope, true).Data;
+      int treeSize = GetVariableValue<IntData>("TreeSize", scope, true).Data;
+      int treeHeight = GetVariableValue<IntData>("TreeHeight", scope, true).Data;
+      TreeGardener gardener = new TreeGardener(random, library);
+      IFunctionTree parent = gardener.GetRandomParentNode(root);
+      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));
+
+        // update the variables in the scope with the new values
+        GetVariableValue<IntData>("TreeSize", scope, true).Data = newTree.Size;
+        GetVariableValue<IntData>("TreeHeight", scope, true).Data = newTree.Height;
+        scope.GetVariable(scope.TranslateName("FunctionTree")).Value = newTree;
+        
+        // return a CompositeOperation that randomly initializes the new tree
+        return gardener.CreateInitializationOperation(gardener.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(root, parent);
+        int maxSubTreeHeight = maxTreeHeight - parentLevel;
+        int maxSubTreeSize = maxTreeSize - (treeSize - parent.SubTrees[childIndex].Size);
+
+        // create a random function tree
+        IFunctionTree newTree = gardener.CreateRandomTree(allowedFunctions, maxSubTreeSize, maxSubTreeHeight);
+        parent.RemoveSubTree(childIndex);
+        parent.InsertSubTree(childIndex, newTree);
+
+        Debug.Assert(gardener.IsValidTree(root));
+        // update the values of treeSize and treeHeight
+        GetVariableValue<IntData>("TreeSize", scope, true).Data = root.Size;
+        GetVariableValue<IntData>("TreeHeight", scope, true).Data = root.Height;
+        // 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 gardener.CreateInitializationOperation(gardener.GetAllSubTrees(newTree), scope);
+      }
+    }
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/OffspringEqualiser.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/OffspringEqualiser.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/OffspringEqualiser.cs	(revision 1295)
@@ -0,0 +1,63 @@
+#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.Data;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.GP {
+  public class OffspringEqualiser : OperatorBase {
+    public override string Description {
+      get { return @"TODO\r\nOperator description still missing ..."; }
+    }
+
+    public OffspringEqualiser() {
+      AddVariableInfo(new VariableInfo("Random", "Pseudo random number generator", typeof(MersenneTwister), VariableKind.In));
+      AddVariableInfo(new VariableInfo("Value", "The value to equalise", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("BinSize", "Size of histogram bins", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("EqualiserHistogram", "Histogram of the target distribution", typeof(DoubleArrayData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("AcceptanceProbabilities", "Acceptance probabilities of individuals falling into bins", typeof(DoubleArrayData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("Histogram", "The histogram of the actual distribution", typeof(IntArrayData), VariableKind.In));
+    }
+
+    public override IOperation Apply(IScope scope) {
+      int binSize = GetVariableValue<IntData>("BinSize", scope, true).Data;
+      DoubleArrayData equaliserHistogram = GetVariableValue<DoubleArrayData>("EqualiserHistogram", scope, true);
+      IRandom random = GetVariableValue<IRandom>("Random", scope, true);
+      DoubleArrayData acceptanceProbabilities = GetVariableValue<DoubleArrayData>("AcceptanceProbabilities", scope, true);
+      IntArrayData currentHistogram = GetVariableValue<IntArrayData>("Histogram", scope, true);
+
+      int value = GetVariableValue<IntData>("Value", scope, false).Data;
+      int bin = value / binSize;
+      if(bin<acceptanceProbabilities.Data.Length && random.NextDouble() < acceptanceProbabilities.Data[bin]) {
+        currentHistogram.Data[bin]++;
+        currentHistogram.FireChanged();
+        return new AtomicOperation(SubOperators[0], scope);
+      } else {
+        scope.AddVariable(new Variable(scope.TranslateName("Quality"), new DoubleData(double.NaN)));
+        return null;
+      }
+    }
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/ProbabilisticTreeCreator.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/ProbabilisticTreeCreator.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/ProbabilisticTreeCreator.cs	(revision 1295)
@@ -0,0 +1,83 @@
+#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.Data;
+using HeuristicLab.Operators;
+using System;
+using HeuristicLab.Random;
+using System.Diagnostics;
+
+namespace HeuristicLab.GP {
+  public class ProbabilisticTreeCreator : OperatorBase {
+    private 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("OperatorLibrary", "The operator library containing all available operators", typeof(GPOperatorLibrary), 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(IFunctionTree), 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);
+      GPOperatorLibrary opLibrary = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", 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;
+
+      TreeGardener gardener = new TreeGardener(random, opLibrary);
+
+      int treeSize = random.Next(minTreeSize, maxTreeSize + 1);
+
+      IFunctionTree root;
+      int actualTreeSize;
+      int actualTreeHeight;
+      int tries = 0;
+      do {
+        root = gardener.PTC2(random, treeSize, maxTreeHeight);
+        actualTreeSize = root.Size;
+        actualTreeHeight = root.Height;
+        if (tries++ >= MAX_TRIES) {
+          // try a different size
+          treeSize = random.Next(minTreeSize, maxTreeSize + 1);
+          tries = 0;
+        }
+      } while (actualTreeSize > maxTreeSize || actualTreeHeight > maxTreeHeight);
+
+      scope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("FunctionTree"), root));
+      scope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeSize"), new IntData(actualTreeSize)));
+      scope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeHeight"), new IntData(actualTreeHeight)));
+
+      return gardener.CreateInitializationOperation(gardener.GetAllSubTrees(root), scope);
+    }
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/Properties/AssemblyInfo.frame
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/Properties/AssemblyInfo.frame	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/Properties/AssemblyInfo.frame	(revision 1295)
@@ -0,0 +1,58 @@
+#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.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using HeuristicLab.PluginInfrastructure;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("HeuristicLab.GP")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("HeuristicLab")]
+[assembly: AssemblyCopyright("(c) 2002-2008 HEAL")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("863021a4-3cde-48be-8af6-dac1077f5fb5")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("3.2.0.$WCREV$")]
+[assembly: AssemblyFileVersion("3.2.0.$WCREV$")]
+[assembly: AssemblyBuildDate("$WCNOW$")]
Index: /branches/plugins/HeuristicLab.GP/3.2/RampedTreeCreator.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/RampedTreeCreator.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/RampedTreeCreator.cs	(revision 1295)
@@ -0,0 +1,77 @@
+#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.Data;
+using HeuristicLab.Operators;
+using System;
+using HeuristicLab.Random;
+using System.Diagnostics;
+
+namespace HeuristicLab.GP {
+  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("OperatorLibrary", "The operator library containing all available operators", typeof(GPOperatorLibrary), 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(IFunctionTree), 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);
+      GPOperatorLibrary opLibrary = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", 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);
+      }
+
+      int actualTreeSize = root.Size;
+      int actualTreeHeight = root.Height;
+
+      scope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("FunctionTree"), root));
+      scope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeSize"), new IntData(actualTreeSize)));
+      scope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeHeight"), new IntData(actualTreeHeight)));
+
+      Debug.Assert(gardener.IsValidTree(root) && actualTreeHeight <= maxTreeHeight);
+
+      return gardener.CreateInitializationOperation(gardener.GetAllSubTrees(root), scope);
+    }
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/Recombination/GPCrossoverBase.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/Recombination/GPCrossoverBase.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/Recombination/GPCrossoverBase.cs	(revision 1295)
@@ -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 System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Random;
+using HeuristicLab.Data;
+using HeuristicLab.Constraints;
+using System.Diagnostics;
+
+namespace HeuristicLab.GP {
+  public abstract class GPCrossoverBase : OperatorBase {
+    public GPCrossoverBase()
+      : base() {
+      AddVariableInfo(new VariableInfo("Random", "Pseudo random number generator", typeof(MersenneTwister), VariableKind.In));
+      AddVariableInfo(new VariableInfo("OperatorLibrary", "The operator library containing all available operators", typeof(GPOperatorLibrary), VariableKind.In));
+      AddVariableInfo(new VariableInfo("FunctionTree", "The tree to mutate", typeof(IFunctionTree), VariableKind.In | VariableKind.New));
+      AddVariableInfo(new VariableInfo("TreeSize", "The size (number of nodes) of the tree", typeof(IntData), VariableKind.New));
+      AddVariableInfo(new VariableInfo("TreeHeight", "The height of the tree", typeof(IntData), VariableKind.New));
+    }
+
+    public override IOperation Apply(IScope scope) {
+      MersenneTwister random = GetVariableValue<MersenneTwister>("Random", scope, true);
+      GPOperatorLibrary opLibrary = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", scope, true);
+      TreeGardener gardener = new TreeGardener(random, opLibrary);
+
+      if ((scope.SubScopes.Count % 2) != 0)
+        throw new InvalidOperationException("Number of parents is not even");
+
+      int children = scope.SubScopes.Count / 2;
+      for (int i = 0; i < children; i++) {
+        IFunctionTree parent0 = TakeNextParent(scope);
+        IFunctionTree parent1 = TakeNextParent(scope);
+
+        // randomly swap parents to remove a possible bias from selection (e.g. when using gender-specific selection)
+        if (random.NextDouble() < 0.5) {
+          IFunctionTree tmp = parent0;
+          parent0 = parent1;
+          parent1 = tmp;
+        }
+
+        IFunctionTree child = Cross(scope, gardener, random, parent0, parent1);
+        Debug.Assert(gardener.IsValidTree(child));
+        IScope childScope = new Scope(i.ToString());
+        childScope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("FunctionTree"), child));
+        childScope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeSize"), new IntData(child.Size)));
+        childScope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeHeight"), new IntData(child.Height)));
+        scope.AddSubScope(childScope);
+      }
+
+      return null;
+    }
+
+    internal abstract IFunctionTree Cross(IScope scope, TreeGardener gardener, MersenneTwister random, IFunctionTree tree0, IFunctionTree tree1);
+
+    private IFunctionTree TakeNextParent(IScope scope) {
+      IFunctionTree parent = GetVariableValue<IFunctionTree>("FunctionTree", scope.SubScopes[0], false);
+      scope.RemoveSubScope(scope.SubScopes[0]);
+      return parent;
+    }
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/Recombination/LangdonHomologousCrossOver.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/Recombination/LangdonHomologousCrossOver.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/Recombination/LangdonHomologousCrossOver.cs	(revision 1295)
@@ -0,0 +1,62 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Random;
+using HeuristicLab.Data;
+using HeuristicLab.Constraints;
+using System.Diagnostics;
+
+namespace HeuristicLab.GP {
+  /// <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: /branches/plugins/HeuristicLab.GP/3.2/Recombination/OnePointCrossOver.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/Recombination/OnePointCrossOver.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/Recombination/OnePointCrossOver.cs	(revision 1295)
@@ -0,0 +1,81 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Random;
+using HeuristicLab.Data;
+using HeuristicLab.Constraints;
+using System.Diagnostics;
+
+namespace HeuristicLab.GP {
+  /// <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, MersenneTwister random, IFunctionTree tree0, IFunctionTree tree1, int maxTreeSize, int maxTreeHeight) {
+      List<CrossoverPoint> allowedCrossOverPoints = new List<CrossoverPoint>();
+      GetCrossOverPoints(gardener, tree0, tree1, maxTreeSize - tree0.Size, 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].Size - branch0.SubTrees[i].Size <= 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: /branches/plugins/HeuristicLab.GP/3.2/Recombination/SizeConstrictedGPCrossoverBase.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/Recombination/SizeConstrictedGPCrossoverBase.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/Recombination/SizeConstrictedGPCrossoverBase.cs	(revision 1295)
@@ -0,0 +1,72 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Random;
+using HeuristicLab.Data;
+using HeuristicLab.Constraints;
+using System.Diagnostics;
+
+namespace HeuristicLab.GP {
+  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, MersenneTwister 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.Size > maxTreeSize || newTree.Height > maxTreeHeight);
+      return newTree;
+    }
+
+    internal abstract IFunctionTree Cross(TreeGardener gardener, MersenneTwister random, IFunctionTree tree0, IFunctionTree tree1, int maxTreeSize, int maxTreeHeight);
+
+    private IFunctionTree TakeNextParent(IScope scope) {
+      IFunctionTree parent = GetVariableValue<IFunctionTree>("FunctionTree", scope.SubScopes[0], false);
+      scope.RemoveSubScope(scope.SubScopes[0]);
+      return parent;
+    }
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/Recombination/SizeFairCrossOver.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/Recombination/SizeFairCrossOver.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/Recombination/SizeFairCrossOver.cs	(revision 1295)
@@ -0,0 +1,153 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Random;
+using HeuristicLab.Data;
+using HeuristicLab.Constraints;
+using System.Diagnostics;
+
+namespace HeuristicLab.GP {
+  /// <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, MersenneTwister 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(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 = gardener.GetAllowedSubFunctions(parent.Function, replacedBranchIndex);
+      int removedBranchSize = parent.SubTrees[replacedBranchIndex].Size;
+      int maxBranchSize = maxTreeSize - (intoTree.Size - 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.Size == 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.Size;
+      if (allowedFunctions.Contains(tree.Function) && treeSize <= maxBranchSize && tree.Height <= 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: /branches/plugins/HeuristicLab.GP/3.2/Recombination/StandardCrossOver.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/Recombination/StandardCrossOver.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/Recombination/StandardCrossOver.cs	(revision 1295)
@@ -0,0 +1,85 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Random;
+using HeuristicLab.Data;
+using HeuristicLab.Constraints;
+using System.Diagnostics;
+
+namespace HeuristicLab.GP {
+  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, MersenneTwister 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.Size - parent0.SubTrees[replacedChildIndex].Size);
+        int maxInsertedBranchHeight = maxTreeHeight - gardener.GetBranchLevel(tree0, parent0); // branchlevel is 1 if tree0==parent0
+
+        IList<IFunction> allowedFunctions = gardener.GetAllowedSubFunctions(parent0.Function, replacedChildIndex);
+        allowedCrossoverPoints = GetPossibleCrossoverPoints(gardener, 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(TreeGardener gardener, IFunctionTree tree, int maxInsertedBranchSize, int maxInsertedBranchHeight, IList<IFunction> allowedFunctions) {
+      List<IFunctionTree> crossoverPoints = new List<IFunctionTree>();
+      foreach (IFunctionTree possiblePoint in gardener.GetAllSubTrees(tree)) {
+        if (allowedFunctions.Contains(possiblePoint.Function) && possiblePoint.Size <= maxInsertedBranchSize && possiblePoint.Height <= maxInsertedBranchHeight)
+          crossoverPoints.Add(possiblePoint);
+      }
+      return crossoverPoints;
+    }
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/Recombination/UniformCrossover.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/Recombination/UniformCrossover.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/Recombination/UniformCrossover.cs	(revision 1295)
@@ -0,0 +1,162 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Random;
+using HeuristicLab.Data;
+using HeuristicLab.Constraints;
+using System.Diagnostics;
+
+namespace HeuristicLab.GP {
+  /// <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, MersenneTwister 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: /branches/plugins/HeuristicLab.GP/3.2/TreeGardener.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/TreeGardener.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/TreeGardener.cs	(revision 1295)
@@ -0,0 +1,498 @@
+#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.Constraints;
+using System.Diagnostics;
+using HeuristicLab.Data;
+using System.Linq;
+using HeuristicLab.Random;
+using HeuristicLab.Operators;
+using System.Collections;
+using HeuristicLab.Selection;
+
+namespace HeuristicLab.GP {
+  internal class TreeGardener {
+    private IRandom random;
+    private GPOperatorLibrary funLibrary;
+    private List<IFunction> functions;
+
+    private List<IFunction> terminals;
+    internal IList<IFunction> Terminals {
+      get { return terminals; }
+    }
+
+    private List<IFunction> allFunctions;
+    internal IList<IFunction> AllFunctions {
+      get { return allFunctions; }
+    }
+
+    #region constructors
+    internal TreeGardener(IRandom random, GPOperatorLibrary funLibrary) {
+      this.random = random;
+      this.funLibrary = funLibrary;
+      this.allFunctions = new List<IFunction>();
+      terminals = new List<IFunction>();
+      functions = new List<IFunction>();
+      // init functions and terminals based on constraints
+      foreach(IFunction fun in funLibrary.Group.Operators) {
+        if(fun.MaxArity == 0) {
+          terminals.Add(fun);
+          allFunctions.Add(fun);
+        } else {
+          functions.Add(fun);
+          allFunctions.Add(fun);
+        }
+      }
+    }
+    #endregion
+
+    #region random initialization
+    /// <summary>
+    /// Creates a random balanced tree with a maximal size and height. When the max-height or max-size are 1 it will return a random terminal.
+    /// In other cases it will return either a terminal (tree of size 1) or any other tree with a function in it's root (at least height 2).
+    /// </summary>
+    /// <param name="maxTreeSize">Maximal size of the tree (number of nodes).</param>
+    /// <param name="maxTreeHeight">Maximal height of the tree.</param>
+    /// <returns></returns>
+    internal IFunctionTree CreateBalancedRandomTree(int maxTreeSize, int maxTreeHeight) {
+      IFunction rootFunction = GetRandomRoot(maxTreeSize, maxTreeHeight);
+      IFunctionTree tree = MakeBalancedTree(rootFunction, maxTreeHeight - 1);
+      return tree;
+    }
+
+    /// <summary>
+    /// Creates a random (unbalanced) tree with a maximal size and height. When the max-height or max-size are 1 it will return a random terminal.
+    /// In other cases it will return either a terminal (tree of size 1) or any other tree with a function in it's root (at least height 2).
+    /// </summary>
+    /// <param name="maxTreeSize">Maximal size of the tree (number of nodes).</param>
+    /// <param name="maxTreeHeight">Maximal height of the tree.</param>
+    /// <returns></returns>
+    internal IFunctionTree CreateUnbalancedRandomTree(int maxTreeSize, int maxTreeHeight) {
+      IFunction rootFunction = GetRandomRoot(maxTreeSize, maxTreeHeight);
+      IFunctionTree tree = MakeUnbalancedTree(rootFunction, maxTreeHeight - 1);
+      return tree;
+    }
+
+    internal IFunctionTree PTC2(IRandom random, int size, int maxDepth) {
+      return PTC2(random, GetRandomRoot(size, maxDepth), size, maxDepth);
+    }
+
+    internal IFunctionTree PTC2(IRandom random, IFunction rootF, int size, int maxDepth) {
+      IFunctionTree root = rootF.GetTreeNode();
+      if(size <= 1 || maxDepth <= 1) return root;
+      List<object[]> list = new List<object[]>();
+      int currentSize = 1;
+      int totalListMinSize = 0;
+      int minArity = root.Function.MinArity;
+      int maxArity = root.Function.MaxArity;
+      if(maxArity >= size) {
+        maxArity = size;
+      }
+      int actualArity = random.Next(minArity, maxArity + 1);
+      totalListMinSize += GetMinimalTreeSize(root.Function) - 1;
+      for(int i = 0; i < actualArity; i++) {
+        // insert a dummy sub-tree and add the pending extension to the list
+        root.AddSubTree(null);
+        list.Add(new object[] { root, i, 2 });
+      }
+
+      while(list.Count > 0 && totalListMinSize + currentSize < size) {
+        int randomIndex = random.Next(list.Count);
+        object[] nextExtension = list[randomIndex];
+        list.RemoveAt(randomIndex);
+        IFunctionTree parent = (IFunctionTree)nextExtension[0];
+        int a = (int)nextExtension[1];
+        int d = (int)nextExtension[2];
+        if(d == maxDepth) {
+          parent.RemoveSubTree(a);
+          IFunctionTree branch = CreateRandomTree(GetAllowedSubFunctions(parent.Function, a), 1, 1);
+          parent.InsertSubTree(a, branch); // insert a smallest possible tree
+          currentSize += branch.Size;
+          totalListMinSize -= branch.Size;
+        } else {
+          IFunction selectedFunction = RandomSelect(GetAllowedSubFunctions(parent.Function, a).Where(
+            f => !IsTerminal(f) && GetMinimalTreeHeight(f) + (d - 1) <= maxDepth).ToArray());
+          IFunctionTree newTree = selectedFunction.GetTreeNode();
+          parent.RemoveSubTree(a);
+          parent.InsertSubTree(a, newTree);
+          currentSize++;
+          totalListMinSize--;
+
+          minArity = selectedFunction.MinArity;
+          maxArity = selectedFunction.MaxArity;
+          if(maxArity >= size) {
+            maxArity = size;
+          }
+          actualArity = random.Next(minArity, maxArity + 1);
+          for(int i = 0; i < actualArity; i++) {
+            // insert a dummy sub-tree and add the pending extension to the list
+            newTree.AddSubTree(null);
+            list.Add(new object[] { newTree, i, d + 1 });
+          }
+          totalListMinSize += GetMinimalTreeSize(newTree.Function) - 1;
+        }
+      }
+      while(list.Count > 0) {
+        int randomIndex = random.Next(list.Count);
+        object[] nextExtension = list[randomIndex];
+        list.RemoveAt(randomIndex);
+        IFunctionTree parent = (IFunctionTree)nextExtension[0];
+        int a = (int)nextExtension[1];
+        int d = (int)nextExtension[2];
+        parent.RemoveSubTree(a);
+        parent.InsertSubTree(a,
+          CreateRandomTree(GetAllowedSubFunctions(parent.Function, a), 1, 1)); // append a tree with minimal possible height
+      }
+      return root;
+    }
+
+    /// <summary>
+    /// selects a random function from allowedFunctions and creates a random (unbalanced) tree with maximal size and height.
+    /// </summary>
+    /// <param name="allowedFunctions">Set of allowed functions.</param>
+    /// <param name="maxTreeSize">Maximal size of the tree (number of nodes).</param>
+    /// <param name="maxTreeHeight">Maximal height of the tree.</param>
+    /// <returns>New random unbalanced tree</returns>
+    internal IFunctionTree CreateRandomTree(ICollection<IFunction> allowedFunctions, int maxTreeSize, int maxTreeHeight) {
+      // get the minimal needed height based on allowed functions and extend the max-height if necessary
+      int minTreeHeight = allowedFunctions.Select(f => GetMinimalTreeHeight(f)).Min();
+      if(minTreeHeight > maxTreeHeight)
+        maxTreeHeight = minTreeHeight;
+      // get the minimal needed size based on allowed functions and extend the max-size if necessary
+      int minTreeSize = allowedFunctions.Select(f => GetMinimalTreeSize(f)).Min();
+      if(minTreeSize > maxTreeSize)
+        maxTreeSize = minTreeSize;
+
+      // select a random value for the size and height
+      int treeHeight = random.Next(minTreeHeight, maxTreeHeight + 1);
+      int treeSize = random.Next(minTreeSize, maxTreeSize + 1);
+
+      // filter the set of allowed functions and select only from those that fit into the given maximal size and height limits
+      IFunction[] possibleFunctions = allowedFunctions.Where(f => GetMinimalTreeHeight(f) <= treeHeight &&
+        GetMinimalTreeSize(f) <= treeSize).ToArray();
+      IFunction selectedFunction = RandomSelect(possibleFunctions);
+
+      // build the tree 
+      IFunctionTree root;
+      root = PTC2(random, selectedFunction, maxTreeSize, maxTreeHeight);
+      return root;
+    }
+
+    internal CompositeOperation CreateInitializationOperation(ICollection<IFunctionTree> trees, IScope scope) {
+      // needed for the parameter shaking operation
+      CompositeOperation initializationOperation = new CompositeOperation();
+      Scope tempScope = new Scope("Temp. initialization scope");
+
+      var parametricTrees = trees.Where(t => t.Function.GetVariable(FunctionBase.INITIALIZATION) != null);
+      foreach(IFunctionTree tree in parametricTrees) {
+        // enqueue an initialization operation for each operator with local variables 
+        IOperator initialization = (IOperator)tree.Function.GetVariable(FunctionBase.INITIALIZATION).Value;
+        Scope initScope = new Scope();
+        // copy the local variables into a temporary scope used for initialization
+        foreach(IVariable variable in tree.LocalVariables) {
+          initScope.AddVariable(variable);
+        }
+        tempScope.AddSubScope(initScope);
+        initializationOperation.AddOperation(new AtomicOperation(initialization, initScope));
+      }
+      Scope backupScope = new Scope("backup");
+      foreach(Scope subScope in scope.SubScopes) {
+        backupScope.AddSubScope(subScope);
+      }
+      scope.AddSubScope(tempScope);
+      scope.AddSubScope(backupScope);
+      // add an operation to remove the temporary scopes        
+      initializationOperation.AddOperation(new AtomicOperation(new RightReducer(), scope));
+      return initializationOperation;
+    }
+    #endregion
+
+    #region tree information gathering
+    internal IFunctionTree GetRandomParentNode(IFunctionTree tree) {
+      List<IFunctionTree> parentNodes = new List<IFunctionTree>();
+
+      // add null for the parent of the root node
+      parentNodes.Add(null);
+
+      TreeForEach(tree, delegate(IFunctionTree possibleParentNode) {
+        if(possibleParentNode.SubTrees.Count > 0) {
+          parentNodes.Add(possibleParentNode);
+        }
+      });
+
+      return parentNodes[random.Next(parentNodes.Count)];
+    }
+
+    internal ICollection<IFunctionTree> GetAllSubTrees(IFunctionTree root) {
+      List<IFunctionTree> allTrees = new List<IFunctionTree>();
+      TreeForEach(root, t => { allTrees.Add(t); });
+      return allTrees;
+    }
+
+    /// <summary>
+    /// returns the height level of branch in the tree
+    /// if the branch == tree => 1
+    /// if branch is in the sub-trees of tree => 2
+    /// ...
+    /// if branch is not found => -1
+    /// </summary>
+    /// <param name="tree">root of the function tree to process</param>
+    /// <param name="branch">branch that is searched in the tree</param>
+    /// <returns></returns>
+    internal int GetBranchLevel(IFunctionTree tree, IFunctionTree branch) {
+      return GetBranchLevelHelper(tree, branch, 1);
+    }
+
+    // 'tail-recursive' helper
+    private int GetBranchLevelHelper(IFunctionTree tree, IFunctionTree branch, int level) {
+      if(branch == tree) return level;
+
+      foreach(IFunctionTree subTree in tree.SubTrees) {
+        int result = GetBranchLevelHelper(subTree, branch, level + 1);
+        if(result != -1) return result;
+      }
+
+      return -1;
+    }
+
+    internal bool IsValidTree(IFunctionTree tree) {
+      for(int i = 0; i < tree.SubTrees.Count; i++) {
+        if(!tree.Function.AllowedSubFunctions(i).Contains(tree.SubTrees[i].Function)) return false;
+      }
+
+      if(tree.SubTrees.Count < tree.Function.MinArity || tree.SubTrees.Count > tree.Function.MaxArity)
+        return false;
+      foreach(IFunctionTree subTree in tree.SubTrees) {
+        if(!IsValidTree(subTree)) return false;
+      }
+      return true;
+    }
+
+    // returns a random branch from the specified level in the tree
+    internal IFunctionTree GetRandomBranch(IFunctionTree tree, int level) {
+      if(level == 0) return tree;
+      List<IFunctionTree> branches = new List<IFunctionTree>();
+      GetBranchesAtLevel(tree, level, branches);
+      return branches[random.Next(branches.Count)];
+    }
+    #endregion
+
+    #region function information (arity, allowed childs and parents)
+    internal ICollection<IFunction> GetPossibleParents(List<IFunction> list) {
+      List<IFunction> result = new List<IFunction>();
+      foreach(IFunction f in functions) {
+        if(IsPossibleParent(f, list)) {
+          result.Add(f);
+        }
+      }
+      return result;
+    }
+
+    private bool IsPossibleParent(IFunction f, List<IFunction> children) {
+      int minArity = f.MinArity;
+      int maxArity = f.MaxArity;
+      // note: we can't assume that the operators in the children list have different types!
+
+      // when the maxArity of this function is smaller than the list of operators that
+      // should be included as sub-operators then it can't be a parent
+      if(maxArity < children.Count()) {
+        return false;
+      }
+      int nSlots = Math.Max(minArity, children.Count);
+
+      List<HashSet<IFunction>> slotSets = new List<HashSet<IFunction>>();
+
+      // we iterate through all slots for sub-trees and calculate the set of 
+      // allowed functions for this slot.
+      // we only count those slots that can hold at least one of the children that we should combine
+      for(int slot = 0; slot < nSlots; slot++) {
+        HashSet<IFunction> functionSet = new HashSet<IFunction>(f.AllowedSubFunctions(slot));
+        if(functionSet.Count() > 0) {
+          slotSets.Add(functionSet);
+        }
+      }
+
+      // ok at the end of this operation we know how many slots of the parent can actually
+      // hold one of our children.
+      // if the number of slots is smaller than the number of children we can be sure that
+      // we can never combine all children as sub-trees of the function and thus the function
+      // can't be a parent.
+      if(slotSets.Count() < children.Count()) {
+        return false;
+      }
+
+      // finally we sort the sets by size and beginning from the first set select one
+      // function for the slot and thus remove it as possible sub-tree from the remaining sets.
+      // when we can successfully assign all available children to a slot the function is a valid parent
+      // when only a subset of all children can be assigned to slots the function is no valid parent
+      slotSets.Sort((p, q) => p.Count() - q.Count());
+
+      int assignments = 0;
+      for(int i = 0; i < slotSets.Count() - 1; i++) {
+        if(slotSets[i].Count > 0) {
+          IFunction selected = slotSets[i].ElementAt(0);
+          assignments++;
+          for(int j = i + 1; j < slotSets.Count(); j++) {
+            slotSets[j].Remove(selected);
+          }
+        }
+      }
+
+      // sanity check 
+      if(assignments > children.Count) throw new InvalidProgramException();
+      return assignments == children.Count - 1;
+    }
+    internal IList<IFunction> GetAllowedParents(IFunction child, int childIndex) {
+      List<IFunction> parents = new List<IFunction>();
+      foreach(IFunction function in functions) {
+        ICollection<IFunction> allowedSubFunctions = GetAllowedSubFunctions(function, childIndex);
+        if(allowedSubFunctions.Contains(child)) {
+          parents.Add(function);
+        }
+      }
+      return parents;
+    }
+    internal bool IsTerminal(IFunction f) {
+      return f.MinArity == 0 && f.MaxArity == 0;
+    }
+    internal IList<IFunction> GetAllowedSubFunctions(IFunction f, int index) {
+      if(f == null) {
+        return allFunctions;
+      } else {
+        return f.AllowedSubFunctions(index);
+      }
+    }
+    #endregion
+
+    #region private utility methods
+    private IFunction GetRandomRoot(int maxTreeSize, int maxTreeHeight) {
+      if(maxTreeHeight == 1 || maxTreeSize == 1) {
+        IFunction selectedTerminal = RandomSelect(terminals);
+        return selectedTerminal;
+      } else {
+        IFunction[] possibleFunctions = functions.Where(f => GetMinimalTreeHeight(f) <= maxTreeHeight &&
+          GetMinimalTreeSize(f) <= maxTreeSize).ToArray();
+        IFunction selectedFunction = RandomSelect(possibleFunctions);
+        return selectedFunction;
+      }
+    }
+
+
+    private IFunctionTree MakeUnbalancedTree(IFunction parent, int maxTreeHeight) {
+      if(maxTreeHeight == 0) return parent.GetTreeNode();
+      int minArity = parent.MinArity;
+      int maxArity = parent.MaxArity;
+      int actualArity = random.Next(minArity, maxArity + 1);
+      if(actualArity > 0) {
+        IFunctionTree parentTree = parent.GetTreeNode();
+        for(int i = 0; i < actualArity; i++) {
+          IFunction[] possibleFunctions = GetAllowedSubFunctions(parent, i).Where(f => GetMinimalTreeHeight(f) <= maxTreeHeight).ToArray();
+          IFunction selectedFunction = RandomSelect(possibleFunctions);
+          IFunctionTree newSubTree = MakeUnbalancedTree(selectedFunction, maxTreeHeight - 1);
+          parentTree.InsertSubTree(i, newSubTree);
+        }
+        return parentTree;
+      }
+      return parent.GetTreeNode();
+    }
+
+
+    // NOTE: this method doesn't build fully balanced trees because we have constraints on the
+    // types of possible sub-functions which can indirectly impose a limit for the depth of a given sub-tree
+    private IFunctionTree MakeBalancedTree(IFunction parent, int maxTreeHeight) {
+      if(maxTreeHeight == 0) return parent.GetTreeNode();
+      int minArity = parent.MinArity;
+      int maxArity = parent.MaxArity;
+      int actualArity = random.Next(minArity, maxArity + 1);
+      if(actualArity > 0) {
+        IFunctionTree parentTree = parent.GetTreeNode();
+        for(int i = 0; i < actualArity; i++) {
+          // first try to find a function that fits into the maxHeight limit
+          IFunction[] possibleFunctions = GetAllowedSubFunctions(parent, i).Where(f => GetMinimalTreeHeight(f) <= maxTreeHeight &&
+            !IsTerminal(f)).ToArray();
+          // no possible function found => extend function set to terminals
+          if(possibleFunctions.Length == 0) {
+            possibleFunctions = GetAllowedSubFunctions(parent, i).Where(f => IsTerminal(f)).ToArray();
+            IFunction selectedTerminal = RandomSelect(possibleFunctions);
+            IFunctionTree newTree = selectedTerminal.GetTreeNode();
+            parentTree.InsertSubTree(i, newTree);
+          } else {
+            IFunction selectedFunction = RandomSelect(possibleFunctions);
+            IFunctionTree newTree = MakeBalancedTree(selectedFunction, maxTreeHeight - 1);
+            parentTree.InsertSubTree(i, newTree);
+          }
+        }
+        return parentTree;
+      }
+      return parent.GetTreeNode();
+    }
+
+    private int GetMinimalTreeHeight(IOperator op) {
+      return ((IntData)op.GetVariable(GPOperatorLibrary.MIN_TREE_HEIGHT).Value).Data;
+    }
+
+    private int GetMinimalTreeSize(IOperator op) {
+      return ((IntData)op.GetVariable(GPOperatorLibrary.MIN_TREE_SIZE).Value).Data;
+    }
+
+    private void TreeForEach(IFunctionTree tree, Action<IFunctionTree> action) {
+      action(tree);
+      foreach(IFunctionTree subTree in tree.SubTrees) {
+        TreeForEach(subTree, action);
+      }
+    }
+
+    private void GetBranchesAtLevel(IFunctionTree tree, int level, List<IFunctionTree> result) {
+      if(level == 1) result.AddRange(tree.SubTrees);
+      foreach(IFunctionTree subTree in tree.SubTrees) {
+        if(subTree.Height >= level - 1)
+          GetBranchesAtLevel(subTree, level - 1, result);
+      }
+    }
+
+    private IFunction RandomSelect(IList<IFunction> functionSet) {
+      double[] accumulatedTickets = new double[functionSet.Count];
+      double ticketAccumulator = 0;
+      int i = 0;
+      // precalculate the slot-sizes
+      foreach(IFunction function in functionSet) {
+        ticketAccumulator += ((DoubleData)function.GetVariable(GPOperatorLibrary.TICKETS).Value).Data;
+        accumulatedTickets[i] = ticketAccumulator;
+        i++;
+      }
+      // throw ball
+      double r = random.NextDouble() * ticketAccumulator;
+      // find the slot that has been hit
+      for(i = 0; i < accumulatedTickets.Length; i++) {
+        if(r < accumulatedTickets[i]) return functionSet[i];
+      }
+      // sanity check
+      throw new InvalidProgramException(); // should never happen
+    }
+
+    #endregion
+
+  }
+}
Index: /branches/plugins/HeuristicLab.GP/3.2/UnknownFunctionException.cs
===================================================================
--- /branches/plugins/HeuristicLab.GP/3.2/UnknownFunctionException.cs	(revision 1295)
+++ /branches/plugins/HeuristicLab.GP/3.2/UnknownFunctionException.cs	(revision 1295)
@@ -0,0 +1,33 @@
+#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 {
+  public class UnknownFunctionException : Exception {
+    public UnknownFunctionException(string functionName)
+      : base("Function "+functionName+" was not expected and can't be handled.") {
+    }
+  }
+}
