Changeset 13877


Ignore:
Timestamp:
06/06/16 19:39:43 (3 years ago)
Author:
bburlacu
Message:

#1772: Improve SymbolicDataAnalysisGenealogyGraphView by using a better coloring scheme for frequent subtrees. Fix bug when reaching the end of the genealogy. Minor refactorings.

Location:
branches/HeuristicLab.EvolutionTracking
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • branches/HeuristicLab.EvolutionTracking/HeuristicLab.EvolutionTracking.Views/3.4/GenealogyGraphChart.cs

    r13426 r13877  
    11#region License Information
    22/* HeuristicLab
    3  * Copyright (C) 2002-2014 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3 * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44 *
    55 * This file is part of HeuristicLab.
     
    6767          return;
    6868        SelectedVisualNode = GetMappedNode(value);
    69         UpdateSelectedVisualNode();
    70       }
    71     }
    72 
     69        RedrawLineages();
     70      }
     71    }
    7372    private void Clear() {
    7473      nodeMap = new Dictionary<IGenealogyGraphNode, VisualGenealogyGraphNode>();
     
    179178        if (primitive != null && primitive != SelectedVisualNode) {
    180179          SelectedVisualNode = (VisualGenealogyGraphNode)primitive;
    181           UpdateSelectedVisualNode(); // redraw ancestries, mark node etc.
     180          RedrawLineages(); // redraw ancestries, mark node etc.
     181
     182          if (SelectedVisualNode != null)
     183            OnGenealogyGraphNodeClicked(SelectedVisualNode, null); // emit clicked event
    182184        }
    183185      }
     
    185187    }
    186188
    187     private void UpdateSelectedVisualNode() {
     189    private void RedrawLineages() {
    188190      if (!LockGenealogy) {
    189191        // new node has been selected, clean up
     
    206208      // update
    207209      ResumeRendering();
    208 
    209       if (SelectedVisualNode != null)
    210         OnGenealogyGraphNodeClicked(SelectedVisualNode, null); // emit clicked event
    211210    }
    212211    #endregion
  • branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/Tracking/SymbolicDataAnalysisGenealogyGraphView.cs

    r13482 r13877  
    11#region License Information
    22/* HeuristicLab
    3  * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3 * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44 *
    55 * This file is part of HeuristicLab.
     
    2626using System.Windows.Forms;
    2727using HeuristicLab.Common;
    28 using HeuristicLab.Core;
    2928using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
    3029using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views;
     
    3231using HeuristicLab.EvolutionTracking.Views;
    3332using HeuristicLab.MainForm;
     33using HeuristicLab.Problems.DataAnalysis.Symbolic;
    3434
    3535namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Views {
     
    3838  public partial class SymbolicDataAnalysisGenealogyGraphView : SymbolicDataAnalysisGenealogyGraphViewDesignable {
    3939    private readonly ISymbolicExpressionTreeNodeEqualityComparer comparer;
     40
     41    private TraceData lastTd;
    4042
    4143    private ISymbolicExpressionTreeNode selectedSubtree;
     
    7981      var graphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)visualNode.Data;
    8082
    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);
    84       nodeWeightLabel.Text = String.Format("{0:0.00}", graphNode.Weight);
    85 
    86       int colorCount = ColorGradient.Colors.Count - 1;
    87       const int alpha = 100;
    88       // calculate max only in the current generation
    89       var nodes = graphNode.Data.IterateNodesPrefix().Skip(1).ToList();
    90       var max = Content.GetByRank(graphNode.Rank).Max(x => ((IGenealogyGraphNode<ISymbolicExpressionTree>)x).Data.IterateNodesPrefix().Max(n => n.NodeWeight));
    91       if (max.IsAlmost(0)) max = 1;
    92       foreach (var n in nodes) {
    93         var visualSymbolicExpressionTreeNode = SymbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(n);
    94         visualSymbolicExpressionTreeNode.ToolTip += Environment.NewLine + String.Format("Weight: {0:0}", n.NodeWeight);
    95         var i = (int)Math.Round(n.NodeWeight / max * colorCount);
    96         var fillColor = Color.FromArgb(alpha, ColorGradient.Colors[i]);
    97         treeChart_HighlightSubtree(n, null, fillColor);
    98       }
    99 
    100       if (!graphNode.InArcs.Any()) return;
     83      lastTd = null;
     84
     85      nodeQualityLabel.Text = string.Format("{0:0.000}", graphNode.Quality);
     86      nodeRankLabel.Text = string.Format("{0:0.0}", graphNode.Rank);
     87      nodeDegreeLabel.Text = string.Format("{0} / {1}", graphNode.InDegree, graphNode.OutDegree);
     88      nodeWeightLabel.Text = string.Format("{0:0.00}", graphNode.Weight);
     89
     90      // update the righthand side tree view when another genealogy graph node is selected
     91      UpdateTreeChart(graphNode);
     92
     93      if (!graphNode.InArcs.Any()) return; // node has no ancestors, nothing to do
    10194
    10295      if (openNew_CheckBox.Checked) {
     
    111104        MainFormManager.MainForm.ShowContent(graph);
    112105      }
    113 
     106    }
     107
     108    private void UpdateTreeChart(IGenealogyGraphNode<ISymbolicExpressionTree> graphNode) {
     109      SymbolicExpressionTreeChart.Tree = graphNode.Data;
     110      var nodes = graphNode.Data.IterateNodesPrefix().ToList();
     111      // calculate max only in the current generation
     112      var max = Content.Vertices.Max(x => ((IGenealogyGraphNode<ISymbolicExpressionTree>)x).Data.IterateNodesPrefix().Max(n => n.NodeWeight));
     113      if (max.IsAlmost(0)) max = 1;
     114      // we skip the program root node because it's useless for display and it just takes space in the chart
     115      foreach (var n in nodes.Skip(1)) {
     116        var visualSymbolicExpressionTreeNode = SymbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(n);
     117        visualSymbolicExpressionTreeNode.ToolTip += Environment.NewLine + string.Format("Weight: {0:0}", n.NodeWeight);
     118        var i = (int)Math.Round(n.NodeWeight / max * 255);
     119        var fillColor = Color.FromArgb(i, Color.Red);
     120        treeChart_HighlightSubtree(n, null, fillColor);
     121      }
     122
     123      if (!graphNode.InArcs.Any()) return;
    114124      var data = graphNode.InArcs.Last().Data;
    115125      var fragment = data as IFragment<ISymbolicExpressionTreeNode>;
    116       var td = data as TraceData;
     126      var td = lastTd;
    117127
    118128      if (fragment != null) {
     
    123133      } else if (td != null) {
    124134        // highlight traced subtree and fragment
    125         treeChart_HighlightSubtree(nodes[td.LastSubtreeIndex], Color.Orange);
    126         treeChart_HighlightSubtree(nodes[td.LastFragmentIndex], Color.CornflowerBlue);
     135        treeChart_HighlightSubtree(nodes[td.SubtreeIndex], Color.Orange);
     136        treeChart_HighlightSubtree(nodes[td.FragmentIndex], Color.CornflowerBlue);
    127137      }
    128138    }
     
    143153        var rankMaximums = new Dictionary<double, double>();
    144154        // fill each vertex in the graph with a grayscale color according to average subtree weight
     155
     156        int colorCount = ColorGradient.GrayscaledColors.Count - 1;
     157        var colorGradient = ColorGradient.GrayscaledColors;
    145158        foreach (var r in Content.Ranks) {
    146159          var vertices = r.Value.Cast<IGenealogyGraphNode<ISymbolicExpressionTree>>().ToList();
     
    149162          rankMaximums.Add(r.Key, max);
    150163          if (max.IsAlmost(0.0)) continue;
    151           int colorCount = ColorGradient.GrayscaledColors.Count - 1;
    152164          for (int i = 0; i < vertices.Count; ++i) {
    153             var color = ColorGradient.GrayscaledColors[(int)Math.Round(averages[i] / max * colorCount)];
     165            var color = colorGradient[(int)Math.Round(averages[i] / max * colorCount)];
    154166            var vNode = genealogyGraphChart.GetMappedNode(vertices[i]);
    155167            vNode.Brush = new SolidBrush(color);
     
    159171        if (traceGraph.Vertices.Any()) {
    160172          var ranks = traceGraph.Vertices.Select(x => Content.GetByContent(x.Data)).GroupBy(x => x.Rank);
    161           int colorCount = ColorGradient.Colors.Count - 1;
    162173          foreach (var g in ranks) {
    163174            var vertices = g.ToList();
     
    168179              var vNode = genealogyGraphChart.GetMappedNode(vertices[i]);
    169180              // use a grayscale gradient
    170               var color = ColorGradient.Colors[(int)Math.Round(averages[i] / max * colorCount)];
     181              var color = colorGradient[(int)Math.Round(averages[i] / max * colorCount)];
    171182              vNode.Brush = new SolidBrush(color);
    172183            }
     
    281292    private void navigateLeftButton_Click(object sender, EventArgs e) {
    282293      var graphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)genealogyGraphChart.SelectedGraphNode;
    283       var inArcs = (List<IArc>)((IVertex)graphNode).InArcs;
    284       if (inArcs.Count > 0) {
    285         genealogyGraphChart.SelectedGraphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)inArcs[0].Source;
    286       }
     294      if (!graphNode.InArcs.Any()) return;
     295
     296      // check if the arc contains fragment data
     297      var arc = graphNode.InArcs.First();
     298      var fragment = arc.Data as IFragment<ISymbolicExpressionTreeNode>;
     299
     300      if (fragment != null) {
     301        genealogyGraphChart.SelectedGraphNode = arc.Source;
     302        UpdateTreeChart((IGenealogyGraphNode<ISymbolicExpressionTree>)arc.Source);
     303        return;
     304      }
     305
     306      if (lastTd != null && graphNode.InDegree > 1) {
     307        var c = graphNode.Data;
     308        var s = c.NodeAt(lastTd.SubtreeIndex);
     309        var f = c.NodeAt(lastTd.FragmentIndex);
     310        arc = graphNode.InArcs.FirstOrDefault(
     311          a => {
     312            var td = a.Data as TraceData;
     313            if (td == null) return false;
     314            var p = (ISymbolicExpressionTree)a.Source.Data;
     315            var d = s.Difference(p.NodeAt(td.SubtreeIndex));
     316            if (d == null) return true;
     317            return f.IterateNodesPrefix().Any(x => x.IsIsomorphicWith(d));
     318          });
     319      }
     320      if (arc == null) return;
     321      lastTd = arc.Data as TraceData;
     322      genealogyGraphChart.SelectedGraphNode = arc.Source;
     323      UpdateTreeChart((IGenealogyGraphNode<ISymbolicExpressionTree>)arc.Source);
    287324    }
    288325
    289326    private void navigateRightButton_Click(object sender, EventArgs e) {
    290327      var graphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)genealogyGraphChart.SelectedGraphNode;
    291       var inArcs = (List<IArc>)((IVertex)graphNode).InArcs;
    292       if (inArcs.Count > 0) {
    293         if (inArcs.Count == 1) {
    294           genealogyGraphChart.SelectedGraphNode = (IGenealogyGraphNode<ISymbolicExpressionTree>)inArcs[0].Source;
    295           return;
    296         }
    297         IGenealogyGraphNode<ISymbolicExpressionTree> source = null;
    298         var fragment = ((IArc<IDeepCloneable>)inArcs.Last()).Data as IFragment<ISymbolicExpressionTreeNode>;
    299         var traceData = ((IArc<IDeepCloneable>)inArcs[0]).Data as TraceData;
    300         if (fragment != null) {
    301           source = (IGenealogyGraphNode<ISymbolicExpressionTree>)inArcs.Last().Source;
    302         }
    303         if (traceData != null) {
    304           var f = graphNode.Data.NodeAt(traceData.LastFragmentIndex);
    305           var selected = inArcs.Skip(1).First(x => {
    306             var td = (TraceData)((IArc<IDeepCloneable>)x).Data;
    307             var s = (IGenealogyGraphNode<ISymbolicExpressionTree>)x.Source;
    308             return f.Difference(s.Data.NodeAt(td.SubtreeIndex)) == null;
     328      if (!graphNode.InArcs.Any()) return;
     329
     330      // check if the arc contains fragment data
     331      var arc = graphNode.InArcs.Last();
     332      var fragment = arc.Data as IFragment<ISymbolicExpressionTreeNode>;
     333      if (fragment != null) {
     334        genealogyGraphChart.SelectedGraphNode = arc.Source;
     335        UpdateTreeChart((IGenealogyGraphNode<ISymbolicExpressionTree>)arc.Source);
     336        return;
     337      }
     338
     339      if (lastTd != null && graphNode.InDegree > 1) {
     340        var c = graphNode.Data;
     341        var f = c.NodeAt(lastTd.FragmentIndex);
     342        arc = graphNode.InArcs.FirstOrDefault(
     343          a => {
     344            var td = a.Data as TraceData;
     345            var p = (ISymbolicExpressionTree)a.Source.Data;
     346            return td != null && p.NodeAt(td.SubtreeIndex).Difference(f) == null;
    309347          });
    310           source = (IGenealogyGraphNode<ISymbolicExpressionTree>)selected.Source;
    311         }
    312         if (source != null)
    313           genealogyGraphChart.SelectedGraphNode = source;
    314       }
    315     }
    316     #endregion
    317   }
    318 
    319   // bogus class needed in order to be able to "design" the view
    320   public class SymbolicDataAnalysisGenealogyGraphViewDesignable : GenealogyGraphView<ISymbolicExpressionTree> { }
    321 
    322   #region helper methods
    323   internal static class Util {
    324     internal static ISymbolicExpressionTreeNode NodeAt(this ISymbolicExpressionTree tree, int position) {
    325       return NodeAt(tree.Root, position);
    326     }
    327     internal static ISymbolicExpressionTreeNode NodeAt(this ISymbolicExpressionTreeNode root, int position) {
    328       return root.IterateNodesPrefix().ElementAt(position);
     348      }
     349      if (arc == null) return;
     350      lastTd = arc.Data as TraceData;
     351      genealogyGraphChart.SelectedGraphNode = arc.Source;
     352      UpdateTreeChart((IGenealogyGraphNode<ISymbolicExpressionTree>)arc.Source);
    329353    }
    330354  }
    331355  #endregion
    332356}
     357
     358// bogus class needed in order to be able to "design" the view
     359public class SymbolicDataAnalysisGenealogyGraphViewDesignable : GenealogyGraphView<ISymbolicExpressionTree> { }
     360
     361#region helper methods
     362internal static class Util {
     363  internal static ISymbolicExpressionTreeNode NodeAt(this ISymbolicExpressionTree tree, int position) {
     364    return NodeAt(tree.Root, position);
     365  }
     366  internal static ISymbolicExpressionTreeNode NodeAt(this ISymbolicExpressionTreeNode root, int position) {
     367    return root.IterateNodesPrefix().ElementAt(position);
     368  }
     369  internal static bool IsIsomorphicWith(this ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
     370    return a.Difference(b) == null;
     371  }
     372}
     373#endregion
  • branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/TraceCalculator.cs

    r13479 r13877  
    11#region License Information
    22/* HeuristicLab
    3  * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3 * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44 *
    55 * This file is part of HeuristicLab.
     
    233233    /// </summary>
    234234    /// <param name="g">The genealogy graph node</param>
    235     /// <param name="si">The subtree index</param>
    236     /// <param name="fi">The fragment index</param>
    237235    /// <returns></returns>
    238236    private IGenealogyGraphNode<ISymbolicExpressionTree> AddTraceNode(IGenealogyGraphNode<ISymbolicExpressionTree> g) {
  • branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/QueryMatch.cs

    r13482 r13877  
    203203
    204204    public bool IsFirstSibling {
    205       get { return Node.Parent != null && Node == Node.Parent.Subtrees.First(); }
     205      get { return Parent != null && Node == Node.Parent.Subtrees.First(); }
    206206    }
    207207
    208208    public bool IsLastSibling {
    209       get { return Node.Parent != null && Node == Node.Parent.Subtrees.Last(); }
     209      get { return Parent != null && Node == Node.Parent.Subtrees.Last(); }
    210210    }
    211211
Note: See TracChangeset for help on using the changeset viewer.