Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 10650 was 10650, checked in by bburlacu, 11 years ago

#1772: Added new SymbolicDataAnalysisGenealogyView and added support for the tracing of building blocks (finding the constituent ancestral elements of a selected subtree).

File size: 10.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.Collections.Generic;
23using System.Drawing;
24using System.Linq;
25using System.Windows.Forms;
26using HeuristicLab.Core.Views;
27using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
28using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views;
29using HeuristicLab.EvolutionTracking;
30using HeuristicLab.EvolutionTracking.Views;
31using HeuristicLab.MainForm;
32
33using FragmentGraph = HeuristicLab.EvolutionTracking.IGenealogyGraph<HeuristicLab.EvolutionTracking.IFragment<HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.ISymbolicExpressionTreeNode>>;
34
35
36using FragmentNode = HeuristicLab.EvolutionTracking.GenealogyGraphNode<HeuristicLab.EvolutionTracking.IFragment<HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.ISymbolicExpressionTreeNode>>;
37
38namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Views {
39  [View("SymboldDataAnalysisGenealogyView")]
40  [Content(typeof(IGenealogyGraph<ISymbolicExpressionTree>), IsDefaultView = true)]
41  public partial class SymboldDataAnalysisGenealogyView : ItemView {
42    private readonly ISymbolicExpressionTreeNodeSimilarityComparer comparer;
43
44    public SymboldDataAnalysisGenealogyView() {
45      InitializeComponent();
46
47      comparer = new SymbolicExpressionTreeNodeSimilarityComparer();
48    }
49
50    public new IGenealogyGraph<ISymbolicExpressionTree> Content {
51      get { return (IGenealogyGraph<ISymbolicExpressionTree>)base.Content; }
52      set { base.Content = value; }
53    }
54
55    #region event handlers
56
57    protected override void OnContentChanged() {
58      base.OnContentChanged();
59      if (Content != null) {
60        genealogyGraphChart.GenealogyGraph = Content;
61      }
62    }
63
64    #endregion
65
66    protected override void RegisterContentEvents() {
67      genealogyGraphChart.GenealogyGraphNodeClicked += graphChart_GenealogyGraphNodeClicked;
68      symbolicExpressionTreeChart.SymbolicExpressionTreeNodeClicked += treeChart_SymbolicExpressionNodeClicked;
69      base.RegisterContentEvents();
70    }
71
72    protected override void DeregisterContentEvents() {
73      base.DeregisterContentEvents();
74      genealogyGraphChart.GenealogyGraphNodeClicked -= graphChart_GenealogyGraphNodeClicked;
75      symbolicExpressionTreeChart.SymbolicExpressionTreeNodeClicked -= treeChart_SymbolicExpressionNodeClicked;
76    }
77
78    public void graphChart_GenealogyGraphNodeClicked(object sender, MouseEventArgs args) {
79      var visualNode = (VisualGenealogyGraphNode)sender;
80      var graphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)visualNode.Data;
81      var tree = graphNode.Content;
82      symbolicExpressionTreeChart.Tree = tree;
83    }
84
85    public void treeChart_SymbolicExpressionNodeClicked(object sender, MouseEventArgs args) {
86      var visualNode = (VisualTreeNode<ISymbolicExpressionTreeNode>)sender;
87      var subtree = visualNode.Content;
88
89      // highlight the selected subtree inside the displayed tree on the right hand side
90      treeChart_ClearColors();
91      treeChart_HighlightSubtree(subtree);
92
93      bool trace = genealogyGraphChart.TraceFragments; // check whether the mode is 'trace' or 'match'
94
95      if (trace) {
96        // perform fragment tracing
97        var fragmentGraph = TraceSubtree(subtree);
98
99        // find all the genealogy graph nodes that contain the building blocks which formed the currently selected subtree
100        // this should maybe be limited to nodes of the ancestry (can be very computationally expensive)
101        var vertices = from x in fragmentGraph.Nodes
102                       let fragmentNode = (FragmentNode)x
103                       let fragment = fragmentNode.Content
104                       from y in Content.Nodes
105                       let graphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)y
106                       let tree = graphNode.Content
107                       where tree.Root.ContainsSubtree(fragment.Root, comparer)
108                       select graphNode;
109
110        graphChart_highlightMatchingVertices(vertices);
111      } else {
112        // perform matching like before
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    private FragmentGraph TraceSubtree(ISymbolicExpressionTreeNode subtree) {
170      var graphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)genealogyGraphChart.SelectedGraphNode;
171      var graph = new GenealogyGraph<IFragment<ISymbolicExpressionTreeNode>>();
172      Trace(graphNode, subtree, graph);
173      return graph;
174    }
175
176    private void Trace(IGenealogyGraphNode<ISymbolicExpressionTree> graphNode, ISymbolicExpressionTreeNode subtree, FragmentGraph fragmentGraph, FragmentNode fragmentNode = null) {
177      // add the subtree as a vertex in the fragment graph
178      var fn = new FragmentNode { Content = new Fragment<ISymbolicExpressionTreeNode> { Root = subtree }, Rank = graphNode.Rank };
179      fragmentGraph.AddVertex(fn);
180
181      // maybe we reached the end of the genealogy
182      if (graphNode.InArcs == null) return;
183
184      // the subtree must belong to the currently displayed tree which in turn must belong to the currently selected graph node
185      var tree = graphNode.Content;
186      var index = tree.IterateNodesPrefix().ToList().IndexOf(subtree);
187      var length = subtree.GetLength();
188
189      var fragment = (IFragment<ISymbolicExpressionTreeNode>)graphNode.InArcs.Last().Data;
190      var fragmentLength = fragment.Root.GetLength();
191
192      if (fragment.Index <= index && index < fragment.Index + fragmentLength) {
193        // the selected subtree is contained by the fragment
194        var fn1 = new FragmentNode { Content = fragment };
195        if (fragmentNode != null) {
196          AddChild(fragmentNode, fn1);
197        }
198        fragmentGraph.AddVertex(fn1);
199        graphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)graphNode.InArcs.Last().Source;
200        subtree = graphNode.Content.IterateNodesPrefix().ToList()[fragment.OldIndex];
201        Trace(graphNode, subtree, fragmentGraph, fn1);
202      } else if (fragment.Index > index && fragment.Index < index + length) {
203        // the selected subtree contains the fragment
204        // first trace the fragment, then trace the subtree
205        graphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)graphNode.InArcs.Last().Source;
206        subtree = graphNode.Content.IterateNodesPrefix().ToList()[fragment.OldIndex];
207
208        var fn0 = new FragmentNode { Content = new Fragment<ISymbolicExpressionTreeNode> { Root = subtree } };
209        var fn1 = new FragmentNode { Content = fragment };
210
211        if (fragmentNode != null) {
212          AddChild(fragmentNode, fn0);
213          AddChild(fragmentNode, fn1);
214        }
215        fragmentGraph.AddVertex(fn0);
216        fragmentGraph.AddVertex(fn1);
217
218        var graphNode0 = (IGenealogyGraphNode<ISymbolicExpressionTree>)graphNode.InArcs[0].Source;
219        var subtree0 = graphNode0.Content.IterateNodesPrefix().ToList()[index];
220        Trace(graphNode0, subtree0, fragmentGraph, fn0);
221
222        var graphNode1 = (IGenealogyGraphNode<ISymbolicExpressionTree>)graphNode.InArcs.Last().Source;
223        var subtree1 = graphNode1.Content.IterateNodesPrefix().ToList()[fragment.OldIndex];
224        Trace(graphNode1, subtree1, fragmentGraph, fn1);
225      } else {
226        // the fragment is not contained by the selected subtree, so we go one level up
227        graphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)graphNode.InArcs[0].Source;
228        subtree = graphNode.Content.IterateNodesPrefix().ToList()[index];
229        fragmentGraph.Clear(); // restart the trace one level up
230        Trace(graphNode, subtree, fragmentGraph);
231      }
232    }
233
234    private void AddChild(FragmentNode parent, FragmentNode child) {
235      child.Rank = parent.Rank - 1;
236      parent.AddForwardArc(child);
237      child.AddReverseArc(parent);
238    }
239    #endregion
240  }
241}
Note: See TracBrowser for help on using the repository browser.