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,6 +1,6 @@
1
1
  # topsort.rb
2
2
 
3
- require 'rgl/traversal'
3
+ require 'rgl/graph_iterator'
4
4
 
5
5
  module RGL
6
6
 
@@ -11,19 +11,19 @@ module RGL
11
11
  # the ordering. The graph must be a directed acyclic graph (DAG).
12
12
  #
13
13
  # The iterator can also be applied to undirected graph or to a DG graph
14
- # which contains a cycle. In this case, the Iterator does not reach all
15
- # vertices. The implementation of acyclic? uses this fact.
16
-
14
+ # which contains a cycle. In this case, the Iterator does not reach all
15
+ # vertices. The implementation of acyclic? uses this fact.
16
+ #
17
17
  class TopsortIterator
18
18
 
19
19
  include GraphIterator
20
20
 
21
- def initialize (g)
21
+ def initialize(g)
22
22
  super(g)
23
23
  set_to_begin
24
24
  end
25
25
 
26
- def set_to_begin # :nodoc:
26
+ def set_to_begin # :nodoc:
27
27
  @waiting = Array.new
28
28
  @inDegrees = Hash.new(0)
29
29
 
@@ -39,7 +39,7 @@ module RGL
39
39
  end
40
40
  end
41
41
 
42
- def basic_forward # :nodoc:
42
+ def basic_forward # :nodoc:
43
43
  u = @waiting.pop
44
44
  graph.each_adjacent(u) do |v|
45
45
  @inDegrees[v] -= 1
@@ -48,25 +48,32 @@ module RGL
48
48
  u
49
49
  end
50
50
 
51
- def at_beginning?; true; end # :nodoc: FIXME
52
- def at_end?; @waiting.empty?; end # :nodoc:
51
+ def at_beginning?
52
+ true
53
+ end
54
+
55
+ # :nodoc: FIXME
56
+ def at_end?
57
+ @waiting.empty?
58
+ end # :nodoc:
53
59
 
54
- end # class TopsortIterator
60
+ end # class TopsortIterator
55
61
 
56
62
  module Graph
57
63
 
58
64
  # Returns a TopsortIterator.
59
-
65
+ #
60
66
  def topsort_iterator
61
67
  TopsortIterator.new(self)
62
68
  end
63
-
64
- # Returns true if the graph contains no cycles. This is only meaningful
65
- # for directed graphs. Returns false for undirected graphs.
66
69
 
70
+ # Returns true if the graph contains no cycles. This is only meaningful
71
+ # for directed graphs. Returns false for undirected graphs.
72
+ #
67
73
  def acyclic?
68
74
  topsort_iterator.length == num_vertices
69
75
  end
70
76
 
71
- end # module Graph
72
- end # module RGL
77
+ end # module Graph
78
+
79
+ end # module RGL
@@ -1,14 +1,14 @@
1
- require 'enumerator'
2
-
3
- require 'rgl/adjacency'
4
1
  require 'rgl/base'
2
+ require 'rgl/adjacency'
5
3
  require 'rgl/condensation'
6
4
 
7
5
  module RGL
6
+
8
7
  module Graph
8
+
9
9
  # Returns an RGL::DirectedAdjacencyGraph which is the transitive closure of
10
- # this graph. Meaning, for each path u -> ... -> v in this graph, the path
11
- # is copied and the edge u -> v is added. This method supports working with
10
+ # this graph. Meaning, for each path u -> ... -> v in this graph, the path
11
+ # is copied and the edge u -> v is added. This method supports working with
12
12
  # cyclic graphs by ensuring that edges are created between every pair of
13
13
  # vertices in the cycle, including self-referencing edges.
14
14
  #
@@ -16,17 +16,18 @@ module RGL
16
16
  # of vertices and edges respectively.
17
17
  #
18
18
  # Raises RGL::NotDirectedError if run on an undirected graph.
19
+ #
19
20
  def transitive_closure
20
21
  raise NotDirectedError,
21
- "transitive_closure only supported for directed graphs" unless directed?
22
+ "transitive_closure only supported for directed graphs" unless directed?
22
23
 
23
24
  # Compute a condensation graph in order to hide cycles.
24
25
  cg = condensation_graph
25
26
 
26
27
  # Use a depth first search to calculate the transitive closure over the
27
- # condensation graph. This ensures that as we traverse up the graph we
28
+ # condensation graph. This ensures that as we traverse up the graph we
28
29
  # know the transitive closure of each subgraph rooted at each node
29
- # starting at the leaves. Subsequent root nodes which consume these
30
+ # starting at the leaves. Subsequent root nodes which consume these
30
31
  # subgraphs by way of the nodes' immediate successors can then immediately
31
32
  # add edges to the roots of the subgraphs and to every successor of those
32
33
  # roots.
@@ -52,7 +53,7 @@ module RGL
52
53
  # For each NON-trivial strongly connected component in the condensed
53
54
  # graph, add each node it contains to the new graph and add edges to
54
55
  # every node in the strongly connected component, including self
55
- # referential edges. Then for each edge of the original graph from any
56
+ # referential edges. Then for each edge of the original graph from any
56
57
  # of the contained nodes, add edges from each of the contained nodes to
57
58
  # all the edge targets.
58
59
  g = DirectedAdjacencyGraph.new
@@ -61,7 +62,7 @@ module RGL
61
62
  # Add edges between all members of non-trivial strongly connected
62
63
  # components (size > 1) and ensure that self referential edges are
63
64
  # added when necessary for trivial strongly connected components.
64
- if scc.size > 1 || has_edge?(v, v) then
65
+ if scc.size > 1 || has_edge?(v, v)
65
66
  scc.each do |w|
66
67
  g.add_edge(v, w)
67
68
  end
@@ -86,8 +87,8 @@ module RGL
86
87
  end
87
88
 
88
89
  # Returns an RGL::DirectedAdjacencyGraph which is the transitive reduction
89
- # of this graph. Meaning, that each edge u -> v is omitted if path
90
- # u -> ... -> v exists. This method supports working with cyclic graphs;
90
+ # of this graph. Meaning, that each edge u -> v is omitted if path
91
+ # u -> ... -> v exists. This method supports working with cyclic graphs;
91
92
  # however, cycles are arbitrarily simplified which may lead to variant,
92
93
  # although equally valid, results on equivalent graphs.
93
94
  #
@@ -95,17 +96,18 @@ module RGL
95
96
  # of vertices and edges respectively.
96
97
  #
97
98
  # Raises RGL::NotDirectedError if run on an undirected graph.
99
+ #
98
100
  def transitive_reduction
99
101
  raise NotDirectedError,
100
- "transitive_reduction only supported for directed graphs" unless directed?
102
+ "transitive_reduction only supported for directed graphs" unless directed?
101
103
 
102
104
  # Compute a condensation graph in order to hide cycles.
103
105
  cg = condensation_graph
104
106
 
105
107
  # Use a depth first search to compute the transitive reduction over the
106
- # condensed graph. This is similar to the computation of the transitive
108
+ # condensed graph. This is similar to the computation of the transitive
107
109
  # closure over the graph in that for any node of the graph all nodes
108
- # reachable from the node are tracked. Using a depth first search ensures
110
+ # reachable from the node are tracked. Using a depth first search ensures
109
111
  # that all nodes reachable from a target node are known when considering
110
112
  # whether or not to add an edge pointing to that target.
111
113
  tr_cg = DirectedAdjacencyGraph.new
@@ -114,11 +116,9 @@ module RGL
114
116
  paths_from[v] = Set.new
115
117
  cg.each_adjacent(v) do |w|
116
118
  # Only add the edge v -> w if there is no other edge v -> x such that
117
- # w is reachable from x. Make sure to completely skip the case where
119
+ # w is reachable from x. Make sure to completely skip the case where
118
120
  # x == w.
119
- unless Enumerable::Enumerator.new(cg, :each_adjacent, v).any? do |x|
120
- x != w && paths_from[x].include?(w)
121
- end then
121
+ unless cg.to_enum(:each_adjacent, v).any? { |x| x != w && paths_from[x].include?(w) }
122
122
  tr_cg.add_edge(v, w)
123
123
 
124
124
  # For each vertex v, track all nodes reachable from v by adding node
@@ -138,7 +138,7 @@ module RGL
138
138
  # edge the node begins in the original graph.
139
139
  # For each NON-trivial strongly connected component in the condensed
140
140
  # graph, add each node it contains to the new graph and add arbitrary
141
- # edges between the nodes to form a simple cycle. Then for each strongly
141
+ # edges between the nodes to form a simple cycle. Then for each strongly
142
142
  # connected component adjacent to the current one, find and add the first
143
143
  # edge which exists in the original graph, starts in the first strongly
144
144
  # connected component, and ends in the second strongly connected
@@ -148,7 +148,7 @@ module RGL
148
148
  # Make a cycle of the contents of non-trivial strongly connected
149
149
  # components.
150
150
  scc_arr = scc.to_a
151
- if scc.size > 1 || has_edge?(scc_arr.first, scc_arr.first) then
151
+ if scc.size > 1 || has_edge?(scc_arr.first, scc_arr.first)
152
152
  0.upto(scc_arr.size - 2) do |idx|
153
153
  g.add_edge(scc_arr[idx], scc_arr[idx + 1])
154
154
  end
@@ -157,12 +157,12 @@ module RGL
157
157
 
158
158
  # Choose a single edge between the members of two different strongly
159
159
  # connected component to add to the graph.
160
- edges = Enumerable::Enumerator.new(self, :each_edge)
160
+ edges = self.to_enum(:each_edge)
161
161
  tr_cg.each_adjacent(scc) do |scc2|
162
162
  g.add_edge(
163
- *edges.find do |v, w|
164
- scc.member?(v) && scc2.member?(w)
165
- end
163
+ *edges.find do |v, w|
164
+ scc.member?(v) && scc2.member?(w)
165
+ end
166
166
  )
167
167
  end
168
168
 
@@ -175,5 +175,7 @@ module RGL
175
175
  # Finally, the transitive reduction...
176
176
  g
177
177
  end
178
- end # module Graph
179
- end # module RGL
178
+
179
+ end # module Graph
180
+
181
+ end # module RGL
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # This file defines the basic graph traversal algorithm for DFS and BFS search.
4
4
  # They are implemented as an RGL::GraphIterator, which is a Stream of vertices
5
- # of a given graph. The streams are not reversable.
5
+ # of a given graph. The streams are not reversable.
6
6
  #
7
7
  # Beside being an iterator in the sense of the Stream mixin, RGL::BFSIterator
8
8
  # and RGL::DFSIterator follow the BGL
@@ -10,153 +10,24 @@
10
10
  # in a slightly modified fashion (especially for the RGL::DFSIterator).
11
11
 
12
12
  require 'rgl/base'
13
- require 'rubygems' rescue LoadError # If using stream gem
14
- require 'stream'
13
+ require 'rgl/graph_visitor'
14
+ require 'rgl/graph_iterator'
15
15
 
16
16
  module RGL
17
17
 
18
- module GraphWrapper # :nodoc:
19
-
20
- attr_accessor :graph
21
-
22
- # Creates a new GraphWrapper on _graph_.
23
- def initialize (graph)
24
- @graph = graph
25
- end
26
-
27
- end # module GraphWrapper
28
-
29
- # A GraphIterator is the abstract superclass of all Iterators on graphs.
30
- # Each such iterator should implement the protocol defined in module Stream.
31
- module GraphIterator
32
- include Stream
33
- include GraphWrapper
34
- end
35
-
36
- # Module GraphVisitor defines the BGL
37
- # BFS[http://www.boost.org/libs/graph/doc/BFSVisitor.html] Visitor Concept).
38
- #
39
- # Visitors provide a mechanism for extending an algorithm (i.e., for
40
- # customizing what is done at each step of the algorithm). They allow users
41
- # to insert their own operations at various steps within a graph algorithm.
42
- #
43
- # Graph algorithms typically have multiple event points where one may want to
44
- # insert a call-back. Therefore, visitors have several methods that
45
- # correspond to the various event points. Each algorithm has a different
46
- # set of event points. The following are common to both DFS and BFS search.
47
- #
48
- # * examine_vertex
49
- # * finish_vertex
50
- # * examine_edge
51
- # * tree_edge
52
- # * back_edge
53
- # * forward_edge
54
- #
55
- # These methods are all called handle_* and can be set to appropriate blocks,
56
- # using the methods set_*_event_handler, which are defined for each event
57
- # mentioned above.
58
- #
59
- # As an alternative, you can also override the handle_* methods in a
60
- # subclass, to configure the algorithm (as an example, see TarjanSccVisitor).
61
- #
62
- # During a graph traversal, vertices are *colored* using the colors :GRAY
63
- # (when waiting) and :BLACK when finished. All other vertices are :WHITE.
64
- # The color_map is also maintained in the visitor.
65
-
66
- module GraphVisitor
67
-
68
- include GraphWrapper
69
-
70
- attr_reader :color_map
71
-
72
- # Create a new GraphVisitor on _graph_.
73
-
74
- def initialize (graph)
75
- super graph
76
- reset
77
- end
78
-
79
- # Mark each vertex unvisited (i.e. :WHITE)
80
-
81
- def reset
82
- @color_map = Hash.new(:WHITE)
83
- end
84
-
85
- # Returns true if vertex _v_ is colored :BLACK (i.e. finished).
86
-
87
- def finished_vertex? (v)
88
- @color_map[v] == :BLACK
89
- end
90
-
91
- # Attach a map to the visitor which records the distance of a visited
92
- # vertex to the start vertex.
93
- #
94
- # This is similar to BGLs
95
- # distance_recorder[http://www.boost.org/libs/graph/doc/distance_recorder.html].
96
- #
97
- # After the distance_map is attached, the visitor has a new method
98
- # distance_to_root, which answers the distance to the start vertex.
99
-
100
- def attach_distance_map (map = Hash.new(0))
101
- @dist_map = map
102
-
103
- class << self
104
-
105
- def handle_tree_edge (u, v)
106
- super
107
- @dist_map[v] = @dist_map[u] + 1
108
- end
109
-
110
- # Answer the distance to the start vertex.
111
-
112
- def distance_to_root (v)
113
- @dist_map[v]
114
- end
115
-
116
- end # class
117
- end
118
-
119
- # Shall we follow the edge (u,v); i.e. v has color :WHITE
120
-
121
- def follow_edge? (u, v) # :nodoc:
122
- @color_map[v] == :WHITE
123
- end
124
-
125
- # == Visitor Event Points
126
-
127
- def self.def_event_handler (m)
128
- params = m =~ /edge/ ? "u,v" : "u"
129
- self.class_eval %{
130
- def handle_#{m} (#{params})
131
- @#{m}_event_handler.call(#{params}) if defined? @#{m}_event_handler
132
- end
133
-
134
- def set_#{m}_event_handler (&b)
135
- @#{m}_event_handler = b
136
- end
137
- }
138
- end
139
-
140
- %w[examine_vertex finish_vertex examine_edge tree_edge back_edge
141
- forward_edge].each do |m|
142
- def_event_handler(m)
143
- end
144
-
145
- end # module GraphVisitor
146
-
147
18
  # A BFSIterator can be used to traverse a graph from a given start vertex in
148
- # breath first search order. Since the Iterator also mixins the GraphVisitor,
19
+ # breath first search order. Since the Iterator also mixins the GraphVisitor,
149
20
  # it provides all event points defined there.
150
21
  #
151
22
  # The vertices which are not yet visited are held in the queue @waiting.
152
23
  # During the traversal, vertices are *colored* using the colors :GRAY
153
- # (when waiting) and :BLACK when finished. All other vertices are :WHITE.
24
+ # (when waiting) and :BLACK when finished. All other vertices are :WHITE.
154
25
  #
155
26
  # For more doc see the BGL
156
27
  # BFS[http://www.boost.org/libs/graph/doc/BFSVisitor.html] Visitor Concept .
157
28
  #
158
29
  # See the implementation of bfs_search_tree_from for an example usage.
159
-
30
+ #
160
31
  class BFSIterator
161
32
 
162
33
  include GraphIterator
@@ -165,96 +36,99 @@ module RGL
165
36
  attr_accessor :start_vertex
166
37
 
167
38
  # Create a new BFSIterator on _graph_, starting at vertex _start_.
168
-
169
- def initialize (graph, start=graph.detect{ |x| true })
39
+ #
40
+ def initialize(graph, start = graph.detect { |x| true })
170
41
  super(graph)
171
42
  @start_vertex = start
172
43
  set_to_begin
173
44
  end
174
45
 
175
46
  # Returns true if the @color_map has only one entry (for the start vertex).
176
-
177
- def at_beginning? # :nodoc:
47
+ #
48
+ def at_beginning? # :nodoc:
178
49
  @color_map.size == 1
179
50
  end
180
-
181
- # Returns true if @waiting is empty.
182
51
 
52
+ # Returns true if @waiting is empty.
53
+ #
183
54
  def at_end?
184
55
  @waiting.empty?
185
56
  end
186
57
 
187
58
  # Reset the iterator to the initial state (i.e. at_beginning? == true).
188
-
59
+ #
189
60
  def set_to_begin
190
61
  color_map[@start_vertex] = :GRAY
191
- @waiting = [@start_vertex] # a queue
192
- handle_tree_edge(nil, @start_vertex) # discovers start vertex
62
+ @waiting = [@start_vertex] # a queue
63
+ handle_tree_edge(nil, @start_vertex) # discovers start vertex
193
64
  end
194
65
 
195
- def basic_forward # :nodoc:
66
+ def basic_forward # :nodoc:
196
67
  u = next_vertex
197
68
  handle_examine_vertex(u)
198
- graph.each_adjacent(u) { |v|
69
+
70
+ graph.each_adjacent(u) do |v|
199
71
  handle_examine_edge(u, v)
200
- if follow_edge?(u, v) # (u,v) is a tree edge
201
- handle_tree_edge(u, v) # also discovers v
202
- color_map[v] = :GRAY # color of v was :WHITE
72
+ if follow_edge?(u, v) # (u,v) is a tree edge
73
+ handle_tree_edge(u, v) # also discovers v
74
+ color_map[v] = :GRAY # color of v was :WHITE
203
75
  @waiting.push(v)
204
- else # (u,v) is a non tree edge
76
+ else # (u,v) is a non tree edge
205
77
  if color_map[v] == :GRAY
206
- handle_back_edge(u, v) # (u,v) has gray target
78
+ handle_back_edge(u, v) # (u,v) has gray target
207
79
  else
208
- handle_forward_edge(u, v) # (u,v) has black target
80
+ handle_forward_edge(u, v) # (u,v) has black target
209
81
  end
210
82
  end
211
- }
83
+ end
84
+
212
85
  color_map[u] = :BLACK
213
- handle_finish_vertex(u) # finish vertex
86
+ handle_finish_vertex(u) # finish vertex
214
87
  u
215
88
  end
216
89
 
217
90
  protected
218
91
 
219
- def next_vertex # :nodoc:
92
+ def next_vertex # :nodoc:
220
93
  # waiting is a queue
221
94
  @waiting.shift
222
95
  end
223
- end # class BFSIterator
224
96
 
97
+ end # class BFSIterator
225
98
 
226
99
  module Graph
227
100
 
228
101
  # Returns a BFSIterator, starting at vertex _v_.
229
102
 
230
- def bfs_iterator (v = self.detect { |x| true})
103
+ def bfs_iterator(v = self.detect { |x| true })
231
104
  BFSIterator.new(self, v)
232
105
  end
233
106
 
234
107
  # Returns a DirectedAdjacencyGraph, which represents a BFS search tree
235
- # starting at _v_. This method uses the tree_edge_event of BFSIterator
108
+ # starting at _v_. This method uses the tree_edge_event of BFSIterator
236
109
  # to record all tree edges of the search tree in the result.
237
110
 
238
- def bfs_search_tree_from (v)
111
+ def bfs_search_tree_from(v)
239
112
  require 'rgl/adjacency'
240
113
  bfs = bfs_iterator(v)
241
114
  tree = DirectedAdjacencyGraph.new
242
- bfs.set_tree_edge_event_handler { |from, to|
115
+
116
+ bfs.set_tree_edge_event_handler do |from, to|
243
117
  tree.add_edge(from, to)
244
- }
245
- bfs.set_to_end # does the search
118
+ end
119
+
120
+ bfs.set_to_end # does the search
246
121
  tree
247
122
  end
248
123
 
249
- end # module Graph
124
+ end # module Graph
250
125
 
251
-
252
- # Iterator for a depth first search, starting at a given vertex. The only
126
+ # Iterator for a depth first search, starting at a given vertex. The only
253
127
  # difference from BFSIterator is that @waiting is a stack, instead of a queue.
254
128
  #
255
129
  # Note that this is different from DFSVisitor, which is used in the recursive
256
130
  # version for depth first search (see depth_first_search).
257
-
131
+ #
258
132
  class DFSIterator < BFSIterator
259
133
 
260
134
  def next_vertex
@@ -262,11 +136,10 @@ module RGL
262
136
  @waiting.pop
263
137
  end
264
138
 
265
- end # class DFSIterator
266
-
139
+ end # class DFSIterator
267
140
 
268
141
  # A DFSVisitor is needed by the depth_first_search and depth_first_visit
269
- # methods of a graph. Besides the eventpoint of GraphVisitor, it provides
142
+ # methods of a graph. Besides the eventpoint of GraphVisitor, it provides
270
143
  # an additional eventpoint start_vertex, which is called when a
271
144
  # depth_first_search starts a new subtree of the depth first forest that is
272
145
  # defined by the search.
@@ -275,29 +148,28 @@ module RGL
275
148
  # DFSVisitor[http://www.boost.org/libs/graph/doc/DFSVisitor.html] is not
276
149
  # this is also defined in the common mixin GraphVisitor of DFSVisitor,
277
150
  # DFSIterator, and BFSIterator.
278
-
151
+ #
279
152
  class DFSVisitor
280
153
 
281
154
  include GraphVisitor
282
155
 
283
- GraphVisitor.def_event_handler("start_vertex")
284
-
285
- end # class DFSVisitor
156
+ def_event_handler 'start_vertex'
286
157
 
158
+ end # class DFSVisitor
287
159
 
288
160
  module Graph
289
161
 
290
162
  # Returns a DFSIterator staring at vertex _v_.
291
163
 
292
- def dfs_iterator (v = self.detect { |x| true })
164
+ def dfs_iterator(v = self.detect { |x| true })
293
165
  DFSIterator.new(self, v)
294
166
  end
295
167
 
296
- # Do a recursive DFS search on the whole graph. If a block is passed,
297
- # it is called on each _finish_vertex_ event. See
168
+ # Do a recursive DFS search on the whole graph. If a block is passed,
169
+ # it is called on each _finish_vertex_ event. See
298
170
  # strongly_connected_components for an example usage.
299
-
300
- def depth_first_search (vis = DFSVisitor.new(self), &b)
171
+ #
172
+ def depth_first_search(vis = DFSVisitor.new(self), &b)
301
173
  each_vertex do |u|
302
174
  unless vis.finished_vertex?(u)
303
175
  vis.handle_start_vertex(u)
@@ -306,44 +178,34 @@ module RGL
306
178
  end
307
179
  end
308
180
 
309
- # Start a depth first search at vertex _u_. The block _b_ is called on
181
+ # Start a depth first search at vertex _u_. The block _b_ is called on
310
182
  # each finish_vertex event.
311
-
312
- def depth_first_visit (u, vis = DFSVisitor.new(self), &b)
183
+ #
184
+ def depth_first_visit(u, vis = DFSVisitor.new(self), &b)
313
185
  vis.color_map[u] = :GRAY
314
186
  vis.handle_examine_vertex(u)
315
- each_adjacent(u) { |v|
187
+
188
+ each_adjacent(u) do |v|
316
189
  vis.handle_examine_edge(u, v)
317
- if vis.follow_edge?(u, v) # (u,v) is a tree edge
318
- vis.handle_tree_edge(u, v) # also discovers v
319
- vis.color_map[v] = :GRAY # color of v was :WHITE
190
+
191
+ if vis.follow_edge?(u, v) # (u,v) is a tree edge
192
+ vis.handle_tree_edge(u, v) # also discovers v
193
+ vis.color_map[v] = :GRAY # color of v was :WHITE
320
194
  depth_first_visit(v, vis, &b)
321
- else # (u,v) is a non tree edge
195
+ else # (u,v) is a non tree edge
322
196
  if vis.color_map[v] == :GRAY
323
- vis.handle_back_edge(u, v) # (u,v) has gray target
197
+ vis.handle_back_edge(u, v) # (u,v) has gray target
324
198
  else
325
- vis.handle_forward_edge(u, v) # (u,v) is a cross or forward edge
199
+ vis.handle_forward_edge(u, v) # (u,v) is a cross or forward edge
326
200
  end
327
201
  end
328
- }
202
+ end
203
+
329
204
  vis.color_map[u] = :BLACK
330
- vis.handle_finish_vertex(u) # finish vertex
205
+ vis.handle_finish_vertex(u) # finish vertex
331
206
  b.call(u)
332
207
  end
333
208
 
334
- end # module Graph
335
-
336
- =begin
337
- def acyclic?
338
- has_cycle = false
339
- dfs = DFSIterator.new(self)
340
- dfs.set_back_edge_event {has_cycle = true}
341
- dfs_each(dfs) do |x|
342
- puts x,has_cycle,dfs.inspect
343
- return false if has_cycle
344
- end
345
- true
346
- end
347
- =end
209
+ end # module Graph
348
210
 
349
- end # module RGL
211
+ end # module RGL