Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.EvolutionTracking/HeuristicLab.EvolutionTracking/3.4/DirectedGraph/DirectedGraph.cs @ 10903

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

#1772: Removed Storable property from Vertex in- and outArcs as it causes a stack overflow exception during serialization. Added a list of arcs to the DirectedGraph class which is persisted. The Vertex in- and outArcs lists are then restored by the graph after the deserialization. Renamed Nodes data member to Vertices.

File size: 5.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.Common;
27using HeuristicLab.Core;
28using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
29
30namespace HeuristicLab.EvolutionTracking {
31  [Item("DirectedGraph", "Generic class representing a directed graph with custom vertices and content")]
32  [StorableClass]
33  public class DirectedGraph : Item, IDirectedGraph {
34    public bool AllowDuplicateContent { get; set; }
35
36    [Storable]
37    protected readonly List<IVertex> vertices; // for performance reasons, maybe this should be a linked list (fast remove)
38    public IEnumerable<IVertex> Vertices {
39      get { return vertices; }
40    }
41
42    [Storable]
43    private readonly Dictionary<string, IVertex> idMap;
44
45    [Storable]
46    private readonly Dictionary<object, IVertex> contentMap;
47
48    [Storable]
49    protected readonly List<IArc> arcs;
50    public IEnumerable<IArc> Arcs {
51      get { return arcs; }
52    }
53
54    [StorableConstructor]
55    protected DirectedGraph(bool serializing)
56      : base(serializing) {
57    }
58
59    [StorableHook(HookType.AfterDeserialization)]
60    private void AfterDeserialization() {
61      foreach (var arc in arcs) {
62        arc.Source.AddForwardArc(arc);
63        arc.Target.AddReverseArc(arc);
64      }
65
66      foreach (var vertex in vertices) {
67        vertex.PreContentChanged += Vertex_PreContentChanged;
68        vertex.PostContentChanged += Vertex_PostContentChanged;
69      }
70    }
71
72    public DirectedGraph() {
73      vertices = new List<IVertex>();
74      arcs = new List<IArc>();
75      contentMap = new Dictionary<object, IVertex>();
76      idMap = new Dictionary<string, IVertex>();
77    }
78
79    protected DirectedGraph(DirectedGraph original, Cloner cloner)
80      : base(original, cloner) {
81      vertices = new List<IVertex>(original.vertices);
82      arcs = new List<IArc>(original.arcs);
83      contentMap = new Dictionary<object, IVertex>(original.contentMap);
84      idMap = new Dictionary<string, IVertex>(original.idMap);
85    }
86
87    public override IDeepCloneable Clone(Cloner cloner) {
88      return new DirectedGraph(this, cloner);
89    }
90
91    public bool Contains(IVertex t) {
92      return vertices.Contains(t);
93    }
94
95    public bool Contains(object content) {
96      return contentMap.ContainsKey(content);
97    }
98
99    public IVertex GetVertex(string id) {
100      IVertex result;
101      idMap.TryGetValue(id, out result);
102      return result;
103    }
104
105    public IVertex GetVertex(object content) {
106      IVertex result;
107      contentMap.TryGetValue(content, out result);
108      return result;
109    }
110
111    public virtual bool Any(Func<IVertex, bool> predicate) {
112      return vertices.Any(predicate);
113    }
114
115    public virtual bool IsEmpty {
116      get { return !vertices.Any(); }
117    }
118
119    public virtual void Clear() {
120      vertices.Clear();
121      contentMap.Clear();
122      idMap.Clear();
123    }
124
125    public virtual void AddVertex(IVertex vertex) {
126      if (vertex.Content != null) {
127        if (!AllowDuplicateContent && contentMap.ContainsKey(vertex.Content)) {
128          throw new Exception("Content already exists in the graph.");
129        }
130        contentMap.Add(vertex.Content, vertex);
131      }
132      idMap.Add(vertex.Id, vertex);
133      vertices.Add(vertex);
134
135      vertex.PreContentChanged += Vertex_PreContentChanged;
136      vertex.PostContentChanged += Vertex_PostContentChanged;
137    }
138
139    public virtual void RemoveVertex(IVertex vertex) {
140      contentMap.Remove(vertex.Content);
141      idMap.Remove(vertex.Id);
142      vertices.Remove(vertex);
143
144      // remove connections to/from the removed vertex
145      foreach (var arc in vertex.InArcs) {
146        arc.Source.OutArcs = arc.Source.OutArcs.Where(x => x.Target != vertex);
147      }
148      foreach (var arc in vertex.OutArcs) {
149        arc.Target.InArcs = arc.Target.InArcs.Where(x => x.Source != vertex);
150      }
151      // de-register event handlers
152      vertex.PreContentChanged -= Vertex_PreContentChanged;
153      vertex.PostContentChanged -= Vertex_PostContentChanged;
154    }
155
156    public virtual IArc AddArc(IVertex source, IVertex target) {
157      var arc = new Arc(source, target);
158      source.AddForwardArc(arc);
159      target.AddReverseArc(arc);
160      arcs.Add(arc);
161      return arc;
162    }
163
164    private void Vertex_PreContentChanged(object sender, EventArgs args) {
165      var vertex = (IVertex)sender;
166      if (contentMap.ContainsKey(vertex.Content)) {
167        contentMap.Remove(vertex.Content);
168      }
169    }
170
171    private void Vertex_PostContentChanged(object sender, EventArgs args) {
172      var vertex = (IVertex)sender;
173      if (vertex.Content != null)
174        contentMap.Add(vertex.Content, vertex);
175    }
176
177    public override Image ItemImage {
178      get { return Common.Resources.VSImageLibrary.Graph; }
179    }
180  }
181}
Note: See TracBrowser for help on using the repository browser.