Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/Tracking/FragmentGraphView.cs @ 11318

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

#1772: Fixed bug and improved handling of elite individuals in the genealogy analyzer. Fixed minor bug in the tracing code. Other minor cosmetic improvements to the GenealogyGraph and FragmentGraphView.

File size: 8.6 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 HeuristicLab.Core.Views;
27using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
28using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views;
29using HeuristicLab.MainForm;
30using HeuristicLab.Visualization;
31
32namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Views {
33  [View("FragmentGraphView")]
34  [Content(typeof(FragmentGraph), IsDefaultView = true)]
35  public sealed partial class FragmentGraphView : ItemView {
36    private const int PreferredHorizontalSpacing = 10;
37    private const int PreferredVerticalSpacing = 25;
38
39    private readonly ReingoldTilfordLayoutEngine<TileLayoutNode> layoutEngine;
40    private readonly ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode> symbolicExpressionEngine;
41
42    private readonly Dictionary<FragmentNode, TileLayoutNode> nodeToTileMap;
43
44    private SymbolicExpressionTreeTile Root { get; set; }
45
46    public new FragmentGraph Content {
47      get { return (FragmentGraph)base.Content; }
48      set { base.Content = value; }
49    }
50
51    public FragmentGraphView() {
52      InitializeComponent();
53
54      layoutEngine = new ReingoldTilfordLayoutEngine<TileLayoutNode>(n => n.Children) {
55        HorizontalSpacing = PreferredHorizontalSpacing,
56        VerticalSpacing = PreferredVerticalSpacing,
57      };
58      symbolicExpressionEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode>(n => n.Subtrees) {
59        HorizontalSpacing = PreferredHorizontalSpacing,
60        VerticalSpacing = PreferredVerticalSpacing,
61        NodeWidth = 80,
62        NodeHeight = 40
63      };
64      nodeToTileMap = new Dictionary<FragmentNode, TileLayoutNode>();
65    }
66
67    private void MakeTiles() {
68      var chart = symbolicExpressionChartControl.Chart;
69      nodeToTileMap.Clear();
70      foreach (var node in Content.Vertices) {
71        var tile = new SymbolicExpressionTreeTile(chart);
72        tile.LayoutEngine = symbolicExpressionEngine;
73        tile.Label = "Generation " + node.Data.Rank + Environment.NewLine +
74                     "Quality " + String.Format("{0:0.000}", node.Data.Quality);
75        tile.Root = node.Data.Data.Root;
76        var tileNode = new TileLayoutNode { Tile = tile };
77        nodeToTileMap.Add(node, tileNode);
78      }
79      foreach (var node in Content.Vertices.Where(n => n.OutArcs.Any())) {
80        var layoutNode = nodeToTileMap[node];
81        layoutNode.Children = new List<TileLayoutNode>(node.OutArcs.Select(a => nodeToTileMap[(FragmentNode)a.Target]));
82      }
83    }
84
85    private void Draw() {
86      var chart = symbolicExpressionChartControl.Chart;
87      var nodes = Content.Vertices.ToList();
88      var root = nodes[0];
89      var fragmentRoot = nodeToTileMap[root];
90      int maxTileWidth = 0, maxTileHeight = 0;
91      var tiles = nodes.Select(x => nodeToTileMap[x].Tile).ToList();
92
93      foreach (var tile in tiles) {
94        var size = tile.Size;
95        if (maxTileWidth < size.Width) maxTileWidth = size.Width;
96        if (maxTileHeight < size.Height) maxTileHeight = size.Height;
97      }
98      layoutEngine.NodeWidth = maxTileWidth;
99      layoutEngine.NodeHeight = maxTileHeight;
100      layoutEngine.HorizontalSpacing = PreferredHorizontalSpacing;
101      layoutEngine.VerticalSpacing = PreferredVerticalSpacing;
102
103      var visualNodes = layoutEngine.CalculateLayout(fragmentRoot);
104
105      symbolicExpressionChartControl.UpdateEnabled = false;
106      foreach (var visualNode in visualNodes) {
107        var tile = visualNode.Content.Tile;
108        tile.Position = new Point(visualNode.X, visualNode.Y);
109        symbolicExpressionChartControl.Add(tile);
110      }
111
112      // add connections between the tiles
113      foreach (var node in nodes) {
114        var aTile = nodeToTileMap[node].Tile;
115        var aSize = aTile.Size;
116        var aPos = aTile.Position;
117        var graphNode = node.Data;
118
119        if (node.SubtreeIndex > 0) {
120          var subtree = graphNode.Data.Root.NodeAt(node.SubtreeIndex);
121          foreach (var s in subtree.IterateNodesPrefix()) {
122            var primitive = aTile.GetPrimitive(s);
123            if (primitive != null) {
124              var rpb = primitive as RectangularPrimitiveBase;
125              if (rpb != null) {
126                rpb.Pen = new Pen(Color.Black);
127              }
128            }
129          }
130        }
131        if (node.FragmentIndex > 0) {
132          var subtree = graphNode.Data.Root.NodeAt(node.FragmentIndex);
133          foreach (var s in subtree.IterateNodesPrefix()) {
134            var primitive = aTile.GetPrimitive(s);
135            if (primitive != null) {
136              var rpb = primitive as RectangularPrimitiveBase;
137              if (rpb != null) {
138                rpb.Brush = new SolidBrush(Color.LightGray);
139              }
140            }
141          }
142        }
143
144        if (node.InArcs.Any()) {
145          var parent = (FragmentNode)node.InArcs.First().Source;
146          if (parent.OutArcs.First().Target == node) {
147            var index = node.SubtreeIndex + (parent.FragmentIndex - parent.SubtreeIndex);
148            // some mutations create discontinuities which invalidate the index
149            if (index >= 0 && index < graphNode.Data.Length) {
150              var subtree = graphNode.Data.NodeAt(index);
151              var primitive = aTile.GetPrimitive(subtree);
152              primitive.Brush = new SolidBrush(Color.LightCoral);
153            }
154          }
155        }
156
157        foreach (var child in node.OutArcs.Select(x => (FragmentNode)x.Target)) {
158          var bTile = nodeToTileMap[child].Tile;
159          var bSize = bTile.Size;
160          var bPos = bTile.Position;
161
162          var line = new Line(chart, new PointD(aPos.X + aSize.Width / 2.0, aPos.Y + aSize.Height), new PointD(bPos.X + bSize.Width / 2.0, bPos.Y)) {
163            Pen = Pens.DimGray
164          };
165          symbolicExpressionChartControl.Add(line);
166        }
167      }
168      // center display on the root of the fragment graph
169      symbolicExpressionChartControl.Chart.Move(nodeToTileMap[root].Tile.Position.X, nodeToTileMap[root].Tile.Position.Y);
170      symbolicExpressionChartControl.UpdateEnabled = true;
171      symbolicExpressionChartControl.EnforceUpdate();
172    }
173
174    protected override void DeregisterContentEvents() {
175      // TODO: Deregister your event handlers here
176      base.DeregisterContentEvents();
177    }
178
179    protected override void RegisterContentEvents() {
180      base.RegisterContentEvents();
181      // TODO: Register your event handlers here
182    }
183
184    #region Event Handlers (Content)
185    // TODO: Put event handlers of the content here
186    protected override void OnContentChanged() {
187      base.OnContentChanged();
188      if (Content != null) {
189        MakeTiles();
190        Draw();
191      }
192    }
193    #endregion
194
195    protected override void SetEnabledStateOfControls() {
196      base.SetEnabledStateOfControls();
197      // TODO: Enable or disable controls based on whether the content is null or the view is set readonly
198    }
199
200    #region Event Handlers (child controls)
201
202    // TODO: Put event handlers of child controls here.
203
204    #endregion
205  }
206
207  internal static class Util {
208    internal static ISymbolicExpressionTreeNode NodeAt(this ISymbolicExpressionTree tree, int position) {
209      return NodeAt(tree.Root, position);
210    }
211    internal static ISymbolicExpressionTreeNode NodeAt(this ISymbolicExpressionTreeNode root, int position) {
212      return root.IterateNodesPrefix().ElementAt(position);
213    }
214  }
215
216  internal class TileLayoutNode {
217    public SymbolicExpressionTreeTile Tile { get; set; }
218
219    private List<TileLayoutNode> children;
220    public IEnumerable<TileLayoutNode> Children {
221      get { return children ?? Enumerable.Empty<TileLayoutNode>(); }
222      set { children = value.ToList(); }
223    }
224  }
225}
Note: See TracBrowser for help on using the repository browser.