rgl 0.4.0 → 0.5.0

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