source: branches/HeuristicLab.EvolutionTracking/HeuristicLab.EvolutionTracking/3.4/GenealogyGraph/GenealogyGraph.cs @ 11752

Last change on this file since 11752 was 11752, checked in by bburlacu, 7 years ago

#1772: GenealogyGraph: minor refactoring, added a fix/hack to restore correct arcs order for each vertex after deserialization.

File size: 8.0 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.IO;
26using System.Linq;
27using System.Text;
28using HeuristicLab.Common;
29using HeuristicLab.Core;
30using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
31
32namespace HeuristicLab.EvolutionTracking {
33  [StorableClass]
34  [Item("GenealogyGraph", "A class representing a genealogy graph")]
35  public class GenealogyGraph : DirectedGraph, IGenealogyGraph {
36    private Dictionary<object, IGenealogyGraphNode> contentMap;
37    private Dictionary<string, IGenealogyGraphNode> idMap;
38
39    private readonly Comparison<IArc> compareArcs = (a, b) => {
40      if (a.Data == b.Data)
41        return 0;
42      if (a.Data == null)
43        return -1;
44      return 1;
45    };
46
47    protected Dictionary<double, List<IGenealogyGraphNode>> ranks;
48    public IEnumerable<KeyValuePair<double, IEnumerable<IGenealogyGraphNode>>> Ranks {
49      get { return ranks.Select(x => new KeyValuePair<double, IEnumerable<IGenealogyGraphNode>>(x.Key, x.Value)); }
50    }
51    public IEnumerable<IGenealogyGraphNode> GetByRank(double rank) {
52      return ranks.ContainsKey(rank) ? ranks[rank] : Enumerable.Empty<IGenealogyGraphNode>();
53    }
54    protected GenealogyGraph(GenealogyGraph original, Cloner cloner)
55      : base(original, cloner) {
56      RebuildDictionaries();
57
58      foreach (var arcs in Vertices.Select(v => (List<IArc>)((IVertex)v).InArcs)) { arcs.Sort(compareArcs); }
59    }
60    public override IDeepCloneable Clone(Cloner cloner) {
61      return new GenealogyGraph(this, cloner);
62    }
63
64    [StorableConstructor]
65    protected GenealogyGraph(bool deserializing)
66      : base(deserializing) {
67    }
68    [StorableHook(HookType.AfterDeserialization)]
69    private void AfterDeserialization() {
70      RebuildDictionaries();
71      foreach (var arcs in Vertices.Select(v => (List<IArc>)((Vertex)v).InArcs)) { arcs.Sort(compareArcs); }
72    }
73    public GenealogyGraph() {
74      ranks = new Dictionary<double, List<IGenealogyGraphNode>>();
75      contentMap = new Dictionary<object, IGenealogyGraphNode>();
76      idMap = new Dictionary<string, IGenealogyGraphNode>();
77    }
78    new public IEnumerable<IGenealogyGraphNode> Vertices {
79      get { return base.Vertices.Select(x => (IGenealogyGraphNode)x); }
80    }
81    new public IEnumerable<IGenealogyGraphArc> Arcs {
82      get { return base.Arcs.Select(x => (IGenealogyGraphArc)x); }
83    }
84    public override IArc AddArc(IVertex source, IVertex target) {
85      var arc = new GenealogyGraphArc((IGenealogyGraphNode)source, (IGenealogyGraphNode)target);
86      base.AddArc(arc);
87      return arc;
88    }
89    public override void AddVertex(IVertex vertex) {
90      base.AddVertex(vertex);
91      var genealogyGraphNode = (IGenealogyGraphNode)vertex;
92      if (contentMap.ContainsKey(genealogyGraphNode.Data))
93        throw new InvalidOperationException("Duplicate content is not allowed in the genealogy graph.");
94      contentMap[genealogyGraphNode.Data] = genealogyGraphNode;
95      if (idMap.ContainsKey(genealogyGraphNode.Id))
96        throw new InvalidOperationException("Duplicate ids are not allowed in the genealogy graph.");
97      idMap[genealogyGraphNode.Id] = genealogyGraphNode;
98      if (!ranks.ContainsKey(genealogyGraphNode.Rank))
99        ranks[genealogyGraphNode.Rank] = new List<IGenealogyGraphNode>();
100      ranks[genealogyGraphNode.Rank].Add(genealogyGraphNode);
101    }
102    public override void RemoveVertex(IVertex vertex) {
103      var node = (IGenealogyGraphNode)vertex;
104      contentMap.Remove(node.Data);
105      idMap.Remove(node.Id);
106      if (ranks.ContainsKey(node.Rank)) {
107        ranks[node.Rank].Remove(node); // this call will be slow, use with caution
108        if (!ranks[node.Rank].Any())
109          ranks.Remove(node.Rank);
110      }
111      base.RemoveVertex(vertex);
112    }
113    public IGenealogyGraphNode GetByContent(object content) {
114      IGenealogyGraphNode result;
115      contentMap.TryGetValue(content, out result);
116      return result;
117    }
118    public IGenealogyGraphNode GetById(string id) {
119      IGenealogyGraphNode result;
120      idMap.TryGetValue(id, out result);
121      return result;
122    }
123    public bool Contains(object content) {
124      return contentMap.ContainsKey(content);
125    }
126    public event EventHandler GraphUpdated;
127    private void OnGraphUpdated(object sender, EventArgs args) {
128      var updated = GraphUpdated;
129      if (updated != null) updated(sender, args);
130    }
131    public override void Clear() {
132      base.Clear();
133      ranks.Clear();
134      contentMap.Clear();
135      idMap.Clear();
136    }
137    private void RebuildDictionaries() {
138      contentMap = new Dictionary<object, IGenealogyGraphNode>();
139      idMap = new Dictionary<string, IGenealogyGraphNode>();
140      ranks = new Dictionary<double, List<IGenealogyGraphNode>>();
141
142      foreach (var v in Vertices) {
143        contentMap[v.Data] = v;
144        idMap[v.Id] = v;
145        if (ranks.ContainsKey(v.Rank)) {
146          ranks[v.Rank].Add(v);
147        } else {
148          ranks[v.Rank] = new List<IGenealogyGraphNode> { v };
149        }
150      }
151    }
152    public void ExportDot(string path) {
153      var sb = new StringBuilder();
154      sb.AppendLine("graph fragmentgraph {");
155      foreach (var v in Vertices) {
156        sb.AppendLine("\"" + v.Id + "\"[shape=circle, style = filled, width = " + v.Degree / 2.0 + ", label = " + v.Rank + ", fillcolor = \"" + ColorTranslator.ToHtml(GetColor(v)) + "\"]");
157      }
158      foreach (var a in Arcs) {
159        sb.AppendLine("\"" + a.Source.Id + "\" -- \"" + a.Target.Id + "\"");
160      }
161
162      sb.AppendLine("}");
163      File.WriteAllText(path, sb.ToString());
164    }
165    private Color GetColor(IGenealogyGraphNode node) {
166      var colorIndex = (int)Math.Round(node.Quality * ColorGradient.Colors.Count);
167      if (colorIndex >= ColorGradient.Colors.Count) return ColorGradient.Colors.Last();
168      return ColorGradient.Colors[colorIndex];
169    }
170  }
171
172  [Item("GenealogyGraph", "A genealogy graph in which the vertex data is of type T")]
173  [StorableClass]
174  public class GenealogyGraph<T> : GenealogyGraph, IGenealogyGraph<T> where T : class, IItem {
175    public GenealogyGraph() { }
176    private GenealogyGraph(GenealogyGraph original, Cloner cloner)
177      : base(original, cloner) {
178    }
179    public override IDeepCloneable Clone(Cloner cloner) {
180      return new GenealogyGraph<T>(this, cloner);
181    }
182    new public IEnumerable<IGenealogyGraphNode<T>> Vertices {
183      get { return base.Vertices.Select(x => (IGenealogyGraphNode<T>)x); }
184    }
185    new public IGenealogyGraphNode<T> GetByContent(object content) {
186      return (IGenealogyGraphNode<T>)base.GetByContent(content);
187    }
188    new public IGenealogyGraphNode<T> GetById(string id) {
189      return (IGenealogyGraphNode<T>)base.GetById(id);
190    }
191    new public IEnumerable<IGenealogyGraphNode<T>> GetByRank(double rank) {
192      return base.GetByRank(rank).Select(x => (IGenealogyGraphNode<T>)x);
193    }
194    public new IEnumerable<KeyValuePair<double, IEnumerable<IGenealogyGraphNode<T>>>> Ranks {
195      get { return base.Ranks.Select(x => new KeyValuePair<double, IEnumerable<IGenealogyGraphNode<T>>>(x.Key, x.Value.Select(n => (IGenealogyGraphNode<T>)n))); }
196    }
197  }
198}
Note: See TracBrowser for help on using the repository browser.