Changeset 11150 for stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs
Legend:
- Unmodified
- Added
- Removed
-
stable
- Property svn:mergeinfo changed
/trunk/sources merged: 9930,11086,11111-11112,11115,11123
- Property svn:mergeinfo changed
-
stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Views
- Property svn:mergeinfo changed
/trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Views merged: 9930,11086,11111-11112,11115,11123
- Property svn:mergeinfo changed
-
stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs
r11146 r11150 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.Visible = false; 119 } else { 120 btnOptimizeConstants.Enabled = false; 121 btnSimplify.Enabled = false; 122 treeStatusValue.Visible = true; 123 } 124 this.Refresh(); 125 return valid; 43 126 } 44 127 … … 83 166 84 167 var impactAndReplacementValues = CalculateImpactAndReplacementValues(tree); 85 nodeImpacts = impactAndReplacementValues.ToDictionary(x => x.Key, x => x.Value.Item1);86 168 var replacementValues = impactAndReplacementValues.ToDictionary(x => x.Key, x => x.Value.Item2); 87 169 foreach (var pair in replacementValues.Where(pair => !(pair.Key is ConstantTreeNode))) { 88 170 foldedNodes[pair.Key] = MakeConstantTreeNode(pair.Value); 89 171 } 172 nodeImpacts = impactAndReplacementValues.ToDictionary(x => x.Key, x => x.Value.Item1); 90 173 PaintNodeImpacts(); 91 174 } … … 104 187 105 188 private void treeChart_SymbolicExpressionTreeNodeDoubleClicked(object sender, MouseEventArgs e) { 189 if (treeState == TreeState.Invalid) return; 106 190 var visualNode = (VisualTreeNode<ISymbolicExpressionTreeNode>)sender; 107 if (visualNode.Content == null) { throw new Exception("Visual node content cannot be null."); }191 if (visualNode.Content == null) { throw new Exception("VisualNode content cannot be null."); } 108 192 var symbExprTreeNode = (SymbolicExpressionTreeNode)visualNode.Content; 109 if (!foldedNodes.ContainsKey(symbExprTreeNode)) return; // constant nodes cannot be folded193 var tree = Content.Model.SymbolicExpressionTree; 110 194 var parent = symbExprTreeNode.Parent; 111 195 int indexOfSubtree = parent.IndexOfSubtree(symbExprTreeNode); 112 SwitchNodeWithReplacementNode(parent, indexOfSubtree); 113 UpdateModel(Content.Model.SymbolicExpressionTree); 196 if (changedNodes.ContainsKey(symbExprTreeNode)) { 197 // undo node change 198 parent.RemoveSubtree(indexOfSubtree); 199 var originalNode = changedNodes[symbExprTreeNode]; 200 parent.InsertSubtree(indexOfSubtree, originalNode); 201 changedNodes.Remove(symbExprTreeNode); 202 } else if (foldedNodes.ContainsKey(symbExprTreeNode)) { 203 // undo node folding 204 SwitchNodeWithReplacementNode(parent, indexOfSubtree); 205 } 206 UpdateModel(tree); 114 207 } 115 208 … … 130 223 double max = impacts.Max(); 131 224 double min = impacts.Min(); 132 foreach ( vartreeNode in Content.Model.SymbolicExpressionTree.IterateNodesPostfix()) {225 foreach (ISymbolicExpressionTreeNode treeNode in Content.Model.SymbolicExpressionTree.IterateNodesPostfix()) { 133 226 VisualTreeNode<ISymbolicExpressionTreeNode> visualTree = treeChart.GetVisualSymbolicExpressionTreeNode(treeNode); 134 227 135 228 if (!(treeNode is ConstantTreeNode) && nodeImpacts.ContainsKey(treeNode)) { 136 visualTree.ToolTip = visualTree.Content.ToString(); // to avoid duplicate tooltips229 visualTree.ToolTip = visualTree.Content.ToString(); 137 230 double impact = nodeImpacts[treeNode]; 138 231 … … 156 249 } 157 250 if (visualTree != null) 158 if (treeNode is ConstantTreeNode && foldedNodes.ContainsKey(treeNode)) { 251 if (changedNodes.ContainsKey(treeNode)) { 252 visualTree.LineColor = Color.DodgerBlue; 253 } else if (treeNode is ConstantTreeNode && foldedNodes.ContainsKey(treeNode)) { 159 254 visualTree.LineColor = Color.DarkOrange; 160 255 }
Note: See TracChangeset
for help on using the changeset viewer.