Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 12225 was 12225, checked in by bburlacu, 9 years ago

#1772: Work in progress for calculating sampling counts for subtrees in the population: updated TraceCalculator to aggregate tracing statistics, updated SymbolicDataAnalysisGenealogyGraphView, added SymbolicDataAnalysisSubtreeSampleCountAnalyzer.

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