rgl 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +19 -10
- data/Gemfile +3 -0
- data/{README → README.rdoc} +70 -98
- data/Rakefile +44 -150
- data/examples/canvas.rb +63 -64
- data/examples/examples.rb +42 -42
- data/examples/graph.dot +46 -0
- data/examples/images/example.jpg +0 -0
- data/examples/images/module_graph.jpg +0 -0
- data/examples/images/rgl_modules.png +0 -0
- data/examples/{insel-der-tausend-gefahren.rb → insel_der_tausend_gefahren.rb} +18 -19
- data/examples/north.rb +2 -2
- data/examples/north2.rb +11 -11
- data/examples/rdep-rgl.rb +218 -222
- data/lib/rgl/adjacency.rb +78 -74
- data/lib/rgl/base.rb +160 -78
- data/lib/rgl/bellman_ford.rb +115 -0
- data/lib/rgl/bidirectional.rb +17 -10
- data/lib/rgl/bipartite.rb +87 -0
- data/lib/rgl/condensation.rb +13 -4
- data/lib/rgl/connected_components.rb +38 -30
- data/lib/rgl/dijkstra.rb +158 -0
- data/lib/rgl/dijkstra_visitor.rb +42 -0
- data/lib/rgl/dot.rb +40 -32
- data/lib/rgl/edge_properties_map.rb +55 -0
- data/lib/rgl/edmonds_karp.rb +136 -0
- data/lib/rgl/enumerable_ext.rb +4 -1
- data/lib/rgl/graph_iterator.rb +15 -0
- data/lib/rgl/graph_visitor.rb +138 -0
- data/lib/rgl/graph_wrapper.rb +15 -0
- data/lib/rgl/graphxml.rb +20 -10
- data/lib/rgl/implicit.rb +68 -66
- data/lib/rgl/mutable.rb +37 -31
- data/lib/rgl/path_builder.rb +40 -0
- data/lib/rgl/prim.rb +52 -0
- data/lib/rgl/rdot.rb +411 -374
- data/lib/rgl/topsort.rb +23 -16
- data/lib/rgl/transitivity.rb +29 -27
- data/lib/rgl/traversal.rb +67 -205
- data/rakelib/dep_graph.rake +4 -3
- data/test/bellman_ford_test.rb +187 -0
- data/test/bipartite_test.rb +47 -0
- data/test/components_test.rb +80 -0
- data/test/cycles_test.rb +60 -0
- data/test/dijkstra_test.rb +148 -0
- data/test/directed_graph_test.rb +118 -0
- data/test/dot_test.rb +26 -0
- data/test/edge_properties_map_test.rb +63 -0
- data/test/edge_test.rb +35 -0
- data/test/edmonds_karp_test.rb +105 -0
- data/{tests/TestGraph.rb → test/graph_test.rb} +6 -6
- data/test/graph_xml_test.rb +57 -0
- data/test/implicit_test.rb +53 -0
- data/test/prim_test.rb +98 -0
- data/{tests/TestRdot.rb → test/rdot_test.rb} +309 -308
- data/{tests → test}/test_helper.rb +4 -1
- data/{tests/TestTransitivity.rb → test/transitivity_test.rb} +43 -43
- data/test/traversal_test.rb +221 -0
- data/test/undirected_graph_test.rb +103 -0
- metadata +226 -145
- data/examples/example.jpg +0 -0
- data/examples/module_graph.jpg +0 -0
- data/install.rb +0 -49
- data/tests/TestComponents.rb +0 -65
- data/tests/TestCycles.rb +0 -61
- data/tests/TestDirectedGraph.rb +0 -125
- data/tests/TestDot.rb +0 -18
- data/tests/TestEdge.rb +0 -34
- data/tests/TestGraphXML.rb +0 -57
- data/tests/TestImplicit.rb +0 -52
- data/tests/TestTraversal.rb +0 -220
- data/tests/TestUnDirectedGraph.rb +0 -102
data/lib/rgl/adjacency.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# adjacency.rb
|
2
|
-
#
|
3
|
-
# $Id
|
4
|
-
#
|
2
|
+
#
|
3
|
+
# $Id$
|
4
|
+
#
|
5
5
|
# The DirectedAdjacencyGraph class implements a generalized adjacency list
|
6
|
-
# graph structure.
|
7
|
-
# (ie, a list of lists).
|
8
|
-
# vertex.
|
6
|
+
# graph structure. An AdjacencyGraph is basically a two-dimensional structure
|
7
|
+
# (ie, a list of lists). Each element of the first dimension represents a
|
8
|
+
# vertex. Each of the vertices contains a one-dimensional structure that is
|
9
9
|
# the list of all adjacent vertices.
|
10
10
|
#
|
11
11
|
# The class for representing the adjacency list of a vertex is, by default, a
|
12
|
-
# Set.
|
12
|
+
# Set. This can be configured by the client, however, when an AdjacencyGraph
|
13
13
|
# is created.
|
14
14
|
|
15
15
|
require 'rgl/mutable'
|
@@ -25,156 +25,159 @@ module RGL
|
|
25
25
|
#
|
26
26
|
# RGL::DirectedAdjacencyGraph[1,2, 2,3, 2,4, 4,5].edges.to_a.to_s =>
|
27
27
|
# "(1-2)(2-3)(2-4)(4-5)"
|
28
|
-
|
29
|
-
def self.[]
|
28
|
+
#
|
29
|
+
def self.[](*a)
|
30
30
|
result = new
|
31
|
-
0.step(a.size-1, 2) { |i| result.add_edge(a[i], a[i+1]) }
|
31
|
+
0.step(a.size - 1, 2) { |i| result.add_edge(a[i], a[i + 1]) }
|
32
32
|
result
|
33
33
|
end
|
34
34
|
|
35
35
|
# Returns a new empty DirectedAdjacencyGraph which has as its edgelist
|
36
|
-
# class the given class.
|
36
|
+
# class the given class. The default edgelist class is Set, to ensure
|
37
37
|
# set semantics for edges and vertices.
|
38
38
|
#
|
39
39
|
# If other graphs are passed as parameters their vertices and edges are
|
40
40
|
# added to the new graph.
|
41
|
-
|
41
|
+
#
|
42
|
+
def initialize(edgelist_class = Set, *other_graphs)
|
42
43
|
@edgelist_class = edgelist_class
|
43
|
-
@
|
44
|
+
@vertices_dict = Hash.new
|
44
45
|
other_graphs.each do |g|
|
45
|
-
g.each_vertex {|v| add_vertex v}
|
46
|
-
g.each_edge {|v,w| add_edge v,w}
|
46
|
+
g.each_vertex { |v| add_vertex v }
|
47
|
+
g.each_edge { |v, w| add_edge v, w }
|
47
48
|
end
|
48
49
|
end
|
49
50
|
|
50
|
-
# Copy internal
|
51
|
+
# Copy internal vertices_dict
|
52
|
+
#
|
51
53
|
def initialize_copy(orig)
|
52
|
-
@
|
53
|
-
@
|
54
|
-
@
|
54
|
+
@vertices_dict = orig.instance_eval { @vertices_dict }.dup
|
55
|
+
@vertices_dict.keys.each do |v|
|
56
|
+
@vertices_dict[v] = @vertices_dict[v].dup
|
55
57
|
end
|
56
58
|
end
|
57
59
|
|
58
|
-
# Iterator for the keys of the
|
59
|
-
|
60
|
-
def each_vertex
|
61
|
-
@
|
60
|
+
# Iterator for the keys of the vertices list hash.
|
61
|
+
#
|
62
|
+
def each_vertex(&b)
|
63
|
+
@vertices_dict.each_key(&b)
|
62
64
|
end
|
63
65
|
|
64
|
-
def each_adjacent
|
65
|
-
adjacency_list = (@
|
66
|
-
raise NoVertexError, "No vertex #{v}.")
|
66
|
+
def each_adjacent(v, &b) # :nodoc:
|
67
|
+
adjacency_list = (@vertices_dict[v] or raise NoVertexError, "No vertex #{v}.")
|
67
68
|
adjacency_list.each(&b)
|
68
69
|
end
|
69
70
|
|
70
71
|
# Returns true.
|
71
|
-
|
72
|
+
#
|
72
73
|
def directed?
|
73
74
|
true
|
74
75
|
end
|
75
76
|
|
76
77
|
# Complexity is O(1), because the vertices are kept in a Hash containing
|
77
78
|
# as values the lists of adjacent vertices of _v_.
|
78
|
-
|
79
|
+
#
|
79
80
|
def has_vertex? (v)
|
80
|
-
@
|
81
|
+
@vertices_dict.has_key?(v)
|
81
82
|
end
|
82
83
|
|
83
|
-
# Complexity is O(1), if a Set is used as adjacency list.
|
84
|
+
# Complexity is O(1), if a Set is used as adjacency list. Otherwise,
|
84
85
|
# complexity is O(out_degree(v)).
|
85
86
|
#
|
86
87
|
# ---
|
87
88
|
# MutableGraph interface.
|
88
|
-
|
89
|
+
#
|
89
90
|
def has_edge? (u, v)
|
90
|
-
has_vertex?(u)
|
91
|
+
has_vertex?(u) && @vertices_dict[u].include?(v)
|
91
92
|
end
|
92
93
|
|
93
94
|
# See MutableGraph#add_vertex.
|
94
95
|
#
|
95
96
|
# If the vertex is already in the graph (using eql?), the method does
|
96
97
|
# nothing.
|
97
|
-
|
98
|
-
def add_vertex
|
99
|
-
@
|
98
|
+
#
|
99
|
+
def add_vertex(v)
|
100
|
+
@vertices_dict[v] ||= @edgelist_class.new
|
100
101
|
end
|
101
102
|
|
102
103
|
# See MutableGraph#add_edge.
|
103
|
-
|
104
|
-
def add_edge
|
105
|
-
add_vertex(u)
|
106
|
-
add_vertex(v)
|
104
|
+
#
|
105
|
+
def add_edge(u, v)
|
106
|
+
add_vertex(u) # ensure key
|
107
|
+
add_vertex(v) # ensure key
|
107
108
|
basic_add_edge(u, v)
|
108
109
|
end
|
109
110
|
|
110
111
|
# See MutableGraph#remove_vertex.
|
112
|
+
#
|
113
|
+
def remove_vertex(v)
|
114
|
+
@vertices_dict.delete(v)
|
111
115
|
|
112
|
-
def remove_vertex (v)
|
113
|
-
@vertice_dict.delete(v)
|
114
|
-
|
115
116
|
# remove v from all adjacency lists
|
116
|
-
|
117
|
-
@vertice_dict.each_value { |adjList| adjList.delete(v) }
|
117
|
+
@vertices_dict.each_value { |adjList| adjList.delete(v) }
|
118
118
|
end
|
119
119
|
|
120
120
|
# See MutableGraph::remove_edge.
|
121
|
-
|
122
|
-
def remove_edge
|
123
|
-
@
|
121
|
+
#
|
122
|
+
def remove_edge(u, v)
|
123
|
+
@vertices_dict[u].delete(v) unless @vertices_dict[u].nil?
|
124
124
|
end
|
125
125
|
|
126
126
|
# Converts the adjacency list of each vertex to be of type _klass_. The
|
127
|
-
# class is expected to have a new
|
127
|
+
# class is expected to have a new constructor which accepts an enumerable as
|
128
128
|
# parameter.
|
129
|
+
#
|
129
130
|
def edgelist_class=(klass)
|
130
|
-
@
|
131
|
-
|
131
|
+
@vertices_dict.keys.each do |v|
|
132
|
+
@vertices_dict[v] = klass.new @vertices_dict[v].to_a
|
132
133
|
end
|
133
134
|
end
|
134
135
|
|
135
136
|
protected
|
136
137
|
|
137
|
-
def basic_add_edge
|
138
|
-
@
|
138
|
+
def basic_add_edge(u, v)
|
139
|
+
@vertices_dict[u].add(v)
|
139
140
|
end
|
140
141
|
|
141
|
-
end
|
142
|
+
end # class DirectedAdjacencyGraph
|
142
143
|
|
143
|
-
# AdjacencyGraph is an undirected Graph.
|
144
|
-
# remove_edge are reimplemented:
|
144
|
+
# AdjacencyGraph is an undirected Graph. The methods add_edge and
|
145
|
+
# remove_edge are reimplemented: if an edge (u,v) is added or removed,
|
145
146
|
# then the reverse edge (v,u) is also added or removed.
|
147
|
+
#
|
148
|
+
class AdjacencyGraph < DirectedAdjacencyGraph
|
146
149
|
|
147
|
-
|
148
|
-
|
149
|
-
def directed?
|
150
|
+
# Always returns false.
|
151
|
+
#
|
152
|
+
def directed?
|
150
153
|
false
|
151
154
|
end
|
152
|
-
|
153
|
-
# Also removes (v,u)
|
154
155
|
|
155
|
-
|
156
|
+
# Also removes (v,u)
|
157
|
+
#
|
158
|
+
def remove_edge(u, v)
|
156
159
|
super
|
157
|
-
@
|
160
|
+
@vertices_dict[v].delete(u) unless @vertices_dict[v].nil?
|
158
161
|
end
|
159
162
|
|
160
163
|
protected
|
161
164
|
|
162
|
-
def basic_add_edge
|
165
|
+
def basic_add_edge(u, v)
|
163
166
|
super
|
164
|
-
@
|
167
|
+
@vertices_dict[v].add(u) # Insert backwards edge
|
165
168
|
end
|
166
169
|
|
167
|
-
end
|
170
|
+
end # class AdjacencyGraph
|
168
171
|
|
169
172
|
module Graph
|
170
173
|
|
171
|
-
# Convert a general graph to an AdjacencyGraph.
|
174
|
+
# Convert a general graph to an AdjacencyGraph. If the graph is directed,
|
172
175
|
# returns a DirectedAdjacencyGraph; otherwise, returns an AdjacencyGraph.
|
173
|
-
|
176
|
+
#
|
174
177
|
def to_adjacency
|
175
178
|
result = (directed? ? DirectedAdjacencyGraph : AdjacencyGraph).new
|
176
179
|
each_vertex { |v| result.add_vertex(v) }
|
177
|
-
each_edge { |u,v| result.add_edge(u, v) }
|
180
|
+
each_edge { |u, v| result.add_edge(u, v) }
|
178
181
|
result
|
179
182
|
end
|
180
183
|
|
@@ -182,25 +185,26 @@ module RGL
|
|
182
185
|
# If (u,v) is an edge of the graph, then (v,u) is an edge of the result.
|
183
186
|
#
|
184
187
|
# If the graph is undirected, the result is self.
|
185
|
-
|
188
|
+
#
|
186
189
|
def reverse
|
187
190
|
return self unless directed?
|
188
191
|
result = DirectedAdjacencyGraph.new
|
189
192
|
each_vertex { |v| result.add_vertex v }
|
190
|
-
each_edge { |u,v| result.add_edge(v, u) }
|
193
|
+
each_edge { |u, v| result.add_edge(v, u) }
|
191
194
|
result
|
192
195
|
end
|
193
196
|
|
194
|
-
# Return a new AdjacencyGraph which has the same set of vertices.
|
197
|
+
# Return a new AdjacencyGraph which has the same set of vertices. If (u,v)
|
195
198
|
# is an edge of the graph, then (u,v) and (v,u) (which are the same edges)
|
196
199
|
# are edges of the result.
|
197
200
|
#
|
198
201
|
# If the graph is undirected, the result is self.
|
199
|
-
|
202
|
+
#
|
200
203
|
def to_undirected
|
201
204
|
return self unless directed?
|
202
205
|
AdjacencyGraph.new(Set, self)
|
203
206
|
end
|
204
207
|
|
205
|
-
end
|
206
|
-
|
208
|
+
end # module Graph
|
209
|
+
|
210
|
+
end # module RGL
|
data/lib/rgl/base.rb
CHANGED
@@ -3,114 +3,144 @@
|
|
3
3
|
# Module RGL defines the namespace for all modules and classes of the graph
|
4
4
|
# library. The main module is RGL::Graph which defines the abstract behavior of
|
5
5
|
# all graphs in the library.
|
6
|
+
|
6
7
|
require 'rgl/enumerable_ext'
|
7
8
|
|
8
|
-
RGL_VERSION = "0.
|
9
|
+
RGL_VERSION = "0.5.0"
|
9
10
|
|
10
11
|
module RGL
|
11
12
|
class NotDirectedError < RuntimeError; end
|
13
|
+
|
12
14
|
class NotUndirectedError < RuntimeError; end
|
13
15
|
|
14
16
|
class NoVertexError < IndexError; end
|
17
|
+
|
15
18
|
class NoEdgeError < IndexError; end
|
16
19
|
|
17
|
-
|
20
|
+
INFINITY = 1.0 / 0.0 # positive infinity
|
21
|
+
|
22
|
+
# Module Edge includes classes for representing edges of directed and
|
18
23
|
# undirected graphs. There is no need for a Vertex class, because every ruby
|
19
24
|
# object can be a vertex of a graph.
|
25
|
+
#
|
20
26
|
module Edge
|
21
27
|
# Simply a directed pair (source -> target). Most library functions try do
|
22
28
|
# omit to instantiate edges. They instead use two vertex parameters for
|
23
29
|
# representing edges (see each_edge). If a client wants to store edges
|
24
|
-
# explicitly
|
30
|
+
# explicitly DirectedEdge or UnDirectedEdge instances are returned
|
25
31
|
# (i.e. Graph#edges).
|
32
|
+
#
|
26
33
|
class DirectedEdge
|
27
|
-
attr_accessor :source, :target
|
28
34
|
|
35
|
+
attr_accessor :source, :target
|
29
36
|
# Can be used to create an edge from a two element array.
|
37
|
+
#
|
30
38
|
def self.[](*a)
|
31
|
-
new(a[0],a[1])
|
39
|
+
new(a[0], a[1])
|
32
40
|
end
|
33
41
|
|
34
42
|
# Create a new DirectedEdge with source _a_ and target _b_.
|
35
|
-
|
36
|
-
|
43
|
+
#
|
44
|
+
def initialize(a, b)
|
45
|
+
@source, @target = a, b
|
37
46
|
end
|
38
|
-
|
47
|
+
|
39
48
|
# Two directed edges (u,v) and (x,y) are equal iff u == x and v == y. eql?
|
40
49
|
# is needed when edges are inserted into a Set. eql? is aliased to ==.
|
50
|
+
#
|
41
51
|
def eql?(edge)
|
42
|
-
source == edge.source
|
52
|
+
(source == edge.source) && (target == edge.target)
|
43
53
|
end
|
54
|
+
|
44
55
|
alias == eql?
|
45
56
|
|
57
|
+
def hash
|
58
|
+
source.hash ^ target.hash
|
59
|
+
end
|
60
|
+
|
46
61
|
# Returns (v,u) if self == (u,v).
|
62
|
+
#
|
47
63
|
def reverse
|
48
64
|
self.class.new(target, source)
|
49
65
|
end
|
50
66
|
|
51
67
|
# Edges can be indexed. edge[0] == edge.source, edge[n] == edge.target for
|
52
68
|
# all n>0. Edges can thus be used as a two element array.
|
53
|
-
|
69
|
+
#
|
70
|
+
def [](index)
|
71
|
+
index.zero? ? source : target
|
72
|
+
end
|
54
73
|
|
55
74
|
# DirectedEdge[1,2].to_s == "(1-2)"
|
75
|
+
#
|
56
76
|
def to_s
|
57
77
|
"(#{source}-#{target})"
|
58
78
|
end
|
79
|
+
|
59
80
|
# Returns the array [source,target].
|
60
|
-
|
81
|
+
#
|
82
|
+
def to_a
|
83
|
+
[source, target]
|
84
|
+
end
|
61
85
|
|
62
86
|
# Sort support is dispatched to the <=> method of Array
|
87
|
+
#
|
63
88
|
def <=> e
|
64
89
|
self.to_a <=> e.to_a
|
65
90
|
end
|
66
|
-
|
91
|
+
|
92
|
+
end # DirectedEdge
|
67
93
|
|
68
94
|
# An undirected edge is simply an undirected pair (source, target) used in
|
69
95
|
# undirected graphs. UnDirectedEdge[u,v] == UnDirectedEdge[v,u]
|
96
|
+
#
|
70
97
|
class UnDirectedEdge < DirectedEdge
|
71
98
|
def eql?(edge)
|
72
|
-
super
|
99
|
+
super || ((target == edge.source) && (source == edge.target))
|
73
100
|
end
|
74
|
-
|
75
|
-
def hash
|
76
|
-
source.hash ^ target.hash
|
77
|
-
end
|
78
|
-
|
101
|
+
|
79
102
|
# UnDirectedEdge[1,2].to_s == "(1=2)"
|
80
|
-
|
103
|
+
#
|
104
|
+
def to_s
|
105
|
+
"(#{source}=#{target})"
|
106
|
+
end
|
107
|
+
|
81
108
|
end
|
82
109
|
|
83
|
-
end
|
110
|
+
end # Edge
|
84
111
|
|
85
112
|
# In BGL terminology the module Graph defines the graph concept (see
|
86
113
|
# http://www.boost.org/libs/graph/doc/graph_concepts.html). We however do not
|
87
114
|
# distinguish between the IncidenceGraph, EdgeListGraph and VertexListGraph
|
88
|
-
|
89
|
-
|
90
|
-
|
115
|
+
# concepts, which would complicate the interface too much. These concepts are
|
116
|
+
# defined in BGL to differentiate between efficient access to edges and
|
117
|
+
# vertices.
|
91
118
|
#
|
92
119
|
# The RGL Graph concept contains only a few requirements that are common to
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
120
|
+
# all the graph concepts. These include, especially, the iterators defining
|
121
|
+
# the sets of vertices and edges (see each_vertex and each_adjacent). Most
|
122
|
+
# other functions are derived from these fundamental iterators, i.e.
|
123
|
+
# num_vertices or num_edges.
|
97
124
|
#
|
98
125
|
# Each graph is an enumerable of vertices.
|
126
|
+
#
|
99
127
|
module Graph
|
128
|
+
|
100
129
|
include Enumerable
|
101
130
|
include Edge
|
102
|
-
|
103
131
|
# The each_vertex iterator defines the set of vertices. This method must be
|
104
132
|
# defined by concrete graph classes. It defines the BGL VertexListGraph
|
105
133
|
# concept.
|
106
|
-
|
134
|
+
#
|
135
|
+
def each_vertex() # :yields: v
|
107
136
|
raise NotImplementedError
|
108
137
|
end
|
109
138
|
|
110
139
|
# The each_adjacent iterator defines the out edges of vertex _v_. This
|
111
140
|
# method must be defined by concrete graph classes. Its defines the BGL
|
112
141
|
# IncidenceGraph concept.
|
113
|
-
|
142
|
+
#
|
143
|
+
def each_adjacent(v) # :yields: v
|
114
144
|
raise NotImplementedError
|
115
145
|
end
|
116
146
|
|
@@ -121,109 +151,161 @@ module RGL
|
|
121
151
|
# can be implemented using each_vertex and each_adjacent. However for
|
122
152
|
# undirected graph the function is inefficient because we must not yield
|
123
153
|
# (v,u) if we already visited edge (u,v).
|
124
|
-
|
154
|
+
#
|
155
|
+
def each_edge(&block)
|
125
156
|
if directed?
|
126
|
-
each_vertex
|
127
|
-
each_adjacent(u) { |v| yield u,v }
|
128
|
-
|
157
|
+
each_vertex do |u|
|
158
|
+
each_adjacent(u) { |v| yield u, v }
|
159
|
+
end
|
129
160
|
else
|
130
|
-
each_edge_aux(&block)
|
161
|
+
each_edge_aux(&block) # concrete graphs should to this better
|
131
162
|
end
|
132
163
|
end
|
133
164
|
|
134
165
|
# Vertices get enumerated. A graph is thus an enumerable of vertices.
|
135
|
-
#
|
136
|
-
|
137
|
-
|
166
|
+
#
|
167
|
+
def each(&block)
|
168
|
+
each_vertex(&block)
|
169
|
+
end
|
138
170
|
|
139
171
|
# Is the graph directed? The default returns false.
|
140
|
-
|
172
|
+
#
|
173
|
+
def directed?
|
174
|
+
false
|
175
|
+
end
|
141
176
|
|
142
177
|
# Returns true if _v_ is a vertex of the graph. Same as #include? inherited
|
143
178
|
# from Enumerable. Complexity is O(num_vertices) by default. Concrete graph
|
144
179
|
# may be better here (see AdjacencyGraph).
|
145
|
-
|
180
|
+
#
|
181
|
+
def has_vertex?(v)
|
182
|
+
include?(v) # inherited from enumerable
|
183
|
+
end
|
146
184
|
|
147
185
|
# Returns true if the graph has no vertices, i.e. num_vertices == 0.
|
148
|
-
#
|
149
|
-
|
150
|
-
|
186
|
+
#
|
187
|
+
def empty?
|
188
|
+
num_vertices.zero?
|
189
|
+
end
|
151
190
|
|
152
191
|
# Return the array of vertices. Synonym for #to_a inherited by Enumerable.
|
153
|
-
|
192
|
+
#
|
193
|
+
def vertices
|
194
|
+
to_a
|
195
|
+
end
|
154
196
|
|
155
197
|
# Returns the class for edges: DirectedEdge or UnDirectedEdge.
|
156
|
-
|
198
|
+
#
|
199
|
+
def edge_class
|
200
|
+
directed? ? DirectedEdge : UnDirectedEdge
|
201
|
+
end
|
157
202
|
|
158
203
|
# Return the array of edges (DirectedEdge or UnDirectedEdge) of the graph
|
159
204
|
# using each_edge, depending whether the graph is directed or not.
|
160
205
|
def edges
|
161
206
|
result = []
|
162
207
|
c = edge_class
|
163
|
-
each_edge { |u,v| result << c.new(u,v) }
|
208
|
+
each_edge { |u, v| result << c.new(u, v) }
|
164
209
|
result
|
165
210
|
end
|
166
211
|
|
167
212
|
# Returns an array of vertices adjacent to vertex _v_.
|
168
|
-
|
213
|
+
#
|
214
|
+
def adjacent_vertices(v)
|
169
215
|
r = []
|
170
|
-
each_adjacent(v) {|u| r << u}
|
216
|
+
each_adjacent(v) { |u| r << u }
|
171
217
|
r
|
172
218
|
end
|
173
219
|
|
174
220
|
# Returns the number of out-edges (for directed graphs) or the number of
|
175
|
-
|
176
|
-
|
221
|
+
# incident edges (for undirected graphs) of vertex _v_.
|
222
|
+
#
|
223
|
+
def out_degree(v)
|
177
224
|
r = 0
|
178
|
-
each_adjacent(v) { |u| r += 1}
|
225
|
+
each_adjacent(v) { |u| r += 1 }
|
179
226
|
r
|
180
227
|
end
|
181
228
|
|
182
229
|
# Returns the number of vertices.
|
183
|
-
|
230
|
+
#
|
231
|
+
def size # Why not in Enumerable?
|
184
232
|
inject(0) { |n, v| n + 1 }
|
185
233
|
end
|
186
|
-
|
234
|
+
|
235
|
+
alias num_vertices size
|
187
236
|
|
188
237
|
# Returns the number of edges.
|
189
|
-
|
238
|
+
#
|
239
|
+
def num_edges
|
240
|
+
r = 0
|
241
|
+
each_edge { |u, v| r +=1 }
|
242
|
+
r
|
243
|
+
end
|
190
244
|
|
191
245
|
# Utility method to show a string representation of the edges of the graph.
|
246
|
+
#
|
192
247
|
def to_s
|
193
|
-
edges.sort.
|
194
|
-
end
|
195
|
-
|
196
|
-
#
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
g.is_a?(Graph) and directed? == g.directed? and
|
201
|
-
g.inject(0) { |n, v| has_vertex?(v) or return false; n+1} ==
|
202
|
-
num_vertices and begin
|
203
|
-
ng = 0
|
204
|
-
g.each_edge {|u,v| has_edge? u,v or return false; ng += 1}
|
205
|
-
ng == num_edges
|
206
|
-
end
|
207
|
-
end
|
248
|
+
edges.collect {|e| e.to_s}.sort.join
|
249
|
+
end
|
250
|
+
|
251
|
+
# Two graphs are equal iff they have equal directed? property as well as vertices and edges sets.
|
252
|
+
#
|
253
|
+
def eql?(other)
|
254
|
+
equal?(other) || eql_graph?(other)
|
208
255
|
end
|
256
|
+
|
209
257
|
alias == eql?
|
210
258
|
|
211
259
|
private
|
212
260
|
|
261
|
+
def eql_graph?(other)
|
262
|
+
other.is_a?(Graph) && directed? == other.directed? && eql_vertices_set?(other) && eql_edges_set?(other)
|
263
|
+
end
|
264
|
+
|
265
|
+
def eql_vertices_set?(other)
|
266
|
+
other_num_vertices = 0
|
267
|
+
|
268
|
+
other.each_vertex do |v|
|
269
|
+
if has_vertex?(v)
|
270
|
+
other_num_vertices += 1
|
271
|
+
else
|
272
|
+
return false
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
other_num_vertices == num_vertices
|
277
|
+
end
|
278
|
+
|
279
|
+
def eql_edges_set?(other)
|
280
|
+
other_num_edges = 0
|
281
|
+
|
282
|
+
other.each_edge do |u, v|
|
283
|
+
if has_edge?(u, v)
|
284
|
+
other_num_edges += 1
|
285
|
+
else
|
286
|
+
return false
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
other_num_edges == num_edges
|
291
|
+
end
|
292
|
+
|
213
293
|
def each_edge_aux
|
214
294
|
# needed in each_edge
|
215
295
|
visited = Hash.new
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
296
|
+
|
297
|
+
each_vertex do |u|
|
298
|
+
each_adjacent(u) do |v|
|
299
|
+
edge = UnDirectedEdge.new(u, v)
|
300
|
+
|
301
|
+
unless visited.has_key?(edge)
|
302
|
+
visited[edge] = true
|
221
303
|
yield u, v
|
222
304
|
end
|
223
|
-
|
224
|
-
|
305
|
+
end
|
306
|
+
end
|
225
307
|
end
|
226
|
-
end # module Graph
|
227
308
|
|
228
|
-
end
|
309
|
+
end # module Graph
|
229
310
|
|
311
|
+
end # module RGL
|