rgl 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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