Index: /trunk/sources/HeuristicLab.GP/3.3/BaseClasses/Function.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP/3.3/BaseClasses/Function.cs	(revision 2728)
+++ /trunk/sources/HeuristicLab.GP/3.3/BaseClasses/Function.cs	(revision 2729)
@@ -227,11 +227,12 @@
     public override object Clone(IDictionary<Guid, object> clonedObjects) {
       Function clone = (Function)base.Clone(clonedObjects);
-      clone.initializer = (IOperator)Auxiliary.Clone(initializer, clonedObjects);
-      clone.manipulator = (IOperator)Auxiliary.Clone(manipulator, clonedObjects);
-      clone.maxArity = maxArity;
-      clone.minArity = minArity;
-      clone.minTreeHeight = minTreeHeight;
-      clone.minTreeSize = minTreeSize;
-      clone.tickets = tickets;
+      if (initializer != null) clone.initializer = (IOperator)Auxiliary.Clone(initializer, clonedObjects);
+      else clone.initializer = null;
+      if (manipulator != null) clone.manipulator = (IOperator)Auxiliary.Clone(manipulator, clonedObjects);
+      else clone.manipulator = null;
+      clone.MaxSubTrees = maxArity;
+      clone.MinSubTrees = minArity;
+      clone.Tickets = tickets;
+      clone.allowedSubFunctions.Clear();
       for (int i = 0; i < MaxSubTrees; i++) {
         var allowedSubFunctionsForSlot = new List<IFunction>();
@@ -252,4 +253,8 @@
       node.Attributes.Append(minSubTreesAttr);
       node.Attributes.Append(maxSubTreesAttr);
+      if (initializer != null)
+        node.AppendChild(PersistenceManager.Persist("Initializer", initializer, document, persistedObjects));
+      if (manipulator != null)
+        node.AppendChild(PersistenceManager.Persist("Manipulator", manipulator, document, persistedObjects));
       for (int i = 0; i < MaxSubTrees; i++) {
         XmlNode slotNode = document.CreateElement("AllowedSubFunctions");
@@ -269,4 +274,11 @@
       MinSubTrees = XmlConvert.ToInt32(node.Attributes["MinSubTrees"].Value);
       MaxSubTrees = XmlConvert.ToInt32(node.Attributes["MaxSubTrees"].Value);
+      if (node.SelectSingleNode("Initializer") != null) {
+        initializer = (IOperator)PersistenceManager.Restore(node.SelectSingleNode("Initializer"), restoredObjects);
+      }
+      if (node.SelectSingleNode("Manipulator") != null) {
+        manipulator = (IOperator)PersistenceManager.Restore(node.SelectSingleNode("Manipulator"), restoredObjects);
+      }
+      foreach (var subFunctionsList in allowedSubFunctions) subFunctionsList.Clear();
       foreach (XmlNode allowedSubFunctionsNode in node.SelectNodes("AllowedSubFunctions")) {
         int slot = XmlConvert.ToInt32(allowedSubFunctionsNode.Attributes["Slot"].Value);
Index: /trunk/sources/HeuristicLab.GP/3.3/BaseClasses/FunctionLibraryInjectorBase.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP/3.3/BaseClasses/FunctionLibraryInjectorBase.cs	(revision 2728)
+++ /trunk/sources/HeuristicLab.GP/3.3/BaseClasses/FunctionLibraryInjectorBase.cs	(revision 2729)
@@ -76,4 +76,21 @@
       return new FunctionLibraryInjectorView(this);
     }
+
+    #region persistence
+    public override object Clone(IDictionary<Guid, object> clonedObjects) {
+      FunctionLibraryInjectorBase clone = (FunctionLibraryInjectorBase)base.Clone(clonedObjects);
+      clone.functionLibrary = (FunctionLibrary)Auxiliary.Clone(functionLibrary, clonedObjects);
+      return clone;
+    }
+    public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary<Guid, IStorable> persistedObjects) {
+      XmlNode node = base.GetXmlNode(name, document, persistedObjects);
+      node.AppendChild(PersistenceManager.Persist("FunctionLibrary", FunctionLibrary, document, persistedObjects));
+      return node;
+    }
+    public override void Populate(XmlNode node, IDictionary<Guid, IStorable> restoredObjects) {
+      base.Populate(node, restoredObjects);
+      functionLibrary = (FunctionLibrary)PersistenceManager.Restore(node.SelectSingleNode("FunctionLibrary"), restoredObjects);
+    }
+    #endregion
   }
 }
Index: /trunk/sources/HeuristicLab.GP/3.3/FunctionLibrary.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP/3.3/FunctionLibrary.cs	(revision 2728)
+++ /trunk/sources/HeuristicLab.GP/3.3/FunctionLibrary.cs	(revision 2729)
@@ -64,4 +64,5 @@
     }
 
+    #region persistence
     public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary<Guid, IStorable> persistedObjects) {
       XmlNode node = base.GetXmlNode(name, document, persistedObjects);
@@ -79,4 +80,13 @@
     }
 
+    public override object Clone(IDictionary<Guid, object> clonedObjects) {
+      FunctionLibrary clone = (FunctionLibrary)base.Clone(clonedObjects);
+      foreach (var function in functions) {
+        clone.AddFunction((Function)Auxiliary.Clone(function, clonedObjects));
+      }
+      return clone;
+    }
+    #endregion
+
     public override IView CreateView() {
       return new FunctionLibraryEditor(this);
Index: /trunk/sources/HeuristicLab.GP/3.3/FunctionLibraryEditor.Designer.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP/3.3/FunctionLibraryEditor.Designer.cs	(revision 2728)
+++ /trunk/sources/HeuristicLab.GP/3.3/FunctionLibraryEditor.Designer.cs	(revision 2729)
@@ -64,4 +64,5 @@
       this.mutationVariableView = new HeuristicLab.Core.VariableView();
       this.testTabPage = new System.Windows.Forms.TabPage();
+      this.testButton = new System.Windows.Forms.Button();
       this.outputTextBox = new System.Windows.Forms.TextBox();
       this.tabControl.SuspendLayout();
@@ -95,5 +96,4 @@
       this.tabControl.Size = new System.Drawing.Size(677, 561);
       this.tabControl.TabIndex = 1;
-      this.tabControl.Selected += new System.Windows.Forms.TabControlEventHandler(this.tabControl_Selected);
       // 
       // functionsTabPage
@@ -144,5 +144,4 @@
                   | System.Windows.Forms.AnchorStyles.Right)));
       this.functionsListView.Location = new System.Drawing.Point(6, 19);
-      this.functionsListView.MultiSelect = false;
       this.functionsListView.Name = "functionsListView";
       this.functionsListView.Size = new System.Drawing.Size(218, 475);
@@ -308,4 +307,5 @@
       // testTabPage
       // 
+      this.testTabPage.Controls.Add(this.testButton);
       this.testTabPage.Controls.Add(this.outputTextBox);
       this.testTabPage.Location = new System.Drawing.Point(4, 22);
@@ -317,11 +317,25 @@
       this.testTabPage.UseVisualStyleBackColor = true;
       // 
+      // testButton
+      // 
+      this.testButton.Location = new System.Drawing.Point(6, 6);
+      this.testButton.Name = "testButton";
+      this.testButton.Size = new System.Drawing.Size(75, 23);
+      this.testButton.TabIndex = 1;
+      this.testButton.Text = "Run test";
+      this.testButton.UseVisualStyleBackColor = true;
+      this.testButton.Click += new System.EventHandler(this.testButton_Click);
+      // 
       // outputTextBox
       // 
-      this.outputTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
-      this.outputTextBox.Location = new System.Drawing.Point(3, 3);
+      this.outputTextBox.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.outputTextBox.Location = new System.Drawing.Point(3, 35);
       this.outputTextBox.Multiline = true;
       this.outputTextBox.Name = "outputTextBox";
-      this.outputTextBox.Size = new System.Drawing.Size(663, 529);
+      this.outputTextBox.ReadOnly = true;
+      this.outputTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+      this.outputTextBox.Size = new System.Drawing.Size(663, 497);
       this.outputTextBox.TabIndex = 0;
       // 
@@ -376,4 +390,5 @@
     private System.Windows.Forms.TabPage testTabPage;
     private System.Windows.Forms.TextBox outputTextBox;
+    private System.Windows.Forms.Button testButton;
   }
 }
Index: /trunk/sources/HeuristicLab.GP/3.3/FunctionLibraryEditor.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP/3.3/FunctionLibraryEditor.cs	(revision 2728)
+++ /trunk/sources/HeuristicLab.GP/3.3/FunctionLibraryEditor.cs	(revision 2729)
@@ -161,18 +161,29 @@
       }
     }
-
-    private void tabControl_Selected(object sender, TabControlEventArgs e) {
-      if (e.TabPage == testTabPage) {
-        outputTextBox.Text = TestFunctionLibrary();
-      }
-    }
-
+    #region fun lib test
     private string TestFunctionLibrary() {
       int n = 1000;
-      IFunctionTree[] randomTrees = CreateRandomTrees(n, 1, 100);
-
-      StringBuilder builder = new StringBuilder();
-      builder.AppendLine(CalculateFunctionFrequencies(randomTrees));
-      return builder.ToString();
+      try {
+        IFunctionTree[] randomTrees = CreateRandomTrees(n, 1, 100);
+        StringBuilder builder = new StringBuilder();
+        builder.AppendLine("Function symbol frequencies:");
+        builder.AppendLine(CalculateFunctionFrequencies(randomTrees));
+        builder.AppendLine("-----------------------------------------");
+        builder.AppendLine("Terminal symbol frequencies:");
+        builder.AppendLine(CalculateTerminalFrequencies(randomTrees));
+        builder.AppendLine("-----------------------------------------");
+        builder.AppendLine("Function arity frequencies:");
+        builder.AppendLine(CalculateFunctionArityFrequencies(randomTrees));
+        builder.AppendLine("-----------------------------------------");
+        builder.AppendLine("Tree size frequencies:");
+        builder.AppendLine(CalculateTreeSizeFrequencies(randomTrees));
+        builder.AppendLine("-----------------------------------------");
+        builder.AppendLine("Tree height frequencies:");
+        builder.AppendLine(CalculateTreeHeightFrequencies(randomTrees));
+        return builder.ToString();
+      }
+      catch (ArgumentException ex) {
+        return "Could not create random trees:" + Environment.NewLine + ex.Message + Environment.NewLine + ex.StackTrace;
+      }
     }
 
@@ -199,4 +210,74 @@
     }
 
+    public string CalculateTreeSizeFrequencies(IFunctionTree[] randomTrees) {
+      int[] histogram = new int[105 / 5];
+      for (int i = 0; i < randomTrees.Length; i++) {
+        histogram[randomTrees[i].GetSize() / 5]++;
+      }
+      StringBuilder strBuilder = new StringBuilder();
+      for (int i = 0; i < histogram.Length; i++) {
+        strBuilder.Append(Environment.NewLine);
+        strBuilder.Append("< "); strBuilder.Append((i + 1) * 5);
+        strBuilder.Append(": "); strBuilder.AppendFormat("{0:#0.00%}", histogram[i] / (double)randomTrees.Length);
+      }
+      return strBuilder.ToString();
+    }
+
+    public string CalculateTreeHeightFrequencies(IFunctionTree[] randomTrees) {
+      int[] histogram = new int[100];
+      for (int i = 0; i < randomTrees.Length; i++) {
+        histogram[randomTrees[i].GetHeight()]++;
+      }
+      StringBuilder strBuilder = new StringBuilder();
+      for (int i = 0; i < histogram.Length; i++) {
+        strBuilder.Append(Environment.NewLine);
+        strBuilder.Append("< "); strBuilder.Append((i + 1));
+        strBuilder.Append(": "); strBuilder.AppendFormat("{0:#0.00%}", histogram[i] / (double)randomTrees.Length);
+      }
+      return strBuilder.ToString();
+    }
+
+    public string CalculateFunctionArityFrequencies(IFunctionTree[] randomTrees) {
+      Dictionary<int, int> occurances = new Dictionary<int, int>();
+      double n = 0.0;
+      for (int i = 0; i < randomTrees.Length; i++) {
+        foreach (var node in FunctionTreeIterator.IteratePrefix(randomTrees[i])) {
+          if (!occurances.ContainsKey(node.SubTrees.Count))
+            occurances[node.SubTrees.Count] = 0;
+          occurances[node.SubTrees.Count]++;
+          n++;
+        }
+      }
+      StringBuilder strBuilder = new StringBuilder();
+      foreach (var arity in occurances.Keys) {
+        strBuilder.Append(Environment.NewLine);
+        strBuilder.Append(arity); strBuilder.Append(": ");
+        strBuilder.AppendFormat("{0:#0.00%}", occurances[arity] / n);
+      }
+      return strBuilder.ToString();
+    }
+
+    public string CalculateTerminalFrequencies(IFunctionTree[] randomTrees) {
+      Dictionary<IFunction, int> occurances = new Dictionary<IFunction, int>();
+      double n = 0.0;
+      for (int i = 0; i < randomTrees.Length; i++) {
+        foreach (var node in FunctionTreeIterator.IteratePrefix(randomTrees[i])) {
+          if (node.SubTrees.Count == 0) {
+            if (!occurances.ContainsKey(node.Function))
+              occurances[node.Function] = 0;
+            occurances[node.Function]++;
+            n++;
+          }
+        }
+      }
+      StringBuilder strBuilder = new StringBuilder();
+      foreach (var function in occurances.Keys) {
+        strBuilder.Append(Environment.NewLine);
+        strBuilder.Append(function.Name); strBuilder.Append(": ");
+        strBuilder.AppendFormat("{0:#0.00%}", occurances[function] / n);
+      }
+      return strBuilder.ToString();
+    }
+
     private IFunctionTree[] CreateRandomTrees(int popSize, int minSize, int maxSize) {
       int maxHeight = 10;
@@ -206,9 +287,16 @@
       for (int i = 0; i < randomTrees.Length; i++) {
         int treeSize = twister.Next(minSize, maxSize);
-        IFunctionTree root;
+        IFunctionTree root = null;
         int tries = 0;
         TreeGardener gardener = new TreeGardener(twister, FunctionLibrary);
         do {
-          root = gardener.PTC2(treeSize, maxSize);
+          try {
+            root = gardener.PTC2(treeSize, maxSize);
+          }
+          catch (ArgumentException) {
+            // try a different size
+            treeSize = twister.Next(minSize, maxSize);
+            tries = 0;
+          }
           if (tries++ >= maxTries) {
             // try a different size
@@ -216,5 +304,5 @@
             tries = 0;
           }
-        } while (root.GetSize() > maxSize || root.GetHeight() > maxHeight);
+        } while (root == null || root.GetSize() > maxSize || root.GetHeight() > maxHeight);
         randomTrees[i] = root;
       }
@@ -222,4 +310,14 @@
     }
 
+    private void testButton_Click(object sender, EventArgs e) {
+      try {
+        Cursor = Cursors.WaitCursor;
+        outputTextBox.Text = TestFunctionLibrary();
+      }
+      finally {
+        Cursor = Cursors.Default;
+      }
+    }
+    #endregion
   }
 }
Index: /trunk/sources/HeuristicLab.GP/3.3/FunctionLibraryInjectorView.Designer.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP/3.3/FunctionLibraryInjectorView.Designer.cs	(revision 2728)
+++ /trunk/sources/HeuristicLab.GP/3.3/FunctionLibraryInjectorView.Designer.cs	(revision 2729)
@@ -46,19 +46,7 @@
       this.variableInfosTabPage.Size = new System.Drawing.Size(470, 411);
       // 
-      // variablesTabPage
-      // 
-      this.variablesTabPage.Size = new System.Drawing.Size(470, 411);
-      // 
-      // constrainedItemBaseView
-      // 
-      this.constrainedItemBaseView.Size = new System.Drawing.Size(464, 405);
-      // 
       // operatorBaseVariableInfosView
       // 
       this.operatorBaseVariableInfosView.Size = new System.Drawing.Size(464, 405);
-      // 
-      // operatorBaseVariablesView
-      // 
-      this.operatorBaseVariablesView.Size = new System.Drawing.Size(464, 405);
       // 
       // loadButton
@@ -69,5 +57,5 @@
       this.loadButton.Size = new System.Drawing.Size(75, 23);
       this.loadButton.TabIndex = 0;
-      this.loadButton.Text = "Load...";
+      this.loadButton.Text = "Import...";
       this.loadButton.UseVisualStyleBackColor = true;
       this.loadButton.Click += new System.EventHandler(this.loadButton_Click);
@@ -80,5 +68,5 @@
       this.saveButton.Size = new System.Drawing.Size(75, 23);
       this.saveButton.TabIndex = 2;
-      this.saveButton.Text = "Save...";
+      this.saveButton.Text = "Export...";
       this.saveButton.UseVisualStyleBackColor = true;
       this.saveButton.Click += new System.EventHandler(this.saveButton_Click);
Index: /trunk/sources/HeuristicLab.GP/3.3/FunctionLibraryInjectorView.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP/3.3/FunctionLibraryInjectorView.cs	(revision 2728)
+++ /trunk/sources/HeuristicLab.GP/3.3/FunctionLibraryInjectorView.cs	(revision 2729)
@@ -37,21 +37,29 @@
     private SaveFileDialog saveFileDialog;
 
-    public FunctionLibraryInjectorView() {
+    public FunctionLibraryInjectorView()
+      : base() {
       InitializeComponent();
+      CreateFileDialogs();
+    }
+
+    public FunctionLibraryInjectorView(FunctionLibraryInjectorBase functionLibraryInjector)
+      : base(functionLibraryInjector) {
+      InitializeComponent();
+      this.functionLibraryInjector = functionLibraryInjector;
+      functionLibraryEditor.FunctionLibrary = functionLibraryInjector.FunctionLibrary;
+
+      CreateFileDialogs();
+    }
+
+    private void CreateFileDialogs() {
       openFileDialog = new OpenFileDialog();
       openFileDialog.AddExtension = true;
       openFileDialog.DefaultExt = ".hl";
-      openFileDialog.Filter = "HeuristicLab Dateien (*.hl) | *.hl | Alle Dateien (*.*) | *.*";
+      openFileDialog.Filter = "HeuristicLab Dateien (*.hl) |*.hl| Alle Dateien (*.*) |*.*";
       openFileDialog.Multiselect = false;
       saveFileDialog = new SaveFileDialog();
       saveFileDialog.AddExtension = true;
       saveFileDialog.DefaultExt = ".hl";
-      saveFileDialog.Filter = "HeuristicLab Dateien (*.hl) | *.hl | Alle Dateien (*.*) | *.*";
-    }
-
-    public FunctionLibraryInjectorView(FunctionLibraryInjectorBase functionLibraryInjector)
-      : this() {
-      this.functionLibraryInjector = functionLibraryInjector;
-      functionLibraryEditor.FunctionLibrary = functionLibraryInjector.FunctionLibrary;
+      saveFileDialog.Filter = "HeuristicLab Dateien (*.hl) |*.hl| Alle Dateien (*.*) |*.*";
     }
 
Index: /trunk/sources/HeuristicLab.GP/3.3/FunctionView.Designer.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP/3.3/FunctionView.Designer.cs	(revision 2728)
+++ /trunk/sources/HeuristicLab.GP/3.3/FunctionView.Designer.cs	(revision 2729)
@@ -149,4 +149,5 @@
       this.subFunctionsListBox.Location = new System.Drawing.Point(6, 46);
       this.subFunctionsListBox.Name = "subFunctionsListBox";
+      this.subFunctionsListBox.SelectionMode = System.Windows.Forms.SelectionMode.MultiExtended;
       this.subFunctionsListBox.Size = new System.Drawing.Size(405, 225);
       this.subFunctionsListBox.TabIndex = 12;
Index: /trunk/sources/HeuristicLab.GP/3.3/FunctionView.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP/3.3/FunctionView.cs	(revision 2728)
+++ /trunk/sources/HeuristicLab.GP/3.3/FunctionView.cs	(revision 2729)
@@ -187,6 +187,7 @@
         if (subFunctionsListBox.SelectedItems.Count > 0 && e.KeyCode == Keys.Delete) {
           if (selectedSlot == ALL_SLOTS) {
+            List<IFunction> removedSubFunctions = new List<IFunction>(subFunctionsListBox.SelectedItems.Cast<IFunction>());
             for (int slot = 0; slot < function.MaxSubTrees; slot++) {
-              foreach (var subFun in subFunctionsListBox.SelectedItems) {
+              foreach (var subFun in removedSubFunctions) {
                 function.RemoveAllowedSubFunction((IFunction)subFun, slot);
               }
@@ -194,6 +195,7 @@
           } else {
             int slot = int.Parse(selectedSlot);
-            foreach (var subFun in subFunctionsListBox.SelectedItems) {
-              function.RemoveAllowedSubFunction((IFunction)subFun, slot);
+            List<IFunction> removedSubFunctions = new List<IFunction>(subFunctionsListBox.SelectedItems.Cast<IFunction>());
+            foreach (var subFun in removedSubFunctions) {
+              function.RemoveAllowedSubFunction(subFun, slot);
             }
           }
