Changeset 11086 for trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs
- Timestamp:
- 07/04/14 13:38:38 (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs
r10799 r11086 1 1 #region License Information 2 2 /* HeuristicLab 3 * Copyright (C) 2002-201 3Heuristic and Evolutionary Algorithms Laboratory (HEAL)3 * Copyright (C) 2002-2014 Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 4 * 5 5 * This file is part of HeuristicLab. … … 33 33 public abstract partial class InteractiveSymbolicDataAnalysisSolutionSimplifierView : AsynchronousContentView { 34 34 private Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> foldedNodes; 35 private Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> changedNodes; 35 36 private Dictionary<ISymbolicExpressionTreeNode, double> nodeImpacts; 37 36 38 private enum TreeState { Valid, Invalid } 37 38 public InteractiveSymbolicDataAnalysisSolutionSimplifierView() { 39 private TreeState treeState; 40 41 protected InteractiveSymbolicDataAnalysisSolutionSimplifierView() { 39 42 InitializeComponent(); 40 43 foldedNodes = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>(); 44 changedNodes = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>(); 41 45 nodeImpacts = new Dictionary<ISymbolicExpressionTreeNode, double>(); 42 46 this.Caption = "Interactive Solution Simplifier"; 47 48 // initialize the tree modifier that will be used to perform edit operations over the tree 49 treeChart.ModifyTree = Modify; 50 } 51 52 /// <summary> 53 /// Remove, Replace or Insert subtrees 54 /// </summary> 55 /// <param name="tree">The symbolic expression tree</param> 56 /// <param name="parent">The insertion point (ie, the parent node who will receive a new child)</param> 57 /// <param name="oldChild">The subtree to be replaced</param> 58 /// <param name="newChild">The replacement subtree</param> 59 /// <param name="removeSubtree">Flag used to indicate if whole subtrees should be removed (default behavior), or just the subtree root</param> 60 private void Modify(ISymbolicExpressionTree tree, ISymbolicExpressionTreeNode parent, 61 ISymbolicExpressionTreeNode oldChild, ISymbolicExpressionTreeNode newChild, bool removeSubtree = true) { 62 if (oldChild == null && newChild == null) 63 throw new ArgumentNullException("Cannot deduce operation type from the arguments. Please provide non null operands."); 64 if (oldChild == null) { 65 // insertion operation 66 parent.AddSubtree(newChild); 67 newChild.Parent = parent; 68 } else if (newChild == null) { 69 // removal operation 70 parent.RemoveSubtree(parent.IndexOfSubtree(oldChild)); 71 if (!removeSubtree) { 72 for (int i = oldChild.SubtreeCount - 1; i >= 0; --i) { 73 var subtree = oldChild.GetSubtree(i); 74 oldChild.RemoveSubtree(i); 75 parent.AddSubtree(subtree); 76 } 77 } 78 } else { 79 // replacement operation 80 var replacementIndex = parent.IndexOfSubtree(oldChild); 81 parent.RemoveSubtree(replacementIndex); 82 parent.InsertSubtree(replacementIndex, newChild); 83 newChild.Parent = parent; 84 if (changedNodes.ContainsKey(oldChild)) { 85 changedNodes.Add(newChild, changedNodes[oldChild]); // so that on double click the original node is restored 86 changedNodes.Remove(oldChild); 87 } else { 88 changedNodes.Add(newChild, oldChild); 89 } 90 } 91 treeState = IsValid(tree) ? TreeState.Valid : TreeState.Invalid; 92 switch (treeState) { 93 case TreeState.Valid: 94 this.grpViewHost.Enabled = true; 95 UpdateModel(Content.Model.SymbolicExpressionTree); 96 break; 97 case TreeState.Invalid: 98 this.grpViewHost.Enabled = false; 99 break; 100 } 101 } 102 103 // the optimizer always assumes 2 children for multiplication and addition nodes 104 // thus, we enforce that the tree stays valid so that the constant optimization won't throw an exception 105 // by returning 2 as the minimum allowed arity for addition and multiplication symbols 106 private readonly Func<ISymbol, int> GetMinArity = symbol => { 107 var min = symbol.MinimumArity; 108 if (symbol is Multiplication || symbol is Division) return Math.Max(2, min); 109 return min; 110 }; 111 private bool IsValid(ISymbolicExpressionTree tree) { 112 treeChart.Tree = tree; 113 treeChart.Repaint(); 114 bool valid = !tree.IterateNodesPostfix().Any(node => node.SubtreeCount < GetMinArity(node.Symbol) || node.SubtreeCount > node.Symbol.MaximumArity); 115 if (valid) { 116 btnOptimizeConstants.Enabled = true; 117 btnSimplify.Enabled = true; 118 treeStatusValue.Text = "Valid"; 119 treeStatusValue.ForeColor = Color.Green; 120 } else { 121 btnOptimizeConstants.Enabled = false; 122 btnSimplify.Enabled = false; 123 treeStatusValue.Text = "Invalid"; 124 treeStatusValue.ForeColor = Color.Red; 125 } 126 this.Refresh(); 127 return valid; 43 128 } 44 129 … … 83 168 84 169 var impactAndReplacementValues = CalculateImpactAndReplacementValues(tree); 85 nodeImpacts = impactAndReplacementValues.ToDictionary(x => x.Key, x => x.Value.Item1);86 170 var replacementValues = impactAndReplacementValues.ToDictionary(x => x.Key, x => x.Value.Item2); 87 171 foreach (var pair in replacementValues.Where(pair => !(pair.Key is ConstantTreeNode))) { 88 172 foldedNodes[pair.Key] = MakeConstantTreeNode(pair.Value); 89 173 } 174 nodeImpacts = impactAndReplacementValues.ToDictionary(x => x.Key, x => x.Value.Item1); 90 175 PaintNodeImpacts(); 91 176 } … … 104 189 105 190 private void treeChart_SymbolicExpressionTreeNodeDoubleClicked(object sender, MouseEventArgs e) { 191 if (treeState == TreeState.Invalid) return; 106 192 var visualNode = (VisualTreeNode<ISymbolicExpressionTreeNode>)sender; 107 if (visualNode.Content == null) { throw new Exception("Visual node content cannot be null."); }193 if (visualNode.Content == null) { throw new Exception("VisualNode content cannot be null."); } 108 194 var symbExprTreeNode = (SymbolicExpressionTreeNode)visualNode.Content; 109 if (!foldedNodes.ContainsKey(symbExprTreeNode)) return; // constant nodes cannot be folded195 var tree = Content.Model.SymbolicExpressionTree; 110 196 var parent = symbExprTreeNode.Parent; 111 197 int indexOfSubtree = parent.IndexOfSubtree(symbExprTreeNode); 112 SwitchNodeWithReplacementNode(parent, indexOfSubtree); 113 UpdateModel(Content.Model.SymbolicExpressionTree); 198 if (changedNodes.ContainsKey(symbExprTreeNode)) { 199 // undo node change 200 parent.RemoveSubtree(indexOfSubtree); 201 var originalNode = changedNodes[symbExprTreeNode]; 202 parent.InsertSubtree(indexOfSubtree, originalNode); 203 changedNodes.Remove(symbExprTreeNode); 204 } else if (foldedNodes.ContainsKey(symbExprTreeNode)) { 205 // undo node folding 206 SwitchNodeWithReplacementNode(parent, indexOfSubtree); 207 } 208 UpdateModel(tree); 114 209 } 115 210 … … 130 225 double max = impacts.Max(); 131 226 double min = impacts.Min(); 132 foreach ( vartreeNode in Content.Model.SymbolicExpressionTree.IterateNodesPostfix()) {227 foreach (ISymbolicExpressionTreeNode treeNode in Content.Model.SymbolicExpressionTree.IterateNodesPostfix()) { 133 228 VisualTreeNode<ISymbolicExpressionTreeNode> visualTree = treeChart.GetVisualSymbolicExpressionTreeNode(treeNode); 134 229 135 230 if (!(treeNode is ConstantTreeNode) && nodeImpacts.ContainsKey(treeNode)) { 136 visualTree.ToolTip = visualTree.Content.ToString(); // to avoid duplicate tooltips231 visualTree.ToolTip = visualTree.Content.ToString(); 137 232 double impact = nodeImpacts[treeNode]; 138 233 … … 156 251 } 157 252 if (visualTree != null) 158 if (treeNode is ConstantTreeNode && foldedNodes.ContainsKey(treeNode)) { 253 if (changedNodes.ContainsKey(treeNode)) { 254 visualTree.LineColor = Color.DodgerBlue; 255 } else if (treeNode is ConstantTreeNode && foldedNodes.ContainsKey(treeNode)) { 159 256 visualTree.LineColor = Color.DarkOrange; 160 257 }
Note: See TracChangeset
for help on using the changeset viewer.