rgl 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. data/ChangeLog +74 -0
  2. data/Makefile +72 -0
  3. data/README +240 -0
  4. data/Rakefile +210 -0
  5. data/TAGS +209 -0
  6. data/examples/canvas.rb +103 -0
  7. data/examples/codegraph +238 -0
  8. data/examples/example.jpg +0 -0
  9. data/examples/examples.rb +112 -0
  10. data/examples/graph.dot +54 -0
  11. data/examples/graph.png +0 -0
  12. data/examples/module_graph.jpg +0 -0
  13. data/examples/north.rb +12 -0
  14. data/examples/north/Graph.log +128 -0
  15. data/examples/north/g.10.0.graphml +28 -0
  16. data/examples/north/g.10.1.graphml +28 -0
  17. data/examples/north/g.10.11.graphml +31 -0
  18. data/examples/north/g.10.12.graphml +27 -0
  19. data/examples/north/g.10.13.graphml +27 -0
  20. data/examples/north/g.10.14.graphml +27 -0
  21. data/examples/north/g.10.15.graphml +26 -0
  22. data/examples/north/g.10.16.graphml +26 -0
  23. data/examples/north/g.10.17.graphml +26 -0
  24. data/examples/north/g.10.19.graphml +37 -0
  25. data/examples/north/g.10.2.graphml +28 -0
  26. data/examples/north/g.10.20.graphml +38 -0
  27. data/examples/north/g.10.22.graphml +43 -0
  28. data/examples/north/g.10.24.graphml +30 -0
  29. data/examples/north/g.10.25.graphml +45 -0
  30. data/examples/north/g.10.27.graphml +38 -0
  31. data/examples/north/g.10.28.graphml +30 -0
  32. data/examples/north/g.10.29.graphml +38 -0
  33. data/examples/north/g.10.3.graphml +26 -0
  34. data/examples/north/g.10.30.graphml +34 -0
  35. data/examples/north/g.10.31.graphml +42 -0
  36. data/examples/north/g.10.34.graphml +42 -0
  37. data/examples/north/g.10.37.graphml +28 -0
  38. data/examples/north/g.10.38.graphml +38 -0
  39. data/examples/north/g.10.39.graphml +36 -0
  40. data/examples/north/g.10.4.graphml +26 -0
  41. data/examples/north/g.10.40.graphml +37 -0
  42. data/examples/north/g.10.41.graphml +37 -0
  43. data/examples/north/g.10.42.graphml +26 -0
  44. data/examples/north/g.10.45.graphml +28 -0
  45. data/examples/north/g.10.46.graphml +32 -0
  46. data/examples/north/g.10.5.graphml +31 -0
  47. data/examples/north/g.10.50.graphml +30 -0
  48. data/examples/north/g.10.56.graphml +29 -0
  49. data/examples/north/g.10.57.graphml +32 -0
  50. data/examples/north/g.10.58.graphml +32 -0
  51. data/examples/north/g.10.6.graphml +26 -0
  52. data/examples/north/g.10.60.graphml +32 -0
  53. data/examples/north/g.10.61.graphml +34 -0
  54. data/examples/north/g.10.62.graphml +34 -0
  55. data/examples/north/g.10.68.graphml +30 -0
  56. data/examples/north/g.10.69.graphml +32 -0
  57. data/examples/north/g.10.7.graphml +29 -0
  58. data/examples/north/g.10.70.graphml +26 -0
  59. data/examples/north/g.10.71.graphml +27 -0
  60. data/examples/north/g.10.72.graphml +28 -0
  61. data/examples/north/g.10.74.graphml +29 -0
  62. data/examples/north/g.10.75.graphml +29 -0
  63. data/examples/north/g.10.78.graphml +27 -0
  64. data/examples/north/g.10.79.graphml +34 -0
  65. data/examples/north/g.10.8.graphml +29 -0
  66. data/examples/north/g.10.80.graphml +34 -0
  67. data/examples/north/g.10.82.graphml +35 -0
  68. data/examples/north/g.10.83.graphml +32 -0
  69. data/examples/north/g.10.85.graphml +34 -0
  70. data/examples/north/g.10.86.graphml +34 -0
  71. data/examples/north/g.10.88.graphml +37 -0
  72. data/examples/north/g.10.89.graphml +29 -0
  73. data/examples/north/g.10.9.graphml +26 -0
  74. data/examples/north/g.10.90.graphml +32 -0
  75. data/examples/north/g.10.91.graphml +31 -0
  76. data/examples/north/g.10.92.graphml +26 -0
  77. data/examples/north/g.10.93.graphml +32 -0
  78. data/examples/north/g.10.94.graphml +34 -0
  79. data/examples/north/g.12.8.graphml +40 -0
  80. data/examples/north/g.14.9.graphml +36 -0
  81. data/examples/north2.rb +21 -0
  82. data/examples/rdep-rgl.rb +395 -0
  83. data/install.rb +49 -0
  84. data/lib/rgl/adjacency.rb +151 -0
  85. data/lib/rgl/base.rb +299 -0
  86. data/lib/rgl/connected_components.rb +125 -0
  87. data/lib/rgl/dot.rb +63 -0
  88. data/lib/rgl/graphxml.rb +52 -0
  89. data/lib/rgl/implicit.rb +151 -0
  90. data/lib/rgl/mutable.rb +54 -0
  91. data/lib/rgl/rdot.rb +264 -0
  92. data/lib/rgl/topsort.rb +61 -0
  93. data/lib/rgl/transitiv_closure.rb +34 -0
  94. data/lib/rgl/traversal.rb +296 -0
  95. data/tests/TestComponents.rb +67 -0
  96. data/tests/TestDirectedGraph.rb +100 -0
  97. data/tests/TestEdge.rb +33 -0
  98. data/tests/TestGraphXML.rb +57 -0
  99. data/tests/TestImplicit.rb +52 -0
  100. data/tests/TestTransitiveClosure.rb +29 -0
  101. data/tests/TestTraversal.rb +222 -0
  102. data/tests/TestUnDirectedGraph.rb +98 -0
  103. metadata +163 -0
@@ -0,0 +1,49 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require 'getoptlong'
4
+ require 'rbconfig'
5
+ require 'ftools'
6
+ require 'find'
7
+
8
+ SRC_BASE = 'lib'
9
+ SRC = 'rgl'
10
+
11
+
12
+ INSTDIR = File.join Config::CONFIG['sitedir']
13
+ DESTDIR = File.join INSTDIR, SRC
14
+
15
+ opts = GetoptLong.new( [ "--uninstall", "-u", GetoptLong::NO_ARGUMENT ] )
16
+
17
+ def install
18
+ begin
19
+ File.makedirs( DESTDIR )
20
+ pwd = Dir.pwd
21
+ Dir.chdir(SRC_BASE)
22
+ Dir['*.rb'].each do |file|
23
+ dst = File.join( INSTDIR, file )
24
+ File.install(file, dst, 0644, true)
25
+ end
26
+ Find.find(SRC) do |file|
27
+ dst = File.join( INSTDIR, file )
28
+ File.install(file, dst, 0644, true) if file =~ /.rb$/
29
+ end
30
+ Dir.chdir(pwd)
31
+ rescue
32
+ puts $!
33
+ end
34
+ end
35
+
36
+ def uninstall
37
+ begin
38
+ puts "Deleting:"
39
+ Find.find(DESTDIR) { |file| File.rm_f file,true }
40
+ Dir.delete DESTDIR
41
+ rescue
42
+ end
43
+ end
44
+
45
+ if (opt = opts.get) and opt[0] =~ /^-?-u/
46
+ uninstall
47
+ else
48
+ install
49
+ end
@@ -0,0 +1,151 @@
1
+ #
2
+ # $Id: adjacency.rb,v 1.4 2002/11/10 21:21:20 monora Exp $
3
+ #
4
+ # The DirectedAdjacencyGraph class implements a generalized adjacency list
5
+ # graph structure. An AdjacencyGraph is basically a two-dimensional structure,
6
+ # where each element of the first dimension represents a vertex, and each of
7
+ # the vertices contains a one-dimensional structure that is the list of all
8
+ # adjacent vertices.
9
+ #
10
+ # The class for representing the adjacency list of a vertex is by default a
11
+ # Set, but can be configured by the client when a AdjacencyGraph is created.
12
+
13
+ require 'rgl/mutable'
14
+ require 'set'
15
+
16
+ module RGL
17
+ class DirectedAdjacencyGraph
18
+ include MutableGraph
19
+
20
+ # Shortcut for creating a DirectedAdjacencyGraph:
21
+ #
22
+ # RGL::DirectedAdjacencyGraph[1,2, 2,3, 2,4, 4,5].edges.to_a.to_s =>
23
+ # "(1-2)(2-3)(2-4)(4-5)"
24
+ def self.[](*a)
25
+ result = new
26
+ 0.step(a.size-1,2) { |i| result.add_edge(a[i],a[i+1])}
27
+ result
28
+ end
29
+
30
+ # Returns a new empty DirectedAdjacencyGraph which has as edgelist class the
31
+ # given class. The default edgelist class is Set to ensure set semantics for
32
+ # edges and vertices.
33
+ def initialize(edgelist_class=Set)
34
+ @edgelist_class = edgelist_class
35
+ @vertice_dict = Hash.new
36
+ end
37
+
38
+ # Iterator for the keys of the vertice list hash.
39
+ def each_vertex(&b)
40
+ @vertice_dict.each_key(&b)
41
+ end
42
+
43
+ def each_adjacent(v, &b) # :nodoc:
44
+ adjacency_list = @vertice_dict[v] or raise NoVertexError, "No vertex #{v}."
45
+ adjacency_list.each(&b)
46
+ end
47
+
48
+ # Returns true.
49
+ def directed?; true; end
50
+
51
+ # Complexity is O(1), since the vertices are kept in a Hash containing as
52
+ # value the list of adjacent vertices of _v_.
53
+ def has_vertex?(v); @vertice_dict.has_key?(v); end
54
+
55
+ # Complexity is O(1), if a Set is used as adjacency list, otherwise
56
+ # O(out_degree(v))
57
+ #
58
+ # ---
59
+ # MutableGraph interface.
60
+ def has_edge? (u, v)
61
+ has_vertex?(u) and @vertice_dict[u].include? v
62
+ end
63
+
64
+ # See MutableGraph#add_vertex.
65
+ #
66
+ # If the vertex is already in (using eql?) the method does nothing.
67
+ def add_vertex(v)
68
+ @vertice_dict[v] ||= @edgelist_class.new
69
+ end
70
+
71
+ # See MutableGraph#add_edge.
72
+ def add_edge (u,v)
73
+ add_vertex(u) # ensure key
74
+ add_vertex(v) # ensure key
75
+ basic_add_edge(u,v)
76
+ end
77
+
78
+ # See MutableGraph#remove_vertex.
79
+ def remove_vertex(v)
80
+ @vertice_dict.delete(v)
81
+
82
+ # remove v from all adjacency lists
83
+ @vertice_dict.each_value { |adjList| adjList.delete(v) }
84
+ end
85
+
86
+ # See MutableGraph::remove_edge.
87
+ def remove_edge (u,v)
88
+ @vertice_dict[u].delete(v) unless @vertice_dict[u].nil?
89
+ end
90
+
91
+ protected
92
+
93
+ def basic_add_edge(u,v)
94
+ @vertice_dict[u].add v
95
+ end
96
+ end # class AdjacencyGraph
97
+
98
+ # AdjacencyGraph is an undirected Graph. The methods add_edge and remove_edge
99
+ # are reimplemented: If an edge (u,v) is added or removed then the reverse
100
+ # edge (v,u) is also added or removed.
101
+ class AdjacencyGraph < DirectedAdjacencyGraph
102
+ # Always returns false.
103
+ def directed?; false; end
104
+
105
+ # Also removes (v,u)
106
+ def remove_edge (u,v)
107
+ super
108
+ @vertice_dict[v].delete(u) unless @vertice_dict[v].nil?
109
+ end
110
+
111
+ protected
112
+ def basic_add_edge(u,v)
113
+ super
114
+ # Insert backwards edge
115
+ @vertice_dict[v].add u
116
+ end
117
+ end
118
+
119
+ module Graph
120
+ # Convert a general graph to an AdjacencyGraph. If the graph is directed
121
+ # returns a DirectedAdjacencyGraph else a AdjacencyGraph.
122
+ def to_adjacency
123
+ result = (directed? ? DirectedAdjacencyGraph : AdjacencyGraph).new
124
+ each_edge { |u,v| result.add_edge u,v }
125
+ result
126
+ end
127
+
128
+ # Return a new DirectedAdjacencyGraph which has the same set of vertices. If
129
+ # (u,v) is an edge of the graph then (v,u) is an edge of the result.
130
+ #
131
+ # If the graph is undirected the result is self.
132
+ def reverse
133
+ reurn self unless directed?
134
+ result = DirectedAdjacencyGraph.new
135
+ each_edge { |u,v| result.add_edge v,u }
136
+ result
137
+ end
138
+
139
+ # Return a new AdjacencyGraph which has the same set of vertices. If (u,v)
140
+ # is an edge of the graph (u,v) and (v,u) (which are the same edges) is an
141
+ # edge of the result.
142
+ #
143
+ # If the graph is undirected the result is self.
144
+ def to_undirected
145
+ return self unless directed?
146
+ result = AdjacencyGraph.new
147
+ each_edge { |u,v| result.add_edge u,v }
148
+ result
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,299 @@
1
+ # :include: ../../README
2
+ #
3
+ # ----
4
+ #
5
+ # Module RGL defines the namespace for all modules and classes of the graph
6
+ # library. The main module is RGL::Graph which defines the abstract behavior of
7
+ # all graphs in the library.
8
+
9
+ RGL_VERSION = "0.2.2"
10
+
11
+ unless Enumerable.instance_methods(true).grep(/inject/)
12
+ module Enumerable
13
+ def inject(*argv)
14
+ argc = argv.size
15
+
16
+ if argc == 0
17
+ first = true
18
+ result = nil
19
+
20
+ each { |e|
21
+ if first
22
+ first = false
23
+ result = e
24
+ else
25
+ result = yield(result, e)
26
+ end
27
+ }
28
+ elsif argc == 1
29
+ result = argv[0]
30
+
31
+ each { |e| result = yield(result, e) }
32
+ else
33
+ raise ArgumentError, "wrong # of arguments(#{argc} for 1)"
34
+ end
35
+
36
+ result
37
+ end
38
+ end
39
+ end
40
+
41
+ module Enumerable
42
+ # Fixnum()
43
+ #
44
+ # Return the number of elements of the Enumerable. Same as _size_ but not all
45
+ # Enumerables implement size.
46
+ #--
47
+ # Should we call the methods _size_?
48
+ def length
49
+ inject(0) do |sum,v|
50
+ sum + 1
51
+ end
52
+ end
53
+ end
54
+
55
+ module RGL
56
+ class NotDirectedError < RuntimeError; end
57
+ class NotUndirectedError < RuntimeError; end
58
+
59
+ class NoVertexError < IndexError; end
60
+ class NoEdgeError < IndexError; end
61
+
62
+ # Module Edge includes classes for representing egdes of directed and
63
+ # undirected graphs. There is no need for a Vertex class, because every ruby
64
+ # object can be a vertex of a graph.
65
+ module Edge
66
+ # Simply a directed pair (source -> target). Must library functions try do
67
+ # omit to instantiate edges. They instead use two vertex parameters for
68
+ # representing edges (see each_edge). If a client wants to store edges
69
+ # explicitly DirecteEdge or UnDirectedEdge instances are return
70
+ # (i.e. Graph#edges).
71
+ class DirectedEdge
72
+ attr_accessor :source, :target
73
+
74
+ # Can be used to create an edge from a two element array.
75
+ def self.[](*a)
76
+ new(a[0],a[1])
77
+ end
78
+
79
+ # Create a new DirectedEdge with source _a_ and target _b_.
80
+ def initialize (a,b)
81
+ @source, @target = a,b
82
+ end
83
+
84
+ # Two directed edges (u,v) and (x,y) are equal iff u == x and v == y. eql?
85
+ # is needed when edges are inserted into a Set. eql? is aliased to ==.
86
+ def eql?(edge)
87
+ source == edge.source and target == edge.target
88
+ end
89
+ alias == eql?
90
+
91
+ # Returns (v,u) if self == (u,v).
92
+ def reverse
93
+ self.class.new(target, source)
94
+ end
95
+
96
+ # Edges can be indexed. edge[0] == edge.source, edge[n] == edge.target for
97
+ # all n>0. Edges can thus be used as a two element array.
98
+ def [](index); index.zero? ? source : target; end
99
+
100
+ # DirectedEdge[1,2].to_s == "(1-2)"
101
+ def to_s
102
+ "(#{source}-#{target})"
103
+ end
104
+ # Returns the array [source,target].
105
+ def to_a; [source,target]; end
106
+
107
+ # Sort support is dispatched to the <=> method of Array
108
+ def <=> e
109
+ self.to_a <=> e.to_a
110
+ end
111
+ end # DirectedEdge
112
+
113
+ # An undirected edge is simply an undirected pair (source, target) used in
114
+ # undirected graphs. UnDirectedEdge[u,v] == UnDirectedEdge[v,u]
115
+ class UnDirectedEdge < DirectedEdge
116
+ def eql?(edge)
117
+ super or (target == edge.source and source == edge.target)
118
+ end
119
+
120
+ def hash
121
+ source.hash ^ target.hash
122
+ end
123
+
124
+ # UnDirectedEdge[1,2].to_s == "(1=2)"
125
+ def to_s; "(#{source}=#{target})"; end
126
+ end
127
+ end # Edge
128
+
129
+ # In BGL terminology the module Graph defines the concept graph (see
130
+ # BOOST_DOC/graph_concepts.html). We though do not
131
+ # distinguish between IncidenceGraph, EdgeListGraph and VertexListGraph
132
+ # concept, which would complicate
133
+ # the interface two much. These concepts are defined in BGL to differentiate
134
+ # between efficient access to edges and vertices.
135
+ #
136
+ # The RGL Graph concept contains only few requirements that are common to all
137
+ # the graph
138
+ # concepts. These include especially the iterators defining the set of
139
+ # vertices and edges (see each_vertex and each_adjacent). Most other functions
140
+ # are derived from these fundamental iterators, i.e. num_vertices() or
141
+ # num_edges().
142
+ #
143
+ # Each graph is an enumerable of vertices.
144
+ module Graph
145
+ include Enumerable
146
+ include Edge
147
+
148
+ # The each_vertex iterator defines the set of vertices. This method must be
149
+ # defined be concrete graph classes. It defines the BGL VertexListGraph
150
+ # concept.
151
+ def each_vertex
152
+ raise NotImplementedError
153
+ yield v # for RDoc
154
+ end
155
+
156
+ # The each_adjacent iterator defines the out edges of vertex _v_. This
157
+ # method must be defined be concrete graph classes. Its defines the BGL
158
+ # IncidenceGraph concept.
159
+ def each_adjacent (v)
160
+ raise NotImplementedError
161
+ yield u # for RDoc
162
+ end
163
+
164
+ # The each_edge iterator should provide efficient access to all edges of the
165
+ # graph. Its defines the EdgeListGraph concept.
166
+ #
167
+ # This method must _not_ be defined be concrete graph classes, because it
168
+ # can be implemented using each_vertex and each_adjacent. However for
169
+ # undirected graph the function is inefficient because we must may not yield
170
+ # (v,u) if we already visited edge (u,v).
171
+ def each_edge (&block)
172
+ if directed?
173
+ each_vertex { |u|
174
+ each_adjacent(u) { |v| yield u,v }
175
+ }
176
+ else
177
+ each_edge_aux(&block) # concrete graphs should to this better
178
+ end
179
+ end
180
+
181
+ # Vertices get enumerated. A graph is thus an enumerable of vertices.
182
+ # ---
183
+ # === Testing
184
+ def each(&block); each_vertex(&block); end
185
+
186
+ # Is the graph directed? The default returns false.
187
+ def directed?; false; end
188
+
189
+ # Returns true if _v_ is a vertex of the graph. Same as include? inherited
190
+ # from enumerable. Complexity is O(num_vertices) by default. Concrete graph
191
+ # may bee better here (see AdjacencyGraph).
192
+ def has_vertex?(v); include?(v); end # inherited from enumerable
193
+
194
+ # Returns true if the graph has no vertex, i.e. num_vertices == 0.
195
+ # ---
196
+ # === accessing vertices and edges
197
+ def empty?; num_vertices.zero?; end
198
+
199
+ # Return the array of vertices. Synonym for to_a inherited by enumerable.
200
+ def vertices; to_a; end
201
+
202
+ # Returns the class for edges: DirectedEdge or UnDirectedEdge.
203
+ def edge_class; directed? ? DirectedEdge : UnDirectedEdge; end
204
+
205
+ # Return the array of edges (DirectedEdge or UnDirectedEdge) of the graph
206
+ # using each_edge, depending whether the graph is directed or not.
207
+ def edges
208
+ result = []
209
+ c = edge_class
210
+ each_edge { |u,v| result << c.new(u,v) }
211
+ result
212
+ end
213
+
214
+ # Returns an array of vertices adjacent to vertex _v_.
215
+ def adjacent_vertices (v)
216
+ r = []
217
+ each_adjacent(v) {|u| r << u}
218
+ r
219
+ end
220
+
221
+ # Returns the number of out-edges (for directed graphs) or the number of incident
222
+ # edges (for undirected graphs) of vertex _v_.
223
+ def out_degree (v)
224
+ r = 0
225
+ each_adjacent(v) { |u| r += 1}
226
+ r
227
+ end
228
+
229
+ # Returns the number of vertices.
230
+ def size # Why not in Enumerable?
231
+ #inject(0) { |n, v| n + 1 } # inject not yet available in Enumerable!
232
+ r = 0; each_vertex {|v| r +=1}; r
233
+ end
234
+
235
+ # Synonym for size.
236
+ def num_vertices; size; end
237
+
238
+ # Returns the number of edges.
239
+ def num_edges; r = 0; each_edge {|u,v| r +=1}; r; end
240
+
241
+ # Utility method to show a string representation of the edges of the graph.
242
+ def to_s
243
+ edges.sort.to_s
244
+ end
245
+
246
+ private
247
+
248
+ def each_edge_aux
249
+ # needed in each_edge
250
+ visited = Hash.new
251
+ each_vertex { |u|
252
+ each_adjacent(u) { |v|
253
+ edge = UnDirectedEdge.new u,v
254
+ unless visited.has_key? edge
255
+ visited[edge]=true
256
+ yield u, v
257
+ end
258
+ }
259
+ }
260
+ end
261
+ end # module Graph
262
+
263
+ # BGL defines the concept BidirectionalGraph as follows:
264
+ #
265
+ # The BidirectionalGraph concept refines IncidenceGraph and adds the
266
+ # requirement for efficient access to the in-edges of each vertex. This
267
+ # concept is separated from IncidenceGraph because for directed graphs
268
+ # efficient access to in-edges typically requires more storage space, and many
269
+ # algorithms do not require access to in-edges. For undirected graphs this is
270
+ # not an issue, since the in_edges() and out_edges() functions are the same,
271
+ # they both return the edges incident to the vertex.
272
+ module BidirectionalGraph
273
+ include Graph
274
+
275
+ # Iterator providing access to the in-edges (for directed graphs) or incident
276
+ # edges (for undirected graphs) of vertex _v_. For both directed and
277
+ # undirected graphs, the target of an out-edge is required to be vertex _v_
278
+ # and the source is required to be a vertex that is adjacent to _v_.
279
+ def each_in_neighbor (v)
280
+ raise NotImplementedError
281
+ yield u
282
+ end
283
+
284
+ # Returns the number of in-edges (for directed graphs) or the number of
285
+ # incident edges (for undirected graphs) of vertex _v_.
286
+ def in_degree (v)
287
+ r = 0;
288
+ each_in_neighbor(v) { |u| r += 1}
289
+ r
290
+ end
291
+
292
+ # Returns the number of in-edges plus out-edges (for directed graphs) or the
293
+ # number of incident edges (for undirected graphs) of vertex _v_.
294
+ def degree (v)
295
+ in_degree(v) + out_degree(v)
296
+ end
297
+ end
298
+ end # module RGL
299
+