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.
@@ -1,40 +1,38 @@
1
- # :include: ../../README
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.2"
7
+ RGL_VERSION = "0.2.3"
10
8
 
11
9
  unless Enumerable.instance_methods(true).grep(/inject/)
12
10
  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
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
- inject(0) do |sum,v|
50
- sum + 1
51
- end
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
- # 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
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
- # 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
- #
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
- 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
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 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.
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
- 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
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 # module RGL
294
+ end # module RGL
299
295