Free cookie consent management tool by TermsFeed Policy Generator

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

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

Added support for automatic symbolic simplification and manual impact-guided pruning for symbolic time series prognosis solutions. #1142

File size: 12.8 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[] alpha, beta;
98        double quality;
99        conditionVariableName = Content.ConditionalEvaluationVariable;
100        targetVariables = Content.ProblemData.TargetVariables.CheckedItems.Select(x => x.Value.Value);
101        int nTargetVariables = Content.ProblemData.TargetVariables.CheckedItems.Count();
102        lowerEstimationLimit = new DoubleArray(Enumerable.Repeat(double.NegativeInfinity, nTargetVariables).ToArray());
103        upperEstimationLimit = new DoubleArray(Enumerable.Repeat(double.PositiveInfinity, nTargetVariables).ToArray());
104        interpreter = Content.Model.Interpreter;
105        horizon = Content.Horizon;
106        IEnumerable<int> rows = Enumerable.Range(samplesStart, samplesEnd - samplesStart);
107        SymbolicExpressionTree tree = (SymbolicExpressionTree)simplifiedExpressionTree.Clone();
108        SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator.CalculateScalingParameters(tree,
109          Content.ProblemData, interpreter,
110          conditionVariableName, rows,
111          out beta, out alpha);
112
113        quality = SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator.Evaluate(tree, Content.ProblemData, interpreter,
114          conditionVariableName, rows, horizon,
115          lowerEstimationLimit, upperEstimationLimit,
116          beta, alpha);
117
118        //double originalQuality = SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator.Evaluate(
119
120        //  .Calculate(
121        //    Content.Model.Interpreter, new SymbolicExpressionTree(root), Content.LowerEstimationLimit, Content.UpperEstimationLimit,
122        //    Content.ProblemData.Dataset, Content.ProblemData.TargetVariable.Value,
123        //    Enumerable.Range(samplesStart, samplesEnd - samplesStart));
124
125        this.CalculateReplacementNodes();
126
127        this.CalculateNodeImpacts(tree, tree.Root, quality);
128        this.treeChart.Tree = new SymbolicExpressionTree(simplifiedExpressionTree.Root.SubTrees[0]);
129        this.PaintNodeImpacts();
130      }
131    }
132
133    private void CalculateReplacementNodes() {
134      IEnumerable<int> trainingSamples = Enumerable.Range(Content.ProblemData.TrainingSamplesStart.Value, Content.ProblemData.TrainingSamplesEnd.Value - Content.ProblemData.TrainingSamplesStart.Value);
135      SymbolicExpressionTreeNode root = new ProgramRootSymbol().CreateTreeNode();
136      SymbolicExpressionTreeNode start = new StartSymbol().CreateTreeNode();
137      root.AddSubTree(start);
138      SymbolicExpressionTree tree = new SymbolicExpressionTree(root);
139      foreach (SymbolicExpressionTreeNode node in this.simplifiedExpressionTree.IterateNodesPrefix()) {
140        if (!(node.Symbol is StartSymbol)) {
141          while (start.SubTrees.Count > 0) start.RemoveSubTree(0);
142          start.AddSubTree(node);
143          double constantTreeNodeValue = interpreter.GetSymbolicExpressionTreeValues(tree, Content.ProblemData.Dataset, targetVariables, trainingSamples, 1).Select(x => x[0]).Median();
144          ConstantTreeNode constantTreeNode = MakeConstantTreeNode(constantTreeNodeValue);
145          replacementNodes[node] = constantTreeNode;
146        }
147      }
148    }
149
150    private void CalculateNodeImpacts(SymbolicExpressionTree tree, SymbolicExpressionTreeNode currentTreeNode, double originalQuality) {
151      foreach (SymbolicExpressionTreeNode childNode in currentTreeNode.SubTrees.ToList()) {
152        if (!(childNode.Symbol is StartSymbol)) {
153          SwitchNode(currentTreeNode, childNode, replacementNodes[childNode]);
154          int samplesStart = Content.ProblemData.TrainingSamplesStart.Value;
155          int samplesEnd = Content.ProblemData.TrainingSamplesEnd.Value;
156          double[] alpha;
157          double[] beta;
158          int horizon = Content.Horizon;
159          IEnumerable<int> rows = Enumerable.Range(samplesStart, samplesEnd - samplesStart);
160          //SymbolicExpressionTree tree = new SymbolicExpressionTree(root);
161          SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator.CalculateScalingParameters(tree,
162            Content.ProblemData, interpreter,
163            conditionVariableName, rows,
164            out beta, out alpha);
165
166          double newQuality = SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator.Evaluate(tree, Content.ProblemData, interpreter,
167            conditionVariableName, rows, horizon,
168            lowerEstimationLimit, upperEstimationLimit,
169            beta, alpha);
170
171          nodeImpacts[childNode] = newQuality / originalQuality;
172          SwitchNode(currentTreeNode, replacementNodes[childNode], childNode);
173        }
174        CalculateNodeImpacts(tree, childNode, originalQuality);
175      }
176    }
177
178    private void SwitchNode(SymbolicExpressionTreeNode root, SymbolicExpressionTreeNode oldBranch, SymbolicExpressionTreeNode newBranch) {
179      for (int i = 0; i < root.SubTrees.Count; i++) {
180        if (root.SubTrees[i] == oldBranch) {
181          root.RemoveSubTree(i);
182          root.InsertSubTree(i, newBranch);
183          return;
184        }
185      }
186    }
187
188    private ConstantTreeNode MakeConstantTreeNode(double value) {
189      Constant constant = new Constant();
190      constant.MinValue = value - 1;
191      constant.MaxValue = value + 1;
192      ConstantTreeNode constantTreeNode = (ConstantTreeNode)constant.CreateTreeNode();
193      constantTreeNode.Value = value;
194      return constantTreeNode;
195    }
196
197    private void treeChart_SymbolicExpressionTreeNodeDoubleClicked(object sender, MouseEventArgs e) {
198      VisualSymbolicExpressionTreeNode visualTreeNode = (VisualSymbolicExpressionTreeNode)sender;
199      foreach (SymbolicExpressionTreeNode treeNode in simplifiedExpressionTree.IterateNodesPostfix()) {
200        for (int i = 0; i < treeNode.SubTrees.Count; i++) {
201          SymbolicExpressionTreeNode subTree = treeNode.SubTrees[i];
202          if (subTree == visualTreeNode.SymbolicExpressionTreeNode) {
203            treeNode.RemoveSubTree(i);
204            if (replacementNodes.ContainsKey(subTree))
205              treeNode.InsertSubTree(i, replacementNodes[subTree]);
206            else if (subTree is ConstantTreeNode && replacementNodes.ContainsValue((ConstantTreeNode)subTree))
207              treeNode.InsertSubTree(i, replacementNodes.Where(v => v.Value == subTree).Single().Key);
208            else if (!(subTree is ConstantTreeNode))
209              throw new InvalidOperationException("Could not find replacement value.");
210          }
211        }
212      }
213      this.treeChart.Tree = new SymbolicExpressionTree(simplifiedExpressionTree.Root.SubTrees[0]);
214
215      SymbolicExpressionTree tree = (SymbolicExpressionTree)simplifiedExpressionTree.Clone();
216
217      this.Content.ModelChanged -= new EventHandler(Content_ModelChanged);
218      this.Content.Model = new SymbolicTimeSeriesPrognosisModel(Content.Model.Interpreter, tree);
219      this.Content.ModelChanged += new EventHandler(Content_ModelChanged);
220
221      this.PaintNodeImpacts();
222    }
223
224    private void PaintNodeImpacts() {
225      var impacts = nodeImpacts.Values;
226      double max = impacts.Max();
227      double min = impacts.Min();
228      foreach (SymbolicExpressionTreeNode treeNode in simplifiedExpressionTree.IterateNodesPostfix()) {
229        if (!(treeNode is ConstantTreeNode) && nodeImpacts.ContainsKey(treeNode)) {
230          double impact = nodeImpacts[treeNode];
231          double replacementValue = replacementNodes[treeNode].Value;
232          VisualSymbolicExpressionTreeNode visualTree = treeChart.GetVisualSymbolicExpressionTreeNode(treeNode);
233
234          if (impact < 1.0) {
235            visualTree.FillColor = Color.FromArgb((int)((1.0 - impact) * 255), Color.Red);
236          } else {
237            visualTree.FillColor = Color.FromArgb((int)((impact - 1.0) / max * 255), Color.Green);
238          }
239          visualTree.ToolTip += Environment.NewLine + "Node impact: " + impact;
240          visualTree.ToolTip += Environment.NewLine + "Replacement value: " + replacementValue;
241        }
242      }
243      this.PaintCollapsedNodes();
244      this.treeChart.Repaint();
245    }
246
247    private void PaintCollapsedNodes() {
248      foreach (SymbolicExpressionTreeNode treeNode in simplifiedExpressionTree.IterateNodesPostfix()) {
249        if (treeNode is ConstantTreeNode && replacementNodes.ContainsValue((ConstantTreeNode)treeNode))
250          this.treeChart.GetVisualSymbolicExpressionTreeNode(treeNode).LineColor = Color.DarkOrange;
251        else
252          this.treeChart.GetVisualSymbolicExpressionTreeNode(treeNode).LineColor = Color.Black;
253      }
254    }
255
256    private void btnSimplify_Click(object sender, EventArgs e) {
257      this.CalculateReplacementNodesAndNodeImpacts();
258    }
259  }
260}
Note: See TracBrowser for help on using the repository browser.