Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Problems.DataAnalysis.Views/3.3/Symbolic/InteractiveSymbolicRegressionSolutionSimplifierView.cs @ 6064

Last change on this file since 6064 was 5455, checked in by gkronber, 14 years ago

#1227 Merged changesets r4878 and r4880 from branch into trunk.

File size: 11.7 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 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.Symbols;
30using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views;
31using HeuristicLab.MainForm.WindowsForms;
32using HeuristicLab.Problems.DataAnalysis.Regression.Symbolic;
33using HeuristicLab.Problems.DataAnalysis.Symbolic;
34using HeuristicLab.Problems.DataAnalysis.Symbolic.Symbols;
35
36namespace HeuristicLab.Problems.DataAnalysis.Views.Symbolic {
37  public partial class InteractiveSymbolicRegressionSolutionSimplifierView : AsynchronousContentView {
38    private SymbolicExpressionTree simplifiedExpressionTree;
39    private Dictionary<SymbolicExpressionTreeNode, ConstantTreeNode> replacementNodes;
40    private Dictionary<SymbolicExpressionTreeNode, double> nodeImpacts;
41
42    public InteractiveSymbolicRegressionSolutionSimplifierView() {
43      InitializeComponent();
44      this.replacementNodes = new Dictionary<SymbolicExpressionTreeNode, ConstantTreeNode>();
45      this.nodeImpacts = new Dictionary<SymbolicExpressionTreeNode, double>();
46      this.simplifiedExpressionTree = null;
47      this.Caption = "Interactive Solution Simplifier";
48    }
49
50    public new SymbolicRegressionSolution Content {
51      get { return (SymbolicRegressionSolution)base.Content; }
52      set { base.Content = value; }
53    }
54
55    protected override void RegisterContentEvents() {
56      base.RegisterContentEvents();
57      Content.ModelChanged += new EventHandler(Content_ModelChanged);
58      Content.ProblemDataChanged += new EventHandler(Content_ProblemDataChanged);
59    }
60    protected override void DeregisterContentEvents() {
61      base.DeregisterContentEvents();
62      Content.ModelChanged -= new EventHandler(Content_ModelChanged);
63      Content.ProblemDataChanged -= new EventHandler(Content_ProblemDataChanged);
64    }
65
66    private void Content_ModelChanged(object sender, EventArgs e) {
67      this.CalculateReplacementNodesAndNodeImpacts();
68    }
69    private void Content_ProblemDataChanged(object sender, EventArgs e) {
70      this.CalculateReplacementNodesAndNodeImpacts();
71    }
72
73    protected override void OnContentChanged() {
74      base.OnContentChanged();
75      this.CalculateReplacementNodesAndNodeImpacts();
76      this.viewHost.Content = this.Content;
77    }
78
79    private void CalculateReplacementNodesAndNodeImpacts() {
80      this.replacementNodes.Clear();
81      this.nodeImpacts.Clear();
82      if (Content != null && Content.Model != null && Content.ProblemData != null) {
83        SymbolicSimplifier simplifier = new SymbolicSimplifier();
84        simplifiedExpressionTree = simplifier.Simplify(Content.Model.SymbolicExpressionTree);
85        int samplesStart = Content.ProblemData.TrainingSamplesStart.Value;
86        int samplesEnd = Content.ProblemData.TrainingSamplesEnd.Value;
87        double originalTrainingMeanSquaredError = SymbolicRegressionMeanSquaredErrorEvaluator.Calculate(
88            Content.Model.Interpreter, simplifiedExpressionTree, Content.LowerEstimationLimit, Content.UpperEstimationLimit,
89            Content.ProblemData.Dataset, Content.ProblemData.TargetVariable.Value,
90            Enumerable.Range(samplesStart, samplesEnd - samplesStart));
91
92        this.CalculateReplacementNodes();
93
94        this.CalculateNodeImpacts(simplifiedExpressionTree, simplifiedExpressionTree.Root.SubTrees[0], originalTrainingMeanSquaredError);
95        // automatically fold all branches with impact = 1
96        List<SymbolicExpressionTreeNode> nodeList = simplifiedExpressionTree.Root.SubTrees[0].IterateNodesPrefix().ToList();
97        foreach (var parent in nodeList) {
98          for (int subTreeIndex = 0; subTreeIndex < parent.SubTrees.Count; subTreeIndex++) {
99            var child = parent.SubTrees[subTreeIndex];
100            if (!(child.Symbol is Constant) && nodeImpacts[child].IsAlmost(1.0)) {
101              ReplaceNodeWithConstant(parent, subTreeIndex);
102            }
103          }
104        }
105        // show only interesting part of solution
106        this.treeChart.Tree = new SymbolicExpressionTree(simplifiedExpressionTree.Root.SubTrees[0].SubTrees[0]);
107        this.PaintNodeImpacts();
108      }
109    }
110
111    private void CalculateReplacementNodes() {
112      ISymbolicExpressionTreeInterpreter interpreter = Content.Model.Interpreter;
113      IEnumerable<int> trainingSamples = Enumerable.Range(Content.ProblemData.TrainingSamplesStart.Value, Content.ProblemData.TrainingSamplesEnd.Value - Content.ProblemData.TrainingSamplesStart.Value);
114      SymbolicExpressionTreeNode root = new ProgramRootSymbol().CreateTreeNode();
115      SymbolicExpressionTreeNode start = new StartSymbol().CreateTreeNode();
116      root.AddSubTree(start);
117      SymbolicExpressionTree tree = new SymbolicExpressionTree(root);
118      foreach (SymbolicExpressionTreeNode node in this.simplifiedExpressionTree.IterateNodesPrefix()) {
119        if (!(node.Symbol is ProgramRootSymbol || node.Symbol is StartSymbol)) {
120          while (start.SubTrees.Count > 0) start.RemoveSubTree(0);
121          start.AddSubTree(node);
122          double constantTreeNodeValue = interpreter.GetSymbolicExpressionTreeValues(tree, Content.ProblemData.Dataset, trainingSamples).Median();
123          ConstantTreeNode constantTreeNode = MakeConstantTreeNode(constantTreeNodeValue);
124          replacementNodes[node] = constantTreeNode;
125        }
126      }
127    }
128
129    private void CalculateNodeImpacts(SymbolicExpressionTree tree, SymbolicExpressionTreeNode currentTreeNode, double originalTrainingMeanSquaredError) {
130      foreach (SymbolicExpressionTreeNode childNode in currentTreeNode.SubTrees.ToList()) {
131        SwitchNode(currentTreeNode, childNode, replacementNodes[childNode]);
132        int samplesStart = Content.ProblemData.TrainingSamplesStart.Value;
133        int samplesEnd = Content.ProblemData.TrainingSamplesEnd.Value;
134        double newTrainingMeanSquaredError = SymbolicRegressionMeanSquaredErrorEvaluator.Calculate(
135          Content.Model.Interpreter, tree,
136          Content.LowerEstimationLimit, Content.UpperEstimationLimit,
137          Content.ProblemData.Dataset, Content.ProblemData.TargetVariable.Value,
138          Enumerable.Range(samplesStart, samplesEnd - samplesStart));
139        nodeImpacts[childNode] = newTrainingMeanSquaredError / originalTrainingMeanSquaredError;
140        SwitchNode(currentTreeNode, replacementNodes[childNode], childNode);
141        CalculateNodeImpacts(tree, childNode, originalTrainingMeanSquaredError);
142      }
143    }
144
145    private void SwitchNode(SymbolicExpressionTreeNode root, SymbolicExpressionTreeNode oldBranch, SymbolicExpressionTreeNode newBranch) {
146      for (int i = 0; i < root.SubTrees.Count; i++) {
147        if (root.SubTrees[i] == oldBranch) {
148          root.RemoveSubTree(i);
149          root.InsertSubTree(i, newBranch);
150          return;
151        }
152      }
153    }
154
155    private ConstantTreeNode MakeConstantTreeNode(double value) {
156      Constant constant = new Constant();
157      constant.MinValue = value - 1;
158      constant.MaxValue = value + 1;
159      ConstantTreeNode constantTreeNode = (ConstantTreeNode)constant.CreateTreeNode();
160      constantTreeNode.Value = value;
161      return constantTreeNode;
162    }
163
164    private void treeChart_SymbolicExpressionTreeNodeDoubleClicked(object sender, MouseEventArgs e) {
165      VisualSymbolicExpressionTreeNode visualTreeNode = (VisualSymbolicExpressionTreeNode)sender;
166      foreach (SymbolicExpressionTreeNode treeNode in simplifiedExpressionTree.IterateNodesPostfix()) {
167        for (int i = 0; i < treeNode.SubTrees.Count; i++) {
168          SymbolicExpressionTreeNode subTree = treeNode.SubTrees[i];
169          if (subTree == visualTreeNode.SymbolicExpressionTreeNode) {
170            ReplaceNodeWithConstant(treeNode, i);
171          }
172        }
173      }
174
175      // show only interesting part of solution
176      this.treeChart.Tree = new SymbolicExpressionTree(simplifiedExpressionTree.Root.SubTrees[0].SubTrees[0]);
177
178      SymbolicExpressionTree tree = (SymbolicExpressionTree)simplifiedExpressionTree.Clone();
179
180      this.Content.ModelChanged -= new EventHandler(Content_ModelChanged);
181      this.Content.Model = new SymbolicRegressionModel(Content.Model.Interpreter, tree);
182      this.Content.ModelChanged += new EventHandler(Content_ModelChanged);
183
184      this.PaintNodeImpacts();
185    }
186
187    private void ReplaceNodeWithConstant(SymbolicExpressionTreeNode parent, int subTreeIndex) {
188      SymbolicExpressionTreeNode subTree = parent.SubTrees[subTreeIndex];
189      parent.RemoveSubTree(subTreeIndex);
190      if (replacementNodes.ContainsKey(subTree))
191        parent.InsertSubTree(subTreeIndex, replacementNodes[subTree]);
192      else if (subTree is ConstantTreeNode && replacementNodes.ContainsValue((ConstantTreeNode)subTree))
193        parent.InsertSubTree(subTreeIndex, replacementNodes.Where(v => v.Value == subTree).Single().Key);
194      else if (!(subTree is ConstantTreeNode))
195        throw new InvalidOperationException("Could not find replacement value.");
196    }
197
198    private void PaintNodeImpacts() {
199      var impacts = nodeImpacts.Values;
200      double max = impacts.Max();
201      double min = impacts.Min();
202      foreach (SymbolicExpressionTreeNode treeNode in simplifiedExpressionTree.IterateNodesPostfix()) {
203        if (!(treeNode is ConstantTreeNode) && nodeImpacts.ContainsKey(treeNode)) {
204          double impact = this.nodeImpacts[treeNode];
205          double replacementValue = this.replacementNodes[treeNode].Value;
206          VisualSymbolicExpressionTreeNode visualTree = treeChart.GetVisualSymbolicExpressionTreeNode(treeNode);
207
208          if (impact < 1.0) {
209            visualTree.FillColor = Color.FromArgb((int)((1.0 - impact) * 255), Color.Red);
210          } else {
211            visualTree.FillColor = Color.FromArgb((int)((impact - 1.0) / max * 255), Color.Green);
212          }
213          visualTree.ToolTip += Environment.NewLine + "Node impact: " + impact;
214          visualTree.ToolTip += Environment.NewLine + "Replacement value: " + replacementValue;
215        }
216      }
217      this.PaintCollapsedNodes();
218      this.treeChart.Repaint();
219    }
220
221    private void PaintCollapsedNodes() {
222      foreach (SymbolicExpressionTreeNode treeNode in simplifiedExpressionTree.IterateNodesPostfix()) {
223        if (treeNode is ConstantTreeNode && replacementNodes.ContainsValue((ConstantTreeNode)treeNode))
224          this.treeChart.GetVisualSymbolicExpressionTreeNode(treeNode).LineColor = Color.DarkOrange;
225        else {
226          VisualSymbolicExpressionTreeNode visNode = treeChart.GetVisualSymbolicExpressionTreeNode(treeNode);
227          if (visNode != null)
228            visNode.LineColor = Color.Black;
229        }
230      }
231    }
232
233    private void btnSimplify_Click(object sender, EventArgs e) {
234      this.CalculateReplacementNodesAndNodeImpacts();
235    }
236  }
237}
Note: See TracBrowser for help on using the repository browser.