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

Last change on this file since 11694 was 11694, checked in by bburlacu, 8 years ago

#1772: Fixed cloning in tracking operators for symbolic data analysis. Added unit tests (in progress).

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