Index: /branches/ExperimentalStructureIdentification/Evaluation/CoefficientOfDeterminationEvaluator.cs
===================================================================
--- /branches/ExperimentalStructureIdentification/Evaluation/CoefficientOfDeterminationEvaluator.cs	(revision 204)
+++ /branches/ExperimentalStructureIdentification/Evaluation/CoefficientOfDeterminationEvaluator.cs	(revision 204)
@@ -0,0 +1,75 @@
+#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 HeuristicLab.Operators;
+using HeuristicLab.Functions;
+using HeuristicLab.DataAnalysis;
+
+namespace HeuristicLab.StructureIdentification {
+  public class CoefficientOfDeterminationEvaluator : GPEvaluatorBase {
+    public override string Description {
+      get {
+        return @"Evaluates 'FunctionTree' for all samples of 'Dataset' and calculates
+the 'coefficient of determination' of estimated values vs. real values of 'TargetVariable'.";
+      }
+    }
+
+    public CoefficientOfDeterminationEvaluator()
+      : base() {
+    }
+
+    public override double Evaluate(IScope scope, IFunctionTree functionTree, int targetVariable, Dataset dataset) {
+      double errorsSquaredSum = 0.0;
+      double originalDeviationTotalSumOfSquares = 0.0;
+      double targetMean = dataset.GetMean(targetVariable);
+      for(int sample = 0; sample < dataset.Rows; sample++) {
+        double estimated = functionTree.Evaluate(dataset, sample);
+        double original = dataset.GetValue(sample, targetVariable);
+        if(!double.IsNaN(original) && !double.IsInfinity(original)) {
+          if(double.IsNaN(estimated) || double.IsInfinity(estimated))
+            estimated = targetMean + maximumPunishment;
+          else if(estimated > (targetMean + maximumPunishment))
+            estimated = targetMean + maximumPunishment;
+          else if(estimated < (targetMean - maximumPunishment))
+            estimated = targetMean - maximumPunishment;
+
+          double error = estimated - original;
+          errorsSquaredSum += error * error;
+
+          double origDeviation = original - targetMean;
+          originalDeviationTotalSumOfSquares += origDeviation * origDeviation;
+        }
+      }
+      double quality = 1 - errorsSquaredSum / originalDeviationTotalSumOfSquares;
+      if(quality > 1) 
+        throw new InvalidProgramException();
+      if(double.IsNaN(quality) || double.IsInfinity(quality)) 
+        quality = double.MaxValue;
+      return quality;
+    }
+  }
+}
Index: /branches/ExperimentalStructureIdentification/Evaluation/EarlyStoppingMeanSquaredErrorEvaluator.cs
===================================================================
--- /branches/ExperimentalStructureIdentification/Evaluation/EarlyStoppingMeanSquaredErrorEvaluator.cs	(revision 204)
+++ /branches/ExperimentalStructureIdentification/Evaluation/EarlyStoppingMeanSquaredErrorEvaluator.cs	(revision 204)
@@ -0,0 +1,78 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Functions;
+using HeuristicLab.DataAnalysis;
+
+namespace HeuristicLab.StructureIdentification {
+  public class EarlyStoppingMeanSquaredErrorEvaluator : MeanSquaredErrorEvaluator {
+    public override string Description {
+      get {
+        return @"Evaluates 'FunctionTree' for all samples of the dataset and calculates the mean-squared-error
+for the estimated values vs. the real values of 'TargetVariable'.
+This operator stops the computation as soon as an upper limit for the mean-squared-error is reached.";
+      }
+    }
+
+    public EarlyStoppingMeanSquaredErrorEvaluator()
+      : base() {
+      AddVariableInfo(new VariableInfo("QualityLimit", "The upper limit of the MSE which is used as early stopping criterion.", typeof(DoubleData), VariableKind.In));
+    }
+
+    public override double Evaluate(IScope scope, IFunctionTree functionTree, int targetVariable, Dataset dataset) {
+      double qualityLimit = GetVariableValue<DoubleData>("QualityLimit", scope, false).Data;
+      double errorsSquaredSum = 0;
+      double targetMean = dataset.GetMean(targetVariable);
+      for(int sample = 0; sample < dataset.Rows; sample++) {
+        double estimated = functionTree.Evaluate(dataset, sample);
+        double original = dataset.GetValue(sample, targetVariable);
+        if(double.IsNaN(estimated) || double.IsInfinity(estimated)) {
+          estimated = targetMean + maximumPunishment;
+        } else if(estimated > targetMean + maximumPunishment) {
+          estimated = targetMean + maximumPunishment;
+        } else if(estimated < targetMean - maximumPunishment) {
+          estimated = targetMean - maximumPunishment;
+        }
+        double error = estimated - original;
+        errorsSquaredSum += error * error;
+
+        // check the limit and stop as soon as we hit the limit
+        if(errorsSquaredSum / dataset.Rows >= qualityLimit) {
+          scope.GetVariableValue<DoubleData>("TotalEvaluatedNodes", true).Data = totalEvaluatedNodes + treeSize * sample+1;
+          return errorsSquaredSum / (sample + 1); // return estimated MSE (when the remaining errors are on average the same)
+        }
+      }
+      errorsSquaredSum /= dataset.Rows;
+      if(double.IsNaN(errorsSquaredSum) || double.IsInfinity(errorsSquaredSum)) {
+        errorsSquaredSum = double.MaxValue;
+      }
+      scope.GetVariableValue<DoubleData>("TotalEvaluatedNodes", true).Data = totalEvaluatedNodes + treeSize * dataset.Rows;
+      return errorsSquaredSum;
+    }
+  }
+}
Index: /branches/ExperimentalStructureIdentification/Evaluation/GPEvaluatorBase.cs
===================================================================
--- /branches/ExperimentalStructureIdentification/Evaluation/GPEvaluatorBase.cs	(revision 204)
+++ /branches/ExperimentalStructureIdentification/Evaluation/GPEvaluatorBase.cs	(revision 204)
@@ -0,0 +1,64 @@
+#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 HeuristicLab.Operators;
+using HeuristicLab.Functions;
+using HeuristicLab.DataAnalysis;
+
+namespace HeuristicLab.StructureIdentification {
+  public abstract class GPEvaluatorBase : OperatorBase {
+    protected double maximumPunishment;
+    protected int treeSize;
+    protected double totalEvaluatedNodes;
+
+    public GPEvaluatorBase()
+      : base() {
+      AddVariableInfo(new VariableInfo("FunctionTree", "The function tree that should be evaluated", typeof(IFunctionTree), VariableKind.In));
+      AddVariableInfo(new VariableInfo("TreeSize", "Size (number of nodes) of the tree to evaluate", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("Dataset", "Dataset with all samples on which to apply the function", typeof(Dataset), VariableKind.In));
+      AddVariableInfo(new VariableInfo("TargetVariable", "Index of the column of the dataset that holds the target variable", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("PunishmentFactor", "Punishment factor for invalid estimations", typeof(DoubleData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("TotalEvaluatedNodes", "Number of evaluated nodes", typeof(DoubleData), VariableKind.In | VariableKind.Out)); 
+      AddVariableInfo(new VariableInfo("Quality", "The evaluated quality of the model", typeof(DoubleData), VariableKind.New));
+    }
+
+    public override IOperation Apply(IScope scope) {
+      int targetVariable = GetVariableValue<IntData>("TargetVariable", scope, true).Data;
+      Dataset dataset = GetVariableValue<Dataset>("Dataset", scope, true);
+      IFunctionTree functionTree = GetVariableValue<IFunctionTree>("FunctionTree", scope, true);
+      this.maximumPunishment = GetVariableValue<DoubleData>("PunishmentFactor", scope, true).Data * dataset.GetRange(targetVariable);
+      this.treeSize = scope.GetVariableValue<IntData>("TreeSize", false).Data;
+      this.totalEvaluatedNodes = scope.GetVariableValue<DoubleData>("TotalEvaluatedNodes", true).Data;
+
+      double result = Evaluate(scope, functionTree, targetVariable, dataset);
+      scope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("Quality"), new DoubleData(result)));
+      return null;
+    }
+
+    public abstract double Evaluate(IScope scope, IFunctionTree functionTree, int targetVariable, Dataset dataset);
+  }
+}
Index: /branches/ExperimentalStructureIdentification/Evaluation/MCCEvaluator.cs
===================================================================
--- /branches/ExperimentalStructureIdentification/Evaluation/MCCEvaluator.cs	(revision 204)
+++ /branches/ExperimentalStructureIdentification/Evaluation/MCCEvaluator.cs	(revision 204)
@@ -0,0 +1,91 @@
+#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 HeuristicLab.Operators;
+using HeuristicLab.Functions;
+using HeuristicLab.DataAnalysis;
+
+namespace HeuristicLab.StructureIdentification {
+  public class MCCEvaluator : GPEvaluatorBase {
+    public override string Description {
+      get {
+        return @"TASK";
+      }
+    }
+
+    public MCCEvaluator()
+      : base() {
+      AddVariableInfo(new VariableInfo("ClassSeparation", "The value of separation between negative and positive target classification values (for instance 0.5 if negative=0 and positive=1).", typeof(DoubleData), VariableKind.In));
+    }
+
+    private double[] original = new double[1];
+    private double[] estimated = new double[1];
+    public override double Evaluate(IScope scope, IFunctionTree functionTree, int targetVariable, Dataset dataset) {
+      double limit = GetVariableValue<DoubleData>("ClassSeparation", scope, false).Data;
+      if(estimated.Length != dataset.Rows) {
+        estimated = new double[dataset.Rows];
+        original = new double[dataset.Rows];
+      }
+      double positive = 0;
+      double negative = 0;
+      double targetMean = dataset.GetMean(targetVariable);
+      for(int sample = 0; sample < dataset.Rows; sample++) {
+        double est = functionTree.Evaluate(dataset, sample);
+        double orig = dataset.GetValue(sample, targetVariable);
+        if(double.IsNaN(est) || double.IsInfinity(est)) {
+          est = targetMean + maximumPunishment;
+        } else if(est > targetMean + maximumPunishment) {
+          est = targetMean + maximumPunishment;
+        } else if(est < targetMean - maximumPunishment) {
+          est = targetMean - maximumPunishment;
+        }
+        estimated[sample] = est;
+        original[sample] = orig;
+        if(orig >= limit) positive++;
+        else negative++;
+      }
+      Array.Sort(estimated, original);
+      double best_mcc = -1.0;
+      double tp = 0;
+      double fn = positive;
+      double tn = negative;
+      double fp = 0;
+      for(int i = original.Length-1; i >= 0 ; i--) {
+        if(original[i] >= limit) {
+          tp++; fn--;
+        } else {
+          tn--; fp++;
+        }
+        double mcc = (tp * tn - fp * fn) / Math.Sqrt(positive * (tp + fn) * (tn + fp) * negative);
+        if(best_mcc < mcc) {
+          best_mcc = mcc;
+        }
+      }
+      return best_mcc;
+    }
+  }
+}
Index: /branches/ExperimentalStructureIdentification/Evaluation/MeanSquaredErrorEvaluator.cs
===================================================================
--- /branches/ExperimentalStructureIdentification/Evaluation/MeanSquaredErrorEvaluator.cs	(revision 204)
+++ /branches/ExperimentalStructureIdentification/Evaluation/MeanSquaredErrorEvaluator.cs	(revision 204)
@@ -0,0 +1,70 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Functions;
+using HeuristicLab.DataAnalysis;
+
+namespace HeuristicLab.StructureIdentification {
+  public class MeanSquaredErrorEvaluator : GPEvaluatorBase {
+    public override string Description {
+      get {
+        return @"Evaluates 'FunctionTree' for all samples of 'DataSet' and calculates the mean-squared-error
+for the estimated values vs. the real values of 'TargetVariable'.";
+      }
+    }
+
+    public MeanSquaredErrorEvaluator()
+      : base() {
+    }
+
+    public override double Evaluate(IScope scope, IFunctionTree functionTree, int targetVariable, Dataset dataset) {
+      double errorsSquaredSum = 0;
+      double targetMean = dataset.GetMean(targetVariable);
+      for(int sample = 0; sample < dataset.Rows; sample++) {
+
+        double estimated = functionTree.Evaluate(dataset, sample);
+        double original = dataset.GetValue(sample, targetVariable);
+        if(double.IsNaN(estimated) || double.IsInfinity(estimated)) {
+          estimated = targetMean + maximumPunishment;
+        } else if(estimated > targetMean + maximumPunishment) {
+          estimated = targetMean + maximumPunishment;
+        } else if(estimated < targetMean - maximumPunishment) {
+          estimated = targetMean - maximumPunishment;
+        }
+        double error = estimated - original;
+        errorsSquaredSum += error * error;
+      }
+      errorsSquaredSum /= dataset.Rows;
+      if(double.IsNaN(errorsSquaredSum) || double.IsInfinity(errorsSquaredSum)) {
+        errorsSquaredSum = double.MaxValue;
+      }
+      scope.GetVariableValue<DoubleData>("TotalEvaluatedNodes", true).Data = totalEvaluatedNodes + treeSize * dataset.Rows;
+      return errorsSquaredSum;
+    }
+  }
+}
Index: /branches/ExperimentalStructureIdentification/Evaluation/VarianceAccountedForEvaluator.cs
===================================================================
--- /branches/ExperimentalStructureIdentification/Evaluation/VarianceAccountedForEvaluator.cs	(revision 204)
+++ /branches/ExperimentalStructureIdentification/Evaluation/VarianceAccountedForEvaluator.cs	(revision 204)
@@ -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.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.DataAnalysis;
+using HeuristicLab.Functions;
+
+namespace HeuristicLab.StructureIdentification {
+  public class VarianceAccountedForEvaluator : GPEvaluatorBase {
+    public override string Description {
+      get {
+        return @"Evaluates 'FunctionTree' for all samples of 'DataSet' and calculates 
+the variance-accounted-for quality measure for the estimated values vs. the real values of 'TargetVariable'.
+
+The Variance Accounted For (VAF) function is computed as
+VAF(y,y') = ( 1 - var(y-y')/var(y) )
+where y' denotes the predicted / modelled values for y and var(x) the variance of a signal x.";
+      }
+    }
+
+    /// <summary>
+    /// The Variance Accounted For (VAF) function calculates is computed as
+    /// VAF(y,y') = ( 1 - var(y-y')/var(y) )
+    /// where y' denotes the predicted / modelled values for y and var(x) the variance of a signal x.
+    /// </summary>
+    public VarianceAccountedForEvaluator()
+      : base() {
+    }
+
+
+    public override double Evaluate(IScope scope, IFunctionTree functionTree, int targetVariable, Dataset dataset) {
+      double[] errors = new double[dataset.Rows];
+      double[] originalTargetVariableValues = new double[dataset.Rows];
+      double targetMean = dataset.GetMean(targetVariable);
+      for(int sample = 0; sample < dataset.Rows; sample++) {
+        double estimated = functionTree.Evaluate(dataset, sample);
+        double original = dataset.GetValue(sample, targetVariable);
+        if(!double.IsNaN(original) && !double.IsInfinity(original)) {
+          if(double.IsNaN(estimated) || double.IsInfinity(estimated))
+            estimated = targetMean + maximumPunishment;
+          else if(estimated > (targetMean + maximumPunishment))
+            estimated = targetMean + maximumPunishment;
+          else if(estimated < (targetMean - maximumPunishment))
+            estimated = targetMean - maximumPunishment;
+        }
+
+        errors[sample] = original - estimated;
+        originalTargetVariableValues[sample] = original;
+      }
+
+      double errorsVariance = Statistics.Variance(errors);
+      double originalsVariance = Statistics.Variance(originalTargetVariableValues);
+      double quality = 1 - errorsVariance / originalsVariance;
+
+      if(double.IsNaN(quality) || double.IsInfinity(quality)) {
+        quality = double.MaxValue;
+      }
+      return quality;
+    }
+  }
+}
Index: /branches/ExperimentalStructureIdentification/GPOperatorGroup.cs
===================================================================
--- /branches/ExperimentalStructureIdentification/GPOperatorGroup.cs	(revision 204)
+++ /branches/ExperimentalStructureIdentification/GPOperatorGroup.cs	(revision 204)
@@ -0,0 +1,324 @@
+#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.StructureIdentification {
+  public class GPOperatorGroup : OperatorGroup {
+    public GPOperatorGroup()
+      : base() {
+    }
+
+    public override void AddOperator(IOperator op) {
+      base.AddOperator(op);
+
+      var localVariableInfos = op.VariableInfos.Where(f => f.Local);
+
+      if(op.GetVariable(GPOperatorLibrary.MANIPULATION) == null) {
+        CombinedOperator manipulationOperator = new CombinedOperator();
+        SequentialProcessor manipulationSequence = new SequentialProcessor();
+        foreach(IVariableInfo variableInfo in localVariableInfos) {
+          IOperator manipulator = GetDefaultManipulationOperator(variableInfo);
+          if (manipulator != null) {
+            manipulationSequence.AddSubOperator(manipulator);
+          }
+        }
+        if(manipulationSequence.SubOperators.Count > 0) {
+          op.AddVariable(new Variable(GPOperatorLibrary.MANIPULATION, manipulationOperator));
+
+          manipulationOperator.OperatorGraph.AddOperator(manipulationSequence);
+          manipulationOperator.OperatorGraph.InitialOperator = manipulationSequence;
+          foreach(IOperator subOp in manipulationSequence.SubOperators) {
+            manipulationOperator.OperatorGraph.AddOperator(subOp);
+          }
+        }
+      }
+
+      if(op.GetVariable(GPOperatorLibrary.INITIALIZATION) == null) {
+        CombinedOperator initOperator = new CombinedOperator();
+        SequentialProcessor initSequence = new SequentialProcessor();
+        foreach(IVariableInfo variableInfo in localVariableInfos) {
+          IOperator initializer = GetDefaultInitOperator(variableInfo);
+          if (initializer != null) {
+            initSequence.AddSubOperator(initializer);
+          }
+        }
+        if(initSequence.SubOperators.Count > 0) {
+          op.AddVariable(new Variable(GPOperatorLibrary.INITIALIZATION, initOperator));
+          initOperator.OperatorGraph.AddOperator(initSequence);
+          initOperator.OperatorGraph.InitialOperator = initSequence;
+          foreach(IOperator subOp in initSequence.SubOperators) {
+            initOperator.OperatorGraph.AddOperator(subOp);
+          }
+        }
+      }
+
+      // add a new typeid if necessary
+      if(op.GetVariable(GPOperatorLibrary.TYPE_ID) == null) {
+        op.AddVariable(new Variable(GPOperatorLibrary.TYPE_ID, new StringData(Guid.NewGuid().ToString())));
+      }
+
+      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.ALLOWED_SUBOPERATORS) == null) {
+        op.AddVariable(new Variable(GPOperatorLibrary.ALLOWED_SUBOPERATORS, new ItemList()));
+      }
+      if(op.GetVariable(GPOperatorLibrary.TICKETS) == null) {
+        op.AddVariable(new Variable(GPOperatorLibrary.TICKETS, new DoubleData(1.0)));
+      }
+
+      RecalculateAllowedSuboperators();
+      RecalculateMinimalTreeBounds();
+
+      OnOperatorAdded(op);
+    }
+
+
+    private Dictionary<string, int> minTreeHeight = new Dictionary<string, int>();
+    private Dictionary<string, int> minTreeSize = new Dictionary<string, int>();
+    private SubOperatorsConstraintAnalyser constraintAnalyser = new SubOperatorsConstraintAnalyser();
+
+    private void RecalculateAllowedSuboperators() {
+      foreach(IOperator op in Operators) {
+        RecalculateAllowedSuboperators(op);
+      }
+    }
+
+    private void RecalculateAllowedSuboperators(IOperator op) {
+      constraintAnalyser.AllPossibleOperators = Operators;
+      int minArity;
+      int maxArity;
+      GetMinMaxArity(op, out minArity, out maxArity);
+      var slotsList = (ItemList)op.GetVariable(GPOperatorLibrary.ALLOWED_SUBOPERATORS).Value;
+      slotsList.Clear();
+      for(int i = 0; i < maxArity; i++) {
+        ItemList slotList = new ItemList();
+        foreach(IOperator allowedOp in constraintAnalyser.GetAllowedOperators(op, i)) {
+          slotList.Add(allowedOp);
+        }
+        slotsList.Add(slotList);
+      }
+    }
+
+
+    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) {
+      string typeId = GetTypeId(op);
+      // check for memoized value
+      if(minTreeSize.ContainsKey(typeId)) {
+        return minTreeSize[typeId];
+      }
+
+      int minArity;
+      int maxArity;
+      GetMinMaxArity(op, out minArity, out maxArity);
+      // no suboperators possible => minimalTreeSize == 1 (the current node)
+      if(minArity == 0 && maxArity == 0) {
+        minTreeSize[typeId] = 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[typeId] = 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[typeId] = subTreeSizeSum + 1;
+      return subTreeSizeSum + 1;
+    }
+
+
+    private int RecalculateMinimalTreeHeight(IOperator op) {
+      string typeId = GetTypeId(op);
+      // check for memoized value
+      if(minTreeHeight.ContainsKey(typeId)) {
+        return minTreeHeight[typeId];
+      }
+
+      int minArity;
+      int maxArity;
+      GetMinMaxArity(op, out minArity, out maxArity);
+      // no suboperators possible => minimalTreeHeight == 1
+      if(minArity == 0 && maxArity == 0) {
+        minTreeHeight[typeId] = 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[typeId] = 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[typeId] = 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;
+    }
+
+    private string GetTypeId(IOperator op) {
+      return ((StringData)op.GetVariable(GPOperatorLibrary.TYPE_ID).Value).Data;
+    }
+
+
+    private IOperator GetDefaultManipulationOperator(IVariableInfo variableInfo) {
+      IOperator shaker;
+      if(variableInfo.DataType == typeof(ConstrainedDoubleData) ||
+        variableInfo.DataType == typeof(ConstrainedIntData) ||
+        variableInfo.DataType == typeof(DoubleData) ||
+        variableInfo.DataType == typeof(IntData)) {
+        shaker = new NormalRandomAdder();
+      } else {
+        return null;
+      }
+      shaker.GetVariableInfo("Value").ActualName = variableInfo.FormalName;
+      shaker.Name = variableInfo.FormalName + " manipulation";
+      return shaker;
+    }
+
+    private IOperator GetDefaultInitOperator(IVariableInfo variableInfo) {
+      IOperator shaker;
+      if(variableInfo.DataType == typeof(ConstrainedDoubleData) ||
+        variableInfo.DataType == typeof(ConstrainedIntData) ||
+        variableInfo.DataType == typeof(DoubleData) ||
+        variableInfo.DataType == typeof(IntData)) {
+        shaker = new UniformRandomizer();
+      } else {
+        return null;
+      }
+      shaker.GetVariableInfo("Value").ActualName = variableInfo.FormalName;
+      shaker.Name = variableInfo.FormalName + " initialization";
+      return shaker;
+    }
+
+    public override void AddSubGroup(IOperatorGroup group) {
+      throw new NotSupportedException();
+    }
+
+    public override void RemoveOperator(IOperator op) {
+      base.RemoveOperator(op);
+      op.RemoveVariable(GPOperatorLibrary.MANIPULATION);
+      op.RemoveVariable(GPOperatorLibrary.INITIALIZATION);
+      op.RemoveVariable(GPOperatorLibrary.TYPE_ID);
+      op.RemoveVariable(GPOperatorLibrary.MIN_TREE_SIZE);
+      op.RemoveVariable(GPOperatorLibrary.MIN_TREE_HEIGHT);
+      op.RemoveVariable(GPOperatorLibrary.ALLOWED_SUBOPERATORS);
+      op.RemoveVariable(GPOperatorLibrary.TICKETS);
+
+      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/ExperimentalStructureIdentification/GPOperatorLibrary.cs
===================================================================
--- /branches/ExperimentalStructureIdentification/GPOperatorLibrary.cs	(revision 204)
+++ /branches/ExperimentalStructureIdentification/GPOperatorLibrary.cs	(revision 204)
@@ -0,0 +1,90 @@
+#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.StructureIdentification {
+  public class GPOperatorLibrary : ItemBase, IOperatorLibrary, IEditable  {
+    // constants for variable names
+    internal const string MANIPULATION = "Manipulation";
+    internal const string INITIALIZATION = "Initialization";
+    internal const string TYPE_ID = "TypeId";
+    internal const string MIN_TREE_HEIGHT = "MinTreeHeight";
+    internal const string MIN_TREE_SIZE = "MinTreeSize";
+    internal const string ALLOWED_SUBOPERATORS = "AllowedSuboperators";
+    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/ExperimentalStructureIdentification/GPOperatorLibraryEditor.Designer.cs
===================================================================
--- /branches/ExperimentalStructureIdentification/GPOperatorLibraryEditor.Designer.cs	(revision 204)
+++ /branches/ExperimentalStructureIdentification/GPOperatorLibraryEditor.Designer.cs	(revision 204)
@@ -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.StructureIdentification {
+  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.mutationVariableView = new HeuristicLab.Core.VariableView();
+      this.mutationListView = new System.Windows.Forms.ListView();
+      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;
+      // 
+      // 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;
+      // 
+      // 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);
+      // 
+      // 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/ExperimentalStructureIdentification/GPOperatorLibraryEditor.cs
===================================================================
--- /branches/ExperimentalStructureIdentification/GPOperatorLibraryEditor.cs	(revision 204)
+++ /branches/ExperimentalStructureIdentification/GPOperatorLibraryEditor.cs	(revision 204)
@@ -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.StructureIdentification {
+  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(GPOperatorLibrary.MANIPULATION) != null) {
+          ListViewItem item = new ListViewItem();
+          item.Text = op.Name;
+          item.Name = op.Name;
+          item.Tag = op;
+          mutationListView.Items.Add(item);
+        }
+        if(op.GetVariable(GPOperatorLibrary.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(GPOperatorLibrary.MANIPULATION) != null) {
+        ListViewItem operatorMutationItem = new ListViewItem();
+        operatorMutationItem.Name = op.Name;
+        operatorMutationItem.Text = op.Name;
+        operatorMutationItem.Tag = op;
+        mutationListView.Items.Add(operatorMutationItem);
+      }
+
+      if (op.GetVariable(GPOperatorLibrary.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(GPOperatorLibrary.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(GPOperatorLibrary.INITIALIZATION);
+        initVariableView.Enabled = true;
+        initVariableView.Variable = variable;
+      } else {
+        initVariableView.Enabled = false;
+      }
+    }
+  }
+}
Index: /branches/ExperimentalStructureIdentification/GPOperatorLibraryEditor.resx
===================================================================
--- /branches/ExperimentalStructureIdentification/GPOperatorLibraryEditor.resx	(revision 204)
+++ /branches/ExperimentalStructureIdentification/GPOperatorLibraryEditor.resx	(revision 204)
@@ -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/ExperimentalStructureIdentification/HeuristicLab.StructureIdentification.csproj
===================================================================
--- /branches/ExperimentalStructureIdentification/HeuristicLab.StructureIdentification.csproj	(revision 204)
+++ /branches/ExperimentalStructureIdentification/HeuristicLab.StructureIdentification.csproj	(revision 204)
@@ -0,0 +1,146 @@
+﻿<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.21022</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{5948F299-0A5E-43B9-8F17-2D15298EEC34}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.StructureIdentification</RootNamespace>
+    <AssemblyName>HeuristicLab.StructureIdentification</AssemblyName>
+    <SignAssembly>true</SignAssembly>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <OldToolsVersion>2.0</OldToolsVersion>
+    <UpgradeBackupLocation>
+    </UpgradeBackupLocation>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+  </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>
+    <DocumentationFile>bin\Release\HeuristicLab.StructureIdentification.XML</DocumentationFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.XML" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Evaluation\CoefficientOfDeterminationEvaluator.cs" />
+    <Compile Include="Evaluation\MCCEvaluator.cs" />
+    <Compile Include="Evaluation\GPEvaluatorBase.cs" />
+    <Compile Include="Evaluation\EarlyStoppingMeanSquaredErrorEvaluator.cs" />
+    <Compile Include="Evaluation\MeanSquaredErrorEvaluator.cs" />
+    <Compile Include="Evaluation\VarianceAccountedForEvaluator.cs" />
+    <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="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="HeuristicLabStructureIdentificationPlugin.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="RandomTreeCreator.cs" />
+    <Compile Include="Recombination\SizeFairCrossOver.cs" />
+    <Compile Include="TreeGardener.cs" />
+    <Compile Include="StructIdProblemInjector.cs" />
+    <Compile Include="StructIdProblemInjectorView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="StructIdProblemInjectorView.Designer.cs">
+      <DependentUpon>StructIdProblemInjectorView.cs</DependentUpon>
+    </Compile>
+  </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.DataAnalysis\HeuristicLab.DataAnalysis.csproj">
+      <Project>{7DD3A97A-56E9-462F-90E2-A351FE7AF5C2}</Project>
+      <Name>HeuristicLab.DataAnalysis</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\HeuristicLab.Data\HeuristicLab.Data.csproj">
+      <Project>{F473D9AF-3F09-4296-9F28-3C65118DAFFA}</Project>
+      <Name>HeuristicLab.Data</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\HeuristicLab.Functions\HeuristicLab.Functions.csproj">
+      <Project>{B95CA6E2-34BC-4430-994D-BD6E99375319}</Project>
+      <Name>HeuristicLab.Functions</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>
+    <None Include="HeuristicLab.snk" />
+    <None Include="Properties\AssemblyInfo.frame" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="GPOperatorLibraryEditor.resx">
+      <DependentUpon>GPOperatorLibraryEditor.cs</DependentUpon>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+    <EmbeddedResource Include="StructIdProblemInjectorView.resx">
+      <DependentUpon>StructIdProblemInjectorView.cs</DependentUpon>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\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>cmd /c ..\..\..\PreBuildEvent.cmd</PreBuildEvent>
+  </PropertyGroup>
+</Project>
Index: /branches/ExperimentalStructureIdentification/HeuristicLabStructureIdentificationPlugin.cs
===================================================================
--- /branches/ExperimentalStructureIdentification/HeuristicLabStructureIdentificationPlugin.cs	(revision 204)
+++ /branches/ExperimentalStructureIdentification/HeuristicLabStructureIdentificationPlugin.cs	(revision 204)
@@ -0,0 +1,40 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.StructureIdentification {
+  [ClassInfo(Name = "HeuristicLab.StructureIdentification")]
+  [PluginFile(Filename = "HeuristicLab.StructureIdentification.dll", Filetype = PluginFileType.Assembly)]
+  [Dependency(Dependency = "HeuristicLab.Constraints")]
+  [Dependency(Dependency = "HeuristicLab.Core")]
+  [Dependency(Dependency = "HeuristicLab.Data")]
+  [Dependency(Dependency = "HeuristicLab.DataAnalysis")]
+  [Dependency(Dependency = "HeuristicLab.Functions")]
+  [Dependency(Dependency = "HeuristicLab.Operators")]
+  [Dependency(Dependency = "HeuristicLab.Selection")]
+  [Dependency(Dependency = "HeuristicLab.Random")]
+  public class HeuristicLabStructureIdentificationPlugin : PluginBase {
+  }
+}
Index: /branches/ExperimentalStructureIdentification/Manipulation/ChangeNodeTypeManipulation.cs
===================================================================
--- /branches/ExperimentalStructureIdentification/Manipulation/ChangeNodeTypeManipulation.cs	(revision 204)
+++ /branches/ExperimentalStructureIdentification/Manipulation/ChangeNodeTypeManipulation.cs	(revision 204)
@@ -0,0 +1,194 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Random;
+using HeuristicLab.Data;
+using HeuristicLab.Constraints;
+using HeuristicLab.Functions;
+
+namespace HeuristicLab.StructureIdentification {
+  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
+        }
+        if(!gardener.IsValidTree(root)) throw new InvalidProgramException();
+        // 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 = gardener.GetTreeSize(selectedChild);
+        int oldChildHeight = gardener.GetTreeSize(selectedChild);
+        int newChildSize = gardener.GetTreeSize(newFunctionTree);
+        int newChildHeight = gardener.GetTreeHeight(newFunctionTree);
+        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 = gardener.GetTreeHeight(root); // must recalculate height because we can't know wether the manipulated branch was the deepest branch
+        // check if whole tree is ok
+        if(!gardener.IsValidTree(root))
+          throw new InvalidProgramException();
+        // 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;
+      // arity of the selected operator
+      int minArity;
+      int maxArity;
+      // create a new tree-node for a randomly selected function
+      IFunction selectedFunction = allowedFunctions[random.Next(allowedFunctions.Count)];
+      gardener.GetMinMaxArity(selectedFunction, 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
+      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/ExperimentalStructureIdentification/Manipulation/CutOutNodeManipulation.cs
===================================================================
--- /branches/ExperimentalStructureIdentification/Manipulation/CutOutNodeManipulation.cs	(revision 204)
+++ /branches/ExperimentalStructureIdentification/Manipulation/CutOutNodeManipulation.cs	(revision 204)
@@ -0,0 +1,139 @@
+#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 HeuristicLab.Functions;
+
+namespace HeuristicLab.StructureIdentification {
+  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 = gardener.GetTreeSize(root);
+          GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(root);
+          // update the variable
+          scope.GetVariable(scope.TranslateName("FunctionTree")).Value = root;
+          if (!gardener.IsValidTree(root)) {
+            throw new InvalidProgramException();
+          }
+          // 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 = gardener.GetTreeSize(newTree);
+          GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(newTree);
+          // update the variable
+          scope.GetVariable(scope.TranslateName("FunctionTree")).Value = newTree;
+          if (!gardener.IsValidTree(newTree)) {
+            throw new InvalidProgramException();
+          }
+          // 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);
+        if (!gardener.IsValidTree(root)) {
+          throw new InvalidProgramException();
+        }
+        // update the size and height of our tree
+        GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(root);
+        GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(root);
+        // 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 = gardener.GetTreeSize(root);
+        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 = gardener.GetTreeSize(root);
+        GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(root);
+        if (!gardener.IsValidTree(root)) {
+          throw new InvalidProgramException();
+        }
+        // schedule an initialization operation for the new function-tree
+        return gardener.CreateInitializationOperation(gardener.GetAllSubTrees(newFunctionTree), scope);
+      }
+    }
+  }
+}
Index: /branches/ExperimentalStructureIdentification/Manipulation/DeleteSubTreeManipulation.cs
===================================================================
--- /branches/ExperimentalStructureIdentification/Manipulation/DeleteSubTreeManipulation.cs	(revision 204)
+++ /branches/ExperimentalStructureIdentification/Manipulation/DeleteSubTreeManipulation.cs	(revision 204)
@@ -0,0 +1,112 @@
+#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 HeuristicLab.Functions;
+
+namespace HeuristicLab.StructureIdentification {
+  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
+        if(!gardener.IsValidTree(newTree)) {
+          throw new InvalidOperationException();
+        }
+        // update sizes to match the new tree
+        GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(newTree);
+        GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(newTree);
+        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);
+      int min;
+      int max;
+      gardener.GetMinMaxArity(parent.Function, out min, out max);
+      if(parent.SubTrees.Count > min) {
+        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)
+
+        if(!gardener.IsValidTree(root)) {
+          throw new InvalidOperationException();
+        }
+        GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(root);
+        GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(root);
+        // 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);
+        if(!gardener.IsValidTree(root)) {
+          throw new InvalidProgramException();
+        }
+        GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(root);
+        GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(root);
+        // 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/ExperimentalStructureIdentification/Manipulation/FullTreeShaker.cs
===================================================================
--- /branches/ExperimentalStructureIdentification/Manipulation/FullTreeShaker.cs	(revision 204)
+++ /branches/ExperimentalStructureIdentification/Manipulation/FullTreeShaker.cs	(revision 204)
@@ -0,0 +1,88 @@
+#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;
+using HeuristicLab.Functions;
+
+namespace HeuristicLab.StructureIdentification {
+  public class FullTreeShaker : DelegatingOperator {
+    public override string Description {
+      get { return "Manipulates all tree nodes for which a '"+GPOperatorLibrary.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 = true;
+
+      Scope tempScope = new Scope("Temp. manipulation scope");
+
+      TreeGardener gardener = new TreeGardener(mt, library);
+      var parametricBranches = gardener.GetAllSubTrees(tree).Where(branch => branch.Function.GetVariable(GPOperatorLibrary.MANIPULATION) != null);
+      foreach(IFunctionTree subTree in parametricBranches) {
+        IOperator mutation =(IOperator)subTree.Function.GetVariable(GPOperatorLibrary.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/ExperimentalStructureIdentification/Manipulation/OnePointShaker.cs
===================================================================
--- /branches/ExperimentalStructureIdentification/Manipulation/OnePointShaker.cs	(revision 204)
+++ /branches/ExperimentalStructureIdentification/Manipulation/OnePointShaker.cs	(revision 204)
@@ -0,0 +1,82 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using 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;
+using HeuristicLab.Functions;
+
+namespace HeuristicLab.StructureIdentification {
+  public class OnePointShaker : DelegatingOperator {
+    public override string Description {
+      get { return "Selects a random node of all tree-nodes that have a '"+GPOperatorLibrary.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(GPOperatorLibrary.MANIPULATION) != null);
+      IFunctionTree selectedBranch = parametricBranches.ElementAt(mt.Next(parametricBranches.Count()));
+      IOperator mutation = (IOperator)selectedBranch.Function.GetVariable(GPOperatorLibrary.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/ExperimentalStructureIdentification/Manipulation/SubstituteSubTreeManipulation.cs
===================================================================
--- /branches/ExperimentalStructureIdentification/Manipulation/SubstituteSubTreeManipulation.cs	(revision 204)
+++ /branches/ExperimentalStructureIdentification/Manipulation/SubstituteSubTreeManipulation.cs	(revision 204)
@@ -0,0 +1,109 @@
+#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 HeuristicLab.Functions;
+
+namespace HeuristicLab.StructureIdentification {
+  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);
+        if(!gardener.IsValidTree(newTree)) {
+          throw new InvalidProgramException();
+        }
+
+        // update the variables in the scope with the new values
+        GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(newTree);
+        GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(newTree);
+        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 - gardener.GetTreeSize(parent.SubTrees[childIndex]));
+
+        // create a random function tree
+        IFunctionTree newTree = gardener.CreateRandomTree(allowedFunctions, maxSubTreeSize, maxSubTreeHeight);
+        parent.RemoveSubTree(childIndex);
+        parent.InsertSubTree(childIndex, newTree);
+
+        if(!gardener.IsValidTree(root)) {
+          throw new InvalidProgramException();
+        }
+
+        // update the values of treeSize and treeHeight
+        GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(root);
+        GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(root);
+        // 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/ExperimentalStructureIdentification/Properties/AssemblyInfo.frame
===================================================================
--- /branches/ExperimentalStructureIdentification/Properties/AssemblyInfo.frame	(revision 204)
+++ /branches/ExperimentalStructureIdentification/Properties/AssemblyInfo.frame	(revision 204)
@@ -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.StructureIdentification")]
+[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("ca7d6d59-76a3-4dc3-8a90-dafadec08959")]
+
+// 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.0.0.$WCREV$")]
+[assembly: AssemblyFileVersion("3.0.0.$WCREV$")]
+[assembly: AssemblyBuildDate("$WCNOW$")]
Index: /branches/ExperimentalStructureIdentification/RandomTreeCreator.cs
===================================================================
--- /branches/ExperimentalStructureIdentification/RandomTreeCreator.cs	(revision 204)
+++ /branches/ExperimentalStructureIdentification/RandomTreeCreator.cs	(revision 204)
@@ -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 HeuristicLab.Functions;
+
+namespace HeuristicLab.StructureIdentification {
+  public class RandomTreeCreator : OperatorBase {
+    public override string Description {
+      get { return @"Generates a new random operator tree."; }
+    }
+
+    public RandomTreeCreator()
+      : 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("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 maxTreeHeight = GetVariableValue<IntData>("MaxTreeHeight", scope, true).Data;
+      int maxTreeSize = GetVariableValue<IntData>("MaxTreeSize", scope, true).Data;
+      double balancedTreesRate = GetVariableValue<DoubleData>("BalancedTreesRate", scope, true).Data;
+
+      TreeGardener gardener = new TreeGardener(random, opLibrary);
+
+      int treeHeight = random.Next(1, maxTreeHeight + 1);
+      int treeSize = random.Next(1, maxTreeSize + 1);
+      IFunctionTree root;
+      if(random.NextDouble() <= balancedTreesRate) {
+        root = gardener.CreateBalancedRandomTree(treeSize, treeHeight);
+      } else {
+        root = gardener.CreateBalancedRandomTree(treeSize, treeHeight);
+      }
+
+      int actualTreeSize = gardener.GetTreeSize(root);
+      int actualTreeHeight = gardener.GetTreeHeight(root);
+
+      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)));
+
+      if(!gardener.IsValidTree(root)) { throw new InvalidProgramException(); }
+
+      if(actualTreeSize > maxTreeSize ||
+        actualTreeHeight > maxTreeHeight) {
+        throw new InvalidProgramException();
+      }
+
+      return gardener.CreateInitializationOperation(gardener.GetAllSubTrees(root), scope);
+    }
+  }
+}
Index: /branches/ExperimentalStructureIdentification/Recombination/SizeFairCrossOver.cs
===================================================================
--- /branches/ExperimentalStructureIdentification/Recombination/SizeFairCrossOver.cs	(revision 204)
+++ /branches/ExperimentalStructureIdentification/Recombination/SizeFairCrossOver.cs	(revision 204)
@@ -0,0 +1,274 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Random;
+using HeuristicLab.Data;
+using HeuristicLab.Constraints;
+using HeuristicLab.Functions;
+
+namespace HeuristicLab.StructureIdentification {
+  public class SizeFairCrossOver : OperatorBase {
+
+    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 root 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 the operator randomly either goes
+up in P0 (parent of N0) or down in P1 (random child of N1) until a valid configuration is found.";
+      }
+    }
+    public SizeFairCrossOver()
+      : base() {
+      AddVariableInfo(new VariableInfo("Random", "Pseudo random number generator", typeof(MersenneTwister), VariableKind.In));
+      AddVariableInfo(new VariableInfo("OperatorLibrary", "The operator library containing all available operators", typeof(GPOperatorLibrary), VariableKind.In));
+      AddVariableInfo(new VariableInfo("MaxTreeHeight", "The maximal allowed height of the tree", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("MaxTreeSize", "The maximal allowed size (number of nodes) of the tree", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("FunctionTree", "The tree to mutate", typeof(IFunctionTree), VariableKind.In | VariableKind.New));
+      AddVariableInfo(new VariableInfo("TreeSize", "The size (number of nodes) of the tree", typeof(IntData), VariableKind.New));
+      AddVariableInfo(new VariableInfo("TreeHeight", "The height of the tree", typeof(IntData), VariableKind.New));
+    }
+
+    public override IOperation Apply(IScope scope) {
+      MersenneTwister random = GetVariableValue<MersenneTwister>("Random", scope, true);
+      GPOperatorLibrary opLibrary = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", scope, true);
+      int maxTreeHeight = GetVariableValue<IntData>("MaxTreeHeight", scope, true).Data;
+      int maxTreeSize = GetVariableValue<IntData>("MaxTreeSize", scope, true).Data;
+
+      TreeGardener gardener = new TreeGardener(random, opLibrary);
+
+      if((scope.SubScopes.Count % 2) != 0)
+        throw new InvalidOperationException("Number of parents is not even");
+
+      CompositeOperation initOperations = new CompositeOperation();
+
+      int children = scope.SubScopes.Count / 2;
+      for(int i = 0; i < children; i++) {
+        IScope parent1 = scope.SubScopes[0];
+        scope.RemoveSubScope(parent1);
+        IScope parent2 = scope.SubScopes[0];
+        scope.RemoveSubScope(parent2);
+        IScope child = new Scope(i.ToString());
+        IOperation childInitOperation = Cross(gardener, maxTreeSize, maxTreeHeight, scope, random, parent1, parent2, child);
+        initOperations.AddOperation(childInitOperation);
+        scope.AddSubScope(child);
+      }
+
+      return initOperations;
+    }
+
+    private IOperation Cross(TreeGardener gardener, int maxTreeSize, int maxTreeHeight,
+      IScope scope, MersenneTwister random, IScope parent1, IScope parent2, IScope child) {
+      List<IFunctionTree> newBranches;
+      IFunctionTree newTree = Cross(gardener, parent1, parent2,
+        random, maxTreeSize, maxTreeHeight, out newBranches);
+
+
+      int newTreeSize = gardener.GetTreeSize(newTree);
+      int newTreeHeight = gardener.GetTreeHeight(newTree);
+      child.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("FunctionTree"), newTree));
+      child.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeSize"), new IntData(newTreeSize)));
+      child.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeHeight"), new IntData(newTreeHeight)));
+
+      // check if the new tree is valid and if the size of is still in the allowed bounds
+      if(!gardener.IsValidTree(newTree) ||
+        newTreeHeight > maxTreeHeight ||
+        newTreeSize > maxTreeSize) {
+        throw new InvalidProgramException();
+      }
+      return gardener.CreateInitializationOperation(newBranches, child);
+    }
+
+
+    private IFunctionTree Cross(TreeGardener gardener, IScope f, IScope g, MersenneTwister random, int maxTreeSize, int maxTreeHeight, out List<IFunctionTree> newBranches) {
+      IFunctionTree tree0 = f.GetVariableValue<IFunctionTree>("FunctionTree", false);
+      int tree0Height = f.GetVariableValue<IntData>("TreeHeight", false).Data;
+      int tree0Size = f.GetVariableValue<IntData>("TreeSize", false).Data;
+
+      IFunctionTree tree1 = g.GetVariableValue<IFunctionTree>("FunctionTree", false);
+      int tree1Height = g.GetVariableValue<IntData>("TreeHeight", false).Data;
+      int tree1Size = g.GetVariableValue<IntData>("TreeSize", false).Data;
+
+      if(tree0Size == 1 && tree1Size == 1) {
+        return CombineTerminals(gardener, tree0, tree1, random, maxTreeHeight, out newBranches);
+      } else {
+        // we are going to insert tree1 into tree0 at a random place so we have to make sure that tree0 is not a terminal
+        // in case both trees are higher than 1 we swap the trees with probability 50%
+        if(tree0Height == 1 || (tree1Height > 1 && random.Next(2) == 0)) {
+          IFunctionTree tmp = tree0; tree0 = tree1; tree1 = tmp;
+          int tmpHeight = tree0Height; tree0Height = tree1Height; tree1Height = tmpHeight;
+          int tmpSize = tree0Size; tree0Size = tree1Size; tree1Size = tmpSize;
+        }
+
+        // save the root because later on we change tree0 and tree1 while searching a valid tree configuration
+        IFunctionTree root = tree0;
+        int rootSize = tree0Size;
+
+        // select a random suboperators of the two trees at a random level
+        int tree0Level = random.Next(tree0Height - 1); // since we checked before that the height of tree0 is > 1 this is OK
+        int tree1Level = random.Next(tree1Height);
+        tree0 = gardener.GetRandomBranch(tree0, tree0Level);
+        tree1 = gardener.GetRandomBranch(tree1, tree1Level);
+
+        // recalculate the size and height of tree1 (the one that we want to insert) because we need to check constraints later on
+        tree1Size = gardener.GetTreeSize(tree1);
+        tree1Height = gardener.GetTreeHeight(tree1);
+
+        List<int> possibleChildIndices = new List<int>();
+
+        // Now tree0 is supposed to take tree1 as one if its children. If this is not possible,
+        // then go down in either of the two trees as far as possible. If even then it is not possible
+        // to merge the trees then throw an exception
+        // find the list of allowed indices (regarding allowed sub-trees, maxTreeSize and maxTreeHeight)
+        for(int i = 0; i < tree0.SubTrees.Count; i++) {
+          int subTreeSize = gardener.GetTreeSize(tree0.SubTrees[i]);
+
+          // the index is ok when the function is allowed as sub-tree and we don't violate the maxSize and maxHeight constraints
+          if(gardener.GetAllowedSubFunctions(tree0.Function, i).Contains(tree1.Function) &&
+            rootSize - subTreeSize + tree1Size < maxTreeSize &&
+            tree0Level + tree1Height < maxTreeHeight) {
+            possibleChildIndices.Add(i);
+          }
+        }
+
+        while(possibleChildIndices.Count == 0) {
+          // we couln't find a possible configuration given the current tree0 and tree1
+          // possible reasons for this are: 
+          //  - tree1 is not allowed as sub-tree of tree0
+          //  - appending tree1 as child of tree0 would create a tree that exceedes the maxTreeHeight
+          //  - replacing any child of tree0 with tree1 woulde create a tree that exceedes the maxTeeSize
+          // thus we have to either:
+          //  - go up in tree0 => the insert position allows larger trees
+          //  - go down in tree1 => the tree that is inserted becomes smaller
+          //  - however we have to get lucky to solve the 'allowed sub-trees' problem
+          if(tree1Height == 1 || (tree0Level>0 && random.Next(2) == 0)) {
+            // go up in tree0 
+            tree0Level--;
+            tree0 = gardener.GetRandomBranch(root, tree0Level);
+          } else if(tree1.SubTrees.Count > 0) {
+            // go down in node2:
+            tree1 = tree1.SubTrees[random.Next(tree1.SubTrees.Count)];
+            tree1Size = gardener.GetTreeSize(tree1);
+            tree1Height = gardener.GetTreeHeight(tree1);
+          } else {
+            // could neither go up or down ... don't know what to do ... give up
+            throw new InvalidProgramException();
+          }
+
+          // recalculate the list of possible indices 
+          possibleChildIndices.Clear();
+          for(int i = 0; i < tree0.SubTrees.Count; i++) {
+            int subTreeSize = gardener.GetTreeSize(tree0.SubTrees[i]);
+
+            // when the function is allowed as sub-tree and we don't violate the maxSize and maxHeight constraints
+            // the index is ok
+            if(gardener.GetAllowedSubFunctions(tree0.Function, i).Contains(tree1.Function) &&
+              rootSize - subTreeSize + tree1Size < maxTreeSize &&
+              tree0Level + tree1Height < maxTreeHeight) {
+              possibleChildIndices.Add(i);
+            }
+          }
+        }
+
+        // no possible configuration found this indicates that there is a bigger problem
+        if(possibleChildIndices.Count == 0) {
+          throw new InvalidProgramException();
+        }
+
+        // replace the existing sub-tree at a random index in tree0 with tree1
+        int selectedIndex = possibleChildIndices[random.Next(possibleChildIndices.Count)];
+        tree0.RemoveSubTree(selectedIndex);
+        tree0.InsertSubTree(selectedIndex, tree1);
+
+        // no new operators where needed
+        newBranches = new List<IFunctionTree>();
+        return root;
+      }
+    }
+
+
+    // take f and g and create a tree that has f and g as sub-trees 
+    // example
+    //       O
+    //      /|\
+    //     g 2 f 
+    //
+    private IFunctionTree CombineTerminals(TreeGardener gardener, IFunctionTree f, IFunctionTree g, MersenneTwister random, int maxTreeHeight, out List<IFunctionTree> newBranches) {
+      newBranches = new List<IFunctionTree>();
+      // determine the set of possible parent functions
+      ICollection<IFunction> possibleParents = gardener.GetPossibleParents(new List<IFunction>() { f.Function, g.Function });
+      if(possibleParents.Count == 0) throw new InvalidProgramException();
+      // and select a random one
+      IFunctionTree parent = possibleParents.ElementAt(random.Next(possibleParents.Count())).GetTreeNode();
+
+      int minArity;
+      int maxArity;
+      gardener.GetMinMaxArity(parent.Function, out minArity, out maxArity);
+      int nSlots = Math.Max(2, minArity);
+      // determine which slot can take which sub-trees
+      List<IFunctionTree>[] slots = new List<IFunctionTree>[nSlots];
+      for(int slot = 0; slot < nSlots; slot++) {
+        ICollection<IFunction> allowedSubFunctions = gardener.GetAllowedSubFunctions(parent.Function, slot);
+        List<IFunctionTree> allowedTrees = new List<IFunctionTree>();
+        if(allowedSubFunctions.Contains(f.Function)) allowedTrees.Add(f);
+        if(allowedSubFunctions.Contains(g.Function)) allowedTrees.Add(g);
+        slots[slot] = allowedTrees;
+      }
+      // fill the slots in the order of degrees of freedom
+      int[] slotSequence = Enumerable.Range(0, slots.Count()).OrderBy(slot => slots[slot].Count()).ToArray();
+
+      // tmp arry to store the tree for each sub-tree slot of the parent
+      IFunctionTree[] selectedFunctionTrees = new IFunctionTree[nSlots];
+
+      // fill the sub-tree slots of the parent starting with the slots that can take potentially both functions (f and g)
+      for(int i = 0; i < slotSequence.Length; i++) {
+        int slot = slotSequence[i];
+        List<IFunctionTree> allowedTrees = slots[slot];
+        // when neither f nor g fit into the slot => create a new random tree
+        if(allowedTrees.Count() == 0) {
+          var allowedFunctions = gardener.GetAllowedSubFunctions(parent.Function, slot);
+          selectedFunctionTrees[slot] = gardener.CreateRandomTree(allowedFunctions, 1, 1, true);
+          newBranches.AddRange(gardener.GetAllSubTrees(selectedFunctionTrees[slot]));
+        } else {
+          // select randomly which tree to insert into this slot
+          IFunctionTree selectedTree = allowedTrees[random.Next(allowedTrees.Count())];
+          selectedFunctionTrees[slot] = selectedTree;
+          // remove the tree that we used in this slot from following function-sets
+          for(int j = i + 1; j < slotSequence.Length; j++) {
+            int otherSlot = slotSequence[j];
+            slots[otherSlot].Remove(selectedTree);
+          }
+        }
+      }
+      // actually append the sub-trees to the parent tree
+      for(int i = 0; i < selectedFunctionTrees.Length; i++) {
+        parent.InsertSubTree(i, selectedFunctionTrees[i]);
+      }
+
+      return parent;
+    }
+  }
+}
Index: /branches/ExperimentalStructureIdentification/StructIdProblemInjector.cs
===================================================================
--- /branches/ExperimentalStructureIdentification/StructIdProblemInjector.cs	(revision 204)
+++ /branches/ExperimentalStructureIdentification/StructIdProblemInjector.cs	(revision 204)
@@ -0,0 +1,55 @@
+#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 System.Xml;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.DataAnalysis;
+
+namespace HeuristicLab.StructureIdentification {
+  public class StructIdProblemInjector : OperatorBase {
+    public override string Description {
+      get { return @"Injects the necessary variables for a structure identification problem."; }
+    }
+
+    public StructIdProblemInjector()
+      : base() {
+      AddVariableInfo(new VariableInfo("Dataset", "Dataset", typeof(Dataset), VariableKind.New));
+      AddVariable(new Variable("Dataset", new Dataset()));
+      AddVariableInfo(new VariableInfo("TargetVariable", "TargetVariable", typeof(IntData), VariableKind.New));
+      AddVariable(new Variable("TargetVariable", new IntData()));
+    }
+
+    public override IView CreateView() {
+      return new StructIdProblemInjectorView(this);
+    }
+
+    public override IOperation Apply(IScope scope) {
+      scope.AddVariable(new Variable(scope.TranslateName("Dataset"), (IItem)GetVariable("Dataset").Value.Clone()));
+      scope.AddVariable(new Variable(scope.TranslateName("TargetVariable"), (IItem)GetVariable("TargetVariable").Value.Clone()));
+      return null;
+    }
+  }
+}
Index: /branches/ExperimentalStructureIdentification/StructIdProblemInjectorView.Designer.cs
===================================================================
--- /branches/ExperimentalStructureIdentification/StructIdProblemInjectorView.Designer.cs	(revision 204)
+++ /branches/ExperimentalStructureIdentification/StructIdProblemInjectorView.Designer.cs	(revision 204)
@@ -0,0 +1,183 @@
+#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.StructureIdentification {
+  partial class StructIdProblemInjectorView {
+    /// <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.importInstanceButton = new System.Windows.Forms.Button();
+      this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
+      this.tabControl = new System.Windows.Forms.TabControl();
+      this.dataTabPage = new System.Windows.Forms.TabPage();
+      this.variableInfosTabPage = new System.Windows.Forms.TabPage();
+      this.operatorBaseVariableInfosView = new HeuristicLab.Core.OperatorBaseVariableInfosView();
+      this.descriptionTabPage = new System.Windows.Forms.TabPage();
+      this.operatorBaseDescriptionView = new HeuristicLab.Core.OperatorBaseDescriptionView();
+      this.datasetView = new HeuristicLab.DataAnalysis.DatasetView();
+      this.tabControl.SuspendLayout();
+      this.dataTabPage.SuspendLayout();
+      this.variableInfosTabPage.SuspendLayout();
+      this.descriptionTabPage.SuspendLayout();
+      this.SuspendLayout();
+      // 
+      // importInstanceButton
+      // 
+      this.importInstanceButton.Location = new System.Drawing.Point(6, 6);
+      this.importInstanceButton.Name = "importInstanceButton";
+      this.importInstanceButton.Size = new System.Drawing.Size(129, 21);
+      this.importInstanceButton.TabIndex = 6;
+      this.importInstanceButton.Text = "&Import...";
+      this.importInstanceButton.UseVisualStyleBackColor = true;
+      this.importInstanceButton.Click += new System.EventHandler(this.importInstanceButton_Click);
+      // 
+      // openFileDialog
+      // 
+      this.openFileDialog.DefaultExt = "txt";
+      this.openFileDialog.FileName = "txt";
+      this.openFileDialog.Filter = "Text files|*.txt|All files|*.*";
+      this.openFileDialog.Title = "Import StructId File";
+      // 
+      // tabControl
+      // 
+      this.tabControl.Controls.Add(this.dataTabPage);
+      this.tabControl.Controls.Add(this.variableInfosTabPage);
+      this.tabControl.Controls.Add(this.descriptionTabPage);
+      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(507, 451);
+      this.tabControl.TabIndex = 0;
+      // 
+      // dataTabPage
+      // 
+      this.dataTabPage.Controls.Add(this.datasetView);
+      this.dataTabPage.Controls.Add(this.importInstanceButton);
+      this.dataTabPage.Location = new System.Drawing.Point(4, 22);
+      this.dataTabPage.Name = "dataTabPage";
+      this.dataTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.dataTabPage.Size = new System.Drawing.Size(499, 425);
+      this.dataTabPage.TabIndex = 0;
+      this.dataTabPage.Text = "Data";
+      this.dataTabPage.UseVisualStyleBackColor = true;
+      // 
+      // variableInfosTabPage
+      // 
+      this.variableInfosTabPage.Controls.Add(this.operatorBaseVariableInfosView);
+      this.variableInfosTabPage.Location = new System.Drawing.Point(4, 22);
+      this.variableInfosTabPage.Name = "variableInfosTabPage";
+      this.variableInfosTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.variableInfosTabPage.Size = new System.Drawing.Size(499, 425);
+      this.variableInfosTabPage.TabIndex = 1;
+      this.variableInfosTabPage.Text = "Variable Infos";
+      this.variableInfosTabPage.UseVisualStyleBackColor = true;
+      // 
+      // operatorBaseVariableInfosView
+      // 
+      this.operatorBaseVariableInfosView.Caption = "Operator";
+      this.operatorBaseVariableInfosView.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.operatorBaseVariableInfosView.Location = new System.Drawing.Point(3, 3);
+      this.operatorBaseVariableInfosView.Name = "operatorBaseVariableInfosView";
+      this.operatorBaseVariableInfosView.Operator = null;
+      this.operatorBaseVariableInfosView.Size = new System.Drawing.Size(493, 419);
+      this.operatorBaseVariableInfosView.TabIndex = 0;
+      // 
+      // descriptionTabPage
+      // 
+      this.descriptionTabPage.Controls.Add(this.operatorBaseDescriptionView);
+      this.descriptionTabPage.Location = new System.Drawing.Point(4, 22);
+      this.descriptionTabPage.Name = "descriptionTabPage";
+      this.descriptionTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.descriptionTabPage.Size = new System.Drawing.Size(499, 425);
+      this.descriptionTabPage.TabIndex = 2;
+      this.descriptionTabPage.Text = "Description";
+      this.descriptionTabPage.UseVisualStyleBackColor = true;
+      // 
+      // operatorBaseDescriptionView
+      // 
+      this.operatorBaseDescriptionView.Caption = "Operator";
+      this.operatorBaseDescriptionView.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.operatorBaseDescriptionView.Location = new System.Drawing.Point(3, 3);
+      this.operatorBaseDescriptionView.Name = "operatorBaseDescriptionView";
+      this.operatorBaseDescriptionView.Operator = null;
+      this.operatorBaseDescriptionView.Size = new System.Drawing.Size(493, 419);
+      this.operatorBaseDescriptionView.TabIndex = 0;
+      // 
+      // datasetView
+      // 
+      this.datasetView.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.datasetView.Caption = "View";
+      this.datasetView.Location = new System.Drawing.Point(6, 33);
+      this.datasetView.Name = "datasetView";
+      this.datasetView.Size = new System.Drawing.Size(487, 386);
+      this.datasetView.TabIndex = 7;
+      // 
+      // StructIdProblemInjectorView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.tabControl);
+      this.Name = "StructIdProblemInjectorView";
+      this.Size = new System.Drawing.Size(507, 451);
+      this.tabControl.ResumeLayout(false);
+      this.dataTabPage.ResumeLayout(false);
+      this.variableInfosTabPage.ResumeLayout(false);
+      this.descriptionTabPage.ResumeLayout(false);
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.Button importInstanceButton;
+    private System.Windows.Forms.OpenFileDialog openFileDialog;
+    private System.Windows.Forms.TabControl tabControl;
+    private System.Windows.Forms.TabPage dataTabPage;
+    private System.Windows.Forms.TabPage variableInfosTabPage;
+    private HeuristicLab.Core.OperatorBaseVariableInfosView operatorBaseVariableInfosView;
+    private System.Windows.Forms.TabPage descriptionTabPage;
+    private HeuristicLab.Core.OperatorBaseDescriptionView operatorBaseDescriptionView;
+    private HeuristicLab.DataAnalysis.DatasetView datasetView;
+  }
+}
Index: /branches/ExperimentalStructureIdentification/StructIdProblemInjectorView.cs
===================================================================
--- /branches/ExperimentalStructureIdentification/StructIdProblemInjectorView.cs	(revision 204)
+++ /branches/ExperimentalStructureIdentification/StructIdProblemInjectorView.cs	(revision 204)
@@ -0,0 +1,98 @@
+#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.Text;
+using System.Windows.Forms;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.DataAnalysis;
+
+namespace HeuristicLab.StructureIdentification {
+  public partial class StructIdProblemInjectorView : ViewBase {
+    public StructIdProblemInjector StructIdProblemInjector {
+      get { return (StructIdProblemInjector)Item; }
+      set { base.Item = value; }
+    }
+
+    public StructIdProblemInjectorView() {
+      InitializeComponent();
+    }
+    public StructIdProblemInjectorView(StructIdProblemInjector structIdProblemInjector)
+      : this() {
+      StructIdProblemInjector = structIdProblemInjector;
+    }
+
+    protected override void RemoveItemEvents() {
+      operatorBaseVariableInfosView.Operator = null;
+      operatorBaseDescriptionView.Operator = null;
+      base.RemoveItemEvents();
+    }
+    protected override void AddItemEvents() {
+      base.AddItemEvents();
+      operatorBaseVariableInfosView.Operator = StructIdProblemInjector;
+      operatorBaseDescriptionView.Operator = StructIdProblemInjector;
+    }
+
+    protected override void UpdateControls() {
+      base.UpdateControls();
+      if (StructIdProblemInjector == null) {
+        importInstanceButton.Enabled = false;
+      } else {
+        Dataset dataset = (Dataset)StructIdProblemInjector.GetVariable("Dataset").Value;
+        datasetView.Dataset = dataset;
+        importInstanceButton.Enabled = true;
+      }
+    }
+
+    private void importInstanceButton_Click(object sender, EventArgs e) {
+      if (openFileDialog.ShowDialog(this) == DialogResult.OK) {
+        DatasetParser parser = new DatasetParser();
+        bool success = false;
+        try {
+          parser.Import(openFileDialog.FileName, true);
+          success = true;
+        } catch (Exception) {
+          // not possible to parse strictly => try to parse non-strict
+          parser.Import(openFileDialog.FileName, false);
+          success = true;
+        }
+        if (success) {
+          Dataset dataset = (Dataset)StructIdProblemInjector.GetVariable("Dataset").Value;
+          dataset.Rows = parser.TrainingSamplesEnd - parser.TrainingSamplesStart;
+          dataset.Columns = parser.Columns;
+          dataset.VariableNames = parser.VariableNames;
+          dataset.Name = parser.ProblemName;
+          dataset.Samples = new double[dataset.Rows * dataset.Columns];
+          Array.Copy(parser.Samples, dataset.Samples, dataset.Columns * dataset.Rows);
+
+          ((IntData)StructIdProblemInjector.GetVariable("TargetVariable").Value).Data = parser.TargetVariable;
+          Refresh();
+        }
+      }
+    }
+  }
+}
Index: /branches/ExperimentalStructureIdentification/StructIdProblemInjectorView.resx
===================================================================
--- /branches/ExperimentalStructureIdentification/StructIdProblemInjectorView.resx	(revision 204)
+++ /branches/ExperimentalStructureIdentification/StructIdProblemInjectorView.resx	(revision 204)
@@ -0,0 +1,123 @@
+<?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="openFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+</root>
Index: /branches/ExperimentalStructureIdentification/TreeGardener.cs
===================================================================
--- /branches/ExperimentalStructureIdentification/TreeGardener.cs	(revision 204)
+++ /branches/ExperimentalStructureIdentification/TreeGardener.cs	(revision 204)
@@ -0,0 +1,496 @@
+#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 HeuristicLab.Selection;
+using HeuristicLab.Functions;
+using System.Collections;
+
+namespace HeuristicLab.StructureIdentification {
+  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) {
+        int maxA, minA;
+        GetMinMaxArity(fun, out minA, out maxA);
+        if(maxA == 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, maxTreeSize - 1, 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, maxTreeSize - 1, maxTreeHeight - 1);
+      return tree;
+    }
+
+    /// <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) {
+      // default is non-balanced trees
+      return CreateRandomTree(allowedFunctions, maxTreeSize, maxTreeHeight, false);
+    }
+
+    /// <summary>
+    /// Selects a random function from allowedFunctions and creates a (un)balanced random tree with maximal size and height.
+    /// Max-size and max-height are not accepted as hard constraints, if all functions in the set of allowed functions would
+    /// lead to a bigger tree then the limits are automatically extended to guarantee that we can build a tree.
+    /// </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>
+    /// <param name="balanceTrees">Flag determining whether the tree should be balanced or not.</param>
+    /// <returns>New random tree</returns>
+    internal IFunctionTree CreateRandomTree(ICollection<IFunction> allowedFunctions, int maxTreeSize, int maxTreeHeight, bool balanceTrees) {
+      // get the minimal needed height based on allowed functions and extend the max-height if necessary
+      int minTreeHeight = allowedFunctions.Select(f => ((IntData)f.GetVariable(GPOperatorLibrary.MIN_TREE_HEIGHT).Value).Data).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 => ((IntData)f.GetVariable(GPOperatorLibrary.MIN_TREE_SIZE).Value).Data).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 => ((IntData)f.GetVariable(GPOperatorLibrary.MIN_TREE_HEIGHT).Value).Data <= treeHeight &&
+        ((IntData)f.GetVariable(GPOperatorLibrary.MIN_TREE_SIZE).Value).Data <= treeSize).ToArray();
+      IFunction selectedFunction = RandomSelect(possibleFunctions);
+
+      // build the tree 
+      IFunctionTree root;
+      if(balanceTrees) {
+        root = MakeBalancedTree(selectedFunction, maxTreeSize - 1, maxTreeHeight - 1);
+      } else {
+        root = MakeUnbalancedTree(selectedFunction, maxTreeSize - 1, maxTreeHeight - 1);
+      }
+      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(GPOperatorLibrary.INITIALIZATION) != null);
+      foreach(IFunctionTree tree in parametricTrees) {
+        // enqueue an initialization operation for each operator with local variables 
+        IOperator initialization = (IOperator)tree.Function.GetVariable(GPOperatorLibrary.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 int GetTreeSize(IFunctionTree tree) {
+      return 1 + tree.SubTrees.Sum(f => GetTreeSize(f));
+    }
+
+    internal int GetTreeHeight(IFunctionTree tree) {
+      if(tree.SubTrees.Count == 0) return 1;
+      return 1 + tree.SubTrees.Max(f => GetTreeHeight(f));
+    }
+
+    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) {
+      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;
+        }
+      }
+      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 = GetBranchesAtLevel(tree, level);
+      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;
+      int maxArity;
+      GetMinMaxArity(f, out minArity, out 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);
+
+      SubOperatorsConstraintAnalyser analyzer = new SubOperatorsConstraintAnalyser();
+      analyzer.AllPossibleOperators = children.Cast<IOperator>().ToArray<IOperator>();
+
+      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>(analyzer.GetAllowedOperators(f, slot).Cast<IFunction>());
+        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) {
+      int minArity;
+      int maxArity;
+      GetMinMaxArity(f, out minArity, out maxArity);
+      return minArity == 0 && maxArity == 0;
+    }
+    internal IList<IFunction> GetAllowedSubFunctions(IFunction f, int index) {
+      if(f == null) {
+        return allFunctions;
+      } else {
+        ItemList slotList = (ItemList)f.GetVariable(GPOperatorLibrary.ALLOWED_SUBOPERATORS).Value;
+        List<IFunction> result = new List<IFunction>();
+        foreach(IFunction function in (ItemList)slotList[index]) {
+          result.Add(function);
+        }
+        return result;
+      }
+    }
+    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;
+    }
+    #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 = allFunctions.Where(f => GetMinimalTreeHeight(f) <= maxTreeHeight &&
+          GetMinimalTreeSize(f) <= maxTreeSize).ToArray();
+        IFunction selectedFunction = RandomSelect(possibleFunctions);
+        return selectedFunction;
+      }
+    }
+
+    private IFunctionTree MakeUnbalancedTree(IFunction parent, int maxTreeSize, int maxTreeHeight) {
+      if(maxTreeHeight == 0 || maxTreeSize == 0) return parent.GetTreeNode();
+      int minArity;
+      int maxArity;
+      GetMinMaxArity(parent, out minArity, out maxArity);
+      if(maxArity >= maxTreeSize) {
+        maxArity = maxTreeSize;
+      }
+      int actualArity = random.Next(minArity, maxArity + 1);
+      if(actualArity > 0) {
+        IFunctionTree parentTree = parent.GetTreeNode();
+        int maxSubTreeSize = maxTreeSize / actualArity;
+        for(int i = 0; i < actualArity; i++) {
+          IFunction[] possibleFunctions = GetAllowedSubFunctions(parent, i).Where(f => GetMinimalTreeHeight(f) <= maxTreeHeight &&
+            GetMinimalTreeSize(f) <= maxSubTreeSize).ToArray();
+          IFunction selectedFunction = RandomSelect(possibleFunctions);
+          IFunctionTree newSubTree = MakeUnbalancedTree(selectedFunction, maxSubTreeSize - 1, 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 maxTreeSize, int maxTreeHeight) {
+      if(maxTreeHeight == 0 || maxTreeSize == 0) return parent.GetTreeNode();
+      int minArity;
+      int maxArity;
+      GetMinMaxArity(parent, out minArity, out maxArity);
+      if(maxArity >= maxTreeSize) {
+        maxArity = maxTreeSize;
+      }
+      int actualArity = random.Next(minArity, maxArity + 1);
+      if(actualArity > 0) {
+        IFunctionTree parentTree = parent.GetTreeNode();
+        int maxSubTreeSize = maxTreeSize / actualArity;
+        for(int i = 0; i < actualArity; i++) {
+          // first try to find a function that fits into the maxHeight and maxSize limits 
+          IFunction[] possibleFunctions = GetAllowedSubFunctions(parent, i).Where(
+            f => GetMinimalTreeHeight(f) <= maxTreeHeight &&
+            GetMinimalTreeSize(f) <= maxSubTreeSize &&
+            !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, maxSubTreeSize - 1, 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 List<IFunctionTree> GetBranchesAtLevel(IFunctionTree tree, int level) {
+      if(level == 1) return new List<IFunctionTree>(tree.SubTrees);
+
+      List<IFunctionTree> branches = new List<IFunctionTree>();
+      foreach(IFunctionTree subTree in tree.SubTrees) {
+        branches.AddRange(GetBranchesAtLevel(subTree, level - 1));
+      }
+      return branches;
+    }
+
+    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
+
+  }
+}
