Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/Tracking/SymbolicDataAnalysisGenealogyGraphView.cs @ 11891

Last change on this file since 11891 was 11881, checked in by bburlacu, 8 years ago

#1772:

  • TraceGraph: Improved saving of trace data, changed GetTraceNode method to AddTraceNode and made the code more clear.
  • SymbolicDataAnalysisGenealogyGraphView: added highlighting of trace information (when visualizing trace graphs)
  • GenealogyGraphChart: removed useless code
File size: 10.4 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.Common;
28using HeuristicLab.Core;
29using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
30using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views;
31using HeuristicLab.EvolutionTracking;
32using HeuristicLab.EvolutionTracking.Views;
33using HeuristicLab.MainForm;
34
35namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Views {
36  [View("SymbolicDataAnalysisGenealogyGraphView")]
37  [Content(typeof(IGenealogyGraph<ISymbolicExpressionTree>), IsDefaultView = true)]
38  public partial class SymbolicDataAnalysisGenealogyGraphView : SymbolicDataAnalysisGenealogyGraphViewDesignable {
39    private readonly ISymbolicExpressionTreeNodeSimilarityComparer comparer;
40
41    public SymbolicDataAnalysisGenealogyGraphView() {
42      InitializeComponent();
43      comparer = new SymbolicExpressionTreeNodeSimilarityComparer();
44      viewHost.ViewType = typeof(GraphicalSymbolicExpressionTreeView);
45    }
46    #region event handlers
47    protected override void OnContentChanged() {
48      base.OnContentChanged();
49      if (Content != null) { genealogyGraphChart.GenealogyGraph = Content; }
50    }
51    #endregion
52
53    public SymbolicExpressionTreeChart SymbolicExpressionTreeChart {
54      get {
55        var view = (GraphicalSymbolicExpressionTreeView)base.viewHost.ActiveView;
56        return view == null ? null : view.SymbolicExpressionTreeChart;
57      }
58    }
59
60    protected override void RegisterContentEvents() {
61      base.RegisterContentEvents();
62      if (SymbolicExpressionTreeChart != null)
63        SymbolicExpressionTreeChart.SymbolicExpressionTreeNodeClicked += treeChart_SymbolicExpressionTreeNodeClicked;
64    }
65
66    protected override void DeregisterContentEvents() {
67      if (SymbolicExpressionTreeChart != null)
68        SymbolicExpressionTreeChart.SymbolicExpressionTreeNodeClicked -= treeChart_SymbolicExpressionTreeNodeClicked;
69      base.DeregisterContentEvents();
70    }
71
72    public override void graphChart_GenealogyGraphNodeClicked(object sender, MouseEventArgs args) {
73      base.graphChart_GenealogyGraphNodeClicked(sender, args);
74      var visualNode = (VisualGenealogyGraphNode)sender;
75      var graphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)visualNode.Data;
76
77      nodeQualityLabel.Text = String.Format("{0:0.000}", graphNode.Quality);
78      nodeRankLabel.Text = String.Format("{0:0.0}", graphNode.Rank);
79      nodeDegreeLabel.Text = String.Format("{0} / {1}", graphNode.InDegree, graphNode.OutDegree);
80
81      if (openNew_CheckBox.Checked) {
82        // get the ancestors into a new view
83        var cloner = new Cloner();
84        // clone arcs and vertices and use them to create a new graph
85        // that will include just the individual and its ancestors
86        var graph = new GenealogyGraph<ISymbolicExpressionTree>();
87        var ancestors = new[] { graphNode }.Concat(graphNode.Ancestors);
88        var cloned = ancestors.ToDictionary(x => x, x => cloner.Clone(x));
89        graph.AddVertices(cloned.Values);
90        foreach (var arc in cloned.Keys.SelectMany(x => x.InArcs)) {
91          graph.AddArc(cloner.Clone(arc));
92        }
93        MainFormManager.MainForm.ShowContent(graph);
94      }
95
96      if (graphNode.InArcs.Any()) {
97        var data = graphNode.InArcs.Last().Data;
98        var fragment = data as IFragment<ISymbolicExpressionTreeNode>;
99        var td = data as TraceData;
100        if (fragment != null) {
101          treeChart_HighlightSubtree(graphNode.Data.NodeAt(fragment.Index1));
102        } else if (td != null) {
103          var nodes = graphNode.Data.IterateNodesPrefix().ToList();
104          treeChart_HighlightSubtree(nodes[td.LastSubtreeIndex], Color.Orange);
105          treeChart_HighlightSubtree(nodes[td.LastFragmentIndex], Color.DodgerBlue);
106        }
107      }
108    }
109
110    public void treeChart_SymbolicExpressionTreeNodeClicked(object sender, MouseEventArgs args) {
111      var visualNode = (VisualTreeNode<ISymbolicExpressionTreeNode>)sender;
112      var subtree = visualNode.Content;
113      // highlight the selected subtree inside the displayed tree on the right hand side
114      treeChart_ClearColors();
115      treeChart_HighlightSubtree(subtree);
116
117      bool trace = genealogyGraphChart.TraceFragments; // check whether we are in 'trace' or 'match' mode
118
119      if (trace) {
120        // perform fragment tracing
121        var graphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)genealogyGraphChart.SelectedGraphNode;
122        var subtreeIndex = graphNode.Data.IterateNodesPrefix().ToList().IndexOf(subtree);
123        var traceGraph = TraceCalculator.TraceSubtree(graphNode, subtreeIndex);
124        if (traceGraph.Vertices.Any()) {
125          genealogyGraphChart.UpdateEnabled = false;
126          genealogyGraphChart.ClearArcs();
127          var genealogyNodes = traceGraph.Vertices.Select(v => Content.GetByContent(v.Data));
128          genealogyGraphChart.HighlightNodes(genealogyNodes, Color.Black, false);
129          genealogyGraphChart.UpdateEnabled = true;
130          genealogyGraphChart.EnforceUpdate();
131          MainFormManager.MainForm.ShowContent(traceGraph); // display the fragment graph on the screen
132        }
133      } else {
134        // perform matching like it was done before
135        // currently there is no possibility to specify the subtree matching criteria
136        var trees = Content.Vertices.Select(x => x.Data);
137        var matchingTrees = trees.Where(x => x.Root.ContainsSubtree(subtree, comparer));
138
139        var matchingVertices = matchingTrees.Select(x => Content.GetByContent(x));
140        graphChart_HighlightMatchingVertices(matchingVertices);
141      }
142    }
143
144    private void graphChart_HighlightMatchingVertices(IEnumerable<IGenealogyGraphNode> vertices) {
145      genealogyGraphChart.Chart.UpdateEnabled = false;
146      genealogyGraphChart.ClearPrimitives();
147      genealogyGraphChart.HighlightNodes(vertices);
148      genealogyGraphChart.Chart.UpdateEnabled = true;
149      genealogyGraphChart.Chart.EnforceUpdate();
150    }
151
152    private void treeChart_ClearColors() {
153      foreach (var node in SymbolicExpressionTreeChart.Tree.IterateNodesPrefix()) {
154        var visualNode = SymbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node);
155        if (visualNode != null) {
156          visualNode.LineColor = Color.Black;
157          visualNode.FillColor = Color.Transparent;
158        }
159      }
160      SymbolicExpressionTreeChart.RepaintNodes();
161    }
162
163    private void treeChart_HighlightSubtree(ISymbolicExpressionTreeNode subtree, Color? color = null) {
164      Color myColor = color ?? Color.RoyalBlue;
165      foreach (var s in subtree.IterateNodesPrefix()) {
166        var visualNode = SymbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(s);
167        visualNode.LineColor = myColor;
168
169        foreach (var c in s.Subtrees) {
170          var visualArc = SymbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNodeConnection(s, c);
171          visualArc.LineColor = myColor;
172        }
173      }
174      SymbolicExpressionTreeChart.RepaintNodes();
175    }
176
177    private void navigateLeftButton_Click(object sender, EventArgs e) {
178      var graphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)genealogyGraphChart.SelectedGraphNode;
179      var inArcs = (List<IArc>)((IVertex)graphNode).InArcs;
180      if (inArcs.Count > 0) {
181        genealogyGraphChart.SelectedGraphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)inArcs[0].Source;
182      }
183    }
184
185    private void navigateRightButton_Click(object sender, EventArgs e) {
186      var graphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)genealogyGraphChart.SelectedGraphNode;
187      var inArcs = (List<IArc>)((IVertex)graphNode).InArcs;
188      if (inArcs.Count > 0) {
189        var data = inArcs.Last().Data;
190        var fragment = (data as IFragment<ISymbolicExpressionTreeNode>);
191        var td = data as TraceData;
192        if (fragment != null) {
193          genealogyGraphChart.SelectedGraphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)inArcs.Last().Source;
194        } else if (td != null) {
195          if (inArcs.Count == 1) {
196            genealogyGraphChart.SelectedGraphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)inArcs[0].Source;
197            return;
198          }
199          // the first arc from inArcs will always represent the connection to the root parent
200          // (tracing the body of the traced subtree)
201          // therefore, in order to follow the correct non-root parent, we have to find the correct arc
202          // But, the FragmentIndex recorded in the TraceData of the first arc has to match the SubtreeIndex recorded in the TraceData of the searched arc
203          td = (TraceData)inArcs[0].Data;
204          var f1 = (graphNode.Data).NodeAt(td.LastFragmentIndex);
205          for (int i = 1; i < inArcs.Count; ++i) {
206            td = (TraceData)inArcs[i].Data;
207            var f2 = ((ISymbolicExpressionTree)inArcs[i].Source.Data).NodeAt(td.SubtreeIndex);
208            // if the subtrees are the same we have found a match
209            // note: this is not necessarily 100% correct if in the trace graph we have identical fragments on different arcs
210            if (f1.Difference(f2) == null) {
211              genealogyGraphChart.SelectedGraphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)inArcs[i].Source;
212              return;
213            }
214          }
215          throw new InvalidOperationException("Error calculating the next step.");
216        }
217      }
218    }
219  }
220
221  public class SymbolicDataAnalysisGenealogyGraphViewDesignable : GenealogyGraphView<ISymbolicExpressionTree> { }
222}
Note: See TracBrowser for help on using the repository browser.