Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 11969 was 11969, checked in by bburlacu, 9 years ago

#1772: Restore correct order of arcs when cloning or deserializing a GenealogyGraph (due to changes in the trunk in the Directed graph, previous code was not working anymore).

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