Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1772: Added license headers where they were missing. Introduced an id map to the DirectedGraph to get graph vertices based on the id injected in the scopes by the genealogy analyzer.

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