Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1772: Merged trunk and worked on the graph view.

File size: 12.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.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 ISymbolicExpressionTreeNodeEqualityComparer comparer;
40
41    private ISymbolicExpressionTreeNode selectedSubtree;
42    private ISymbolicExpressionTreeNode SelectedSubtree {
43      get {
44        return selectedSubtree;
45      }
46      set {
47        if (selectedSubtree == value) return;
48        selectedSubtree = value;
49        ClonedSubtree = (ISymbolicExpressionTreeNode)selectedSubtree.Clone();
50      }
51    }
52
53    private ISymbolicExpressionTreeNode ClonedSubtree { get; set; }
54
55    public SymbolicDataAnalysisGenealogyGraphView() {
56      InitializeComponent();
57      comparer = new SymbolicExpressionTreeNodeEqualityComparer();
58      viewHost.ViewType = typeof(GraphicalSymbolicExpressionTreeView);
59    }
60    #region event handlers
61    protected override void OnContentChanged() {
62      base.OnContentChanged();
63      if (Content != null) { genealogyGraphChart.GenealogyGraph = Content; }
64    }
65    #endregion
66
67    public SymbolicExpressionTreeChart SymbolicExpressionTreeChart {
68      get {
69        var view = (GraphicalSymbolicExpressionTreeView)base.viewHost.ActiveView;
70        return view == null ? null : view.SymbolicExpressionTreeChart;
71      }
72    }
73
74    protected override void RegisterContentEvents() {
75      base.RegisterContentEvents();
76      if (SymbolicExpressionTreeChart != null)
77        SymbolicExpressionTreeChart.SymbolicExpressionTreeNodeClicked += treeChart_SymbolicExpressionTreeNodeClicked;
78    }
79
80    protected override void DeregisterContentEvents() {
81      if (SymbolicExpressionTreeChart != null)
82        SymbolicExpressionTreeChart.SymbolicExpressionTreeNodeClicked -= treeChart_SymbolicExpressionTreeNodeClicked;
83      base.DeregisterContentEvents();
84    }
85
86    public override void graphChart_GenealogyGraphNodeClicked(object sender, MouseEventArgs args) {
87      base.graphChart_GenealogyGraphNodeClicked(sender, args);
88      var visualNode = (VisualGenealogyGraphNode)sender;
89      var graphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)visualNode.Data;
90
91      nodeQualityLabel.Text = String.Format("{0:0.000}", graphNode.Quality);
92      nodeRankLabel.Text = String.Format("{0:0.0}", graphNode.Rank);
93      nodeDegreeLabel.Text = String.Format("{0} / {1}", graphNode.InDegree, graphNode.OutDegree);
94      nodeWeightLabel.Text = String.Format("{0:0.00}", graphNode.Weight);
95
96      if (openNew_CheckBox.Checked) {
97        // get the ancestors into a new view
98        var cloner = new Cloner();
99        // clone arcs and vertices and use them to create a new graph
100        // that will include just the individual and its ancestors
101        var graph = new GenealogyGraph<ISymbolicExpressionTree>();
102        var ancestors = new[] { graphNode }.Concat(graphNode.Ancestors).ToList();
103        graph.AddVertices(ancestors.Select(cloner.Clone));
104        graph.AddArcs(ancestors.SelectMany(x => x.InArcs).Select(cloner.Clone));
105        MainFormManager.MainForm.ShowContent(graph);
106      }
107
108      if (graphNode.InArcs.Any()) {
109        var data = graphNode.InArcs.Last().Data;
110        var fragment = data as IFragment<ISymbolicExpressionTreeNode>;
111        var td = data as TraceData;
112        if (fragment != null) {
113          treeChart_HighlightSubtree(graphNode.Data.NodeAt(fragment.Index1));
114        } else if (td != null) {
115          var nodes = graphNode.Data.IterateNodesPrefix().ToList();
116          treeChart_HighlightSubtree(nodes[td.LastSubtreeIndex], Color.Orange);
117          treeChart_HighlightSubtree(nodes[td.LastFragmentIndex], null, Color.PowderBlue);
118        }
119      }
120    }
121
122    public void treeChart_SymbolicExpressionTreeNodeClicked(object sender, MouseEventArgs args) {
123      var visualNode = (VisualTreeNode<ISymbolicExpressionTreeNode>)sender;
124      var subtree = visualNode.Content;
125      // highlight the selected subtree inside the displayed tree on the right hand side
126      treeChart_ClearColors();
127      treeChart_HighlightSubtree(subtree);
128
129      bool trace = genealogyGraphChart.TraceFragments; // check whether we are in 'trace' or 'match' mode
130
131      switch (args.Button) {
132        case MouseButtons.Left:
133          SelectedSubtree = subtree;
134          if (trace) {
135            // perform fragment tracing
136            var graphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)genealogyGraphChart.SelectedGraphNode;
137            var subtreeIndex = graphNode.Data.IterateNodesPrefix().ToList().IndexOf(subtree);
138            var traceGraph = TraceCalculator.TraceSubtree(graphNode, subtreeIndex);
139            if (traceGraph.Vertices.Any()) {
140              genealogyGraphChart.UpdateEnabled = false;
141              genealogyGraphChart.ClearArcs();
142              var genealogyNodes = traceGraph.Vertices.Select(v => Content.GetByContent(v.Data));
143              genealogyGraphChart.HighlightNodes(genealogyNodes, Color.Black, false);
144              genealogyGraphChart.UpdateEnabled = true;
145              genealogyGraphChart.EnforceUpdate();
146              if (openNew_CheckBox.Checked)
147                MainFormManager.MainForm.ShowContent(traceGraph); // display the fragment graph on the screen
148
149              var max = traceGraph.Vertices.Max(x => x.Weight);
150
151              genealogyGraphChart.UpdateEnabled = false;
152              foreach (var traceNode in traceGraph.Vertices) {
153                var g = Content.GetByContent(traceNode.Data);
154                g.Weight = traceNode.Weight;
155                var v = genealogyGraphChart.GetMappedNode(g);
156                if (v != null) {
157                  int i = (int)Math.Round(g.Weight * (ColorGradient.Colors.Count - 1) / max);
158
159                  v.Brush = new SolidBrush(ColorGradient.Colors[i]);
160                }
161              }
162              genealogyGraphChart.UpdateEnabled = true;
163              genealogyGraphChart.EnforceUpdate();
164            }
165          } else {
166            // perform matching like it was done before
167            // currently there is no possibility to specify the subtree matching criteria
168            var trees = Content.Vertices.Select(x => x.Data);
169            var matchingTrees = trees.Where(x => x.Root.ContainsSubtree(subtree, comparer));
170
171            var matchingVertices = matchingTrees.Select(x => Content.GetByContent(x));
172            graphChart_HighlightMatchingVertices(matchingVertices);
173          }
174          break;
175        case MouseButtons.Middle:
176          var index = SelectedSubtree.IterateNodesPrefix().ToList().IndexOf(subtree);
177          if (index > 0) {
178            var s = ClonedSubtree.NodeAt(index);
179            s.Parent.RemoveSubtree(s.Parent.IndexOfSubtree(s));
180
181            var trees = Content.Vertices.Select(x => x.Data);
182            var matchingTrees = trees.Where(x => x.Root.ContainsSubtree(ClonedSubtree, comparer));
183
184            var matchingVertices = matchingTrees.Select(x => Content.GetByContent(x));
185            treeChart_HighlightSubtree(subtree, Color.Black, Color.White);
186            graphChart_HighlightMatchingVertices(matchingVertices);
187          }
188          break;
189      }
190    }
191
192    private void graphChart_HighlightMatchingVertices(IEnumerable<IGenealogyGraphNode> vertices) {
193      genealogyGraphChart.Chart.UpdateEnabled = false;
194      genealogyGraphChart.ClearPrimitives();
195      genealogyGraphChart.HighlightNodes(vertices);
196      genealogyGraphChart.Chart.UpdateEnabled = true;
197      genealogyGraphChart.Chart.EnforceUpdate();
198    }
199
200    private void treeChart_ClearColors() {
201      foreach (var node in SymbolicExpressionTreeChart.Tree.IterateNodesPrefix()) {
202        var visualNode = SymbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node);
203        if (visualNode != null) {
204          visualNode.LineColor = Color.Black;
205          visualNode.FillColor = Color.Transparent;
206        }
207      }
208      SymbolicExpressionTreeChart.RepaintNodes();
209    }
210
211    private void treeChart_HighlightSubtree(ISymbolicExpressionTreeNode subtree, Color? lineColor = null, Color? fillColor = null) {
212      var lc = lineColor ?? Color.RoyalBlue;
213      var fc = fillColor ?? Color.White;
214      foreach (var s in subtree.IterateNodesPrefix()) {
215        var visualNode = SymbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(s);
216        visualNode.LineColor = lc;
217        visualNode.FillColor = fc;
218
219        foreach (var c in s.Subtrees) {
220          var visualArc = SymbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNodeConnection(s, c);
221          visualArc.LineColor = lc;
222        }
223      }
224      SymbolicExpressionTreeChart.RepaintNodes();
225    }
226
227    private void navigateLeftButton_Click(object sender, EventArgs e) {
228      var graphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)genealogyGraphChart.SelectedGraphNode;
229      var inArcs = (List<IArc>)((IVertex)graphNode).InArcs;
230      if (inArcs.Count > 0) {
231        genealogyGraphChart.SelectedGraphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)inArcs[0].Source;
232      }
233    }
234
235    private void navigateRightButton_Click(object sender, EventArgs e) {
236      var graphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)genealogyGraphChart.SelectedGraphNode;
237      var inArcs = graphNode.InArcs.ToList();
238      if (inArcs.Count > 0) {
239        var data = inArcs.Last().Data;
240        var fragment = (data as IFragment<ISymbolicExpressionTreeNode>);
241        var td = data as TraceData;
242        if (fragment != null) {
243          genealogyGraphChart.SelectedGraphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)inArcs.Last().Source;
244        } else if (td != null) {
245          if (inArcs.Count == 1) {
246            genealogyGraphChart.SelectedGraphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)inArcs[0].Source;
247            return;
248          }
249          // the first arc from inArcs will always represent the connection to the root parent
250          // (tracing the body of the traced subtree)
251          // therefore, in order to follow the correct non-root parent, we have to find the correct arc
252          // But, the FragmentIndex recorded in the TraceData of the first arc has to match the SubtreeIndex recorded in the TraceData of the searched arc
253          td = (TraceData)inArcs[0].Data;
254          var f1 = (graphNode.Data).NodeAt(td.LastFragmentIndex);
255          for (int i = 1; i < inArcs.Count; ++i) {
256            td = (TraceData)inArcs[i].Data;
257            var f2 = ((IGenealogyGraphNode<ISymbolicExpressionTree>)inArcs[i].Source).Data.NodeAt(td.SubtreeIndex);
258            // if the subtrees are the same we have found a match
259            // note: this is not necessarily 100% correct if in the trace graph we have identical fragments on different arcs
260            if (f1.Difference(f2) == null) {
261              genealogyGraphChart.SelectedGraphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)inArcs[i].Source;
262              return;
263            }
264          }
265          throw new InvalidOperationException("Error calculating the next step.");
266        }
267      }
268    }
269  }
270  public class SymbolicDataAnalysisGenealogyGraphViewDesignable : GenealogyGraphView<ISymbolicExpressionTree> { }
271
272  internal static class Util {
273    internal static ISymbolicExpressionTreeNode NodeAt(this ISymbolicExpressionTree tree, int position) {
274      return NodeAt(tree.Root, position);
275    }
276    internal static ISymbolicExpressionTreeNode NodeAt(this ISymbolicExpressionTreeNode root, int position) {
277      return root.IterateNodesPrefix().ElementAt(position);
278    }
279  }
280}
Note: See TracBrowser for help on using the repository browser.