Free cookie consent management tool by TermsFeed Policy Generator

source: branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis.Views/3.3/InteractiveSymbolicTimeSeriesPrognosisSolutionSimplifierView.cs @ 12329

Last change on this file since 12329 was 4475, checked in by gkronber, 14 years ago

Fixed bugs in time series prognosis classes #1142.

File size: 12.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 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.Symbolic;
33using HeuristicLab.Problems.DataAnalysis.Symbolic.Symbols;
34using HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis.Symbolic;
35using HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis.Symbolic.Interfaces;
36using HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis.Symbolic.Evaluators;
37using HeuristicLab.Data;
38
39namespace HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis.Views {
40  public partial class InteractiveSymbolicTimeSeriesPrognosisSolutionSimplifierView : AsynchronousContentView {
41    private SymbolicExpressionTree simplifiedExpressionTree;
42    private ISymbolicTimeSeriesExpressionInterpreter interpreter;
43    private DoubleArray lowerEstimationLimit;
44    private DoubleArray upperEstimationLimit;
45    private string conditionVariableName;
46    private IEnumerable<string> targetVariables;
47    private int horizon;
48    private Dictionary<SymbolicExpressionTreeNode, ConstantTreeNode> replacementNodes;
49    private Dictionary<SymbolicExpressionTreeNode, double> nodeImpacts;
50
51    public InteractiveSymbolicTimeSeriesPrognosisSolutionSimplifierView() {
52      InitializeComponent();
53      this.replacementNodes = new Dictionary<SymbolicExpressionTreeNode, ConstantTreeNode>();
54      this.nodeImpacts = new Dictionary<SymbolicExpressionTreeNode, double>();
55      this.simplifiedExpressionTree = null;
56      this.Caption = "Interactive Solution Simplifier";
57    }
58
59    public new SymbolicTimeSeriesPrognosisSolution Content {
60      get { return (SymbolicTimeSeriesPrognosisSolution)base.Content; }
61      set { base.Content = value; }
62    }
63
64    protected override void RegisterContentEvents() {
65      base.RegisterContentEvents();
66      Content.ModelChanged += new EventHandler(Content_ModelChanged);
67      Content.ProblemDataChanged += new EventHandler(Content_ProblemDataChanged);
68    }
69    protected override void DeregisterContentEvents() {
70      base.DeregisterContentEvents();
71      Content.ModelChanged -= new EventHandler(Content_ModelChanged);
72      Content.ProblemDataChanged -= new EventHandler(Content_ProblemDataChanged);
73    }
74
75    private void Content_ModelChanged(object sender, EventArgs e) {
76      this.CalculateReplacementNodesAndNodeImpacts();
77    }
78    private void Content_ProblemDataChanged(object sender, EventArgs e) {
79      this.CalculateReplacementNodesAndNodeImpacts();
80    }
81
82    protected override void OnContentChanged() {
83      base.OnContentChanged();
84      this.CalculateReplacementNodesAndNodeImpacts();
85      this.viewHost.Content = this.Content;
86    }
87
88    private void CalculateReplacementNodesAndNodeImpacts() {
89      this.replacementNodes.Clear();
90      this.nodeImpacts.Clear();
91      if (Content != null && Content.Model != null && Content.ProblemData != null) {
92        SymbolicSimplifier simplifier = new SymbolicSimplifier();
93        simplifiedExpressionTree = simplifier.Simplify(Content.Model.SymbolicExpressionTree);
94        int samplesStart = Content.ProblemData.TrainingSamplesStart.Value;
95        int samplesEnd = Content.ProblemData.TrainingSamplesEnd.Value;
96
97        double quality;
98        conditionVariableName = Content.ConditionalEvaluationVariable;
99        targetVariables = Content.ProblemData.TargetVariables.CheckedItems.Select(x => x.Value.Value);
100        int nTargetVariables = Content.ProblemData.TargetVariables.CheckedItems.Count();
101        interpreter = Content.Model.Interpreter;
102        horizon = Content.Horizon;
103        IEnumerable<int> rows = Enumerable.Range(samplesStart, samplesEnd - samplesStart);
104        if (!string.IsNullOrEmpty(conditionVariableName)) {
105          rows = (from row in rows
106                  where !Content.ProblemData.Dataset[conditionVariableName, row].IsAlmost(0.0)
107                  select row).ToList();
108        }
109        lowerEstimationLimit = new DoubleArray(nTargetVariables);
110        upperEstimationLimit = new DoubleArray(nTargetVariables);
111        for (int i = 0; i < nTargetVariables; i++) {
112          lowerEstimationLimit[i] = Content.GetLowerEstimationLimit(i);
113          upperEstimationLimit[i] = Content.GetUpperEstimationLimit(i);
114        }
115        quality = SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator.Calculate(simplifiedExpressionTree, Content.ProblemData, interpreter,
116          rows, horizon,
117          lowerEstimationLimit, upperEstimationLimit);
118
119        this.CalculateReplacementNodes();
120
121        this.CalculateNodeImpacts(simplifiedExpressionTree, simplifiedExpressionTree.Root, quality, rows);
122        // show only interesing part
123        this.treeChart.Tree = new SymbolicExpressionTree(simplifiedExpressionTree.Root.SubTrees[0]);
124        this.PaintNodeImpacts();
125      }
126    }
127
128    private void CalculateReplacementNodes() {
129      IEnumerable<int> trainingSamples = Enumerable.Range(Content.ProblemData.TrainingSamplesStart.Value, Content.ProblemData.TrainingSamplesEnd.Value - Content.ProblemData.TrainingSamplesStart.Value);
130      SymbolicExpressionTreeNode root = new ProgramRootSymbol().CreateTreeNode();
131      SymbolicExpressionTreeNode start = new StartSymbol().CreateTreeNode();
132      root.AddSubTree(start);
133      SymbolicExpressionTree tree = new SymbolicExpressionTree(root);
134      foreach (SymbolicExpressionTreeNode node in this.simplifiedExpressionTree.IterateNodesPrefix()) {
135        if (!(node.Symbol is StartSymbol || node.Symbol is ProgramRootSymbol)) {
136          while (start.SubTrees.Count > 0) start.RemoveSubTree(0);
137          start.AddSubTree(node);
138          // we only want a scalar replacement value for the single branch that should be evaluated
139          // so assume we only create an estimation for the first target variable
140          double constantTreeNodeValue = interpreter.GetSymbolicExpressionTreeValues(tree, Content.ProblemData.Dataset, targetVariables.Take(1) , trainingSamples, 1).Select(x => x[0]).Median();
141          ConstantTreeNode constantTreeNode = MakeConstantTreeNode(constantTreeNodeValue);
142          replacementNodes[node] = constantTreeNode;
143        }
144      }
145    }
146
147    private void CalculateNodeImpacts(SymbolicExpressionTree tree, SymbolicExpressionTreeNode currentTreeNode, double originalQuality, IEnumerable<int> rows) {
148      foreach (SymbolicExpressionTreeNode childNode in currentTreeNode.SubTrees.ToList()) {
149        if (!(childNode.Symbol is StartSymbol || childNode.Symbol is ProgramRootSymbol)) {
150          SwitchNode(currentTreeNode, childNode, replacementNodes[childNode]);
151          int horizon = Content.Horizon;
152
153          double newQuality = SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator.Calculate(tree, Content.ProblemData, interpreter,
154            rows, horizon,
155            lowerEstimationLimit, upperEstimationLimit);
156
157          nodeImpacts[childNode] = newQuality / originalQuality;
158          SwitchNode(currentTreeNode, replacementNodes[childNode], childNode);
159        }
160        CalculateNodeImpacts(tree, childNode, originalQuality, rows);
161      }
162    }
163
164    private void SwitchNode(SymbolicExpressionTreeNode root, SymbolicExpressionTreeNode oldBranch, SymbolicExpressionTreeNode newBranch) {
165      for (int i = 0; i < root.SubTrees.Count; i++) {
166        if (root.SubTrees[i] == oldBranch) {
167          root.RemoveSubTree(i);
168          root.InsertSubTree(i, newBranch);
169          return;
170        }
171      }
172    }
173
174    private ConstantTreeNode MakeConstantTreeNode(double value) {
175      Constant constant = new Constant();
176      constant.MinValue = value - 1;
177      constant.MaxValue = value + 1;
178      ConstantTreeNode constantTreeNode = (ConstantTreeNode)constant.CreateTreeNode();
179      constantTreeNode.Value = value;
180      return constantTreeNode;
181    }
182
183    private void treeChart_SymbolicExpressionTreeNodeDoubleClicked(object sender, MouseEventArgs e) {
184      VisualSymbolicExpressionTreeNode visualTreeNode = (VisualSymbolicExpressionTreeNode)sender;
185      foreach (SymbolicExpressionTreeNode treeNode in simplifiedExpressionTree.IterateNodesPostfix()) {
186        for (int i = 0; i < treeNode.SubTrees.Count; i++) {
187          SymbolicExpressionTreeNode subTree = treeNode.SubTrees[i];
188          if (subTree == visualTreeNode.SymbolicExpressionTreeNode) {
189            if (replacementNodes.ContainsKey(subTree)) {
190              treeNode.RemoveSubTree(i);
191              treeNode.InsertSubTree(i, replacementNodes[subTree]);
192            } else if (subTree is ConstantTreeNode && replacementNodes.ContainsValue((ConstantTreeNode)subTree)) {
193              treeNode.RemoveSubTree(i);
194              treeNode.InsertSubTree(i, replacementNodes.Where(v => v.Value == subTree).Single().Key);
195            }
196            // if no replacement value is known do nothing
197          }
198        }
199      }
200      // show only interesting part
201      this.treeChart.Tree = new SymbolicExpressionTree(simplifiedExpressionTree.Root.SubTrees[0]);
202
203      SymbolicExpressionTree tree = (SymbolicExpressionTree)simplifiedExpressionTree.Clone();
204
205      this.Content.ModelChanged -= new EventHandler(Content_ModelChanged);
206      this.Content.Model = new SymbolicTimeSeriesPrognosisModel(Content.Model.Interpreter, tree);
207      this.Content.ModelChanged += new EventHandler(Content_ModelChanged);
208
209      this.PaintNodeImpacts();
210    }
211
212    private void PaintNodeImpacts() {
213      var impacts = nodeImpacts.Values;
214      double max = impacts.Max();
215      double min = impacts.Min();
216      foreach (SymbolicExpressionTreeNode treeNode in simplifiedExpressionTree.IterateNodesPostfix()) {
217        if (!(treeNode is ConstantTreeNode) && nodeImpacts.ContainsKey(treeNode)) {
218          double impact = nodeImpacts[treeNode];
219          double replacementValue = replacementNodes[treeNode].Value;
220          VisualSymbolicExpressionTreeNode visualTree = treeChart.GetVisualSymbolicExpressionTreeNode(treeNode);
221
222          if (impact < 1.0) {
223            visualTree.FillColor = Color.FromArgb((int)((1.0 - impact) * 255), Color.Red);
224          } else {
225            visualTree.FillColor = Color.FromArgb((int)((impact - 1.0) / max * 255), Color.Green);
226          }
227          visualTree.ToolTip += Environment.NewLine + "Node impact: " + impact;
228          visualTree.ToolTip += Environment.NewLine + "Replacement value: " + replacementValue;
229        }
230      }
231      this.PaintCollapsedNodes();
232      this.treeChart.Repaint();
233    }
234
235    private void PaintCollapsedNodes() {
236      foreach (SymbolicExpressionTreeNode treeNode in simplifiedExpressionTree.IterateNodesPostfix()) {
237        if (treeNode is ConstantTreeNode && replacementNodes.ContainsValue((ConstantTreeNode)treeNode))
238          this.treeChart.GetVisualSymbolicExpressionTreeNode(treeNode).LineColor = Color.DarkOrange;
239        else {
240          VisualSymbolicExpressionTreeNode visNode = treeChart.GetVisualSymbolicExpressionTreeNode(treeNode);
241          if (visNode != null)
242            visNode.LineColor = Color.Black;
243        }
244      }
245    }
246
247    private void btnSimplify_Click(object sender, EventArgs e) {
248      this.CalculateReplacementNodesAndNodeImpacts();
249    }
250  }
251}
Note: See TracBrowser for help on using the repository browser.