source: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs @ 9445

Last change on this file since 9445 was 9445, checked in by bburlacu, 8 years ago

#1763: We found a bug in the InteractiveSymbolicDataAnalysisSolutionSimplifierView: when the user removes one of the linear scaling nodes from the tree (using the new tree editing functionality) then clicks optimize, an exception is raised by the constants optimizer.

We removed the tree editing functionality from the trunk, to be added again and fixed after the release.

File size: 7.3 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Drawing;
25using System.Linq;
26using System.Windows.Forms;
27using HeuristicLab.Common;
28using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
29using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views;
30using HeuristicLab.MainForm.WindowsForms;
31
32namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Views {
33  public abstract partial class InteractiveSymbolicDataAnalysisSolutionSimplifierView : AsynchronousContentView {
34    private Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> foldedNodes;
35    private Dictionary<ISymbolicExpressionTreeNode, double> nodeImpacts;
36    private enum TreeState { Valid, Invalid }
37    private TreeState treeState;
38
39    public InteractiveSymbolicDataAnalysisSolutionSimplifierView() {
40      InitializeComponent();
41      foldedNodes = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>();
42      nodeImpacts = new Dictionary<ISymbolicExpressionTreeNode, double>();
43      this.Caption = "Interactive Solution Simplifier";
44    }
45
46    public new ISymbolicDataAnalysisSolution Content {
47      get { return (ISymbolicDataAnalysisSolution)base.Content; }
48      set { base.Content = value; }
49    }
50
51    protected override void RegisterContentEvents() {
52      base.RegisterContentEvents();
53      Content.ModelChanged += Content_Changed;
54      Content.ProblemDataChanged += Content_Changed;
55    }
56    protected override void DeregisterContentEvents() {
57      base.DeregisterContentEvents();
58      Content.ModelChanged -= Content_Changed;
59      Content.ProblemDataChanged -= Content_Changed;
60    }
61
62    private void Content_Changed(object sender, EventArgs e) {
63      UpdateView();
64    }
65
66    protected override void OnContentChanged() {
67      base.OnContentChanged();
68      foldedNodes = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>();
69      UpdateView();
70      viewHost.Content = this.Content;
71    }
72
73    private void UpdateView() {
74      if (Content == null || Content.Model == null || Content.ProblemData == null) return;
75      var tree = Content.Model.SymbolicExpressionTree;
76      treeChart.Tree = tree.Root.SubtreeCount > 1 ? new SymbolicExpressionTree(tree.Root) : new SymbolicExpressionTree(tree.Root.GetSubtree(0).GetSubtree(0));
77
78      var replacementValues = CalculateReplacementValues(tree);
79      foreach (var pair in replacementValues.Where(pair => !(pair.Key is ConstantTreeNode))) {
80        foldedNodes[pair.Key] = MakeConstantTreeNode(pair.Value);
81      }
82
83      nodeImpacts = CalculateImpactValues(tree);
84      PaintNodeImpacts();
85    }
86
87    protected abstract Dictionary<ISymbolicExpressionTreeNode, double> CalculateReplacementValues(ISymbolicExpressionTree tree);
88    protected abstract Dictionary<ISymbolicExpressionTreeNode, double> CalculateImpactValues(ISymbolicExpressionTree tree);
89    protected abstract void UpdateModel(ISymbolicExpressionTree tree);
90
91    private static ConstantTreeNode MakeConstantTreeNode(double value) {
92      var constant = new Constant { MinValue = value - 1, MaxValue = value + 1 };
93      var constantTreeNode = (ConstantTreeNode)constant.CreateTreeNode();
94      constantTreeNode.Value = value;
95      return constantTreeNode;
96    }
97
98    private void treeChart_SymbolicExpressionTreeNodeDoubleClicked(object sender, MouseEventArgs e) {
99      var visualNode = (VisualSymbolicExpressionTreeNode)sender;
100      var symbExprTreeNode = (SymbolicExpressionTreeNode)visualNode.SymbolicExpressionTreeNode;
101      if (symbExprTreeNode == null) return;
102      var tree = Content.Model.SymbolicExpressionTree;
103      var parent = symbExprTreeNode.Parent;
104      int indexOfSubtree = parent.IndexOfSubtree(symbExprTreeNode);
105      if (foldedNodes.ContainsKey(symbExprTreeNode)) {
106        // undo node folding
107        SwitchNodeWithReplacementNode(parent, indexOfSubtree);
108      }
109      UpdateModel(tree);
110    }
111
112    private void SwitchNodeWithReplacementNode(ISymbolicExpressionTreeNode parent, int subTreeIndex) {
113      ISymbolicExpressionTreeNode subTree = parent.GetSubtree(subTreeIndex);
114      parent.RemoveSubtree(subTreeIndex);
115      if (foldedNodes.ContainsKey(subTree)) {
116        var replacementNode = foldedNodes[subTree];
117        parent.InsertSubtree(subTreeIndex, replacementNode);
118        // exchange key and value
119        foldedNodes.Remove(subTree);
120        foldedNodes.Add(replacementNode, subTree);
121      }
122    }
123
124    private void PaintNodeImpacts() {
125      var impacts = nodeImpacts.Values;
126      double max = impacts.Max();
127      double min = impacts.Min();
128      foreach (ISymbolicExpressionTreeNode treeNode in Content.Model.SymbolicExpressionTree.IterateNodesPostfix()) {
129        VisualSymbolicExpressionTreeNode visualTree = treeChart.GetVisualSymbolicExpressionTreeNode(treeNode);
130
131        if (!(treeNode is ConstantTreeNode) && nodeImpacts.ContainsKey(treeNode)) {
132          double impact = nodeImpacts[treeNode];
133
134          // impact = 0 if no change
135          // impact < 0 if new solution is better
136          // impact > 0 if new solution is worse
137          if (impact < 0.0) {
138            // min is guaranteed to be < 0
139            visualTree.FillColor = Color.FromArgb((int)(impact / min * 255), Color.Red);
140          } else if (impact.IsAlmost(0.0)) {
141            visualTree.FillColor = Color.White;
142          } else {
143            // max is guaranteed to be > 0
144            visualTree.FillColor = Color.FromArgb((int)(impact / max * 255), Color.Green);
145          }
146          visualTree.ToolTip += Environment.NewLine + "Node impact: " + impact;
147          var constantReplacementNode = foldedNodes[treeNode] as ConstantTreeNode;
148          if (constantReplacementNode != null) {
149            visualTree.ToolTip += Environment.NewLine + "Replacement value: " + constantReplacementNode.Value;
150          }
151        }
152        if (visualTree != null)
153          if (treeNode is ConstantTreeNode && foldedNodes.ContainsKey(treeNode)) {
154            visualTree.LineColor = Color.DarkOrange;
155          }
156      }
157      treeChart.RepaintNodes();
158    }
159
160    private void btnSimplify_Click(object sender, EventArgs e) {
161      var simplifier = new SymbolicDataAnalysisExpressionTreeSimplifier();
162      var simplifiedExpressionTree = simplifier.Simplify(Content.Model.SymbolicExpressionTree);
163      UpdateModel(simplifiedExpressionTree);
164    }
165
166    protected abstract void btnOptimizeConstants_Click(object sender, EventArgs e);
167  }
168}
Note: See TracBrowser for help on using the repository browser.