Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
12/20/12 16:27:58 (11 years ago)
Author:
bburlacu
Message:

#1772: HeuristicLab.EvolutionaryTracking.Views: refactored the GenealogyGraphChart and the GenealogyGraphView. Fixed lineage display bug.

Location:
branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.EvolutionaryTracking.Views/3.4
Files:
5 edited

Legend:

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

    r8556 r9084  
    2828using HeuristicLab.Common;
    2929using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
     30using HeuristicLab.Problems.DataAnalysis.Symbolic;
    3031using HeuristicLab.Visualization;
    3132
    3233namespace HeuristicLab.EvolutionaryTracking.Views {
    3334  public partial class GenealogyGraphChart : ChartControl {
    34     private Dictionary<IGenealogyGraphNode, VisualGenealogyGraphNode> visualNodeMap;
     35    private Dictionary<string, VisualGenealogyGraphNode> visualNodeMap; // map the uid of the genealogy graph vertex with a visual node (in this way each node is uniquely determined)
    3536    private Dictionary<Tuple<VisualGenealogyGraphNode, VisualGenealogyGraphNode>, VisualGenealogyGraphArc> visualArcMap;
    3637    private const int Diameter = 20; // node diameter
     
    4647      internal set {
    4748        graph = value;
    48         visualNodeMap = new Dictionary<IGenealogyGraphNode, VisualGenealogyGraphNode>();
     49        // TODO: should move the subtree sorting code out of here and int the view
     50        var canonicalSorter = new SymbolicExpressionTreeCanonicalSorter();
     51        // sort subtrees in order to improve matching
     52        foreach (var tree in graph.Nodes.Select(n => n.SymbolicExpressionTree))
     53          canonicalSorter.SortSubtrees(tree);
     54
     55        visualNodeMap = new Dictionary<string, VisualGenealogyGraphNode>();
    4956        visualArcMap = new Dictionary<Tuple<VisualGenealogyGraphNode, VisualGenealogyGraphNode>, VisualGenealogyGraphArc>();
     57
     58        Chart.Group.Clear();
    5059        DrawGraph();
    5160      }
     61    }
     62
     63    private VisualGenealogyGraphNode GetVisualGenealogyGraphNode(IVertex node) {
     64      VisualGenealogyGraphNode visualNode;
     65      visualNodeMap.TryGetValue(node.Id, out visualNode);
     66      return visualNode;
    5267    }
    5368
     
    6883      Chart.UpdateEnabled = false;
    6984
    70       var layers = Graph.Nodes.GroupBy(n => n.Ranks[0]).OrderBy(g => g.Key).Select(g => new { Rank = g.Key, Nodes = g.ToList() }).ToList();
     85      var layers = Graph.Nodes.GroupBy(n => n.Rank).OrderBy(g => g.Key).Select(g => new { Rank = g.Key, Nodes = g.ToList() }).ToList();
     86
    7187      for (int i = 0; i != layers.Count; ++i) {
    7288        // sort descending by quality (using comparison defined in GenealogyGraphNode class)
    7389        layers[i].Nodes.Sort((b, a) => Graph.Compare(a, b));
    7490        x = 0; // reset horizontal coordinate
    75         // start laying out visual nodes
    7691        foreach (var node in layers[i].Nodes) {
    7792          var pen = new Pen(Color.LightGray);
     
    8095            Data = node,
    8196            ToolTipText = "Id: " + node.Label + nl +
    82                           "Ranks: " + string.Join(",", node.Ranks) + nl +
     97                          "Rank: " + node.Rank + nl +
    8398                          "Quality: " + String.Format("{0:0.0000}", node.Quality) + nl +
    8499                          "IsElite: " + node.IsElite
    85100          };
    86101          Chart.Group.Add(visualNode);
    87           if (!visualNodeMap.ContainsKey(node))
    88             visualNodeMap[node] = visualNode;
     102          visualNodeMap.Add(node.Id, visualNode);
    89103
    90104          x += Cx; // increment horizontal coordinate
     
    94108
    95109        // connect elites from successive layers with visual arcs
    96         if (i > 0) {
    97           for (int m = 0; m != layers[i].Nodes.Count; ++m)
    98             for (int n = 0; n != layers[i - 1].Nodes.Count; ++n) {
    99               if (layers[i].Nodes[m].SymbolicExpressionTree == layers[i - 1].Nodes[n].SymbolicExpressionTree) {
    100                 var v1 = visualNodeMap[layers[i].Nodes[m]];
    101                 var v2 = visualNodeMap[layers[i - 1].Nodes[n]];
    102                 var pen = new Pen(Color.LightGray);
    103                 visualArcMap[Tuple.Create(v2, v1)] = AddArc(Chart, v2, v1, pen);
    104               }
    105             }
     110        if (i == 0) continue;
     111        var currLayer = layers[i].Nodes;
     112        var prevLayer = layers[i - 1].Nodes;
     113        foreach (var n in currLayer) {
     114          foreach (var m in prevLayer) {
     115            if (n.SymbolicExpressionTree != m.SymbolicExpressionTree) continue;
     116            var v1 = GetVisualGenealogyGraphNode(n);
     117            var v2 = GetVisualGenealogyGraphNode(m);
     118
     119            var pen = new Pen(Color.LightGray);
     120            visualArcMap[Tuple.Create(v2, v1)] = AddArc(Chart, v2, v1, pen);
     121          }
    106122        }
    107123      }
    108124      // add arcs separately (to avoid some ordering problems)
    109       foreach (var node in visualNodeMap.Keys) {
    110         var visualNode = visualNodeMap[node];
     125      foreach (SymbolicExpressionGenealogyGraphNode node in Graph.Nodes) {
     126        VisualGenealogyGraphNode visualNode = GetVisualGenealogyGraphNode(node);
    111127        if (node.InEdges == null) continue;
    112128
    113         foreach (var arc in node.InEdges) {
    114           var visualParent = visualNodeMap[arc.Target];
     129        foreach (Arc arc in node.InEdges) {
     130          var visualParent = GetVisualGenealogyGraphNode(arc.Source);
    115131          var pen = new Pen(Color.Transparent);
    116132          visualArcMap[Tuple.Create(visualParent, visualNode)] = AddArc(Chart, visualParent, visualNode, pen);
     
    134150
    135151    protected override void pictureBox_MouseUp(object sender, MouseEventArgs e) {
    136       if (Chart.Mode != ChartMode.Select)
     152      if (Chart.Mode != ChartMode.Select) {
    137153        base.pictureBox_MouseUp(sender, e);
    138       else { // select mode
    139         // get selected node
    140         var visualNodes = Chart.GetAllPrimitives(e.Location).Where(p => p is VisualGenealogyGraphNode).ToList();
    141         if (visualNodes.Count > 0) {
    142           if (selectedGenealogyGraphNode == visualNodes[0]) return;
    143           selectedGenealogyGraphNode = visualNodes[0] as VisualGenealogyGraphNode;
    144           if (selectedGenealogyGraphNode == null) return;
    145           // new node has been selected, clean up
    146           Chart.UpdateEnabled = false;
    147           // clear colors
    148           ClearAllNodes();
    149           // use a rectangle to highlight the currently selected genealogy graph node
    150           var center = selectedGenealogyGraphNode.Center;
    151           var size = selectedGenealogyGraphNode.Size;
    152           double x1 = center.X - size.Width / 2;
    153           double x2 = x1 + size.Width;
    154           double y1 = center.Y - size.Height / 2;
    155           double y2 = y1 + size.Height;
    156           if (targetRectangle == null) {
    157             targetRectangle = new Visualization.Rectangle(Chart, x1, y1, x2, y2, new Pen(Color.Black), null);
    158             Chart.Group.Add(targetRectangle);
    159           } else {
    160             targetRectangle.SetPosition(x1, y1, x2, y2);
    161           }
    162           var gNode = selectedGenealogyGraphNode.Data; // genealogy graph node (representing an individual in the population)
    163           //          double rank = Graph[gNode].Ranks[0];
    164           double rank = ((SymbolicExpressionGenealogyGraphNode)gNode).Ranks[0];
    165           // ancestors
    166           var ancestors = gNode.Ancestors().Where(n => ((SymbolicExpressionGenealogyGraphNode)n).Ranks.Last() < rank).ToList();
    167           ancestors.Add(gNode);
    168           // descendants
    169           var descendants = gNode.Descendants().Where(n => ((SymbolicExpressionGenealogyGraphNode)n).Ranks.Last() > rank).ToList();
    170           descendants.Add(gNode);
    171           // highlight ancestors
    172           foreach (var node in ancestors.Select(n => visualNodeMap[n])) {
    173             node.Brush = new SolidBrush(((SymbolicExpressionGenealogyGraphNode)node.Data).GetColor());
    174             if (node.IncomingArcs != null)
    175               foreach (var arc in node.IncomingArcs) {
    176                 var start = new Point((int)arc.Start.X, (int)arc.Start.Y);
    177                 var end = new Point((int)arc.End.X, (int)arc.End.Y);
    178                 var srcNode = arc.Source.Data as SymbolicExpressionGenealogyGraphNode;
    179                 var destNode = arc.Target.Data as SymbolicExpressionGenealogyGraphNode;
    180                 arc.Pen.Brush = new LinearGradientBrush(start, end, srcNode.GetColor(), destNode.GetColor());
    181               }
    182           }
    183           // highlight descendants
    184           foreach (var node in descendants.Select(n => visualNodeMap[n])) {
    185             node.Brush = new SolidBrush((node.Data as SymbolicExpressionGenealogyGraphNode).GetColor());
    186             if (node.OutgoingArcs != null)
    187               foreach (var arc in node.OutgoingArcs) {
    188                 var start = new Point((int)arc.Start.X, (int)arc.Start.Y);
    189                 var end = new Point((int)arc.End.X, (int)arc.End.Y);
    190                 var srcNode = arc.Source.Data as SymbolicExpressionGenealogyGraphNode;
    191                 var destNode = arc.Target.Data as SymbolicExpressionGenealogyGraphNode;
    192                 arc.Pen.Brush = new LinearGradientBrush(start, end, srcNode.GetColor(), destNode.GetColor());
    193               }
    194           }
    195         } else {
    196           selectedGenealogyGraphNode = null;
    197         }
    198         // update
    199         Chart.UpdateEnabled = true;
    200         Chart.EnforceUpdate();
    201         if (selectedGenealogyGraphNode != null)
    202           /* emit clicked event */
    203           OnGenealogyGraphNodeClicked(selectedGenealogyGraphNode, e);
     154        return;
     155      }
     156      var visualNodes = Chart.GetAllPrimitives(e.Location).Where(p => p is VisualGenealogyGraphNode).ToList();
     157      if (visualNodes.Count <= 0) {
     158        selectedGenealogyGraphNode = null;
     159        return;
     160      }
     161      if (selectedGenealogyGraphNode == visualNodes[0]) return;
     162      selectedGenealogyGraphNode = visualNodes[0] as VisualGenealogyGraphNode;
     163      if (selectedGenealogyGraphNode == null) return;
     164      // new node has been selected, clean up
     165      Chart.UpdateEnabled = false;
     166      // clear colors
     167      ClearAllNodes();
     168      // use a rectangle to highlight the currently selected genealogy graph node
     169      MarkSelectedNode();
     170      var gNode = selectedGenealogyGraphNode.Data;
     171      var visualNode = GetVisualGenealogyGraphNode(gNode);
     172
     173      DrawLineage(visualNode, n => n.IncomingArcs, a => a.Source);
     174      DrawLineage(visualNode, n => n.OutgoingArcs, a => a.Target);
     175
     176      // update
     177      Chart.UpdateEnabled = true;
     178      Chart.EnforceUpdate();
     179
     180      if (selectedGenealogyGraphNode != null)
     181        /* emit clicked event */
     182        OnGenealogyGraphNodeClicked(selectedGenealogyGraphNode, e);
     183    }
     184
     185    private void DrawLineage(VisualGenealogyGraphNode node,
     186                             Func<VisualGenealogyGraphNode, IEnumerable<VisualGenealogyGraphArc>> arcSelector,
     187                             Func<VisualGenealogyGraphArc, VisualGenealogyGraphNode> nodeSelector) {
     188      node.Brush = new SolidBrush(node.Data.GetColor());
     189      var arcs = arcSelector(node);
     190      foreach (var arc in arcs) {
     191        var source = arc.Source.Data;
     192        var target = arc.Target.Data;
     193        var start = new Point((int)arc.Start.X, (int)arc.Start.Y);
     194        var end = new Point((int)arc.End.X, (int)arc.End.Y);
     195        arc.Pen.Brush = new LinearGradientBrush(start, end, source.GetColor(), target.GetColor());
     196        DrawLineage(nodeSelector(arc), arcSelector, nodeSelector);
     197      }
     198    }
     199
     200    void MarkSelectedNode() {
     201      var center = selectedGenealogyGraphNode.Center;
     202      var size = selectedGenealogyGraphNode.Size;
     203      double x1 = center.X - size.Width / 2;
     204      double x2 = x1 + size.Width;
     205      double y1 = center.Y - size.Height / 2;
     206      double y2 = y1 + size.Height;
     207      if (targetRectangle == null) {
     208        targetRectangle = new Visualization.Rectangle(Chart, x1, y1, x2, y2, new Pen(Color.Black), null);
     209        Chart.Group.Add(targetRectangle);
     210      } else {
     211        targetRectangle.SetPosition(x1, y1, x2, y2);
    204212      }
    205213    }
     
    209217        if (primitive is VisualGenealogyGraphArc) {
    210218          var arc = primitive as VisualGenealogyGraphArc;
    211           var sourceData = (arc.Source.Data as SymbolicExpressionGenealogyGraphNode).SymbolicExpressionTree;
    212           var targetData = (arc.Target.Data as SymbolicExpressionGenealogyGraphNode).SymbolicExpressionTree;
    213           if (sourceData != targetData) {
    214             primitive.Pen.Brush = new SolidBrush(Color.Transparent);
    215           } else {
    216             primitive.Pen.Brush = new SolidBrush(Color.LightGray);
    217           }
     219          var sourceData = arc.Source.Data.SymbolicExpressionTree;
     220          var targetData = arc.Target.Data.SymbolicExpressionTree;
     221          primitive.Pen.Brush = sourceData != targetData ? new SolidBrush(Color.Transparent) : new SolidBrush(Color.LightGray);
    218222        } else {
    219223          primitive.Brush = null;
     
    222226    }
    223227
    224     public void HighlightLineage(IEnumerable<GenealogyGraphNode> nodes) {
    225       foreach (var node in nodes.Select(n => visualNodeMap[n])) {
    226         node.Brush = new SolidBrush((node.Data as SymbolicExpressionGenealogyGraphNode).GetColor());
    227         if (node.IncomingArcs == null || node != visualNodeMap[node.Data]) continue;
    228         foreach (var arc in node.IncomingArcs) {
    229           if (arc.Source.Data == node.Data) continue;
    230           var start = new Point((int)arc.Start.X, (int)arc.Start.Y);
    231           var end = new Point((int)arc.End.X, (int)arc.End.Y);
    232           var srcNode = arc.Source.Data as SymbolicExpressionGenealogyGraphNode;
    233           var destNode = arc.Target.Data as SymbolicExpressionGenealogyGraphNode;
    234           arc.Pen.Brush = new LinearGradientBrush(start, end, srcNode.GetColor(), destNode.GetColor());
    235         }
    236       }
    237     }
    238 
    239228    // TODO: optimize and reduce complexity of this method
    240229    public void HighlightNodes(IEnumerable<ISymbolicExpressionTree> trees, Color color) {
    241       foreach (var tree in trees)
    242         foreach (var graphNode in Graph.Nodes) {
    243           if (graphNode.SymbolicExpressionTree == tree) {
    244             var visualNode = visualNodeMap[graphNode];
    245             visualNode.Brush = new SolidBrush(color);
    246           }
    247         }
     230      foreach (var tree in trees) {
     231        var graphNodes = graph.GetGraphNodes(tree);
     232        foreach (var graphNode in graphNodes) {
     233          GetVisualGenealogyGraphNode(graphNode).Brush = new SolidBrush(color);
     234        }
     235      }
    248236    }
    249237
    250238    public void HighlightNode(SymbolicExpressionGenealogyGraphNode graphNode, Color color) {
    251       visualNodeMap[graphNode].Brush = new SolidBrush(color);
     239      GetVisualGenealogyGraphNode(graphNode).Brush = new SolidBrush(color);
    252240    }
    253241
     
    257245      double max = Graph.Nodes.Max(x => x.InEdges == null ? 0 : x.InEdges.Count);
    258246      foreach (var graphNode in Graph.Nodes) {
    259         var visualNode = visualNodeMap[graphNode];
     247        var visualNode = GetVisualGenealogyGraphNode(graphNode);
    260248        double deg = graphNode.InEdges == null ? 0 : graphNode.InEdges.Count;
    261249        int index = (int)(deg / max * ColorGradient.Colors.Count);
     
    274262      double max = graphNodes.Max(x => x.OutEdges == null ? 0 : x.OutEdges.Count);
    275263      foreach (var graphNode in graphNodes) {
    276         var visualNode = visualNodeMap[graphNode];
     264        var visualNode = GetVisualGenealogyGraphNode(graphNode);
    277265        double deg = graphNode.OutEdges == null ? 0 : graphNode.OutEdges.Count;
    278266        int index = (int)(deg / max * ColorGradient.Colors.Count);
  • branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.EvolutionaryTracking.Views/3.4/GenealogyGraphView.Designer.cs

    r8556 r9084  
    2525    /// </summary>
    2626    private void InitializeComponent() {
     27      this.components = new System.ComponentModel.Container();
    2728      this.mainTableLayout = new System.Windows.Forms.TableLayoutPanel();
    2829      this.splitContainer = new System.Windows.Forms.SplitContainer();
    2930      this.genealogyTableLayout = new System.Windows.Forms.TableLayoutPanel();
     31      this.genealogyGraphChart = new HeuristicLab.EvolutionaryTracking.Views.GenealogyGraphChart();
    3032      this.symbolicExpressionTreeChart = new HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views.SymbolicExpressionTreeChart();
    3133      this.topControlBox = new System.Windows.Forms.GroupBox();
     34      this.matchVariableNamesCheckBox = new System.Windows.Forms.CheckBox();
     35      this.matchVariableWeightsCheckBox = new System.Windows.Forms.CheckBox();
     36      this.matchConstantsCheckBox = new System.Windows.Forms.CheckBox();
     37      this.similarityLabel = new System.Windows.Forms.Label();
    3238      this.graphControlsPanel = new System.Windows.Forms.Panel();
    33       this.similarityModeLabel = new System.Windows.Forms.Label();
    34       this.similarityModeSelector = new System.Windows.Forms.ComboBox();
    3539      this.selectModeButton = new System.Windows.Forms.RadioButton();
    3640      this.moveModeButton = new System.Windows.Forms.RadioButton();
    3741      this.zoomModeButton = new System.Windows.Forms.RadioButton();
    38       this.genealogyGraphChart = new HeuristicLab.EvolutionaryTracking.Views.GenealogyGraphChart();
    3942      this.mainTableLayout.SuspendLayout();
    4043      ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
     
    97100      this.genealogyTableLayout.TabIndex = 4;
    98101      //
     102      // genealogyGraphChart
     103      //
     104      this.genealogyGraphChart.BackColor = System.Drawing.SystemColors.Control;
     105      this.genealogyGraphChart.Dock = System.Windows.Forms.DockStyle.Fill;
     106      this.genealogyGraphChart.Location = new System.Drawing.Point(3, 3);
     107      this.genealogyGraphChart.Name = "genealogyGraphChart";
     108      this.genealogyGraphChart.ScaleOnResize = true;
     109      this.genealogyGraphChart.Size = new System.Drawing.Size(352, 520);
     110      this.genealogyGraphChart.TabIndex = 2;
     111      //
    99112      // symbolicExpressionTreeChart
    100113      //
     
    113126      // topControlBox
    114127      //
     128      this.topControlBox.Controls.Add(this.matchVariableNamesCheckBox);
     129      this.topControlBox.Controls.Add(this.matchVariableWeightsCheckBox);
     130      this.topControlBox.Controls.Add(this.matchConstantsCheckBox);
     131      this.topControlBox.Controls.Add(this.similarityLabel);
    115132      this.topControlBox.Controls.Add(this.graphControlsPanel);
    116       this.topControlBox.Controls.Add(this.similarityModeLabel);
    117       this.topControlBox.Controls.Add(this.similarityModeSelector);
    118133      this.topControlBox.Dock = System.Windows.Forms.DockStyle.Fill;
    119134      this.topControlBox.Location = new System.Drawing.Point(3, 3);
     
    124139      this.topControlBox.Text = "Controls";
    125140      //
     141      // matchVariableNamesCheckBox
     142      //
     143      this.matchVariableNamesCheckBox.AutoSize = true;
     144      this.matchVariableNamesCheckBox.Checked = true;
     145      this.matchVariableNamesCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
     146      this.matchVariableNamesCheckBox.Location = new System.Drawing.Point(436, 23);
     147      this.matchVariableNamesCheckBox.Name = "matchVariableNamesCheckBox";
     148      this.matchVariableNamesCheckBox.Size = new System.Drawing.Size(98, 17);
     149      this.matchVariableNamesCheckBox.TabIndex = 7;
     150      this.matchVariableNamesCheckBox.Text = "Variable names";
     151      this.matchVariableNamesCheckBox.UseVisualStyleBackColor = true;
     152      this.matchVariableNamesCheckBox.CheckedChanged += new System.EventHandler(this.matchVariableNamesCheckBox_CheckedChanged);
     153      //
     154      // matchVariableWeightsCheckBox
     155      //
     156      this.matchVariableWeightsCheckBox.AutoSize = true;
     157      this.matchVariableWeightsCheckBox.Checked = true;
     158      this.matchVariableWeightsCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
     159      this.matchVariableWeightsCheckBox.Location = new System.Drawing.Point(327, 23);
     160      this.matchVariableWeightsCheckBox.Name = "matchVariableWeightsCheckBox";
     161      this.matchVariableWeightsCheckBox.Size = new System.Drawing.Size(103, 17);
     162      this.matchVariableWeightsCheckBox.TabIndex = 6;
     163      this.matchVariableWeightsCheckBox.Text = "Variable weights";
     164      this.matchVariableWeightsCheckBox.UseVisualStyleBackColor = true;
     165      this.matchVariableWeightsCheckBox.CheckedChanged += new System.EventHandler(this.matchVariableWeightsCheckBox_CheckedChanged);
     166      //
     167      // matchConstantsCheckBox
     168      //
     169      this.matchConstantsCheckBox.AutoSize = true;
     170      this.matchConstantsCheckBox.Checked = true;
     171      this.matchConstantsCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
     172      this.matchConstantsCheckBox.Location = new System.Drawing.Point(219, 23);
     173      this.matchConstantsCheckBox.Name = "matchConstantsCheckBox";
     174      this.matchConstantsCheckBox.Size = new System.Drawing.Size(102, 17);
     175      this.matchConstantsCheckBox.TabIndex = 5;
     176      this.matchConstantsCheckBox.Text = "Constant values";
     177      this.matchConstantsCheckBox.UseVisualStyleBackColor = true;
     178      this.matchConstantsCheckBox.CheckedChanged += new System.EventHandler(this.matchConstantsCheckBox_CheckedChanged);
     179      //
     180      // similarityLabel
     181      //
     182      this.similarityLabel.AutoSize = true;
     183      this.similarityLabel.Location = new System.Drawing.Point(105, 24);
     184      this.similarityLabel.Name = "similarityLabel";
     185      this.similarityLabel.Size = new System.Drawing.Size(108, 13);
     186      this.similarityLabel.TabIndex = 3;
     187      this.similarityLabel.Text = "Matching constraints:";
     188      //
    126189      // graphControlsPanel
    127190      //
     
    129192      this.graphControlsPanel.Controls.Add(this.moveModeButton);
    130193      this.graphControlsPanel.Controls.Add(this.zoomModeButton);
    131       this.graphControlsPanel.Location = new System.Drawing.Point(246, 14);
     194      this.graphControlsPanel.Location = new System.Drawing.Point(6, 14);
    132195      this.graphControlsPanel.Name = "graphControlsPanel";
    133196      this.graphControlsPanel.Size = new System.Drawing.Size(93, 30);
    134197      this.graphControlsPanel.TabIndex = 2;
    135       //
    136       // similarityModeLabel
    137       //
    138       this.similarityModeLabel.AutoSize = true;
    139       this.similarityModeLabel.Location = new System.Drawing.Point(6, 20);
    140       this.similarityModeLabel.Name = "similarityModeLabel";
    141       this.similarityModeLabel.Size = new System.Drawing.Size(80, 13);
    142       this.similarityModeLabel.TabIndex = 1;
    143       this.similarityModeLabel.Text = "Similarity Mode:";
    144       //
    145       // similarityModeSelector
    146       //
    147       this.similarityModeSelector.FormattingEnabled = true;
    148       this.similarityModeSelector.Items.AddRange(new object[] {
    149             "Exact",
    150             "High",
    151             "Relaxed"});
    152       this.similarityModeSelector.Location = new System.Drawing.Point(92, 17);
    153       this.similarityModeSelector.Name = "similarityModeSelector";
    154       this.similarityModeSelector.Size = new System.Drawing.Size(148, 21);
    155       this.similarityModeSelector.TabIndex = 0;
    156       this.similarityModeSelector.SelectedIndexChanged += new System.EventHandler(this.similarityModeSelector_SelectedIndexChanged);
    157198      //
    158199      // selectModeButton
     
    188229      this.zoomModeButton.UseVisualStyleBackColor = true;
    189230      this.zoomModeButton.CheckedChanged += new System.EventHandler(this.zoomModeButton_CheckedChanged);
    190       //
    191       // genealogyGraphChart
    192       //
    193       this.genealogyGraphChart.BackColor = System.Drawing.SystemColors.Control;
    194       this.genealogyGraphChart.Dock = System.Windows.Forms.DockStyle.Fill;
    195       this.genealogyGraphChart.Location = new System.Drawing.Point(3, 3);
    196       this.genealogyGraphChart.Name = "genealogyGraphChart";
    197       this.genealogyGraphChart.ScaleOnResize = true;
    198       this.genealogyGraphChart.Size = new System.Drawing.Size(352, 520);
    199       this.genealogyGraphChart.TabIndex = 2;
    200231      //
    201232      // GenealogyGraphView
     
    224255    private System.Windows.Forms.SplitContainer splitContainer;
    225256    private System.Windows.Forms.GroupBox topControlBox;
    226     private System.Windows.Forms.Label similarityModeLabel;
    227     private System.Windows.Forms.ComboBox similarityModeSelector;
    228257    private Encodings.SymbolicExpressionTreeEncoding.Views.SymbolicExpressionTreeChart symbolicExpressionTreeChart;
    229258    private System.Windows.Forms.TableLayoutPanel genealogyTableLayout;
     
    233262    private System.Windows.Forms.RadioButton moveModeButton;
    234263    private System.Windows.Forms.RadioButton zoomModeButton;
     264    private System.Windows.Forms.Label similarityLabel;
     265    private System.Windows.Forms.CheckBox matchVariableNamesCheckBox;
     266    private System.Windows.Forms.CheckBox matchVariableWeightsCheckBox;
     267    private System.Windows.Forms.CheckBox matchConstantsCheckBox;
    235268
    236269  }
  • branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.EvolutionaryTracking.Views/3.4/GenealogyGraphView.cs

    r8556 r9084  
    3737  public sealed partial class GenealogyGraphView : ItemView {
    3838    private VisualSymbolicExpressionTreeNode selectedVisualSymbExprTreeNode;
     39    private SymbolicExpressionTreeNodeSimilarityComparer comparer;
     40    private Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> clonedNodes;
     41
    3942    public new SymbolicExpressionTreeGenealogyGraph Content {
    4043      get { return (SymbolicExpressionTreeGenealogyGraph)base.Content; }
    4144      set { base.Content = value; }
    4245    }
    43 
    44     private Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> clonedNodeMap;
    4546
    4647    public GenealogyGraphView()
     
    5152      this.zoomModeButton.Image = Common.Resources.VSImageLibrary.Zoom;
    5253      this.selectModeButton.Image = Common.Resources.VSImageLibrary.Object;
    53 
    54 
    55       similarityModeSelector.SelectedIndex = 0; // set default similarity mode to "exact"
     54      comparer = new SymbolicExpressionTreeNodeSimilarityComparer {
     55        MatchConstantValues = true,
     56        MatchVariableWeights = true,
     57        MatchVariableNames = true
     58      };
    5659    }
    5760
     
    97100    // TODO: Put event handlers of child controls here.
    98101    private void graphChart_GenealogyGraphNodeClicked(object sender, MouseEventArgs e) {
    99       // the type hierarchy goes like this: VisualGenealogyGraphNode --> GenealogyGraphNode --> symbolicExpressionTree
     102      // the type hierarchy goes like this: VisualGenealogyGraphNode --> GenealogyGraphNode --> SymbolicExpressionTree
    100103      var visualGenealogyGraphNode = (VisualGenealogyGraphNode)sender;
    101       var genealogyGraphNode = (SymbolicExpressionGenealogyGraphNode)visualGenealogyGraphNode.Data;
     104      var genealogyGraphNode = visualGenealogyGraphNode.Data;
    102105      symbolicExpressionTreeChart.Tree = genealogyGraphNode.SymbolicExpressionTree;
    103       // highlight the relevant fragment in the symbolic expression tree
    104       selectedVisualSymbExprTreeNode = null;
    105 
    106       bool repaint = false;
    107 
    108       // paint highlighted nodes in symbolic expression tree
    109       if (selectedVisualSymbExprTreeNode != null) {
    110         // clear selected subtree from the tree chart
    111         var nodes = symbolicExpressionTreeChart.Tree.IterateNodesBreadth() as List<ISymbolicExpressionTreeNode>;
    112         var fragments = selectedVisualSymbExprTreeNode.SymbolicExpressionTreeNode.IterateNodesBreadth() as List<ISymbolicExpressionTreeNode>;
    113         var similarityLevel = Enum.GetNames(typeof(SimilarityLevel))[similarityModeSelector.SelectedIndex];
    114         int index = SymbolicExpressionTreeMatching.FindMatch(nodes, fragments, (SimilarityLevel)Enum.Parse(typeof(SimilarityLevel), similarityLevel));
    115         if (index != -1) {
    116           selectedVisualSymbExprTreeNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(nodes[index]);
    117           var subtree = selectedVisualSymbExprTreeNode.SymbolicExpressionTreeNode;
    118           foreach (var node in subtree.IterateNodesBreadth()) {
    119             var visualNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node);
    120             visualNode.LineColor = Color.Blue;
    121           }
    122           repaint = true;
    123         }
     106      if (genealogyGraphNode.InEdges == null) return;
     107      var arc = genealogyGraphNode.InEdges.First(x => x.Source != x.Target && x.Data != null);
     108      if (arc == null) return;
     109      var fragment = (IFragment)arc.Data;
     110      foreach (var node in fragment.Root.IterateNodesBreadth()) {
     111        var visualSymbExprTreeNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node);
     112        visualSymbExprTreeNode.LineColor = Color.OrangeRed;
    124113      }
    125       // paint graph nodes
    126       var tree = symbolicExpressionTreeChart.Tree;
    127       var graphNodes = Content.Nodes.Where(n => n.SymbolicExpressionTree == tree).ToList();
    128       if (graphNodes.Count > 0) {
    129         foreach (var graphNode in graphNodes)
    130           if (graphNode != null && graphNode.InEdges != null) {
    131             var arc = graphNode.InEdges.Find(a => a.Data != null);
    132             if (arc != null) {
    133               var fragment = arc.Data as ISymbolicExpressionTreeNode;
    134               foreach (var node in fragment.IterateNodesBreadth()) {
    135                 var visualNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node);
    136                 if (visualNode == null)
    137                   continue;
    138                 visualNode.LineColor = Color.Orange;
    139               }
    140             }
    141             repaint = true;
    142           }
    143       }
    144       if (repaint)
    145         symbolicExpressionTreeChart.Repaint();
     114      symbolicExpressionTreeChart.Repaint(); // pain orange nodes
    146115    }
    147116
     
    162131
    163132    private void treeChart_SymbolicExpressionTreeNodeClicked(object sender, MouseEventArgs e) {
    164       ISymbolicExpressionTreeNode selectedSubtree = null;
    165133      genealogyGraphChart.Chart.UpdateEnabled = false;
    166134      switch (e.Button) {
     
    168136            selectedVisualSymbExprTreeNode = (VisualSymbolicExpressionTreeNode)sender;
    169137            if (selectedVisualSymbExprTreeNode == null) return;
    170             // find out which individuals in the genealogy graph contain this specific subtree
    171             selectedSubtree = selectedVisualSymbExprTreeNode.SymbolicExpressionTreeNode;
    172             // clone every node in the selected subtree so that edit operations are possible without altering the original subtree
    173             // save the originalNode-->clone mapping to make it easier to work with subtrees
    174             if (clonedNodeMap == null)
    175               clonedNodeMap = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>();
    176             clonedNodeMap.Clear();
    177             var selectedSubtreeClone = selectedSubtree.Clone() as SymbolicExpressionTreeNode;
    178             var subtreeNodes = selectedSubtree.IterateNodesPostfix().ToList();
    179             var cloneNodes = selectedSubtreeClone.IterateNodesPostfix().ToList();
    180             for (int i = 0; i != subtreeNodes.Count; ++i)
    181               clonedNodeMap.Add(subtreeNodes[i], cloneNodes[i]);
    182             // highlight subtree nodes in the tree chart
    183             foreach (var node in symbolicExpressionTreeChart.Tree.IterateNodesPostfix()) {
    184               var visualNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node);
    185               visualNode.FillColor = Color.Transparent;
     138            ISymbolicExpressionTreeNode selectedSubtree = selectedVisualSymbExprTreeNode.SymbolicExpressionTreeNode;
     139            var clonedSubtree = (ISymbolicExpressionTreeNode)selectedSubtree.Clone();
     140            // map original nodes to cloned nodes
     141            clonedNodes = selectedSubtree.IterateNodesPrefix()
     142                                         .Zip(clonedSubtree.IterateNodesPrefix(), (original, clone) => new { original, clone })
     143                                         .ToDictionary(p => p.original, p => p.clone);
     144
     145            foreach (var node in symbolicExpressionTreeChart.Tree.IterateNodesPrefix()) {
     146              symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node).FillColor = Color.Transparent;
    186147            }
    187             selectedSubtree.ForEachNodePostfix(node => {
     148            foreach (var node in selectedSubtree.IterateNodesPrefix()) {
    188149              symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node).FillColor = Color.LightBlue;
    189             });
     150            }
     151            break;
    190152          }
    191           break;
    192153        case MouseButtons.Middle: {
    193154            var visualNode = (VisualSymbolicExpressionTreeNode)sender;
    194             if (selectedVisualSymbExprTreeNode == null || selectedVisualSymbExprTreeNode == visualNode)
    195               return;
    196             selectedSubtree = clonedNodeMap[selectedVisualSymbExprTreeNode.SymbolicExpressionTreeNode];
     155            if (selectedVisualSymbExprTreeNode == null || selectedVisualSymbExprTreeNode == visualNode) return;
    197156            var selectedNode = visualNode.SymbolicExpressionTreeNode;
    198             if (clonedNodeMap.ContainsKey(selectedNode)) {
    199               var selected = clonedNodeMap[selectedNode];
    200               var parent = selected.Parent;
    201               parent.RemoveSubtree(parent.IndexOfSubtree(selected));
    202               selectedNode.ForEachNodePostfix(node => {
     157            if (clonedNodes.ContainsKey(selectedNode)) {
     158              var selectedClone = clonedNodes[selectedNode];
     159              var parent = selectedClone.Parent;
     160              parent.RemoveSubtree(parent.IndexOfSubtree(selectedClone));
     161              foreach (var node in selectedNode.IterateNodesPrefix()) {
    203162                symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node).FillColor = Color.Transparent;
    204                 clonedNodeMap.Remove(node);
    205               });
     163              }
    206164            }
    207           }
    208           break;
    209       }
    210       // update visual graph nodes that contain matching trees
    211       Color[] colors = { Color.LightSkyBlue, Color.PaleGreen, Color.Tan };
    212       genealogyGraphChart.ClearAllNodes(); // clear node colors
    213       // color each graph node according to the degree to which it matches the selected tree fragment
    214       var similarityValues = Enum.GetValues(typeof(SimilarityLevel)).Cast<SimilarityLevel>().ToList();
    215       foreach (var graphNode in genealogyGraphChart.Graph.Nodes) {
    216         var tree = graphNode.SymbolicExpressionTree;
    217         for (int i = 0; i != similarityValues.Count; ++i) {
    218           if (tree.ContainsFragment(selectedSubtree, similarityValues[i])) {
    219             genealogyGraphChart.HighlightNode(graphNode, colors[i]);
    220165            break;
    221166          }
    222         }
    223167      }
     168      if (selectedVisualSymbExprTreeNode == null || clonedNodes == null) return;
     169      // update visual graph nodes that contain matching trees
     170      MatchNodesAndRepaint();
     171      // refresh the tree chart
     172      symbolicExpressionTreeChart.Repaint();
     173    }
     174
     175    void MatchNodesAndRepaint() {
     176      genealogyGraphChart.Chart.UpdateEnabled = false;
     177      genealogyGraphChart.ClearAllNodes(); // clear node colors
     178      var fragment = new Fragment(clonedNodes[selectedVisualSymbExprTreeNode.SymbolicExpressionTreeNode]);
     179      var fragmentLength = fragment.Length;
     180      genealogyGraphChart.HighlightNodes(from node in genealogyGraphChart.Graph.Nodes
     181                                         let tree = node.SymbolicExpressionTree
     182                                         where tree.Length >= fragmentLength
     183                                         where tree.Root.ContainsFragment(fragment, comparer)
     184                                         select tree, Color.DodgerBlue);
    224185      genealogyGraphChart.Chart.UpdateEnabled = true;
    225186      genealogyGraphChart.Chart.EnforceUpdate();
    226       // refresh the tree chart
    227       symbolicExpressionTreeChart.Repaint();
    228187    }
    229188
    230189    private void treeChart_SymbolicExpressionTreeNodeDoubleClicked(object sender, MouseEventArgs e) {
    231190    }
    232 
    233     private void similarityModeSelector_SelectedIndexChanged(object sender, EventArgs e) {
    234       if (selectedVisualSymbExprTreeNode == null) return;
    235       var treeNode = selectedVisualSymbExprTreeNode.SymbolicExpressionTreeNode;
    236       var similarityLevel = Enum.GetNames(typeof(SimilarityLevel))[similarityModeSelector.SelectedIndex];
    237       var owners = genealogyGraphChart.Graph.TraceFragment(treeNode, (SimilarityLevel)Enum.Parse(typeof(SimilarityLevel), similarityLevel)).ToList();
    238       if (owners.Any()) {
    239         genealogyGraphChart.Chart.UpdateEnabled = false;
    240         genealogyGraphChart.ClearAllNodes(); // clear the fill color of all nodes
    241         genealogyGraphChart.HighlightNodes(owners, Color.LightSkyBlue);
    242         // highlight matching individuals from the genealogy
    243         genealogyGraphChart.Chart.UpdateEnabled = true;
    244       }
    245       genealogyGraphChart.Chart.EnforceUpdate();
    246       // highlight subtree nodes in the tree chart
    247       foreach (var node in symbolicExpressionTreeChart.Tree.IterateNodesPostfix()) {
    248         var visualNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node);
    249         visualNode.FillColor = Color.Transparent;
    250       }
    251       foreach (var node in treeNode.IterateNodesPostfix()) {
    252         var visualNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node);
    253         visualNode.FillColor = Color.LightBlue;
    254       }
    255     }
    256191    #endregion
    257 
    258     private void inDegreeButton_Click(object sender, EventArgs e) {
    259       genealogyGraphChart.HighlightInDegree();
    260     }
    261 
    262     private void outDegreeButton_Click(object sender, EventArgs e) {
    263       genealogyGraphChart.HighlightOutDegree();
     192    private void matchConstantsCheckBox_CheckedChanged(object sender, EventArgs e) {
     193      comparer.MatchConstantValues = matchConstantsCheckBox.Checked;
     194      if (selectedVisualSymbExprTreeNode != null)
     195        MatchNodesAndRepaint();
     196    }
     197
     198    private void matchVariableWeightsCheckBox_CheckedChanged(object sender, EventArgs e) {
     199      comparer.MatchVariableWeights = matchVariableWeightsCheckBox.Checked;
     200      if (selectedVisualSymbExprTreeNode != null)
     201        MatchNodesAndRepaint();
     202    }
     203
     204    private void matchVariableNamesCheckBox_CheckedChanged(object sender, EventArgs e) {
     205      comparer.MatchVariableNames = matchVariableNamesCheckBox.Checked;
     206      if (selectedVisualSymbExprTreeNode != null)
     207        MatchNodesAndRepaint();
    264208    }
    265209  }
  • branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.EvolutionaryTracking.Views/3.4/VisualGenealogyGraphArc.cs

    r8213 r9084  
    4949
    5050    internal void UpdatePosition() {
     51      if (Source.Equals(Target)) return;
    5152      // calculate the positions of the arc ends so that virtually the line will go through the centers of the two elliptical node shapes
    5253      PointD c1 = Source.Center;
     
    7475        p2Y = c2.Y - p1.Y;
    7576      }
     77      if (double.IsNaN(p1X) || double.IsNaN(p1Y) || double.IsNaN(p2X) || double.IsNaN(p2Y))
     78        throw new Exception("Error calculating arc position.");
    7679      p1.X = p1X;
    7780      p1.Y = p1Y;
  • branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.EvolutionaryTracking.Views/3.4/VisualGenealogyGraphNode.cs

    r8556 r9084  
    2727namespace HeuristicLab.EvolutionaryTracking.Views {
    2828  public class VisualGenealogyGraphNode : Ellipse {
    29     public IGenealogyGraphNode Data { get; internal set; }
    30     private List<VisualGenealogyGraphArc> _incomingArcs = new List<VisualGenealogyGraphArc>();
    31     private List<VisualGenealogyGraphArc> _outgoingArgs = new List<VisualGenealogyGraphArc>();
     29    public SymbolicExpressionGenealogyGraphNode Data { get; internal set; }
     30    private List<VisualGenealogyGraphArc> incomingArcs = new List<VisualGenealogyGraphArc>();
     31    private List<VisualGenealogyGraphArc> outgoingArcs = new List<VisualGenealogyGraphArc>();
    3232
    3333    public List<VisualGenealogyGraphArc> IncomingArcs {
    34       get { return _incomingArcs; }
    35       set { _incomingArcs = value; }
     34      get { return incomingArcs; }
     35      set { incomingArcs = value; }
    3636    }
    3737    public List<VisualGenealogyGraphArc> OutgoingArcs {
    38       get { return _outgoingArgs; }
    39       set { _outgoingArgs = value; }
     38      get { return outgoingArcs; }
     39      set { outgoingArcs = value; }
    4040    }
    4141
     
    8181        graphics.FillEllipse(Brush, p.X, p.Y, s.Width, s.Height);
    8282      graphics.DrawEllipse(Pen, p.X, p.Y, s.Width, s.Height);
    83       if (((SymbolicExpressionGenealogyGraphNode)Data).IsElite) {
     83      if (Data.IsElite) {
    8484        graphics.DrawEllipse(Pen, p.X + 2, p.Y + 2, s.Width - 4, s.Height - 4);
    8585      }
Note: See TracChangeset for help on using the changeset viewer.