rgl 0.4.0 → 0.5.0

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 (72) hide show
  1. data/ChangeLog +19 -10
  2. data/Gemfile +3 -0
  3. data/{README → README.rdoc} +70 -98
  4. data/Rakefile +44 -150
  5. data/examples/canvas.rb +63 -64
  6. data/examples/examples.rb +42 -42
  7. data/examples/graph.dot +46 -0
  8. data/examples/images/example.jpg +0 -0
  9. data/examples/images/module_graph.jpg +0 -0
  10. data/examples/images/rgl_modules.png +0 -0
  11. data/examples/{insel-der-tausend-gefahren.rb → insel_der_tausend_gefahren.rb} +18 -19
  12. data/examples/north.rb +2 -2
  13. data/examples/north2.rb +11 -11
  14. data/examples/rdep-rgl.rb +218 -222
  15. data/lib/rgl/adjacency.rb +78 -74
  16. data/lib/rgl/base.rb +160 -78
  17. data/lib/rgl/bellman_ford.rb +115 -0
  18. data/lib/rgl/bidirectional.rb +17 -10
  19. data/lib/rgl/bipartite.rb +87 -0
  20. data/lib/rgl/condensation.rb +13 -4
  21. data/lib/rgl/connected_components.rb +38 -30
  22. data/lib/rgl/dijkstra.rb +158 -0
  23. data/lib/rgl/dijkstra_visitor.rb +42 -0
  24. data/lib/rgl/dot.rb +40 -32
  25. data/lib/rgl/edge_properties_map.rb +55 -0
  26. data/lib/rgl/edmonds_karp.rb +136 -0
  27. data/lib/rgl/enumerable_ext.rb +4 -1
  28. data/lib/rgl/graph_iterator.rb +15 -0
  29. data/lib/rgl/graph_visitor.rb +138 -0
  30. data/lib/rgl/graph_wrapper.rb +15 -0
  31. data/lib/rgl/graphxml.rb +20 -10
  32. data/lib/rgl/implicit.rb +68 -66
  33. data/lib/rgl/mutable.rb +37 -31
  34. data/lib/rgl/path_builder.rb +40 -0
  35. data/lib/rgl/prim.rb +52 -0
  36. data/lib/rgl/rdot.rb +411 -374
  37. data/lib/rgl/topsort.rb +23 -16
  38. data/lib/rgl/transitivity.rb +29 -27
  39. data/lib/rgl/traversal.rb +67 -205
  40. data/rakelib/dep_graph.rake +4 -3
  41. data/test/bellman_ford_test.rb +187 -0
  42. data/test/bipartite_test.rb +47 -0
  43. data/test/components_test.rb +80 -0
  44. data/test/cycles_test.rb +60 -0
  45. data/test/dijkstra_test.rb +148 -0
  46. data/test/directed_graph_test.rb +118 -0
  47. data/test/dot_test.rb +26 -0
  48. data/test/edge_properties_map_test.rb +63 -0
  49. data/test/edge_test.rb +35 -0
  50. data/test/edmonds_karp_test.rb +105 -0
  51. data/{tests/TestGraph.rb → test/graph_test.rb} +6 -6
  52. data/test/graph_xml_test.rb +57 -0
  53. data/test/implicit_test.rb +53 -0
  54. data/test/prim_test.rb +98 -0
  55. data/{tests/TestRdot.rb → test/rdot_test.rb} +309 -308
  56. data/{tests → test}/test_helper.rb +4 -1
  57. data/{tests/TestTransitivity.rb → test/transitivity_test.rb} +43 -43
  58. data/test/traversal_test.rb +221 -0
  59. data/test/undirected_graph_test.rb +103 -0
  60. metadata +226 -145
  61. data/examples/example.jpg +0 -0
  62. data/examples/module_graph.jpg +0 -0
  63. data/install.rb +0 -49
  64. data/tests/TestComponents.rb +0 -65
  65. data/tests/TestCycles.rb +0 -61
  66. data/tests/TestDirectedGraph.rb +0 -125
  67. data/tests/TestDot.rb +0 -18
  68. data/tests/TestEdge.rb +0 -34
  69. data/tests/TestGraphXML.rb +0 -57
  70. data/tests/TestImplicit.rb +0 -52
  71. data/tests/TestTraversal.rb +0 -220
  72. data/tests/TestUnDirectedGraph.rb +0 -102
@@ -1,15 +1,15 @@
1
1
  # adjacency.rb
2
- #
3
- # $Id: adjacency.rb,v 1.12 2008/08/23 05:37:05 javanthropus Exp $
4
- #
2
+ #
3
+ # $Id$
4
+ #
5
5
  # The DirectedAdjacencyGraph class implements a generalized adjacency list
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
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. This can be configured by the client, however, when an AdjacencyGraph
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.[] (*a)
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. The default edgelist class is Set, to ensure
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
- def initialize (edgelist_class = Set, *other_graphs)
41
+ #
42
+ def initialize(edgelist_class = Set, *other_graphs)
42
43
  @edgelist_class = edgelist_class
43
- @vertice_dict = Hash.new
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 vertice_dict
51
+ # Copy internal vertices_dict
52
+ #
51
53
  def initialize_copy(orig)
52
- @vertice_dict = orig.instance_eval{@vertice_dict}.dup
53
- @vertice_dict.keys.each do |v|
54
- @vertice_dict[v] = @vertice_dict[v].dup
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 vertice list hash.
59
-
60
- def each_vertex (&b)
61
- @vertice_dict.each_key(&b)
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 (v, &b) # :nodoc:
65
- adjacency_list = (@vertice_dict[v] or
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
- @vertice_dict.has_key?(v)
81
+ @vertices_dict.has_key?(v)
81
82
  end
82
83
 
83
- # Complexity is O(1), if a Set is used as adjacency list. Otherwise,
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) and @vertice_dict[u].include?(v)
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 (v)
99
- @vertice_dict[v] ||= @edgelist_class.new
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 (u, v)
105
- add_vertex(u) # ensure key
106
- add_vertex(v) # ensure key
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 (u, v)
123
- @vertice_dict[u].delete(v) unless @vertice_dict[u].nil?
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 contructor which accepts an enumerable as
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
- @vertice_dict.keys.each do |v|
131
- @vertice_dict[v] = klass.new @vertice_dict[v].to_a
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 (u, v)
138
- @vertice_dict[u].add(v)
138
+ def basic_add_edge(u, v)
139
+ @vertices_dict[u].add(v)
139
140
  end
140
141
 
141
- end # class DirectedAdjacencyGraph
142
+ end # class DirectedAdjacencyGraph
142
143
 
143
- # AdjacencyGraph is an undirected Graph. The methods add_edge and
144
- # remove_edge are reimplemented: If an edge (u,v) is added or removed,
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
- class AdjacencyGraph < DirectedAdjacencyGraph
148
-
149
- def directed? # Always returns false.
150
+ # Always returns false.
151
+ #
152
+ def directed?
150
153
  false
151
154
  end
152
-
153
- # Also removes (v,u)
154
155
 
155
- def remove_edge (u, v)
156
+ # Also removes (v,u)
157
+ #
158
+ def remove_edge(u, v)
156
159
  super
157
- @vertice_dict[v].delete(u) unless @vertice_dict[v].nil?
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 (u,v)
165
+ def basic_add_edge(u, v)
163
166
  super
164
- @vertice_dict[v].add(u) # Insert backwards edge
167
+ @vertices_dict[v].add(u) # Insert backwards edge
165
168
  end
166
169
 
167
- end # class AdjacencyGraph
170
+ end # class AdjacencyGraph
168
171
 
169
172
  module Graph
170
173
 
171
- # Convert a general graph to an AdjacencyGraph. If the graph is directed,
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. If (u,v)
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 # module Graph
206
- end # module RGL
208
+ end # module Graph
209
+
210
+ end # module RGL
@@ -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.4.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
- # Module Edge includes classes for representing egdes of directed and
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 DirecteEdge or UnDirectedEdge instances are returned
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
- def initialize (a,b)
36
- @source, @target = a,b
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 and target == edge.target
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
- def [](index); index.zero? ? source : target; end
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
- def to_a; [source,target]; end
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
- end # DirectedEdge
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 or (target == edge.source and source == edge.target)
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
- def to_s; "(#{source}=#{target})"; end
103
+ #
104
+ def to_s
105
+ "(#{source}=#{target})"
106
+ end
107
+
81
108
  end
82
109
 
83
- end # Edge
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
- # concepts, which would complicate the interface too much. These concepts are
89
- # defined in BGL to differentiate between efficient access to edges and
90
- # vertices.
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
- # all the graph concepts. These include, especially, the iterators defining
94
- # the sets of vertices and edges (see each_vertex and each_adjacent). Most
95
- # other functions are derived from these fundamental iterators, i.e.
96
- # num_vertices or num_edges.
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
- def each_vertex () # :yields: v
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
- def each_adjacent (v) # :yields: v
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
- def each_edge (&block)
154
+ #
155
+ def each_edge(&block)
125
156
  if directed?
126
- each_vertex { |u|
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) # concrete graphs should to this better
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
- # === Testing
137
- def each(&block); each_vertex(&block); end
166
+ #
167
+ def each(&block)
168
+ each_vertex(&block)
169
+ end
138
170
 
139
171
  # Is the graph directed? The default returns false.
140
- def directed?; false; end
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
- def has_vertex?(v); include?(v); end # inherited from enumerable
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
- # === accessing vertices and edges
150
- def empty?; num_vertices.zero?; end
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
- def vertices; to_a; end
192
+ #
193
+ def vertices
194
+ to_a
195
+ end
154
196
 
155
197
  # Returns the class for edges: DirectedEdge or UnDirectedEdge.
156
- def edge_class; directed? ? DirectedEdge : UnDirectedEdge; end
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
- def adjacent_vertices (v)
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
- # incident edges (for undirected graphs) of vertex _v_.
176
- def out_degree (v)
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
- def size() # Why not in Enumerable?
230
+ #
231
+ def size # Why not in Enumerable?
184
232
  inject(0) { |n, v| n + 1 }
185
233
  end
186
- alias :num_vertices :size
234
+
235
+ alias num_vertices size
187
236
 
188
237
  # Returns the number of edges.
189
- def num_edges; r = 0; each_edge {|u,v| r +=1}; r; end
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.to_s
194
- end
195
-
196
- # Equality is defined to be same set of edges and directed?
197
- def eql?(g)
198
- equal?(g) or
199
- begin
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
- each_vertex { |u|
217
- each_adjacent(u) { |v|
218
- edge = UnDirectedEdge.new u,v
219
- unless visited.has_key? edge
220
- visited[edge]=true
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 # module RGL
309
+ end # module Graph
229
310
 
311
+ end # module RGL