Index: trunk/sources/HeuristicLab.Functions/FunctionBase.cs
===================================================================
--- trunk/sources/HeuristicLab.Functions/FunctionBase.cs	(revision 524)
+++ trunk/sources/HeuristicLab.Functions/FunctionBase.cs	(revision 525)
@@ -27,4 +27,5 @@
 using System.Xml;
 using HeuristicLab.DataAnalysis;
+using HeuristicLab.Constraints;
 
 namespace HeuristicLab.Functions {
@@ -36,5 +37,7 @@
     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(Dataset dataset, int sampleIndex, double[] args) {
@@ -48,4 +51,53 @@
     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) {
+        allowedSubFunctions = new List<IFunction>[MaxArity];
+        for(int i = 0; i < MaxArity; i++) {
+          foreach(IConstraint constraint in Constraints) {
+            if(constraint is SubOperatorTypeConstraint) {
+              SubOperatorTypeConstraint subOpConstraint = constraint as SubOperatorTypeConstraint;
+              if(subOpConstraint.SubOperatorIndex.Data == index) {
+                allowedSubFunctions[i] = new List<IFunction>();
+                foreach(IFunction f in subOpConstraint.AllowedSubOperators) allowedSubFunctions[i].Add(f);
+                break;
+              }
+            } else if(constraint is AllSubOperatorsTypeConstraint) {
+              AllSubOperatorsTypeConstraint subOpConstraint = constraint as AllSubOperatorsTypeConstraint;
+              allowedSubFunctions[i] = new List<IFunction>();
+              foreach(IFunction f in subOpConstraint.AllowedSubOperators) allowedSubFunctions[i].Add(f);
+              break;
+            }
+          }
+        }
+      }
+      return allowedSubFunctions[index];
     }
 
Index: trunk/sources/HeuristicLab.Functions/IFunction.cs
===================================================================
--- trunk/sources/HeuristicLab.Functions/IFunction.cs	(revision 524)
+++ trunk/sources/HeuristicLab.Functions/IFunction.cs	(revision 525)
@@ -31,4 +31,7 @@
     double Apply(Dataset dataset, int sampleIndex, double[] args);
     void Accept(IFunctionVisitor visitor);
+    IList<IFunction> AllowedSubFunctions(int index);
+    int MinArity { get; }
+    int MaxArity { get; }
   }
 }
Index: trunk/sources/HeuristicLab.StructureIdentification/TreeGardener.cs
===================================================================
--- trunk/sources/HeuristicLab.StructureIdentification/TreeGardener.cs	(revision 524)
+++ trunk/sources/HeuristicLab.StructureIdentification/TreeGardener.cs	(revision 525)
@@ -166,5 +166,5 @@
         int d = (int)nextExtension[2];
         parent.RemoveSubTree(a);
-        parent.InsertSubTree(a, 
+        parent.InsertSubTree(a,
           CreateRandomTree(GetAllowedSubFunctions(parent.Function, a), 1, 1)); // append a tree with minimal possible height
       }
@@ -282,18 +282,10 @@
 
     internal bool IsValidTree(IFunctionTree tree) {
-      SubOperatorsConstraintAnalyser analyzer = new SubOperatorsConstraintAnalyser();
-      analyzer.AllPossibleOperators = AllFunctions.Cast<IOperator>().ToArray<IOperator>();
       for(int i = 0; i < tree.SubTrees.Count; i++) {
-        if(!analyzer.GetAllowedOperators(tree.Function, i).Contains(tree.SubTrees[i].Function)) return false;
-      }
-
-      foreach(IConstraint constraint in tree.Function.Constraints) {
-        if(constraint is NumberOfSubOperatorsConstraint) {
-          int max = ((NumberOfSubOperatorsConstraint)constraint).MaxOperators.Data;
-          int min = ((NumberOfSubOperatorsConstraint)constraint).MinOperators.Data;
-          if(tree.SubTrees.Count < min || tree.SubTrees.Count > max)
-            return false;
-        }
-      }
+        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;
@@ -335,7 +327,4 @@
       int nSlots = Math.Max(minArity, children.Count);
 
-      SubOperatorsConstraintAnalyser analyzer = new SubOperatorsConstraintAnalyser();
-      analyzer.AllPossibleOperators = children.Cast<IOperator>().ToArray<IOperator>();
-
       List<HashSet<IFunction>> slotSets = new List<HashSet<IFunction>>();
 
@@ -344,5 +333,5 @@
       // 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>(analyzer.GetAllowedOperators(f, slot).Cast<IFunction>());
+        HashSet<IFunction> functionSet = new HashSet<IFunction>(f.AllowedSubFunctions(slot));
         if(functionSet.Count() > 0) {
           slotSets.Add(functionSet);
@@ -400,25 +389,10 @@
         return allFunctions;
       } else {
-        SubOperatorsConstraintAnalyser analyzer = new SubOperatorsConstraintAnalyser();
-        analyzer.AllPossibleOperators = AllFunctions.Cast<IOperator>().ToArray<IOperator>();
-        List<IFunction> result = new List<IFunction>();
-        foreach(IFunction function in analyzer.GetAllowedOperators(f, index)) {
-          result.Add(function);
-        }
-        return result;
+        return f.AllowedSubFunctions(index);
       }
     }
     internal void GetMinMaxArity(IFunction f, out int minArity, out int maxArity) {
-      foreach(IConstraint constraint in f.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;
+      minArity = f.MinArity;
+      maxArity = f.MaxArity;
     }
     #endregion
