Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.Designer.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.Designer.cs	(revision 9005)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.Designer.cs	(revision 9006)
@@ -52,6 +52,8 @@
       this.btnSimplify = new System.Windows.Forms.Button();
       this.btnOptimizeConstants = new System.Windows.Forms.Button();
+      this.grpViewHost = new System.Windows.Forms.GroupBox();
+      this.treeStatusLabel = new System.Windows.Forms.Label();
+      this.treeStatusValue = new System.Windows.Forms.Label();
       this.treeChart = new HeuristicLab.Problems.DataAnalysis.Symbolic.Views.InteractiveSymbolicExpressionTreeChart();
-      this.grpViewHost = new System.Windows.Forms.GroupBox();
       ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
       this.splitContainer.Panel1.SuspendLayout();
@@ -74,5 +76,5 @@
       this.viewHost.Name = "viewHost";
       this.viewHost.ReadOnly = false;
-      this.viewHost.Size = new System.Drawing.Size(335, 326);
+      this.viewHost.Size = new System.Drawing.Size(336, 383);
       this.viewHost.TabIndex = 0;
       this.viewHost.ViewsLabelVisible = true;
@@ -92,5 +94,5 @@
       // 
       this.splitContainer.Panel2.Controls.Add(this.grpViewHost);
-      this.splitContainer.Size = new System.Drawing.Size(564, 348);
+      this.splitContainer.Size = new System.Drawing.Size(565, 405);
       this.splitContainer.SplitterDistance = 213;
       this.splitContainer.TabIndex = 1;
@@ -99,10 +101,12 @@
       // 
       this.grpSimplify.AutoSize = true;
+      this.grpSimplify.Controls.Add(this.treeStatusValue);
       this.grpSimplify.Controls.Add(this.flowLayoutPanel);
+      this.grpSimplify.Controls.Add(this.treeStatusLabel);
       this.grpSimplify.Controls.Add(this.treeChart);
       this.grpSimplify.Dock = System.Windows.Forms.DockStyle.Fill;
       this.grpSimplify.Location = new System.Drawing.Point(0, 0);
       this.grpSimplify.Name = "grpSimplify";
-      this.grpSimplify.Size = new System.Drawing.Size(213, 348);
+      this.grpSimplify.Size = new System.Drawing.Size(213, 405);
       this.grpSimplify.TabIndex = 1;
       this.grpSimplify.TabStop = false;
@@ -113,7 +117,7 @@
       this.flowLayoutPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
             | System.Windows.Forms.AnchorStyles.Right)));
+      this.flowLayoutPanel.Controls.Add(this.btnOptimizeConstants);
       this.flowLayoutPanel.Controls.Add(this.btnSimplify);
-      this.flowLayoutPanel.Controls.Add(this.btnOptimizeConstants);
-      this.flowLayoutPanel.Location = new System.Drawing.Point(6, 313);
+      this.flowLayoutPanel.Location = new System.Drawing.Point(6, 370);
       this.flowLayoutPanel.Name = "flowLayoutPanel";
       this.flowLayoutPanel.Size = new System.Drawing.Size(204, 29);
@@ -123,5 +127,5 @@
       // btnSimplify
       // 
-      this.btnSimplify.Location = new System.Drawing.Point(3, 3);
+      this.btnSimplify.Location = new System.Drawing.Point(106, 3);
       this.btnSimplify.Name = "btnSimplify";
       this.btnSimplify.Size = new System.Drawing.Size(95, 23);
@@ -135,5 +139,5 @@
       this.btnOptimizeConstants.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
       this.btnOptimizeConstants.Enabled = false;
-      this.btnOptimizeConstants.Location = new System.Drawing.Point(104, 3);
+      this.btnOptimizeConstants.Location = new System.Drawing.Point(3, 3);
       this.btnOptimizeConstants.Name = "btnOptimizeConstants";
       this.btnOptimizeConstants.Size = new System.Drawing.Size(97, 23);
@@ -143,4 +147,36 @@
       this.btnOptimizeConstants.Click += new System.EventHandler(this.btnOptimizeConstants_Click);
       // 
+      // grpViewHost
+      // 
+      this.grpViewHost.Controls.Add(this.viewHost);
+      this.grpViewHost.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.grpViewHost.Location = new System.Drawing.Point(0, 0);
+      this.grpViewHost.Name = "grpViewHost";
+      this.grpViewHost.Size = new System.Drawing.Size(348, 405);
+      this.grpViewHost.TabIndex = 1;
+      this.grpViewHost.TabStop = false;
+      this.grpViewHost.Text = "Details";
+      // 
+      // treeStatusLabel
+      // 
+      this.treeStatusLabel.AutoSize = true;
+      this.treeStatusLabel.BackColor = System.Drawing.Color.Transparent;
+      this.treeStatusLabel.Location = new System.Drawing.Point(6, 16);
+      this.treeStatusLabel.Name = "treeStatusLabel";
+      this.treeStatusLabel.Size = new System.Drawing.Size(68, 13);
+      this.treeStatusLabel.TabIndex = 2;
+      this.treeStatusLabel.Text = "Tree Status: ";
+      // 
+      // treeStatusValue
+      // 
+      this.treeStatusValue.AutoSize = true;
+      this.treeStatusValue.BackColor = System.Drawing.Color.Transparent;
+      this.treeStatusValue.ForeColor = System.Drawing.Color.Green;
+      this.treeStatusValue.Location = new System.Drawing.Point(72, 16);
+      this.treeStatusValue.Name = "treeStatusValue";
+      this.treeStatusValue.Size = new System.Drawing.Size(30, 13);
+      this.treeStatusValue.TabIndex = 3;
+      this.treeStatusValue.Text = "Valid";
+      // 
       // treeChart
       // 
@@ -150,7 +186,8 @@
       this.treeChart.BackgroundColor = System.Drawing.Color.White;
       this.treeChart.LineColor = System.Drawing.Color.Black;
-      this.treeChart.Location = new System.Drawing.Point(6, 16);
+      this.treeChart.Location = new System.Drawing.Point(6, 32);
+      this.treeChart.ModifyTree = null;
       this.treeChart.Name = "treeChart";
-      this.treeChart.Size = new System.Drawing.Size(201, 291);
+      this.treeChart.Size = new System.Drawing.Size(201, 332);
       this.treeChart.Spacing = 5;
       this.treeChart.SuspendRepaint = false;
@@ -158,17 +195,6 @@
       this.treeChart.TextFont = new System.Drawing.Font("Times New Roman", 8F);
       this.treeChart.Tree = null;
-      this.treeChart.SymbolicExpressionTreeChanged += new System.EventHandler(this.treeChart_SymbolicExpressionTreeChanged);
+      this.treeChart.SymbolicExpressionTreeNodeClicked += new System.Windows.Forms.MouseEventHandler(this.treeChart_SymbolicExpressionTreeNodeClicked);
       this.treeChart.SymbolicExpressionTreeNodeDoubleClicked += new System.Windows.Forms.MouseEventHandler(this.treeChart_SymbolicExpressionTreeNodeDoubleClicked);
-      // 
-      // grpViewHost
-      // 
-      this.grpViewHost.Controls.Add(this.viewHost);
-      this.grpViewHost.Dock = System.Windows.Forms.DockStyle.Fill;
-      this.grpViewHost.Location = new System.Drawing.Point(0, 0);
-      this.grpViewHost.Name = "grpViewHost";
-      this.grpViewHost.Size = new System.Drawing.Size(347, 348);
-      this.grpViewHost.TabIndex = 1;
-      this.grpViewHost.TabStop = false;
-      this.grpViewHost.Text = "Details";
       // 
       // InteractiveSymbolicDataAnalysisSolutionSimplifierView
@@ -179,5 +205,5 @@
       this.DoubleBuffered = true;
       this.Name = "InteractiveSymbolicDataAnalysisSolutionSimplifierView";
-      this.Size = new System.Drawing.Size(564, 348);
+      this.Size = new System.Drawing.Size(565, 405);
       this.splitContainer.Panel1.ResumeLayout(false);
       this.splitContainer.Panel1.PerformLayout();
@@ -186,7 +212,9 @@
       this.splitContainer.ResumeLayout(false);
       this.grpSimplify.ResumeLayout(false);
+      this.grpSimplify.PerformLayout();
       this.flowLayoutPanel.ResumeLayout(false);
       this.grpViewHost.ResumeLayout(false);
       this.ResumeLayout(false);
+
     }
 
@@ -201,4 +229,6 @@
     private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel;
     protected System.Windows.Forms.Button btnOptimizeConstants;
+    private System.Windows.Forms.Label treeStatusValue;
+    private System.Windows.Forms.Label treeStatusLabel;
   }
 }
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs	(revision 9005)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs	(revision 9006)
@@ -32,12 +32,100 @@
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Views {
   public abstract partial class InteractiveSymbolicDataAnalysisSolutionSimplifierView : AsynchronousContentView {
-    private Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> replacementNodes;
+    private Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> foldedNodes;
+    private Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> changedNodes;
     private Dictionary<ISymbolicExpressionTreeNode, double> nodeImpacts;
+    private enum TreeState { Valid, Invalid }
+    private TreeState treeState;
 
     public InteractiveSymbolicDataAnalysisSolutionSimplifierView() {
       InitializeComponent();
-      replacementNodes = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>();
+      foldedNodes = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>();
+      changedNodes = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>();
       nodeImpacts = new Dictionary<ISymbolicExpressionTreeNode, double>();
       this.Caption = "Interactive Solution Simplifier";
+
+      // initialize the tree modifier that will be used to perform edit operations over the tree
+      treeChart.ModifyTree = Modify;
+    }
+
+    /// <summary>
+    /// Remove, Replace or Insert subtrees
+    /// </summary>
+    /// <param name="tree">The symbolic expression tree</param>
+    /// <param name="node">The insertion point (the parent node who will receive a new child)</param>
+    /// <param name="oldChild">The subtree to be replaced</param>
+    /// <param name="newChild">The replacement subtree</param>
+    /// <param name="removeSubtree">Flag used to indicate if whole subtrees should be removed (default behavior), or just the subtree root</param>
+    private void Modify(ISymbolicExpressionTree tree, ISymbolicExpressionTreeNode node, ISymbolicExpressionTreeNode oldChild, ISymbolicExpressionTreeNode newChild,
+                        bool removeSubtree = true) {
+      if (oldChild == null && newChild == null) throw new ArgumentException();
+      if (oldChild == null) { // insertion operation
+        node.AddSubtree(newChild);
+        newChild.Parent = node;
+        treeChart.Tree = tree; // because a new node is present in the tree, the visualNodes dictionary needs to be updated
+      } else if (newChild == null) { // removal operation
+        // use switch instead of if/else purely for aesthetical reasons (to avoid nested ifs and elses)
+        switch (removeSubtree) {
+          case true:
+            // remove the whole subtree
+            node.RemoveSubtree(node.IndexOfSubtree(oldChild));
+            if (oldChild.SubtreeCount > 0)
+              foreach (var subtree in oldChild.IterateNodesBreadth()) {
+                changedNodes.Remove(subtree);
+                foldedNodes.Remove(subtree);
+              }
+            break;
+          case false:
+            // only remove the current node and try to preserve its subtrees
+            node.RemoveSubtree(node.IndexOfSubtree(oldChild));
+            if (oldChild.SubtreeCount > 0)
+              for (int i = oldChild.SubtreeCount - 1; i >= 0; --i) {
+                var subtree = oldChild.GetSubtree(i);
+                oldChild.RemoveSubtree(i);
+                node.AddSubtree(subtree);
+              }
+            break;
+        }
+        changedNodes.Remove(oldChild);
+        foldedNodes.Remove(oldChild);
+      } else { // replacement operation
+        var replacementIndex = node.IndexOfSubtree(oldChild);
+        node.RemoveSubtree(replacementIndex);
+        node.InsertSubtree(replacementIndex, newChild);
+        newChild.Parent = node;
+        if (changedNodes.ContainsKey(oldChild)) {
+          changedNodes.Add(newChild, changedNodes[oldChild]); // so that on double click the original node is restored
+          changedNodes.Remove(oldChild);
+        } else {
+          changedNodes.Add(newChild, oldChild);
+        }
+      }
+
+      if (IsValid(tree)) {
+        treeState = TreeState.Valid;
+        UpdateModel(Content.Model.SymbolicExpressionTree);
+        btnOptimizeConstants.Enabled = true;
+        btnSimplify.Enabled = true;
+        treeStatusValue.Text = "Valid";
+        treeStatusValue.ForeColor = Color.Green;
+        this.Refresh();
+      } else {
+        treeState = TreeState.Invalid;
+        btnOptimizeConstants.Enabled = true;
+        btnSimplify.Enabled = true;
+        treeStatusValue.Text = "Invalid";
+        treeStatusValue.ForeColor = Color.Red;
+        treeChart.Repaint();
+        this.Refresh();
+      }
+      foreach (var changedNode in changedNodes.Keys) {
+        var visualNode = treeChart.GetVisualSymbolicExpressionTreeNode(changedNode);
+        visualNode.LineColor = Color.DodgerBlue;
+        treeChart.RepaintNode(visualNode);
+      }
+    }
+
+    private static bool IsValid(ISymbolicExpressionTree tree) {
+      return !tree.IterateNodesPostfix().Any(node => node.SubtreeCount < node.Symbol.MinimumArity || node.SubtreeCount > node.Symbol.MaximumArity);
     }
 
@@ -64,6 +152,5 @@
     protected override void OnContentChanged() {
       base.OnContentChanged();
-      replacementNodes = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>();
-
+      foldedNodes = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>();
       UpdateView();
       viewHost.Content = this.Content;
@@ -77,5 +164,5 @@
       var replacementValues = CalculateReplacementValues(tree);
       foreach (var pair in replacementValues.Where(pair => !(pair.Key is ConstantTreeNode))) {
-        replacementNodes[pair.Key] = MakeConstantTreeNode(pair.Value);
+        foldedNodes[pair.Key] = MakeConstantTreeNode(pair.Value);
       }
 
@@ -95,19 +182,37 @@
     }
 
+    private void treeChart_SymbolicExpressionTreeNodeClicked(object sender, MouseEventArgs e) {
+      var visualNode = (VisualSymbolicExpressionTreeNode)sender;
+      if (visualNode == null) return;
+      var treeNode = visualNode.SymbolicExpressionTreeNode;
+      if (changedNodes.ContainsKey(treeNode)) {
+        visualNode.LineColor = Color.DodgerBlue;
+      } else if (treeNode is ConstantTreeNode && foldedNodes.ContainsKey(treeNode)) {
+        visualNode.LineColor = Color.DarkOrange;
+      } else {
+        visualNode.LineColor = Color.Black;
+      }
+      visualNode.TextColor = Color.Black;
+      treeChart.RepaintNode(visualNode);
+    }
+
     private void treeChart_SymbolicExpressionTreeNodeDoubleClicked(object sender, MouseEventArgs e) {
-      if (!treeChart.TreeValid) return;
+      if (treeState == TreeState.Invalid) return;
       var visualNode = (VisualSymbolicExpressionTreeNode)sender;
       var symbExprTreeNode = (SymbolicExpressionTreeNode)visualNode.SymbolicExpressionTreeNode;
       if (symbExprTreeNode == null) return;
-      if (!replacementNodes.ContainsKey(symbExprTreeNode)) return;
-
       var tree = Content.Model.SymbolicExpressionTree;
-      int indexOfReplacementNode = symbExprTreeNode.Parent.IndexOfSubtree(symbExprTreeNode);
-      SwitchNodeWithReplacementNode(symbExprTreeNode.Parent, indexOfReplacementNode);
-      UpdateModel(tree);
-    }
-
-    private void treeChart_SymbolicExpressionTreeChanged(object sender, EventArgs e) {
-      UpdateModel(Content.Model.SymbolicExpressionTree);
+      var parent = symbExprTreeNode.Parent;
+      int indexOfSubtree = parent.IndexOfSubtree(symbExprTreeNode);
+      if (changedNodes.ContainsKey(symbExprTreeNode)) {
+        parent.RemoveSubtree(indexOfSubtree);
+        ISymbolicExpressionTreeNode originalNode = changedNodes[symbExprTreeNode];
+        parent.InsertSubtree(indexOfSubtree, originalNode);
+        changedNodes.Remove(symbExprTreeNode);
+        UpdateModel(tree);
+      } else if (foldedNodes.ContainsKey(symbExprTreeNode)) {
+        SwitchNodeWithReplacementNode(parent, indexOfSubtree);
+        UpdateModel(tree);
+      }
     }
 
@@ -115,10 +220,10 @@
       ISymbolicExpressionTreeNode subTree = parent.GetSubtree(subTreeIndex);
       parent.RemoveSubtree(subTreeIndex);
-      if (replacementNodes.ContainsKey(subTree)) {
-        var replacementNode = replacementNodes[subTree];
+      if (foldedNodes.ContainsKey(subTree)) {
+        var replacementNode = foldedNodes[subTree];
         parent.InsertSubtree(subTreeIndex, replacementNode);
         // exchange key and value 
-        replacementNodes.Remove(subTree);
-        replacementNodes.Add(replacementNode, subTree);
+        foldedNodes.Remove(subTree);
+        foldedNodes.Add(replacementNode, subTree);
       }
     }
@@ -147,10 +252,10 @@
           }
           visualTree.ToolTip += Environment.NewLine + "Node impact: " + impact;
-          var constantReplacementNode = replacementNodes[treeNode] as ConstantTreeNode;
+          var constantReplacementNode = foldedNodes[treeNode] as ConstantTreeNode;
           if (constantReplacementNode != null) {
             visualTree.ToolTip += Environment.NewLine + "Replacement value: " + constantReplacementNode.Value;
           }
         }
-        if (visualTree != null && treeNode is ConstantTreeNode && replacementNodes.ContainsKey(treeNode)) {
+        if (visualTree != null && treeNode is ConstantTreeNode && foldedNodes.ContainsKey(treeNode)) {
           visualTree.LineColor = Color.DarkOrange;
         }
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicExpressionTreeChart.Designer.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicExpressionTreeChart.Designer.cs	(revision 9005)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicExpressionTreeChart.Designer.cs	(revision 9006)
@@ -54,6 +54,4 @@
       this.removeSubtreeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
       this.pasteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
-      this.treeStatusLabel = new System.Windows.Forms.Label();
-      this.treeStatusValue = new System.Windows.Forms.Label();
       this.toolStripSeparator = new System.Windows.Forms.ToolStripSeparator();
       this.copyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
@@ -63,5 +61,5 @@
       // 
       this.insertNodeToolStripMenuItem.Name = "insertNodeToolStripMenuItem";
-      this.insertNodeToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
+      this.insertNodeToolStripMenuItem.Size = new System.Drawing.Size(147, 22);
       this.insertNodeToolStripMenuItem.Text = "Insert Node";
       this.insertNodeToolStripMenuItem.Click += new System.EventHandler(this.insertNodeToolStripMenuItem_Click);
@@ -69,20 +67,13 @@
       // changeNodeToolStripMenuItem
       // 
-      this.changeNodeToolStripMenuItem.Name = "editNodeToolStripMenuItem";
-      this.changeNodeToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
+      this.changeNodeToolStripMenuItem.Name = "changeNodeToolStripMenuItem";
+      this.changeNodeToolStripMenuItem.Size = new System.Drawing.Size(147, 22);
       this.changeNodeToolStripMenuItem.Text = "Change Node";
       this.changeNodeToolStripMenuItem.Click += new System.EventHandler(this.changeNodeToolStripMenuItem_Click);
-      // 
-      // copyToolStripMenuItem
-      // 
-      this.copyToolStripMenuItem.Name = "copyToolStripMenuItem";
-      this.copyToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
-      this.copyToolStripMenuItem.Text = "Copy";
-      this.copyToolStripMenuItem.Click += new System.EventHandler(this.copyToolStripMenuItem_Click);
       // 
       // cutToolStripMenuItem
       // 
       this.cutToolStripMenuItem.Name = "cutToolStripMenuItem";
-      this.cutToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
+      this.cutToolStripMenuItem.Size = new System.Drawing.Size(147, 22);
       this.cutToolStripMenuItem.Text = "Cut";
       this.cutToolStripMenuItem.Click += new System.EventHandler(this.cutToolStripMenuItem_Click);
@@ -94,5 +85,5 @@
             this.removeSubtreeToolStripMenuItem});
       this.removeToolStripMenuItem.Name = "removeToolStripMenuItem";
-      this.removeToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
+      this.removeToolStripMenuItem.Size = new System.Drawing.Size(147, 22);
       this.removeToolStripMenuItem.Text = "Remove";
       this.removeToolStripMenuItem.Click += new System.EventHandler(this.removeSubtreeToolStripMenuItem_Click);
@@ -101,5 +92,5 @@
       // 
       this.removeNodeToolStripMenuItem.Name = "removeNodeToolStripMenuItem";
-      this.removeNodeToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
+      this.removeNodeToolStripMenuItem.Size = new System.Drawing.Size(114, 22);
       this.removeNodeToolStripMenuItem.Text = "Node";
       this.removeNodeToolStripMenuItem.Click += new System.EventHandler(this.removeNodeToolStripMenuItem_Click);
@@ -108,5 +99,5 @@
       // 
       this.removeSubtreeToolStripMenuItem.Name = "removeSubtreeToolStripMenuItem";
-      this.removeSubtreeToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
+      this.removeSubtreeToolStripMenuItem.Size = new System.Drawing.Size(114, 22);
       this.removeSubtreeToolStripMenuItem.Text = "Subtree";
       this.removeSubtreeToolStripMenuItem.Click += new System.EventHandler(this.removeSubtreeToolStripMenuItem_Click);
@@ -115,38 +106,7 @@
       // 
       this.pasteToolStripMenuItem.Name = "pasteToolStripMenuItem";
-      this.pasteToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
+      this.pasteToolStripMenuItem.Size = new System.Drawing.Size(147, 22);
       this.pasteToolStripMenuItem.Text = "Paste";
       this.pasteToolStripMenuItem.Click += new System.EventHandler(this.pasteToolStripMenuItem_Clicked);
-      //
-      // contextMenuStrip
-      //
-      this.contextMenuStrip.Opened += this.contextMenuStrip_Opened;
-      this.contextMenuStrip.Items.AddRange(new ToolStripItem[] { insertNodeToolStripMenuItem, 
-	                                                               changeNodeToolStripMenuItem, 
-	                                                               copyToolStripMenuItem, 
-	                                                               cutToolStripMenuItem, 
-	                                                               removeToolStripMenuItem, 
-	                                                               pasteToolStripMenuItem });
-      // 
-      // treeStatusLabel
-      // 
-      this.treeStatusLabel.AutoSize = true;
-      this.treeStatusLabel.BackColor = System.Drawing.Color.Transparent;
-      this.treeStatusLabel.Location = new System.Drawing.Point(3, 0);
-      this.treeStatusLabel.Name = "treeStatusLabel";
-      this.treeStatusLabel.Size = new System.Drawing.Size(68, 13);
-      this.treeStatusLabel.TabIndex = 0;
-      this.treeStatusLabel.Text = "Tree Status: ";
-      // 
-      // treeStatusValue
-      // 
-      this.treeStatusValue.AutoSize = true;
-      this.treeStatusValue.BackColor = System.Drawing.Color.Transparent;
-      this.treeStatusValue.ForeColor = System.Drawing.Color.Green;
-      this.treeStatusValue.Location = new System.Drawing.Point(77, 0);
-      this.treeStatusValue.Name = "treeStatusValue";
-      this.treeStatusValue.Size = new System.Drawing.Size(30, 13);
-      this.treeStatusValue.TabIndex = 1;
-      this.treeStatusValue.Text = "Valid";
       // 
       // toolStripSeparator
@@ -155,15 +115,28 @@
       this.toolStripSeparator.Size = new System.Drawing.Size(149, 6);
       // 
+      // copyToolStripMenuItem
+      // 
+      this.copyToolStripMenuItem.Name = "copyToolStripMenuItem";
+      this.copyToolStripMenuItem.Size = new System.Drawing.Size(147, 22);
+      this.copyToolStripMenuItem.Text = "Copy";
+      this.copyToolStripMenuItem.Click += new System.EventHandler(this.copyToolStripMenuItem_Click);
+      //
+      // contextMenuStrip
+      //
+      this.contextMenuStrip.Opened += this.contextMenuStrip_Opened;
+      this.contextMenuStrip.Items.AddRange(new ToolStripItem[] { insertNodeToolStripMenuItem, 
+                                                                 changeNodeToolStripMenuItem, 
+                                                                 copyToolStripMenuItem, 
+                                                                 cutToolStripMenuItem, 
+                                                                 removeToolStripMenuItem, 
+                                                                 pasteToolStripMenuItem });
+      // 
       // InteractiveSymbolicExpressionTreeChart
       // 
       this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
-      this.Controls.Add(this.treeStatusLabel);
-      this.Controls.Add(this.treeStatusValue);
       this.DoubleBuffered = true;
       this.Name = "InteractiveSymbolicExpressionTreeChart";
-      this.MouseClick += new System.Windows.Forms.MouseEventHandler(this.InteractiveSymbolicExpressionTreeChart_MouseClick);
       this.ResumeLayout(false);
-      this.PerformLayout();
 
     }
@@ -178,6 +151,5 @@
 
     #endregion
-    private Label treeStatusLabel;
-    private Label treeStatusValue;
+
     private ToolStripSeparator toolStripSeparator;
     private ToolStripMenuItem copyToolStripMenuItem;
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicExpressionTreeChart.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicExpressionTreeChart.cs	(revision 9005)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicExpressionTreeChart.cs	(revision 9006)
@@ -21,5 +21,4 @@
 
 using System;
-using System.Collections.Generic;
 using System.Drawing;
 using System.Linq;
@@ -29,13 +28,16 @@
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Views {
-  public sealed partial class InteractiveSymbolicExpressionTreeChart : SymbolicExpressionTreeChart {
+  internal delegate void
+  ModifyTree(ISymbolicExpressionTree tree, ISymbolicExpressionTreeNode node, ISymbolicExpressionTreeNode oldChild, ISymbolicExpressionTreeNode newChild,
+             bool removeSubtree = true);
+
+  internal sealed partial class InteractiveSymbolicExpressionTreeChart : SymbolicExpressionTreeChart {
     private ISymbolicExpressionTreeNode tempNode; // node in clipboard (to be cut/copy/pasted etc)
     private VisualSymbolicExpressionTreeNode currSelected; // currently selected node
-    private enum EditOp { NoOp, CopyNode, CopySubtree, CutNode, CutSubtree, RemoveNode, RemoveSubtree }
-    private enum TreeState { Valid, Invalid }
+    public enum EditOp { NoOp, CopySubtree, CutSubtree, ChangeNode, InsertNode, InsertSubtree, RemoveNode, RemoveSubtree }
     private EditOp lastOp = EditOp.NoOp;
-    private TreeState treeState = TreeState.Valid; // tree edit operations must leave the tree in a valid state
-
-    private Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> originalNodes; // map a new node to the original node it replaced
+
+    // delegate to notify the parent container (the view) about the tree edit operations that it needs to perform
+    public ModifyTree ModifyTree { get; set; }
 
     public InteractiveSymbolicExpressionTreeChart() {
@@ -43,32 +45,4 @@
       currSelected = null;
       tempNode = null;
-
-      originalNodes = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>();
-    }
-
-    public bool TreeValid { get { return TreeState.Valid == treeState; } }
-    // expose an additional event for signaling to the parent view when the tree structure was modified
-    // the emitting of the signal is conditional on the tree being valid, otherwise only a Repaint is issued
-    public event EventHandler SymbolicExpressionTreeChanged;
-    private void OnSymbolicExpressionTreeChanged(object sender, EventArgs e) {
-      if (IsValid(Tree)) {
-        treeStatusValue.Text = "Valid";
-        treeStatusValue.ForeColor = Color.Green;
-        treeState = TreeState.Valid;
-        var changed = SymbolicExpressionTreeChanged;
-        if (changed != null)
-          changed(sender, e);
-      } else {
-        treeStatusValue.Text = "Invalid";
-        treeStatusValue.ForeColor = Color.Red;
-        treeState = TreeState.Invalid;
-        Tree = Tree; // reinitialize the dictionaries and repaint
-      }
-      foreach (var node in originalNodes.Keys) {
-        var visualNode = GetVisualSymbolicExpressionTreeNode(node);
-        if (visualNode == null) continue;
-        visualNode.LineColor = Color.DodgerBlue;
-        RepaintNode(visualNode);
-      }
     }
 
@@ -77,5 +51,6 @@
       var point = menuStrip.SourceControl.PointToClient(Cursor.Position);
       var ea = new MouseEventArgs(MouseButtons.Left, 1, point.X, point.Y, 0);
-      InteractiveSymbolicExpressionTreeChart_MouseClick(null, ea);
+      var visualNode = FindVisualSymbolicExpressionTreeNodeAt(ea.X, ea.Y);
+      if (visualNode != null) { OnSymbolicExpressionTreeNodeClicked(visualNode, ea); };
 
       if (currSelected == null) {
@@ -103,9 +78,4 @@
       var visualTreeNode = (VisualSymbolicExpressionTreeNode)sender;
       var lastSelected = currSelected;
-      if (lastSelected != null) {
-        lastSelected.LineColor = originalNodes.ContainsKey(lastSelected.SymbolicExpressionTreeNode) ? Color.DodgerBlue : Color.Black;
-        RepaintNode(lastSelected);
-      }
-
       currSelected = visualTreeNode;
       if (currSelected != null) {
@@ -113,30 +83,11 @@
         RepaintNode(currSelected);
       }
+      if (lastSelected != null)
+        base.OnSymbolicExpressionTreeNodeClicked(lastSelected, e);
     }
 
     protected override void OnSymbolicExpressionTreeNodeDoubleClicked(object sender, MouseEventArgs e) {
-      var visualTreeNode = (VisualSymbolicExpressionTreeNode)sender;
-      if (originalNodes.ContainsKey(visualTreeNode.SymbolicExpressionTreeNode)) {
-        var originalNode = originalNodes[visualTreeNode.SymbolicExpressionTreeNode];
-
-        var parent = visualTreeNode.SymbolicExpressionTreeNode.Parent;
-        var i = parent.IndexOfSubtree(visualTreeNode.SymbolicExpressionTreeNode);
-        parent.RemoveSubtree(i);
-        parent.InsertSubtree(i, originalNode);
-
-        originalNodes.Remove(visualTreeNode.SymbolicExpressionTreeNode);
-        visualTreeNode.SymbolicExpressionTreeNode = originalNode;
-        OnSymbolicExpressionTreeChanged(sender, EventArgs.Empty);
-      } else {
-        currSelected = null; // because the tree node will be folded/unfolded 
-        base.OnSymbolicExpressionTreeNodeDoubleClicked(sender, e);
-        // at this point the tree got redrawn, so we mark the edited nodes
-        foreach (var node in originalNodes.Keys) {
-          var visualNode = GetVisualSymbolicExpressionTreeNode(node);
-          if (visualNode == null) continue;
-          visualNode.LineColor = Color.DodgerBlue;
-          RepaintNode(visualNode);
-        }
-      }
+      currSelected = null;
+      base.OnSymbolicExpressionTreeNodeDoubleClicked(sender, e);
     }
 
@@ -148,32 +99,28 @@
         dialog.SetAllowedSymbols(parent.Grammar.AllowedSymbols.Where(s => s.Enabled && s.InitialFrequency > 0.0 && !(s is ProgramRootSymbol || s is StartSymbol || s is Defun)));
         dialog.ShowDialog(this);
-
-        if (dialog.DialogResult == DialogResult.OK) {
-          var symbol = dialog.SelectedSymbol();
-          var node = symbol.CreateTreeNode();
-          if (node is ConstantTreeNode) {
-            var constant = node as ConstantTreeNode;
-            constant.Value = double.Parse(dialog.constantValueTextBox.Text);
-          } else if (node is VariableTreeNode) {
-            var variable = node as VariableTreeNode;
-            variable.Weight = double.Parse(dialog.variableWeightTextBox.Text);
-            variable.VariableName = dialog.variableNamesCombo.Text;
-          } else {
-            if (node.Symbol.MinimumArity <= parent.SubtreeCount && node.Symbol.MaximumArity >= parent.SubtreeCount) {
-              for (int i = parent.SubtreeCount - 1; i >= 0; --i) {
-                var child = parent.GetSubtree(i);
-                parent.RemoveSubtree(i);
-                node.AddSubtree(child);
-              }
-            }
-          }
-          if (parent.Symbol.MaximumArity > parent.SubtreeCount) {
-            parent.AddSubtree(node);
-            Tree = Tree;
-          }
-          OnSymbolicExpressionTreeChanged(sender, e);
-          currSelected = null;
-        }
-      }
+        if (dialog.DialogResult != DialogResult.OK) return;
+
+        var symbol = dialog.SelectedSymbol();
+        var node = symbol.CreateTreeNode();
+        if (node is ConstantTreeNode) {
+          var constant = node as ConstantTreeNode;
+          constant.Value = double.Parse(dialog.constantValueTextBox.Text);
+        } else if (node is VariableTreeNode) {
+          var variable = node as VariableTreeNode;
+          variable.Weight = double.Parse(dialog.variableWeightTextBox.Text);
+          variable.VariableName = dialog.variableNamesCombo.Text;
+        } else if (node.Symbol.MinimumArity <= parent.SubtreeCount && node.Symbol.MaximumArity >= parent.SubtreeCount) {
+          for (int i = parent.SubtreeCount - 1; i >= 0; --i) {
+            var child = parent.GetSubtree(i);
+            parent.RemoveSubtree(i);
+            node.AddSubtree(child);
+          }
+        }
+        // the if condition will always be true for the final else clause above
+        if (parent.Symbol.MaximumArity > parent.SubtreeCount) {
+          ModifyTree(Tree, parent, null, node);
+        }
+      }
+      currSelected = null;
     }
 
@@ -181,11 +128,7 @@
       if (currSelected == null) return;
 
-      ISymbolicExpressionTreeNode node;
-      if (originalNodes.ContainsKey(currSelected.SymbolicExpressionTreeNode)) {
-        node = currSelected.SymbolicExpressionTreeNode;
-      } else {
-        node = (ISymbolicExpressionTreeNode)currSelected.SymbolicExpressionTreeNode.Clone();
-      }
+      var node = (ISymbolicExpressionTreeNode)currSelected.SymbolicExpressionTreeNode.Clone();
       var originalNode = currSelected.SymbolicExpressionTreeNode;
+
       ISymbolicExpressionTreeNode newNode = null;
       var result = DialogResult.Cancel;
@@ -204,17 +147,20 @@
       }
       if (result != DialogResult.OK) return;
-      if (originalNode != newNode) {
-        var parent = originalNode.Parent;
-        int i = parent.IndexOfSubtree(originalNode);
-        parent.RemoveSubtree(i);
-        parent.InsertSubtree(i, newNode);
-        originalNodes[newNode] = originalNode;
-        currSelected.SymbolicExpressionTreeNode = newNode;
-      }
-      OnSymbolicExpressionTreeChanged(sender, EventArgs.Empty);
+      ModifyTree(Tree, originalNode.Parent, originalNode, newNode); // this will replace the original node with the new node
+      currSelected = null;
     }
 
     private void cutToolStripMenuItem_Click(object sender, EventArgs e) {
       lastOp = EditOp.CutSubtree;
+      if (tempNode != null) {
+        foreach (var subtree in tempNode.IterateNodesBreadth()) {
+          var vNode = GetVisualSymbolicExpressionTreeNode(subtree);
+          base.OnSymbolicExpressionTreeNodeClicked(vNode, null);
+          if (subtree.Parent != null) {
+            var vArc = GetVisualSymbolicExpressionTreeNodeConnection(subtree.Parent, subtree);
+            vArc.LineColor = Color.Black;
+          }
+        }
+      }
       tempNode = currSelected.SymbolicExpressionTreeNode;
       foreach (var node in tempNode.IterateNodesPostfix()) {
@@ -229,9 +175,19 @@
         }
       }
+      currSelected = null;
       Repaint();
     }
-
     private void copyToolStripMenuItem_Click(object sender, EventArgs e) {
       lastOp = EditOp.CopySubtree;
+      if (tempNode != null) {
+        foreach (var subtree in tempNode.IterateNodesBreadth()) {
+          var vNode = GetVisualSymbolicExpressionTreeNode(subtree);
+          base.OnSymbolicExpressionTreeNodeClicked(vNode, null);
+          if (subtree.Parent != null) {
+            var vArc = GetVisualSymbolicExpressionTreeNodeConnection(subtree.Parent, subtree);
+            vArc.LineColor = Color.Black;
+          }
+        }
+      }
       tempNode = currSelected.SymbolicExpressionTreeNode;
       foreach (var node in tempNode.IterateNodesPostfix()) {
@@ -245,39 +201,22 @@
         }
       }
+      currSelected = null;
       Repaint();
     }
-
     private void removeNodeToolStripMenuItem_Click(object sender, EventArgs e) {
       lastOp = EditOp.RemoveNode;
       var node = currSelected.SymbolicExpressionTreeNode;
-      var parent = node.Parent;
-      if (parent == null || parent.Symbol is StartSymbol || parent.Symbol is ProgramRootSymbol)
-        return; // the operation would result in the deletion of the entire tree
-      if (parent.Symbol.MaximumArity >= node.SubtreeCount + parent.SubtreeCount - 1) { // -1 because tempNode will be removed
-        parent.RemoveSubtree(parent.IndexOfSubtree(node));
-        for (int i = node.SubtreeCount - 1; i >= 0; --i) {
-          var child = node.GetSubtree(i);
-          node.RemoveSubtree(i);
-          parent.AddSubtree(child);
-        }
-      }
-      OnSymbolicExpressionTreeChanged(sender, e);
+      ModifyTree(Tree, node.Parent, node, null, removeSubtree: false);
       currSelected = null; // because the currently selected node was just deleted
     }
-
     private void removeSubtreeToolStripMenuItem_Click(object sender, EventArgs e) {
-      lastOp = EditOp.RemoveSubtree;
+      lastOp = EditOp.RemoveNode;
       var node = currSelected.SymbolicExpressionTreeNode;
-      var parent = node.Parent;
-      if (parent == null || parent.Symbol is StartSymbol || parent.Symbol is ProgramRootSymbol)
-        return; // the operation makes no sense as it would result in the deletion of the entire tree
-      parent.RemoveSubtree(parent.IndexOfSubtree(node));
-      OnSymbolicExpressionTreeChanged(sender, e);
+      ModifyTree(Tree, node.Parent, node, null, removeSubtree: true);
       currSelected = null; // because the currently selected node was just deleted
-    }
-
+      contextMenuStrip.Close(); // avoid display of submenus since the action has already been performed
+    }
     private void pasteToolStripMenuItem_Clicked(object sender, EventArgs e) {
-      if (!(lastOp == EditOp.CopyNode || lastOp == EditOp.CopySubtree || lastOp == EditOp.CutNode || lastOp == EditOp.CutSubtree))
-        return;
+      if (!(lastOp == EditOp.CopySubtree || lastOp == EditOp.CutSubtree)) return;
       // check if the copied/cut node (stored in the tempNode) can be inserted as a child of the current selected node
       var node = currSelected.SymbolicExpressionTreeNode;
@@ -285,72 +224,21 @@
       // check if the currently selected node can accept the copied node as a child 
       // no need to check the grammar, an arity check will do just fine here
-      if (node.Symbol.MaximumArity > node.SubtreeCount) {
-        switch (lastOp) {
-          case (EditOp.CutNode): {
-              // when cutting a node from the tree, it's children become children of it's parent
-              var parent = tempNode.Parent;
-              // arity checks to see if parent can accept node's children (we assume the grammar is already ok with that)
-              // (otherise, the 'cut' part of the operation will just not do anything)
-              if (parent.Symbol.MaximumArity >= tempNode.SubtreeCount + parent.SubtreeCount - 1) { // -1 because tempNode will be removed
-                parent.RemoveSubtree(parent.IndexOfSubtree(tempNode));
-                for (int i = tempNode.SubtreeCount - 1; i >= 0; --i) {
-                  var child = tempNode.GetSubtree(i);
-                  tempNode.RemoveSubtree(i);
-                  parent.AddSubtree(child);
-                }
-                lastOp = EditOp.CopyNode;
-              }
-              break;
-            }
-          case (EditOp.CutSubtree): {
-              // cut subtree
-              var parent = tempNode.Parent;
-              parent.RemoveSubtree(parent.IndexOfSubtree(tempNode));
-              lastOp = EditOp.CopySubtree; // do this so the next paste will actually perform a copy   
-              break;
-            }
-          case (EditOp.CopyNode): {
-              // copy node
-              var clone = (SymbolicExpressionTreeNode)tempNode.Clone();
-              clone.Parent = tempNode.Parent;
-              tempNode = clone;
-              for (int i = tempNode.SubtreeCount - 1; i >= 0; --i) tempNode.RemoveSubtree(i);
-              break;
-            }
-          case (EditOp.CopySubtree): {
-              // copy subtree
-              var clone = (SymbolicExpressionTreeNode)tempNode.Clone();
-              clone.Parent = tempNode.Parent;
-              tempNode = clone;
-              break;
-            }
-        }
-        node.AddSubtree(tempNode);
-        Tree = Tree; // hack in order to trigger the reinitialization of the dictionaries after new nodes appeared in the tree
-        OnSymbolicExpressionTreeChanged(sender, e);
-        currSelected = null; // because the tree changed and was completely redrawn
-      }
-    }
-
-    private bool IsValid(ISymbolicExpressionTree tree) {
-      if (tree.IterateNodesPostfix().Any(node => node.SubtreeCount < node.Symbol.MinimumArity || node.SubtreeCount > node.Symbol.MaximumArity)) {
-        treeState = TreeState.Invalid;
-        return false;
-      }
-      treeState = TreeState.Valid;
-      return true;
-    }
-
-    private void InteractiveSymbolicExpressionTreeChart_MouseClick(object sender, MouseEventArgs e) {
-      var visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);
-      if (currSelected != null) {
-        currSelected.LineColor = originalNodes.ContainsKey(currSelected.SymbolicExpressionTreeNode) ? Color.DodgerBlue : Color.Black;
-        RepaintNode(currSelected);
-      }
-      currSelected = visualTreeNode;
-      if (currSelected != null) {
-        currSelected.LineColor = Color.LightGreen;
-        RepaintNode(currSelected);
-      }
+      if (node.Symbol.MaximumArity <= node.SubtreeCount) return;
+      switch (lastOp) {
+        case EditOp.CutSubtree: {
+            ModifyTree(Tree, tempNode.Parent, tempNode, null); //remove node from its original parent
+            ModifyTree(Tree, node, null, tempNode);//insert it as a child to the new parent
+            lastOp = EditOp.CopySubtree; //do this so the next paste will actually perform a copy   
+            break;
+          }
+        case EditOp.CopySubtree: {
+            var clone = (SymbolicExpressionTreeNode)tempNode.Clone();
+            clone.Parent = tempNode.Parent;
+            tempNode = clone;
+            ModifyTree(Tree, node, null, tempNode);
+            break;
+          }
+      }
+      currSelected = null; // because the tree will have changed
     }
   }
