Index: /trunk/sources/HeuristicLab.Functions/And.cs
===================================================================
--- /trunk/sources/HeuristicLab.Functions/And.cs	(revision 188)
+++ /trunk/sources/HeuristicLab.Functions/And.cs	(revision 189)
@@ -42,15 +42,9 @@
     }
 
-    // special form
-    public override double Evaluate(Dataset dataset, int sampleIndex, IFunctionTree tree) {
-      foreach(IFunctionTree subTree in tree.SubTrees) {
-        double result = Math.Round(subTree.Evaluate(dataset, sampleIndex));
-        if(result == 0.0) return 0.0; // one sub-tree is 0.0 (false) => return false
-        else if(result != 1.0) return double.NaN;
-      }
-      // all sub-trees evaluated to 1.0 (true) => return 1.0 (true)
-      return 1.0;
+    public override IFunctionTree GetTreeNode() {
+      return new AndFunctionTree(this);
     }
 
+    // special form
     public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
       throw new NotImplementedException();
@@ -61,3 +55,18 @@
     }
   }
+
+  class AndFunctionTree : FunctionTree {
+    public AndFunctionTree() : base() { }
+    public AndFunctionTree(And and) : base(and) { }
+
+    public override double Evaluate(Dataset dataset, int sampleIndex) {
+      foreach(IFunctionTree subTree in SubTrees) {
+        double result = Math.Round(subTree.Evaluate(dataset, sampleIndex));
+        if(result == 0.0) return 0.0; // one sub-tree is 0.0 (false) => return false
+        else if(result != 1.0) return double.NaN;
+      }
+      // all sub-trees evaluated to 1.0 (true) => return 1.0 (true)
+      return 1.0;      
+    }
+  }
 }
Index: /trunk/sources/HeuristicLab.Functions/Constant.cs
===================================================================
--- /trunk/sources/HeuristicLab.Functions/Constant.cs	(revision 188)
+++ /trunk/sources/HeuristicLab.Functions/Constant.cs	(revision 189)
@@ -52,7 +52,6 @@
     }
 
-    // constant is evaluated directly. Evaluation reads the local variable value from the tree and returns
-    public override double Evaluate(Dataset dataset, int sampleIndex, IFunctionTree tree) {
-      return ((ConstrainedDoubleData)tree.GetLocalVariable(VALUE).Value).Data;
+    public override IFunctionTree GetTreeNode() {
+      return new ConstantFunctionTree(this);
     }
 
@@ -66,3 +65,30 @@
     }
   }
+
+  class ConstantFunctionTree : FunctionTree {
+    private ConstrainedDoubleData value;
+    public ConstantFunctionTree() : base() { }
+    public ConstantFunctionTree(Constant constant) : base(constant) {
+      UpdateCachedValues();
+    }
+
+    private void UpdateCachedValues() {
+      value = (ConstrainedDoubleData)GetLocalVariable(Constant.VALUE).Value;
+    }
+
+    public override double Evaluate(Dataset dataset, int sampleIndex) {
+      return value.Data;
+    }
+
+    public override object Clone(IDictionary<Guid, object> clonedObjects) {
+      ConstantFunctionTree clone = (ConstantFunctionTree)base.Clone(clonedObjects);
+      clone.UpdateCachedValues();
+      return clone;
+    }
+
+    public override void Populate(System.Xml.XmlNode node, IDictionary<Guid, IStorable> restoredObjects) {
+      base.Populate(node, restoredObjects);
+      UpdateCachedValues();
+    }
+  }
 }
Index: /trunk/sources/HeuristicLab.Functions/FunctionBase.cs
===================================================================
--- /trunk/sources/HeuristicLab.Functions/FunctionBase.cs	(revision 188)
+++ /trunk/sources/HeuristicLab.Functions/FunctionBase.cs	(revision 189)
@@ -35,20 +35,12 @@
   public abstract class FunctionBase : OperatorBase, IFunction {
     
-    public virtual double Evaluate(Dataset dataset, int sampleIndex, IFunctionTree tree) {
-      if(tree.SubTrees.Count > 0) {
-        double[] evaluationResults = new double[tree.SubTrees.Count];
-        for(int i = 0; i < evaluationResults.Length; i++) {
-          evaluationResults[i] = tree.SubTrees[i].Evaluate(dataset, sampleIndex);
-        }
-        return Apply(dataset, sampleIndex, evaluationResults);
-      } else {
-        return Apply(dataset, sampleIndex, null);
-      }
-    }
-
     public abstract double Apply(Dataset dataset, int sampleIndex, double[] args);
 
     public virtual void Accept(IFunctionVisitor visitor) {
       visitor.Visit(this);
+    }
+
+    public virtual IFunctionTree GetTreeNode() {
+      return new FunctionTree(this);
     }
 
Index: /trunk/sources/HeuristicLab.Functions/FunctionTree.cs
===================================================================
--- /trunk/sources/HeuristicLab.Functions/FunctionTree.cs	(revision 188)
+++ /trunk/sources/HeuristicLab.Functions/FunctionTree.cs	(revision 189)
@@ -35,10 +35,12 @@
     private IFunction function;
 
-    public FunctionTree() : base() {
+    public FunctionTree()
+      : base() {
       subTrees = new List<IFunctionTree>();
       localVariables = new List<IVariable>();
     }
 
-    public FunctionTree(IFunction function) : this() {
+    internal FunctionTree(IFunction function)
+      : this() {
       this.function = function;
       // create and store clones of all local variables of the function
@@ -91,6 +93,10 @@
     }
 
-    public double Evaluate(Dataset dataset, int sampleIndex) {
-      return function.Evaluate(dataset, sampleIndex, this);
+    public virtual double Evaluate(Dataset dataset, int sampleIndex) {
+      double[] evaluationResults = new double[SubTrees.Count];
+      for(int i = 0; i < evaluationResults.Length; i++) {
+        evaluationResults[i] = SubTrees[i].Evaluate(dataset, sampleIndex);
+      }
+      return function.Apply(dataset, sampleIndex, evaluationResults);
     }
     #endregion
Index: /trunk/sources/HeuristicLab.Functions/IFunction.cs
===================================================================
--- /trunk/sources/HeuristicLab.Functions/IFunction.cs	(revision 188)
+++ /trunk/sources/HeuristicLab.Functions/IFunction.cs	(revision 189)
@@ -28,5 +28,5 @@
 namespace HeuristicLab.Functions {
   public interface IFunction : IOperator {
-    double Evaluate(Dataset dataset, int sampleIndex, IFunctionTree tree);
+    IFunctionTree GetTreeNode();
     double Apply(Dataset dataset, int sampleIndex, double[] args);
     void Accept(IFunctionVisitor visitor);
Index: /trunk/sources/HeuristicLab.Functions/IfThenElse.cs
===================================================================
--- /trunk/sources/HeuristicLab.Functions/IfThenElse.cs	(revision 188)
+++ /trunk/sources/HeuristicLab.Functions/IfThenElse.cs	(revision 189)
@@ -41,12 +41,9 @@
     }
 
-    // special form
-    public override double Evaluate(Dataset dataset, int sampleIndex, IFunctionTree tree) {
-      double condition = Math.Round(tree.SubTrees[0].Evaluate(dataset, sampleIndex));
-      if(condition < .5) return tree.SubTrees[1].Evaluate(dataset, sampleIndex);
-      else if(condition >= .5) return tree.SubTrees[2].Evaluate(dataset, sampleIndex);
-      else return double.NaN;
+    public override IFunctionTree GetTreeNode() {
+      return new IfThenElseFunctionTree(this);
     }
 
+    // special form
     public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
       throw new NotImplementedException();
@@ -57,3 +54,15 @@
     }
   }
+
+  class IfThenElseFunctionTree : FunctionTree {
+    public IfThenElseFunctionTree() : base() { }
+    public IfThenElseFunctionTree(IfThenElse ifte) : base(ifte) { }
+
+    public override double Evaluate(Dataset dataset, int sampleIndex) {
+      double condition = Math.Round(SubTrees[0].Evaluate(dataset, sampleIndex));
+      if(condition < .5) return SubTrees[1].Evaluate(dataset, sampleIndex);
+      else if(condition >= .5) return SubTrees[2].Evaluate(dataset, sampleIndex);
+      else return double.NaN;
+    }
+  }
 }
Index: /trunk/sources/HeuristicLab.Functions/Or.cs
===================================================================
--- /trunk/sources/HeuristicLab.Functions/Or.cs	(revision 188)
+++ /trunk/sources/HeuristicLab.Functions/Or.cs	(revision 189)
@@ -41,6 +41,22 @@
     }
 
-    public override double Evaluate(Dataset dataset, int sampleIndex, IFunctionTree tree) {
-      foreach(IFunctionTree subTree in tree.SubTrees) {
+    public override IFunctionTree GetTreeNode() {
+      return new OrFunctionTree(this);
+    }
+    // or is a special form and can't be applied
+    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
+      throw new NotImplementedException();
+    }
+    public override void Accept(IFunctionVisitor visitor) {
+      visitor.Visit(this);
+    }
+  }
+
+  class OrFunctionTree : FunctionTree {
+    public OrFunctionTree() : base() { }
+    public OrFunctionTree(Or or) : base(or) { }
+
+    public override double Evaluate(Dataset dataset, int sampleIndex) {
+      foreach(IFunctionTree subTree in SubTrees) {
         double result = Math.Round(subTree.Evaluate(dataset, sampleIndex));
         if(result == 1.0) return 1.0; // sub-tree evaluates to 1.0 (true) return 1.0
@@ -50,11 +66,4 @@
       return 0.0;
     }
-
-    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
-      throw new NotImplementedException();
-    }
-    public override void Accept(IFunctionVisitor visitor) {
-      visitor.Visit(this);
-    }
   }
 }
Index: /trunk/sources/HeuristicLab.Functions/ProgrammableFunction.cs
===================================================================
--- /trunk/sources/HeuristicLab.Functions/ProgrammableFunction.cs	(revision 188)
+++ /trunk/sources/HeuristicLab.Functions/ProgrammableFunction.cs	(revision 189)
@@ -119,83 +119,98 @@
     }
 
-    public double Evaluate(Dataset dataset, int sampleIndex, IFunctionTree tree) {
-      // evaluate sub-trees
-      double[] evaluationResults = new double[tree.SubTrees.Count];
-      for(int subTree=0; subTree < tree.SubTrees.Count; subTree++) {
-        evaluationResults[subTree] = tree.SubTrees[subTree].Evaluate(dataset, sampleIndex);
-      }
+    public IFunctionTree GetTreeNode() {
+      return new ProgrammableFunctionTree(this);
+    }
+
+    // application of programmable-function is not possible
+    public double Apply(Dataset dataset, int sampleIndex, double[] args) {
+      throw new NotSupportedException();
+    }
+
+    internal double Call(object[] parameters) {
       // lazy activation of the user-programmed code
       if(applyMethod == null) {
         Compile();
       }
+      return (double)applyMethod.Invoke(null, parameters);
+    }
+
+    #endregion
+
+    #region disabled operator functionality
+    // 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();
+    }
+    #endregion
+  }
+
+  class ProgrammableFunctionTree : FunctionTree {
+    private ProgrammableFunction progFun;
+    public ProgrammableFunctionTree() : base() { }
+    public ProgrammableFunctionTree(ProgrammableFunction progFun) : base(progFun) {
+      this.progFun = progFun;
+    }
+    public override double Evaluate(Dataset dataset, int sampleIndex) {
+      // evaluate sub-trees
+      double[] evaluationResults = new double[SubTrees.Count];
+      for(int subTree = 0; subTree < SubTrees.Count; subTree++) {
+        evaluationResults[subTree] = SubTrees[subTree].Evaluate(dataset, sampleIndex);
+      }
 
       // collect parameters
-      object[] parameters = new object[VariableInfos.Count + 3];
+      object[] parameters = new object[LocalVariables.Count + 3];
       parameters[0] = dataset;
       parameters[1] = sampleIndex;
       int i = 2;
       // all local variables are available in the custom function
-      foreach(IVariable variable in tree.LocalVariables) {
+      foreach(IVariable variable in LocalVariables) {
         parameters[i] = variable;
         i++;
       }
       parameters[i] = evaluationResults;
-      return (double)applyMethod.Invoke(null, parameters);
-    }
-
-    // application of programmable-function is not possible
-    public double Apply(Dataset dataset, int sampleIndex, double[] args) {
-      throw new NotSupportedException();
-    }
-
-    #endregion
-
-    #region disabled operator functionality
-    // 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();
-    }
-    #endregion
+      return progFun.Call(parameters);
+    }
   }
 }
Index: /trunk/sources/HeuristicLab.Functions/Variable.cs
===================================================================
--- /trunk/sources/HeuristicLab.Functions/Variable.cs	(revision 188)
+++ /trunk/sources/HeuristicLab.Functions/Variable.cs	(revision 189)
@@ -68,13 +68,6 @@
     }
 
-    // variable can be evaluated directly
-    // evaluation reads local variables weight, index, offset from function-tree and returns the variable-value * weight
-    public override double Evaluate(Dataset dataset, int sampleIndex, IFunctionTree tree) {
-      double w = ((ConstrainedDoubleData)tree.GetLocalVariable(WEIGHT).Value).Data;
-      int v = ((ConstrainedIntData)tree.GetLocalVariable(INDEX).Value).Data;
-      int offset = ((ConstrainedIntData)tree.GetLocalVariable(OFFSET).Value).Data;
-
-      if(sampleIndex + offset < 0 || sampleIndex + offset >= dataset.Rows) return double.NaN;
-      return w * dataset.GetValue(sampleIndex + offset, v);
+    public override IFunctionTree GetTreeNode() {
+      return new VariableFunctionTree(this);
     }
 
@@ -88,3 +81,34 @@
     }
   }
+  class VariableFunctionTree : FunctionTree {
+    private ConstrainedDoubleData weight;
+    private ConstrainedIntData index;
+    private ConstrainedIntData offset;
+
+    public VariableFunctionTree() : base() { }
+    public VariableFunctionTree(Variable variable) : base(variable) {
+      UpdateCachedValues();
+    }
+
+    protected void UpdateCachedValues() {
+      weight = (ConstrainedDoubleData)GetLocalVariable(Variable.WEIGHT).Value;
+      index = (ConstrainedIntData)GetLocalVariable(Variable.INDEX).Value;
+      offset = (ConstrainedIntData)GetLocalVariable(Variable.OFFSET).Value;
+    }
+
+    public override double Evaluate(Dataset dataset, int sampleIndex) {
+      return weight.Data * dataset.GetValue(sampleIndex + offset.Data, index.Data);
+    }
+
+    public override object Clone(IDictionary<Guid, object> clonedObjects) {
+      VariableFunctionTree clone = (VariableFunctionTree)base.Clone(clonedObjects);
+      clone.UpdateCachedValues();
+      return clone;
+    }
+
+    public override void Populate(System.Xml.XmlNode node, IDictionary<Guid, IStorable> restoredObjects) {
+      base.Populate(node, restoredObjects);
+      UpdateCachedValues();
+    }
+  }
 }
Index: /trunk/sources/HeuristicLab.StructureIdentification/Manipulation/ChangeNodeTypeManipulation.cs
===================================================================
--- /trunk/sources/HeuristicLab.StructureIdentification/Manipulation/ChangeNodeTypeManipulation.cs	(revision 188)
+++ /trunk/sources/HeuristicLab.StructureIdentification/Manipulation/ChangeNodeTypeManipulation.cs	(revision 189)
@@ -156,5 +156,5 @@
       int maxArity;
       // create a new tree-node for a randomly selected function
-      IFunctionTree newTree = new FunctionTree(allowedFunctions[random.Next(allowedFunctions.Count)]);
+      IFunctionTree newTree = allowedFunctions[random.Next(allowedFunctions.Count)].GetTreeNode();
       gardener.GetMinMaxArity(newTree.Function, out minArity, out maxArity);
       // if the old child had too many sub-trees then the new child should keep as many sub-trees as possible
Index: /trunk/sources/HeuristicLab.StructureIdentification/Recombination/SizeFairCrossOver.cs
===================================================================
--- /trunk/sources/HeuristicLab.StructureIdentification/Recombination/SizeFairCrossOver.cs	(revision 188)
+++ /trunk/sources/HeuristicLab.StructureIdentification/Recombination/SizeFairCrossOver.cs	(revision 189)
@@ -223,5 +223,5 @@
       if(possibleParents.Count == 0) throw new InvalidProgramException();
       // and select a random one
-      IFunctionTree parent = new FunctionTree(possibleParents.ElementAt(random.Next(possibleParents.Count())));
+      IFunctionTree parent = possibleParents.ElementAt(random.Next(possibleParents.Count())).GetTreeNode();
 
       int minArity;
Index: /trunk/sources/HeuristicLab.StructureIdentification/TreeGardener.cs
===================================================================
--- /trunk/sources/HeuristicLab.StructureIdentification/TreeGardener.cs	(revision 188)
+++ /trunk/sources/HeuristicLab.StructureIdentification/TreeGardener.cs	(revision 189)
@@ -141,5 +141,5 @@
 
       // build the tree 
-      IFunctionTree root = new FunctionTree(selectedFunction);
+      IFunctionTree root = selectedFunction.GetTreeNode();
       if(balanceTrees) {
         MakeBalancedTree(root, maxTreeSize - 1, maxTreeHeight - 1);
@@ -376,10 +376,10 @@
       if(maxTreeHeight == 1 || maxTreeSize == 1) {
         IFunction selectedTerminal = RandomSelect(terminals);
-        return new FunctionTree(selectedTerminal);
+        return selectedTerminal.GetTreeNode();
       } else {
         IFunction[] possibleFunctions = allFunctions.Where(f => GetMinimalTreeHeight(f) <= maxTreeHeight &&
           GetMinimalTreeSize(f) <= maxTreeSize).ToArray();
         IFunction selectedFunction = RandomSelect(possibleFunctions);
-        return new FunctionTree(selectedFunction);
+        return selectedFunction.GetTreeNode();
       }
     }
@@ -400,5 +400,5 @@
             GetMinimalTreeSize(f) <= maxSubTreeSize).ToArray();
           IFunction selectedFunction = RandomSelect(possibleFunctions);
-          FunctionTree newSubTree = new FunctionTree(selectedFunction);
+          IFunctionTree newSubTree = selectedFunction.GetTreeNode();
           MakeUnbalancedTree(newSubTree, maxSubTreeSize - 1, maxTreeHeight - 1);
           parent.InsertSubTree(i, newSubTree);
@@ -424,5 +424,5 @@
             IFunction[] possibleTerminals = GetAllowedSubFunctions(parent.Function, i).Where(f => IsTerminal(f)).ToArray();
             IFunction selectedTerminal = RandomSelect(possibleTerminals);
-            IFunctionTree newTree = new FunctionTree(selectedTerminal);
+            IFunctionTree newTree = selectedTerminal.GetTreeNode();
             parent.InsertSubTree(i, newTree);
           } else {
@@ -432,5 +432,5 @@
               !IsTerminal(f)).ToArray();
             IFunction selectedFunction = RandomSelect(possibleFunctions);
-            FunctionTree newTree = new FunctionTree(selectedFunction);
+            IFunctionTree newTree = selectedFunction.GetTreeNode();
             parent.InsertSubTree(i, newTree);
             MakeBalancedTree(newTree, maxSubTreeSize - 1, maxTreeHeight - 1);
