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,13 +1,16 @@
1
1
  module Enumerable
2
+
2
3
  # Fixnum()
3
4
  #
4
5
  # Return the number of elements of the Enumerable. Same as _size_ but not all
5
6
  # Enumerables implement size.
6
7
  #--
7
8
  # Should we call the methods _size_?
9
+ #
8
10
  def length
9
- inject(0) do |sum,v|
11
+ inject(0) do |sum, v|
10
12
  sum + 1
11
13
  end
12
14
  end
15
+
13
16
  end
@@ -0,0 +1,15 @@
1
+ require 'stream'
2
+
3
+ require 'rgl/graph_wrapper'
4
+
5
+ module RGL
6
+
7
+ # A GraphIterator is the abstract basis for all Iterators on graphs.
8
+ # Each graph iterator should implement the protocol defined in module Stream.
9
+ #
10
+ module GraphIterator
11
+ include Stream
12
+ include GraphWrapper
13
+ end
14
+
15
+ end # RGL
@@ -0,0 +1,138 @@
1
+ require 'rgl/graph_wrapper'
2
+
3
+ module RGL
4
+
5
+ # Module GraphVisitor defines the BGL
6
+ # BFS[http://www.boost.org/libs/graph/doc/BFSVisitor.html] Visitor Concept).
7
+ #
8
+ # Visitors provide a mechanism for extending an algorithm (i.e., for
9
+ # customizing what is done at each step of the algorithm). They allow users
10
+ # to insert their own operations at various steps within a graph algorithm.
11
+ #
12
+ # Graph algorithms typically have multiple event points where one may want to
13
+ # insert a call-back. Therefore, visitors have several methods that
14
+ # correspond to the various event points. Each algorithm has a different
15
+ # set of event points. The following are common to both DFS and BFS search.
16
+ #
17
+ # * examine_vertex
18
+ # * examine_edge
19
+ # * tree_edge
20
+ # * back_edge
21
+ # * forward_edge
22
+ # * finish_vertex
23
+ #
24
+ # These methods are all called handle_* and can be set to appropriate blocks,
25
+ # using the methods set_*_event_handler, which are defined for each event
26
+ # mentioned above.
27
+ #
28
+ # As an alternative, you can also override the handle_* methods in a
29
+ # subclass, to configure the algorithm (as an example, see TarjanSccVisitor).
30
+ #
31
+ # During a graph traversal, vertices are *colored* using the colors :GRAY
32
+ # (when waiting) and :BLACK when finished. All other vertices are :WHITE.
33
+ # The color_map is also maintained in the visitor.
34
+ #
35
+ module GraphVisitor
36
+
37
+ include GraphWrapper
38
+
39
+ attr_reader :color_map
40
+
41
+ # Create a new GraphVisitor on _graph_.
42
+ #
43
+ def initialize(graph)
44
+ super(graph)
45
+ reset
46
+ end
47
+
48
+ # Mark each vertex unvisited (i.e. :WHITE)
49
+ #
50
+ def reset
51
+ @color_map = Hash.new(:WHITE)
52
+ end
53
+
54
+ # Returns true if vertex _v_ is colored :BLACK (i.e. finished).
55
+ #
56
+ def finished_vertex?(v)
57
+ @color_map[v] == :BLACK
58
+ end
59
+
60
+ # Shall we follow the edge (u,v); i.e. v has color :WHITE
61
+ #
62
+ def follow_edge?(u, v) # :nodoc:
63
+ @color_map[v] == :WHITE
64
+ end
65
+
66
+ # Attach a map to the visitor which records the distance of a visited
67
+ # vertex to the start vertex.
68
+ #
69
+ # This is similar to BGLs
70
+ # distance_recorder[http://www.boost.org/libs/graph/doc/distance_recorder.html].
71
+ #
72
+ # After the distance_map is attached, the visitor has a new method
73
+ # distance_to_root, which answers the distance to the start vertex.
74
+ #
75
+ def attach_distance_map(map = Hash.new(0))
76
+ @distance_map = map
77
+
78
+ # add distance map support to the current visitor instance
79
+ extend(DistanceMapSupport)
80
+ end
81
+
82
+ module DistanceMapSupport
83
+
84
+ def handle_tree_edge(u, v)
85
+ super
86
+ @distance_map[v] = @distance_map[u] + 1
87
+ end
88
+
89
+ # Answer the distance to the start vertex.
90
+
91
+ def distance_to_root(v)
92
+ @distance_map[v]
93
+ end
94
+
95
+ end # module DistanceMapSupport
96
+
97
+ module ClassMethods
98
+
99
+ # Defines an event handler.
100
+ #
101
+ def def_event_handlers(*events)
102
+ events.each do |event|
103
+ params = event.to_s.include?('edge') ? 'u, v' : 'u'
104
+
105
+ handler = "@#{event}_event_handler"
106
+
107
+ class_eval <<-END
108
+ def handle_#{event}(#{params})
109
+ #{handler}.call(#{params}) if defined? #{handler}
110
+ end
111
+
112
+ def set_#{event}_event_handler(&block)
113
+ #{handler} = block
114
+ end
115
+ END
116
+ end
117
+ end
118
+
119
+ alias def_event_handler def_event_handlers
120
+
121
+ end # module ClassMethods
122
+
123
+ extend ClassMethods # add class methods to GraphVisitor class itself
124
+
125
+ def self.included(base)
126
+ base.extend ClassMethods # when GraphVisitor is included into a class/module, add class methods as well
127
+ end
128
+
129
+ def_event_handlers :examine_vertex,
130
+ :examine_edge,
131
+ :tree_edge,
132
+ :back_edge,
133
+ :forward_edge,
134
+ :finish_vertex
135
+
136
+ end # module GraphVisitor
137
+
138
+ end # module RGL
@@ -0,0 +1,15 @@
1
+ module RGL
2
+
3
+ module GraphWrapper # :nodoc:
4
+
5
+ attr_accessor :graph
6
+
7
+ # Creates a new GraphWrapper on _graph_.
8
+ #
9
+ def initialize(graph)
10
+ @graph = graph
11
+ end
12
+
13
+ end # module GraphWrapper
14
+
15
+ end # RGL
@@ -1,7 +1,7 @@
1
1
  # graphxml.rb
2
2
  #
3
3
  # This file contains minimal support for creating RGL graphs from the GraphML
4
- # format (see http://www.graphdrawing.org/graphml). The main purpose is to
4
+ # format (see http://www.graphdrawing.org/graphml). The main purpose is to
5
5
  # have a rich set of example graphs to have some more tests.
6
6
  #
7
7
  # See the examples directory, which contains a subdirectory _north_ with the
@@ -16,36 +16,46 @@ require 'rexml/document'
16
16
  require 'rexml/streamlistener'
17
17
 
18
18
  module RGL
19
+
19
20
  module MutableGraph
21
+
20
22
  # Used to parse a subset of GraphML into an RGL graph implementation.
23
+ #
21
24
  class MutableGraphParser
25
+
22
26
  include REXML::StreamListener
23
27
 
24
28
  # First resets +graph+ to be empty and stores a reference for use with
25
29
  # #tag_start.
26
- def initialize (graph)
30
+ #
31
+ def initialize(graph)
27
32
  @graph = graph
28
33
  @graph.remove_vertices(@graph.vertices)
29
34
  end
30
35
 
31
36
  # Processes incoming edge and node elements from GraphML in order to
32
37
  # populate the graph given to #new.
33
- def tag_start (name, attrs)
38
+ #
39
+ def tag_start(name, attrs)
34
40
  case name
35
- when 'edge'
36
- @graph.add_edge(attrs['source'], attrs['target'])
37
- when 'node'
38
- @graph.add_vertex(attrs['id'])
41
+ when 'edge'
42
+ @graph.add_edge(attrs['source'], attrs['target'])
43
+ when 'node'
44
+ @graph.add_vertex(attrs['id'])
39
45
  end
40
46
  end
41
- end # class MutableGraphParser
47
+
48
+ end # class MutableGraphParser
42
49
 
43
50
  # Initializes an RGL graph from a subset of the GraphML format given in
44
51
  # +source+ (see http://www.graphdrawing.org/graphml).
52
+ #
45
53
  def from_graphxml(source)
46
54
  listener = MutableGraphParser.new(self)
47
55
  REXML::Document.parse_stream(source, listener)
48
56
  self
49
57
  end
50
- end # module MutableGraph
51
- end # module RGL
58
+
59
+ end # module MutableGraph
60
+
61
+ end # module RGL
@@ -1,19 +1,19 @@
1
- # implicit.rb
1
+ # implicit.rb
2
2
  #
3
3
  # This file contains the definition of the class RGL::ImplicitGraph, which
4
4
  # defines vertex and edge iterators using blocks (which again call blocks).
5
- #
5
+ #
6
6
  # An ImplicitGraph provides a handy way to define graphs on the fly, using two
7
- # blocks for the two iterators defining a graph. A directed cyclic graph,
7
+ # blocks for the two iterators defining a graph. A directed cyclic graph,
8
8
  # with five vertices can be created as follows:
9
9
  #
10
- # g = RGL::ImplicitGraph.new { |g|
10
+ # g = RGL::ImplicitGraph.new do |g|
11
11
  # g.vertex_iterator { |b| 0.upto(4,&b) }
12
12
  # g.adjacent_iterator { |x, b| b.call((x+1)%5) }
13
13
  # g.directed = true
14
- # }
14
+ # end
15
15
  #
16
- # g.to_s => "(0-1)(1-2)(2-3)(3-4)(4-0)"
16
+ # g.to_s # => "(0-1)(1-2)(2-3)(3-4)(4-0)"
17
17
  #
18
18
  # Other examples are given by the methods vertices_filtered_by and
19
19
  # edges_filtered_by, which can be applied to any graph.
@@ -28,110 +28,109 @@ module RGL
28
28
 
29
29
  attr_writer :directed
30
30
 
31
- EMPTY_VERTEX_ITERATOR = proc { |b| }
31
+ EMPTY_VERTEX_ITERATOR = proc { |b| }
32
32
  EMPTY_NEIGHBOR_ITERATOR = proc { |x, b| }
33
-
34
- # Create a new ImplicitGraph, which is empty by default. The caller should
35
- # configure the graph using vertex and neighbor iterators. If the graph is
36
- # directed, the client should set _directed_ to true. The default value
37
- # for _directed_ is false.
38
33
 
34
+ # Create a new ImplicitGraph, which is empty by default. The caller should
35
+ # configure the graph using vertex and neighbor iterators. If the graph is
36
+ # directed, the client should set _directed_ to true. The default value
37
+ # for _directed_ is false.
38
+ #
39
39
  def initialize
40
- @directed = false
40
+ @directed = false
41
41
  @vertex_iterator = EMPTY_VERTEX_ITERATOR
42
42
  @adjacent_iterator = EMPTY_NEIGHBOR_ITERATOR
43
- yield self if block_given? # Let client overwrite defaults.
43
+ yield self if block_given? # Let client overwrite defaults.
44
44
  end
45
45
 
46
46
  # Returns the value of @directed.
47
-
47
+ #
48
48
  def directed?
49
49
  @directed
50
50
  end
51
-
52
- def each_vertex (&block) # :nodoc:
51
+
52
+ def each_vertex(&block) # :nodoc:
53
53
  @vertex_iterator.call(block)
54
54
  end
55
55
 
56
- def each_adjacent (v, &block) # :nodoc:
56
+ def each_adjacent(v, &block) # :nodoc:
57
57
  @adjacent_iterator.call(v, block)
58
58
  end
59
59
 
60
- def each_edge (&block) # :nodoc:
60
+ def each_edge(&block) # :nodoc:
61
61
  if defined? @edge_iterator
62
62
  @edge_iterator.call(block)
63
63
  else
64
- super # use default implementation
64
+ super # use default implementation
65
65
  end
66
66
  end
67
67
 
68
68
  # Sets the vertex_iterator to _block_,
69
69
  # which must be a block of one parameter
70
70
  # which again is the block called by each_vertex.
71
-
72
- def vertex_iterator (&block)
71
+ #
72
+ def vertex_iterator(&block)
73
73
  @vertex_iterator = block
74
74
  end
75
75
 
76
76
  # Sets the adjacent_iterator to _block_,
77
- # which must be a block of two parameters:
77
+ # which must be a block of two parameters:
78
78
  #
79
79
  # The first parameter is the vertex the neighbors of which are to be
80
80
  # traversed.
81
81
  #
82
82
  # The second is the block which will be called for each neighbor
83
83
  # of this vertex.
84
-
85
- def adjacent_iterator (&block)
84
+ #
85
+ def adjacent_iterator(&block)
86
86
  @adjacent_iterator = block
87
87
  end
88
88
 
89
89
  # Sets the edge_iterator to _block_, which must be a block of two
90
90
  # parameters: The first parameter is the source of the edges; the
91
91
  # second is the target of the edge.
92
-
93
- def edge_iterator (&block)
92
+ #
93
+ def edge_iterator(&block)
94
94
  @edge_iterator = block
95
95
  end
96
96
 
97
- end # class ImplicitGraph
98
-
97
+ end # class ImplicitGraph
99
98
 
100
99
  module Graph
101
100
 
102
- # ---
103
101
  # === Graph adaptors
104
102
  #
105
103
  # Return a new ImplicitGraph which has as vertices all vertices of the
106
104
  # receiver which satisfy the predicate _filter_.
107
105
  #
108
- # The methods provides similar functionaty as the BGL graph adapter
109
- # filtered_graph (see BOOST_DOC/filtered_graph.html).
106
+ # The methods provides similar functionality as the BGL graph adapter
107
+ # filtered_graph (see BOOST_DOC/filtered_graph.html).
110
108
  #
111
109
  # ==== Example
112
110
  #
113
111
  # def complete (n)
114
112
  # set = n.integer? ? (1..n) : n
115
- # RGL::ImplicitGraph.new { |g|
116
- # g.vertex_iterator { |b| set.each(&b) }
117
- # g.adjacent_iterator { |x, b|
118
- # set.each { |y| b.call(y) unless x == y }
119
- # }
120
- # }
113
+ # RGL::ImplicitGraph.new do |g|
114
+ # g.vertex_iterator { |b| set.each(&b) }
115
+ # g.adjacent_iterator do |x, b|
116
+ # set.each { |y| b.call(y) unless x == y }
117
+ # end
118
+ # end
121
119
  # end
122
120
  #
123
- # complete(4).to_s => "(1=2)(1=3)(1=4)(2=3)(2=4)(3=4)"
124
- # complete(4).vertices_filtered_by {|v| v != 4}.to_s => "(1=2)(1=3)(2=3)"
125
-
126
- def vertices_filtered_by (&filter)
127
- implicit_graph { |g|
128
- g.vertex_iterator { |b|
121
+ # complete(4).to_s # => "(1=2)(1=3)(1=4)(2=3)(2=4)(3=4)"
122
+ # complete(4).vertices_filtered_by { |v| v != 4 }.to_s # => "(1=2)(1=3)(2=3)"
123
+ #
124
+ def vertices_filtered_by(&filter)
125
+ implicit_graph do |g|
126
+ g.vertex_iterator do |b|
129
127
  self.each_vertex { |v| b.call(v) if filter.call(v) }
130
- }
131
- g.adjacent_iterator { |v, b|
128
+ end
129
+
130
+ g.adjacent_iterator do |v, b|
132
131
  self.each_adjacent(v) { |u| b.call(u) if filter.call(u) }
133
- }
134
- }
132
+ end
133
+ end
135
134
  end
136
135
 
137
136
  # Return a new ImplicitGraph which has as edges all edges of the receiver
@@ -139,36 +138,39 @@ module RGL
139
138
  #
140
139
  # ==== Example
141
140
  #
142
- # g = complete(7).edges_filtered_by {|u,v| u+v == 7}
141
+ # g = complete(7).edges_filtered_by { |u,v| u+v == 7 }
143
142
  # g.to_s => "(1=6)(2=5)(3=4)"
144
143
  # g.vertices => [1, 2, 3, 4, 5, 6, 7]
145
-
146
- def edges_filtered_by (&filter)
147
- implicit_graph { |g|
148
- g.adjacent_iterator { |v, b|
149
- self.each_adjacent(v) { |u|
144
+ #
145
+ def edges_filtered_by(&filter)
146
+ implicit_graph do |g|
147
+ g.adjacent_iterator do |v, b|
148
+ self.each_adjacent(v) do |u|
150
149
  b.call(u) if filter.call(v, u)
151
- }
152
- }
153
- g.edge_iterator { |b|
154
- self.each_edge { |u,v| b.call(u, v) if filter.call(u, v) }
155
- }
156
- }
150
+ end
151
+ end
152
+
153
+ g.edge_iterator do |b|
154
+ self.each_edge { |u, v| b.call(u, v) if filter.call(u, v) }
155
+ end
156
+ end
157
157
  end
158
158
 
159
159
  # Return a new ImplicitGraph which is isomorphic (i.e. has same edges and
160
- # vertices) to the receiver. It is a shortcut, also used by
160
+ # vertices) to the receiver. It is a shortcut, also used by
161
161
  # edges_filtered_by and vertices_filtered_by.
162
-
162
+ #
163
163
  def implicit_graph
164
- result = ImplicitGraph.new { |g|
164
+ result = ImplicitGraph.new do |g|
165
165
  g.vertex_iterator { |b| self.each_vertex(&b) }
166
166
  g.adjacent_iterator { |v, b| self.each_adjacent(v, &b) }
167
167
  g.directed = self.directed?
168
- }
168
+ end
169
+
169
170
  yield result if block_given? # let client overwrite defaults
170
171
  result
171
172
  end
172
173
 
173
- end # module Graph
174
- end # module RGL
174
+ end # module Graph
175
+
176
+ end # module RGL