rgl 0.2.2 → 0.2.3
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.
- data/ChangeLog +75 -2
- data/README +52 -28
- data/Rakefile +3 -3
- data/TAGS +242 -198
- data/examples/debgraph.rb +118 -0
- data/examples/examples.rb +5 -3
- data/examples/graph.dot +731 -17
- data/examples/insel.rb +141 -0
- data/lib/rgl/adjacency.rb +172 -139
- data/lib/rgl/base.rb +247 -251
- data/lib/rgl/connected_components.rb +125 -112
- data/lib/rgl/dot.rb +54 -46
- data/lib/rgl/graphxml.rb +48 -37
- data/lib/rgl/implicit.rb +159 -136
- data/lib/rgl/mutable.rb +69 -48
- data/lib/rgl/rdot.rb +268 -205
- data/lib/rgl/topsort.rb +63 -52
- data/lib/rgl/transitiv_closure.rb +40 -28
- data/lib/rgl/traversal.rb +300 -247
- data/tests/TestDirectedGraph.rb +22 -2
- data/tests/TestUnDirectedGraph.rb +4 -0
- metadata +7 -7
- data/Makefile +0 -72
- data/examples/graph.png +0 -0
data/lib/rgl/base.rb
CHANGED
@@ -1,40 +1,38 @@
|
|
1
|
-
#
|
2
|
-
#
|
3
|
-
# ----
|
1
|
+
# base.rb
|
4
2
|
#
|
5
3
|
# Module RGL defines the namespace for all modules and classes of the graph
|
6
4
|
# library. The main module is RGL::Graph which defines the abstract behavior of
|
7
5
|
# all graphs in the library.
|
8
6
|
|
9
|
-
RGL_VERSION = "0.2.
|
7
|
+
RGL_VERSION = "0.2.3"
|
10
8
|
|
11
9
|
unless Enumerable.instance_methods(true).grep(/inject/)
|
12
10
|
module Enumerable
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
11
|
+
def inject(*argv)
|
12
|
+
argc = argv.size
|
13
|
+
|
14
|
+
if argc == 0
|
15
|
+
first = true
|
16
|
+
result = nil
|
17
|
+
|
18
|
+
each { |e|
|
19
|
+
if first
|
20
|
+
first = false
|
21
|
+
result = e
|
22
|
+
else
|
23
|
+
result = yield(result, e)
|
24
|
+
end
|
25
|
+
}
|
26
|
+
elsif argc == 1
|
27
|
+
result = argv[0]
|
28
|
+
|
29
|
+
each { |e| result = yield(result, e) }
|
30
|
+
else
|
31
|
+
raise ArgumentError, "wrong # of arguments(#{argc} for 1)"
|
32
|
+
end
|
33
|
+
|
34
|
+
result
|
35
|
+
end
|
38
36
|
end
|
39
37
|
end
|
40
38
|
|
@@ -46,9 +44,9 @@ module Enumerable
|
|
46
44
|
#--
|
47
45
|
# Should we call the methods _size_?
|
48
46
|
def length
|
49
|
-
|
50
|
-
|
51
|
-
|
47
|
+
inject(0) do |sum,v|
|
48
|
+
sum + 1
|
49
|
+
end
|
52
50
|
end
|
53
51
|
end
|
54
52
|
|
@@ -63,237 +61,235 @@ module RGL
|
|
63
61
|
# undirected graphs. There is no need for a Vertex class, because every ruby
|
64
62
|
# object can be a vertex of a graph.
|
65
63
|
module Edge
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
end
|
64
|
+
# Simply a directed pair (source -> target). Must library functions try do
|
65
|
+
# omit to instantiate edges. They instead use two vertex parameters for
|
66
|
+
# representing edges (see each_edge). If a client wants to store edges
|
67
|
+
# explicitly DirecteEdge or UnDirectedEdge instances are return
|
68
|
+
# (i.e. Graph#edges).
|
69
|
+
class DirectedEdge
|
70
|
+
attr_accessor :source, :target
|
71
|
+
|
72
|
+
# Can be used to create an edge from a two element array.
|
73
|
+
def self.[](*a)
|
74
|
+
new(a[0],a[1])
|
75
|
+
end
|
76
|
+
|
77
|
+
# Create a new DirectedEdge with source _a_ and target _b_.
|
78
|
+
def initialize (a,b)
|
79
|
+
@source, @target = a,b
|
80
|
+
end
|
81
|
+
|
82
|
+
# Two directed edges (u,v) and (x,y) are equal iff u == x and v == y. eql?
|
83
|
+
# is needed when edges are inserted into a Set. eql? is aliased to ==.
|
84
|
+
def eql?(edge)
|
85
|
+
source == edge.source and target == edge.target
|
86
|
+
end
|
87
|
+
alias == eql?
|
88
|
+
|
89
|
+
# Returns (v,u) if self == (u,v).
|
90
|
+
def reverse
|
91
|
+
self.class.new(target, source)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Edges can be indexed. edge[0] == edge.source, edge[n] == edge.target for
|
95
|
+
# all n>0. Edges can thus be used as a two element array.
|
96
|
+
def [](index); index.zero? ? source : target; end
|
97
|
+
|
98
|
+
# DirectedEdge[1,2].to_s == "(1-2)"
|
99
|
+
def to_s
|
100
|
+
"(#{source}-#{target})"
|
101
|
+
end
|
102
|
+
# Returns the array [source,target].
|
103
|
+
def to_a; [source,target]; end
|
104
|
+
|
105
|
+
# Sort support is dispatched to the <=> method of Array
|
106
|
+
def <=> e
|
107
|
+
self.to_a <=> e.to_a
|
108
|
+
end
|
109
|
+
end # DirectedEdge
|
110
|
+
|
111
|
+
# An undirected edge is simply an undirected pair (source, target) used in
|
112
|
+
# undirected graphs. UnDirectedEdge[u,v] == UnDirectedEdge[v,u]
|
113
|
+
class UnDirectedEdge < DirectedEdge
|
114
|
+
def eql?(edge)
|
115
|
+
super or (target == edge.source and source == edge.target)
|
116
|
+
end
|
117
|
+
|
118
|
+
def hash
|
119
|
+
source.hash ^ target.hash
|
120
|
+
end
|
121
|
+
|
122
|
+
# UnDirectedEdge[1,2].to_s == "(1=2)"
|
123
|
+
def to_s; "(#{source}=#{target})"; end
|
124
|
+
end
|
125
|
+
end # Edge
|
128
126
|
|
129
127
|
# In BGL terminology the module Graph defines the concept graph (see
|
130
|
-
#
|
131
|
-
# distinguish between IncidenceGraph, EdgeListGraph and VertexListGraph
|
132
|
-
#
|
133
|
-
#
|
134
|
-
#
|
135
|
-
#
|
128
|
+
# http://www.boost.org/libs/graph/doc/graph_concepts.html). We though do not
|
129
|
+
# distinguish between IncidenceGraph, EdgeListGraph and VertexListGraph concept, which would
|
130
|
+
# complicate the interface two much. These concepts are defined in BGL to
|
131
|
+
# differentiate between efficient access to edges and vertices.
|
132
|
+
#
|
136
133
|
# 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
|
134
|
+
# the graph concepts. These include especially the iterators defining the set of
|
139
135
|
# vertices and edges (see each_vertex and each_adjacent). Most other functions
|
140
136
|
# are derived from these fundamental iterators, i.e. num_vertices() or
|
141
|
-
# num_edges().
|
137
|
+
# num_edges().
|
142
138
|
#
|
143
139
|
# Each graph is an enumerable of vertices.
|
144
140
|
module Graph
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
end
|
141
|
+
include Enumerable
|
142
|
+
include Edge
|
143
|
+
|
144
|
+
# The each_vertex iterator defines the set of vertices. This method must be
|
145
|
+
# defined be concrete graph classes. It defines the BGL VertexListGraph
|
146
|
+
# concept.
|
147
|
+
def each_vertex
|
148
|
+
raise NotImplementedError
|
149
|
+
yield v # for RDoc
|
150
|
+
end
|
151
|
+
|
152
|
+
# The each_adjacent iterator defines the out edges of vertex _v_. This
|
153
|
+
# method must be defined be concrete graph classes. Its defines the BGL
|
154
|
+
# IncidenceGraph concept.
|
155
|
+
def each_adjacent (v)
|
156
|
+
raise NotImplementedError
|
157
|
+
yield u # for RDoc
|
158
|
+
end
|
159
|
+
|
160
|
+
# The each_edge iterator should provide efficient access to all edges of the
|
161
|
+
# graph. Its defines the EdgeListGraph concept.
|
162
|
+
#
|
163
|
+
# This method must _not_ be defined be concrete graph classes, because it
|
164
|
+
# can be implemented using each_vertex and each_adjacent. However for
|
165
|
+
# undirected graph the function is inefficient because we must may not yield
|
166
|
+
# (v,u) if we already visited edge (u,v).
|
167
|
+
def each_edge (&block)
|
168
|
+
if directed?
|
169
|
+
each_vertex { |u|
|
170
|
+
each_adjacent(u) { |v| yield u,v }
|
171
|
+
}
|
172
|
+
else
|
173
|
+
each_edge_aux(&block) # concrete graphs should to this better
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
# Vertices get enumerated. A graph is thus an enumerable of vertices.
|
178
|
+
# ---
|
179
|
+
# === Testing
|
180
|
+
def each(&block); each_vertex(&block); end
|
181
|
+
|
182
|
+
# Is the graph directed? The default returns false.
|
183
|
+
def directed?; false; end
|
184
|
+
|
185
|
+
# Returns true if _v_ is a vertex of the graph. Same as include? inherited
|
186
|
+
# from enumerable. Complexity is O(num_vertices) by default. Concrete graph
|
187
|
+
# may bee better here (see AdjacencyGraph).
|
188
|
+
def has_vertex?(v); include?(v); end # inherited from enumerable
|
189
|
+
|
190
|
+
# Returns true if the graph has no vertex, i.e. num_vertices == 0.
|
191
|
+
# ---
|
192
|
+
# === accessing vertices and edges
|
193
|
+
def empty?; num_vertices.zero?; end
|
194
|
+
|
195
|
+
# Return the array of vertices. Synonym for to_a inherited by enumerable.
|
196
|
+
def vertices; to_a; end
|
197
|
+
|
198
|
+
# Returns the class for edges: DirectedEdge or UnDirectedEdge.
|
199
|
+
def edge_class; directed? ? DirectedEdge : UnDirectedEdge; end
|
200
|
+
|
201
|
+
# Return the array of edges (DirectedEdge or UnDirectedEdge) of the graph
|
202
|
+
# using each_edge, depending whether the graph is directed or not.
|
203
|
+
def edges
|
204
|
+
result = []
|
205
|
+
c = edge_class
|
206
|
+
each_edge { |u,v| result << c.new(u,v) }
|
207
|
+
result
|
208
|
+
end
|
209
|
+
|
210
|
+
# Returns an array of vertices adjacent to vertex _v_.
|
211
|
+
def adjacent_vertices (v)
|
212
|
+
r = []
|
213
|
+
each_adjacent(v) {|u| r << u}
|
214
|
+
r
|
215
|
+
end
|
216
|
+
|
217
|
+
# Returns the number of out-edges (for directed graphs) or the number of incident
|
218
|
+
# edges (for undirected graphs) of vertex _v_.
|
219
|
+
def out_degree (v)
|
220
|
+
r = 0
|
221
|
+
each_adjacent(v) { |u| r += 1}
|
222
|
+
r
|
223
|
+
end
|
224
|
+
|
225
|
+
# Returns the number of vertices.
|
226
|
+
def size() # Why not in Enumerable?
|
227
|
+
inject(0) { |n, v| n + 1 }
|
228
|
+
#r = 0; each_vertex {|v| r +=1}; r
|
229
|
+
end
|
230
|
+
|
231
|
+
# Synonym for size.
|
232
|
+
def num_vertices; size; end
|
233
|
+
|
234
|
+
# Returns the number of edges.
|
235
|
+
def num_edges; r = 0; each_edge {|u,v| r +=1}; r; end
|
236
|
+
|
237
|
+
# Utility method to show a string representation of the edges of the graph.
|
238
|
+
def to_s
|
239
|
+
edges.sort.to_s
|
240
|
+
end
|
241
|
+
|
242
|
+
private
|
243
|
+
|
244
|
+
def each_edge_aux
|
245
|
+
# needed in each_edge
|
246
|
+
visited = Hash.new
|
247
|
+
each_vertex { |u|
|
248
|
+
each_adjacent(u) { |v|
|
249
|
+
edge = UnDirectedEdge.new u,v
|
250
|
+
unless visited.has_key? edge
|
251
|
+
visited[edge]=true
|
252
|
+
yield u, v
|
253
|
+
end
|
254
|
+
}
|
255
|
+
}
|
256
|
+
end
|
257
|
+
end # module Graph
|
262
258
|
|
263
259
|
# BGL defines the concept BidirectionalGraph as follows:
|
264
260
|
#
|
265
261
|
# The BidirectionalGraph concept refines IncidenceGraph and adds the
|
266
|
-
# requirement
|
267
|
-
# concept is separated from IncidenceGraph because for directed graphs
|
268
|
-
# efficient access to in-edges typically requires more storage space,
|
269
|
-
# algorithms do not require access to in-edges.
|
270
|
-
# not an issue
|
271
|
-
# they both return the edges incident to the vertex.
|
262
|
+
# requirement for efficient access to the in-edges of each vertex. This
|
263
|
+
# concept is separated from IncidenceGraph because, for directed graphs,
|
264
|
+
# efficient access to in-edges typically requires more storage space,
|
265
|
+
# and many algorithms do not require access to in-edges. For undirected
|
266
|
+
# graphs, this is not an issue; because the in_edges() and out_edges()
|
267
|
+
# functions are the same, they both return the edges incident to the vertex.
|
272
268
|
module BidirectionalGraph
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
269
|
+
include Graph
|
270
|
+
|
271
|
+
# Iterator providing access to the in-edges (for directed graphs) or incident
|
272
|
+
# edges (for undirected graphs) of vertex _v_. For both directed and
|
273
|
+
# undirected graphs, the target of an out-edge is required to be vertex _v_
|
274
|
+
# and the source is required to be a vertex that is adjacent to _v_.
|
275
|
+
def each_in_neighbor (v)
|
276
|
+
raise NotImplementedError
|
277
|
+
yield u
|
278
|
+
end
|
279
|
+
|
280
|
+
# Returns the number of in-edges (for directed graphs) or the number of
|
281
|
+
# incident edges (for undirected graphs) of vertex _v_.
|
282
|
+
def in_degree (v)
|
283
|
+
r = 0;
|
284
|
+
each_in_neighbor(v) { |u| r += 1}
|
285
|
+
r
|
286
|
+
end
|
287
|
+
|
288
|
+
# Returns the number of in-edges plus out-edges (for directed graphs) or the
|
289
|
+
# number of incident edges (for undirected graphs) of vertex _v_.
|
290
|
+
def degree (v)
|
291
|
+
in_degree(v) + out_degree(v)
|
292
|
+
end
|
297
293
|
end
|
298
|
-
end
|
294
|
+
end # module RGL
|
299
295
|
|