Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1772: Made some progress towards the visualization of building block trajectories. Added the FragmentGraphView.

File size: 10.8 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.Linq;
26using System.Windows.Forms;
27using HeuristicLab.Core.Views;
28using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
29using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views;
30using HeuristicLab.EvolutionTracking;
31using HeuristicLab.EvolutionTracking.Views;
32using HeuristicLab.MainForm;
33
34using FragmentGraph = HeuristicLab.EvolutionTracking.IGenealogyGraph<HeuristicLab.EvolutionTracking.IFragment<HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.ISymbolicExpressionTreeNode>>;
35
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
86    public void treeChart_SymbolicExpressionNodeClicked(object sender, MouseEventArgs args) {
87      var visualNode = (VisualTreeNode<ISymbolicExpressionTreeNode>)sender;
88      var subtree = visualNode.Content;
89
90      // highlight the selected subtree inside the displayed tree on the right hand side
91      treeChart_ClearColors();
92      treeChart_HighlightSubtree(subtree);
93
94      bool trace = genealogyGraphChart.TraceFragments; // check whether the mode is 'trace' or 'match'
95
96      if (trace) {
97        // perform fragment tracing
98        var fragmentGraph = TraceSubtree(subtree);
99
100        // open a FragmentGraphView displaying this fragmentGraph
101      } else {
102        // perform matching like it was done before
103        // currently there is no possibility to specify the subtree matching criteria
104        var trees = Content.Nodes.Select(x => (ISymbolicExpressionTree)x.Content);
105        var matchingTrees = trees.Where(x => x.Root.ContainsSubtree(subtree, comparer));
106
107        var matchingVertices = matchingTrees.SelectMany(x => Content[x]).Cast<IGenealogyGraphNode<ISymbolicExpressionTree>>();
108        graphChart_highlightMatchingVertices(matchingVertices);
109      }
110    }
111
112    private void graphChart_highlightMatchingVertices(IEnumerable<IGenealogyGraphNode> vertices) {
113      genealogyGraphChart.Chart.UpdateEnabled = false;
114      genealogyGraphChart.ClearPrimitives();
115      genealogyGraphChart.HighlightNodes(vertices);
116      genealogyGraphChart.Chart.UpdateEnabled = true;
117      genealogyGraphChart.Chart.EnforceUpdate();
118    }
119
120    private void treeChart_ClearColors() {
121      foreach (var node in symbolicExpressionTreeChart.Tree.IterateNodesPrefix()) {
122        var visualNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node);
123        if (visualNode != null) {
124          visualNode.LineColor = Color.Black;
125          visualNode.FillColor = Color.Transparent;
126        }
127      }
128      symbolicExpressionTreeChart.RepaintNodes();
129    }
130
131    private void treeChart_HighlightSubtree(ISymbolicExpressionTreeNode subtree) {
132      foreach (var s in subtree.IterateNodesPrefix()) {
133        var visualNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(s);
134        visualNode.LineColor = Color.RoyalBlue;
135        visualNode.FillColor = Color.LightBlue;
136
137        foreach (var c in s.Subtrees) {
138          var visualArc = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNodeConnection(s, c);
139          visualArc.LineColor = Color.RoyalBlue;
140        }
141      }
142      symbolicExpressionTreeChart.RepaintNodes();
143    }
144
145    #region events for configuring the behavior of the genealogy chart (trace/match, simple lineages, etc)
146    private void trace_checkBox_CheckedChanged(object sender, System.EventArgs e) {
147      genealogyGraphChart.TraceFragments = trace_checkBox.Checked;
148    }
149
150    private void simpleLineages_checkBox_CheckedChanged(object sender, System.EventArgs e) {
151      genealogyGraphChart.SimpleLineages = simpleLineages_checkBox.Checked;
152    }
153
154    private void lockGraph_checkBox_CheckedChanged(object sender, System.EventArgs e) {
155      genealogyGraphChart.LockGenealogy = lockGraph_checkBox.Checked;
156    }
157    #endregion
158
159    #region fragment tracing
160    private FragmentGraph TraceSubtree(ISymbolicExpressionTreeNode subtree) {
161      var graphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)genealogyGraphChart.SelectedGraphNode;
162      var graph = new GenealogyGraph<IFragment<ISymbolicExpressionTreeNode>>();
163      Trace(graphNode, subtree, graph);
164      return graph;
165    }
166
167    private void Trace(IGenealogyGraphNode<ISymbolicExpressionTree> graphNode, ISymbolicExpressionTreeNode subtree, FragmentGraph fragmentGraph, FragmentNode parentNode = null) {
168      if (graphNode.InArcs == null) return;
169      // the subtree must belong to the currently displayed tree which in turn must belong to the currently selected graph node
170      var tree = graphNode.Content;
171      var index = tree.IterateNodesPrefix().ToList().IndexOf(subtree);
172      var length = subtree.GetLength();
173
174      var fragment = (IFragment<ISymbolicExpressionTreeNode>)graphNode.InArcs.Last().Data;
175      var fragmentLength = fragment.Root.GetLength();
176
177
178      // below, we consider three cases:
179      // 1) the selected subtree is the same as the fragment
180      // 2) the fragment contains the selected subtree
181      // 3) the fragment is contained by the selected subtree
182      // In each case, the idea is to isolate and individually track the fragment and the rest of the subtree (for cases 2 and 3)
183      if (fragment.Index == index) {
184        // the selected subtree is the actual fragment
185        if (fragmentLength != length) throw new Exception("Fragment and subtree lengths should be the same!");
186
187        var node = new FragmentNode { Content = fragment, Rank = graphNode.Rank };
188
189        if (parentNode != null) {
190          AddChild(parentNode, node);
191        }
192
193        fragmentGraph.AddVertex(node);
194
195        graphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)graphNode.InArcs.Last().Source;
196        subtree = graphNode.Content.IterateNodesPrefix().ToList()[fragment.OldIndex];
197        Trace(graphNode, subtree, fragmentGraph, node);
198      } else if (fragment.Index < index && index < fragment.Index + fragmentLength) {
199        // the fragment contains the selected subtree
200        if (length >= fragmentLength) throw new Exception("Fragment contains subtree, so subtree length should be less than the fragment length.");
201
202        var node = new FragmentNode { Content = fragment, Rank = graphNode.Rank };
203        if (parentNode != null) {
204          AddChild(parentNode, node);
205        }
206
207        fragmentGraph.AddVertex(node);
208
209        graphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)graphNode.InArcs.Last().Source;
210        var i = fragment.Root.IterateNodesPrefix().ToList().IndexOf(subtree);
211        subtree = graphNode.Content.IterateNodesPrefix().ToList()[fragment.OldIndex + i];
212        Trace(graphNode, subtree, fragmentGraph, node);
213
214      } else if (index < fragment.Index && fragment.Index < index + length) {
215        // the selected subtree contains the fragment
216        if (fragmentLength >= length) throw new Exception("Subtree contains fragment, so fragment length should be less than the subtree length.");
217
218        var node = new FragmentNode { Content = new Fragment<ISymbolicExpressionTreeNode> { Root = subtree }, Rank = graphNode.Rank };
219
220        if (parentNode != null) {
221          AddChild(parentNode, node);
222        }
223        fragmentGraph.AddVertex(node);
224
225        var graphNode0 = (IGenealogyGraphNode<ISymbolicExpressionTree>)graphNode.InArcs[0].Source;
226        var subtree0 = graphNode0.Content.IterateNodesPrefix().ToList()[index];
227        Trace(graphNode0, subtree0, fragmentGraph, node);
228
229        if (graphNode.InArcs.Count > 1) {
230          var graphNode1 = (IGenealogyGraphNode<ISymbolicExpressionTree>)graphNode.InArcs[1].Source;
231          var subtree1 = graphNode1.Content.IterateNodesPrefix().ToList()[fragment.OldIndex];
232          Trace(graphNode1, subtree1, fragmentGraph, node);
233        }
234      }
235    }
236
237    private void AddChild(FragmentNode parent, FragmentNode child) {
238      child.Rank = parent.Rank - 1;
239      parent.AddForwardArc(child);
240      child.AddReverseArc(parent);
241    }
242    #endregion
243  }
244}
Note: See TracBrowser for help on using the repository browser.