Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/SymboldDataAnalysisGenealogyView.cs @ 10677

Last change on this file since 10677 was 10677, checked in by bburlacu, 10 years ago

#1772: Improved usage of GenealogyGraph and GenealogyGraphNode classes. Made some progress on building block tracing.

File size: 11.9 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2014 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.IO;
26using System.Linq;
27using System.Windows.Forms;
28using HeuristicLab.Core.Views;
29using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
30using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views;
31using HeuristicLab.EvolutionTracking;
32using HeuristicLab.EvolutionTracking.Views;
33using HeuristicLab.MainForm;
34
35using FragmentGraph = HeuristicLab.EvolutionTracking.IGenealogyGraph<HeuristicLab.EvolutionTracking.IFragment<HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.ISymbolicExpressionTreeNode>>;
36
37using FragmentNode = HeuristicLab.EvolutionTracking.GenealogyGraphNode<HeuristicLab.EvolutionTracking.IFragment<HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.ISymbolicExpressionTreeNode>>;
38
39namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Views {
40  [View("SymboldDataAnalysisGenealogyView")]
41  [Content(typeof(IGenealogyGraph<ISymbolicExpressionTree>), IsDefaultView = true)]
42  public partial class SymboldDataAnalysisGenealogyView : ItemView {
43    private readonly ISymbolicExpressionTreeNodeSimilarityComparer comparer;
44
45    public SymboldDataAnalysisGenealogyView() {
46      InitializeComponent();
47
48      comparer = new SymbolicExpressionTreeNodeSimilarityComparer();
49    }
50
51    public new IGenealogyGraph<ISymbolicExpressionTree> Content {
52      get { return (IGenealogyGraph<ISymbolicExpressionTree>)base.Content; }
53      set { base.Content = value; }
54    }
55
56    #region event handlers
57
58    protected override void OnContentChanged() {
59      base.OnContentChanged();
60      if (Content != null) {
61        genealogyGraphChart.GenealogyGraph = Content;
62      }
63    }
64
65    #endregion
66
67    protected override void RegisterContentEvents() {
68      genealogyGraphChart.GenealogyGraphNodeClicked += graphChart_GenealogyGraphNodeClicked;
69      symbolicExpressionTreeChart.SymbolicExpressionTreeNodeClicked += treeChart_SymbolicExpressionNodeClicked;
70      base.RegisterContentEvents();
71    }
72
73    protected override void DeregisterContentEvents() {
74      base.DeregisterContentEvents();
75      genealogyGraphChart.GenealogyGraphNodeClicked -= graphChart_GenealogyGraphNodeClicked;
76      symbolicExpressionTreeChart.SymbolicExpressionTreeNodeClicked -= treeChart_SymbolicExpressionNodeClicked;
77    }
78
79    public void graphChart_GenealogyGraphNodeClicked(object sender, MouseEventArgs args) {
80      var visualNode = (VisualGenealogyGraphNode)sender;
81      var graphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)visualNode.Data;
82      var tree = graphNode.Content;
83      symbolicExpressionTreeChart.Tree = tree;
84
85      if (graphNode.InArcs != null) {
86        var fragment = (IFragment<ISymbolicExpressionTreeNode>)graphNode.InArcs.Last().Data;
87        treeChart_HighlightSubtree(fragment.Root);
88      }
89    }
90
91    public void treeChart_SymbolicExpressionNodeClicked(object sender, MouseEventArgs args) {
92      var visualNode = (VisualTreeNode<ISymbolicExpressionTreeNode>)sender;
93      var subtree = visualNode.Content;
94
95      // highlight the selected subtree inside the displayed tree on the right hand side
96      treeChart_ClearColors();
97      treeChart_HighlightSubtree(subtree);
98
99      bool trace = genealogyGraphChart.TraceFragments; // check whether the mode is 'trace' or 'match'
100
101      if (trace) {
102        // perform fragment tracing
103        var fragmentGraph = TraceSubtree(subtree);
104        MainFormManager.MainForm.ShowContent(fragmentGraph);
105        //        var fragmentGraphView = MainFormManager.MainForm.ShowContent(fragmentGraph);
106        //        fragmentGraphView.Content = fragmentGraph;
107        //        fragmentGraphView.Show();
108
109        // open a FragmentGraphView displaying this fragmentGraph
110      } else {
111        // perform matching like it was done before
112        // currently there is no possibility to specify the subtree matching criteria
113        var trees = Content.Nodes.Select(x => (ISymbolicExpressionTree)x.Content);
114        var matchingTrees = trees.Where(x => x.Root.ContainsSubtree(subtree, comparer));
115
116        var matchingVertices = matchingTrees.SelectMany(x => Content[x]).Cast<IGenealogyGraphNode<ISymbolicExpressionTree>>();
117        graphChart_highlightMatchingVertices(matchingVertices);
118      }
119    }
120
121    private void graphChart_highlightMatchingVertices(IEnumerable<IGenealogyGraphNode> vertices) {
122      genealogyGraphChart.Chart.UpdateEnabled = false;
123      genealogyGraphChart.ClearPrimitives();
124      genealogyGraphChart.HighlightNodes(vertices);
125      genealogyGraphChart.Chart.UpdateEnabled = true;
126      genealogyGraphChart.Chart.EnforceUpdate();
127    }
128
129    private void treeChart_ClearColors() {
130      foreach (var node in symbolicExpressionTreeChart.Tree.IterateNodesPrefix()) {
131        var visualNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node);
132        if (visualNode != null) {
133          visualNode.LineColor = Color.Black;
134          visualNode.FillColor = Color.Transparent;
135        }
136      }
137      symbolicExpressionTreeChart.RepaintNodes();
138    }
139
140    private void treeChart_HighlightSubtree(ISymbolicExpressionTreeNode subtree) {
141      foreach (var s in subtree.IterateNodesPrefix()) {
142        var visualNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(s);
143        visualNode.LineColor = Color.RoyalBlue;
144        visualNode.FillColor = Color.LightBlue;
145
146        foreach (var c in s.Subtrees) {
147          var visualArc = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNodeConnection(s, c);
148          visualArc.LineColor = Color.RoyalBlue;
149        }
150      }
151      symbolicExpressionTreeChart.RepaintNodes();
152    }
153
154    #region events for configuring the behavior of the genealogy chart (trace/match, simple lineages, etc)
155    private void trace_checkBox_CheckedChanged(object sender, System.EventArgs e) {
156      genealogyGraphChart.TraceFragments = trace_checkBox.Checked;
157    }
158
159    private void simpleLineages_checkBox_CheckedChanged(object sender, System.EventArgs e) {
160      genealogyGraphChart.SimpleLineages = simpleLineages_checkBox.Checked;
161    }
162
163    private void lockGraph_checkBox_CheckedChanged(object sender, System.EventArgs e) {
164      genealogyGraphChart.LockGenealogy = lockGraph_checkBox.Checked;
165    }
166    #endregion
167
168    #region fragment tracing
169    #region helper methods to shorten the code
170
171    #endregion
172
173    private FragmentGraph TraceSubtree(ISymbolicExpressionTreeNode subtree) {
174      var graphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)genealogyGraphChart.SelectedGraphNode;
175      var graph = new GenealogyGraph<IFragment<ISymbolicExpressionTreeNode>>();
176      Trace(graphNode, subtree, graph);
177      return graph;
178    }
179
180    private void Trace(IGenealogyGraphNode<ISymbolicExpressionTree> graphNode, ISymbolicExpressionTreeNode subtree, FragmentGraph fragmentGraph, FragmentNode parentNode = null) {
181      while (true) {
182        if (!graphNode.InArcs.Any()) return;
183
184        var parentVertices = graphNode.Parents.ToList();
185        // the subtree must belong to the currently displayed tree which in turn must belong to the currently selected graph node
186        var tree = graphNode.Content;
187        var subtreeIndex = tree.IndexOf(subtree);
188        var subtreeLength = subtree.GetLength();
189
190        var fragment = (IFragment<ISymbolicExpressionTreeNode>)graphNode.InArcs.Last().Data;
191        if (fragment == null) return;
192        var fragmentLength = fragment.Root.GetLength();
193
194        FragmentNode node = new FragmentNode { Content = new Fragment<ISymbolicExpressionTreeNode> { Root = subtree }, Rank = graphNode.Rank };
195        if (parentNode != null) {
196          AddChild(parentNode, node);
197        }
198        fragmentGraph.AddVertex(node);
199
200        // if the selected subtree is the actual fragment
201        if (fragment.Index == subtreeIndex) {
202          if (fragmentLength != subtreeLength) throw new Exception("Fragment and subtree lengths should be the same!");
203          graphNode = parentVertices.Last();
204          tree = graphNode.Content;
205          subtree = tree.NodeAt(fragment.OldIndex);
206          parentNode = node;
207          continue;
208        }
209        // if the fragment contains the selected subtree => track fragment, then track subtree
210        if (fragment.Index < subtreeIndex && subtreeIndex < fragment.Index + fragmentLength) {
211          if (subtreeLength >= fragmentLength) throw new Exception("Fragment contains subtree, so subtree length should be less than the fragment length.");
212
213          graphNode = parentVertices.Last();
214          tree = graphNode.Content;
215          var i = fragment.Root.IndexOf(subtree); // get the index of the selected subtree, relative to the fragment root
216          subtree = tree.NodeAt(fragment.OldIndex + i);
217          parentNode = node;
218          continue;
219        }
220        // if the selected subtree contains the fragment => track fragment and subtree
221        if (subtreeIndex < fragment.Index && fragment.Index < subtreeIndex + subtreeLength) {
222          if (fragmentLength >= subtreeLength) throw new Exception("Subtree contains fragment, so fragment length should be less than the subtree length.");
223
224          graphNode = parentVertices[0];
225          tree = graphNode.Content;
226          subtree = tree.NodeAt(subtreeIndex);
227          // track subtree
228          Trace(graphNode, subtree, fragmentGraph, node);
229
230          // track fragment
231          if (parentVertices.Count > 1) {
232            graphNode = parentVertices[1];
233            tree = graphNode.Content;
234            subtree = tree.NodeAt(fragment.OldIndex);
235            parentNode = node;
236            continue;
237          }
238        } else {
239          // fragment and subtree are completely distinct => we only track the subtree
240          graphNode = parentVertices[0];
241          tree = graphNode.Content;
242          subtree = tree.NodeAt(subtreeIndex);
243          parentNode = node;
244          continue;
245        }
246        break;
247      }
248    }
249
250    private void AddChild(FragmentNode parent, FragmentNode child) {
251      child.Rank = parent.Rank - 1;
252      parent.AddForwardArc(child);
253      child.AddReverseArc(parent);
254    }
255    #endregion
256  }
257
258  internal static class Util {
259    private static string ViewAsText(this ISymbolicExpressionTreeNode root) {
260      var writer = new StringWriter();
261      SymbolicExpressionTreeHierarchicalFormatter.RenderNode(writer, root, string.Empty);
262      return writer.ToString();
263    }
264    internal static ISymbolicExpressionTreeNode NodeAt(this ISymbolicExpressionTree tree, int position) {
265      return NodeAt(tree.Root, position);
266    }
267    internal static ISymbolicExpressionTreeNode NodeAt(this ISymbolicExpressionTreeNode root, int position) {
268      return root.IterateNodesPrefix().ElementAt(position);
269    }
270    internal static int IndexOf(this ISymbolicExpressionTree tree, ISymbolicExpressionTreeNode node) {
271      return IndexOf(tree.Root, node);
272    }
273    internal static int IndexOf(this ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode node) {
274      return root.IterateNodesPrefix().ToList().IndexOf(node); // not too worried about efficiency here
275    }
276  }
277}
Note: See TracBrowser for help on using the repository browser.