gratr19 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/README +335 -0
  2. data/examples/graph_self.rb +54 -0
  3. data/examples/module_graph.jpg +0 -0
  4. data/examples/module_graph.rb +12 -0
  5. data/examples/self_graph.jpg +0 -0
  6. data/examples/visualize.jpg +0 -0
  7. data/examples/visualize.rb +8 -0
  8. data/install.rb +49 -0
  9. data/lib/gratr.rb +42 -0
  10. data/lib/gratr/adjacency_graph.rb +230 -0
  11. data/lib/gratr/base.rb +34 -0
  12. data/lib/gratr/biconnected.rb +116 -0
  13. data/lib/gratr/chinese_postman.rb +123 -0
  14. data/lib/gratr/common.rb +74 -0
  15. data/lib/gratr/comparability.rb +92 -0
  16. data/lib/gratr/digraph.rb +115 -0
  17. data/lib/gratr/digraph_distance.rb +185 -0
  18. data/lib/gratr/dot.rb +90 -0
  19. data/lib/gratr/edge.rb +145 -0
  20. data/lib/gratr/graph.rb +314 -0
  21. data/lib/gratr/graph_api.rb +82 -0
  22. data/lib/gratr/import.rb +44 -0
  23. data/lib/gratr/labels.rb +103 -0
  24. data/lib/gratr/maximum_flow.rb +107 -0
  25. data/lib/gratr/rdot.rb +332 -0
  26. data/lib/gratr/search.rb +422 -0
  27. data/lib/gratr/strong_components.rb +127 -0
  28. data/lib/gratr/undirected_graph.rb +153 -0
  29. data/lib/gratr/version.rb +6 -0
  30. data/lib/priority-queue/benchmark/dijkstra.rb +171 -0
  31. data/lib/priority-queue/compare_comments.rb +49 -0
  32. data/lib/priority-queue/ext/priority_queue/CPriorityQueue/extconf.rb +2 -0
  33. data/lib/priority-queue/lib/priority_queue.rb +14 -0
  34. data/lib/priority-queue/lib/priority_queue/c_priority_queue.rb +1 -0
  35. data/lib/priority-queue/lib/priority_queue/poor_priority_queue.rb +46 -0
  36. data/lib/priority-queue/lib/priority_queue/ruby_priority_queue.rb +525 -0
  37. data/lib/priority-queue/setup.rb +1551 -0
  38. data/lib/priority-queue/test/priority_queue_test.rb +371 -0
  39. data/tests/TestBiconnected.rb +53 -0
  40. data/tests/TestChinesePostman.rb +53 -0
  41. data/tests/TestComplement.rb +54 -0
  42. data/tests/TestDigraph.rb +333 -0
  43. data/tests/TestDigraphDistance.rb +138 -0
  44. data/tests/TestDot.rb +75 -0
  45. data/tests/TestEdge.rb +171 -0
  46. data/tests/TestInspection.rb +57 -0
  47. data/tests/TestMultiEdge.rb +57 -0
  48. data/tests/TestNeighborhood.rb +64 -0
  49. data/tests/TestProperties.rb +160 -0
  50. data/tests/TestSearch.rb +277 -0
  51. data/tests/TestStrongComponents.rb +85 -0
  52. data/tests/TestTriagulated.rb +137 -0
  53. data/tests/TestUndirectedGraph.rb +219 -0
  54. metadata +152 -0
data/README ADDED
@@ -0,0 +1,335 @@
1
+ = GRAph Theory in Ruby (GRATR)
2
+
3
+ link:../gratr.jpg GRATR is a framework for graph data structures and algorithms.
4
+
5
+ This project is a fork of Horst Duchene's RGL library.
6
+
7
+ The design of the library is much influenced by the Boost Graph Library (BGL)
8
+ which is written in C++ heavily using its template mechanism. Refer to
9
+ http://www.boost.org/libs/graph/doc for further links and documentation on graph
10
+ data structures and algorithms and the design rationales of BGL.
11
+
12
+ A comprehensive summary of graph terminology can be found in the the graph
13
+ section of the <em>Dictionary of Algorithms and Data Structures</em> at
14
+ http://www.nist.gov/dads/HTML/graph.html.
15
+
16
+ There are two Arc classes, GRATR::Arc and GRATR::Edge.
17
+
18
+ GRATR::Digraph and it's pseudonym GRATR::DirectedGraph are classes that have single directed edges
19
+ between vertices and loops are forbidden. GRATR::DirectedPseudoGraph allows for
20
+ multiple directed edges between vertices and loops are forbidden.
21
+ GRATR::DirectedMultiGraph allows for multiple directed edges between vertices and
22
+ loops on vertices.
23
+
24
+ GRATR::UndirectedGraph, GRATR::UndirectedPseudoGraph and GRATR::UndirectedMultiGraph are similar
25
+ but all edges are undirected.
26
+
27
+ These classes are all available with a <tt>require 'gratr'</tt> statement in your Ruby code. If one wishes
28
+ to pull the classes into the current namespace, i.e. drop the <tt>GRATR::</tt> from all
29
+ class statements and use <tt>require 'gratr/import'</tt> instead.
30
+
31
+ == Design principles
32
+
33
+ This document concentrates on the special issues of the implementation in
34
+ Ruby. The main design goals directly taken from the BGL design are:
35
+
36
+ * An interface for how the structure of a graph can be accessed using a generic
37
+ interface that hides the details of the graph data structure
38
+ implementation. This interface is defined by the module Graph, which should be
39
+ included in concrete classes.
40
+
41
+ * A standardized generic interface for traversing graphs using standard
42
+ Ruby block iterators.
43
+
44
+ * Implementation is separated from interface, and hidden from the average user.
45
+ An advanced user could also easily override the internals with a different
46
+ implementation if need be.
47
+
48
+ GRATR provides some general purpose graph classes that conform to this interface,
49
+ but they are not meant to be the *only* graph classes. As in BGL I believe that
50
+ the main contribution of the GRATR is the formulation of this interface.
51
+
52
+ The BGL graph interface and graph components are generic in the sense of the C++
53
+ Standard Template Library (STL). In Ruby other techniques are available to
54
+ express the generic character of the algorithms and data structures mainly using
55
+ mixins and iterators. The BGL documentation mentions three means to achieve
56
+ genericity:
57
+
58
+ * Algorithm/Data-Structure Interoperability
59
+ * Extension through Function Objects and Visitors
60
+ * Element Type Parameterization
61
+ * Vertex and Arc Property Multi-Parameterization
62
+
63
+ The first is easily achieved in GRATR using mixins, which of course is not as
64
+ efficient than C++ templates (but much more readable :-). The second one is
65
+ even more easily implemented using standard iterators with blocks.
66
+ The third one is no issue since Ruby is dynamically typed: Each object can
67
+ be a graph vertex (even nil!). There is no need for a vertex (or even edge type). A
68
+ label interface is provided for end users as well. One could simply use
69
+ a hash externally, but the future development of network graphs will require
70
+ a weight or capacity property to be accessible.
71
+
72
+ === Algorithms
73
+
74
+ This version of GRATR contains a core set of algorithm patterns:
75
+
76
+ * Breadth First Search Graph[1,2,1,3,1,4,2,5].bfs => [1, 2, 3, 4, 5]
77
+ * Depth First Search Graph[1,2,1,3,1,4,2,5].dfs => [1, 2, 5, 3, 4]
78
+ * A* Search
79
+ * Lexicographic Search
80
+ * Dijkstra's Algorithm
81
+ * Floyd-Warshall
82
+ * Triangulation and Comparability detection
83
+
84
+ The algorithm patterns by themselves do not compute any meaningful quantities
85
+ over graphs, they are merely building blocks for constructing graph
86
+ algorithms. The graph algorithms in GRATR currently include:
87
+
88
+ * Topological Sort (topsort)
89
+ * Strongly Connected Components (strong_connect)
90
+ * Transitive Closure (transitive_closure)
91
+
92
+ === Data Structures
93
+
94
+ GRATR currently provides one graph module that implement a generalized adjacency
95
+ list and an edge list adaptor.
96
+
97
+ * GRATR::AdjacencyGraph
98
+
99
+ The GRATR::Digraph class is the general purpose *swiss army knife* of graph
100
+ classes, most of the other classes are just modifications to this class.
101
+ It is optimized for efficient access to just the out-edges, fast vertex
102
+ insertion and removal at the cost of extra space overhead, etc.
103
+
104
+ === GEM Installation
105
+
106
+ Download the GEM file and install it with ..
107
+
108
+ % gem install gratr-VERSION.gem
109
+
110
+ or directly with
111
+
112
+ % gem install gratr
113
+
114
+ Use the correct version number for VERSION (e.g. 0.2.x). You may need root
115
+ privileges to install.
116
+
117
+ === Running tests
118
+
119
+ GRATR comes with a Rakefile which automatically runs the tests. Goto the
120
+ installation directory and start rake:
121
+
122
+ % gem env
123
+ Rubygems Environment:
124
+ - VERSION: 0.8.3 (0.8.3)
125
+ - INSTALLATION DIRECTORY: /usr/lib/ruby/gems/1.8
126
+ - GEM PATH:
127
+ - /usr/lib/ruby/gems/1.8
128
+ - REMOTE SOURCES:
129
+ - http://gems.rubyforge.org
130
+
131
+ % cd /usr/lib/ruby/gems/1.8/gems/gratr-0.2.2/
132
+ % r40> rake
133
+ (in /usr/lib/ruby/gems/1.8/gems/gratr-0.2.2)
134
+ ruby1.8 -Ilib:tests -e0 -rtests/TestGraphXML -rtests/TestComponents -rtests/TestDirectedGraph -rtests/TestArc -rtests/TestImplicit -rtests/TestTransitiveClosure -rtests/TestTraversal -rtests/TestUnDirectedGraph
135
+ Loaded suite -e
136
+ Started
137
+ ........................................................................................................
138
+ Finished in 0.736444 seconds.
139
+
140
+ 40 tests, 421 assertions, 0 failures, 0 errors
141
+
142
+ === Normal Installation
143
+
144
+ You have to install stream library before. You can than install GRATR with the
145
+ following command:
146
+
147
+ % ruby install.rb
148
+
149
+ from its distribution directory. To uninstall it use
150
+
151
+ % ruby install.rb -u
152
+
153
+ The rdoc is useful as well:
154
+
155
+ % rake rdoc
156
+
157
+ == Example irb session with GRATR
158
+
159
+ irb> require 'gratr/import'
160
+ => true
161
+ irb> dg = Digraph[1,2, 2,3, 2,4, 4,5, 6,4, 1,6]
162
+ => GRATR::Digraph[[2, 3], [1, 6], [2, 4], [4, 5], [1, 2], [6, 4]]
163
+
164
+ A few properties of the graph
165
+
166
+ irb> dg.directed?
167
+ => true
168
+ irb> dg.vertex?(4)
169
+ => true
170
+ irb> dg.edge?(2,4)
171
+ => true
172
+ irb> dg.edge?(4,2)
173
+ => false
174
+ irb> dg.vertices
175
+ => [5, 6, 1, 2, 3, 4]
176
+
177
+ Every object could be a vertex (there is no class Vertex), even the class
178
+ object _Object_:
179
+
180
+ irb> dg.vertex? Object
181
+ => false
182
+ irb> UndirectedGraph.new(dg).edges.sort.to_s
183
+ => "(1=2)(2=3)(2=4)(4=5)(1=6)(4=6)"
184
+
185
+ Add inverse edge (4-2) to directed graph:
186
+
187
+ irb> dg.add_edge! 4,2
188
+ => GRATR::Digraph[[2, 3], [1, 6], [4, 2], [2, 4], [4, 5], [1, 2], [6, 4]]
189
+
190
+ (4-2) == (2-4) in the undirected graph:
191
+
192
+ irb> UndirectedGraph.new(dg).edges.sort.to_s
193
+ => "(1=2)(2=3)(2=4)(4=5)(1=6)(4=6)"
194
+
195
+ (4-2) != (2-4) in directed graphs:
196
+
197
+ irb> dg.edges.sort.to_s
198
+ => "(1-2)(1-6)(2-3)(2-4)(4-2)(4-5)(6-4)"
199
+ irb> dg.remove_edge! 4,2
200
+ => GRATR::Digraph[[2, 3], [1, 6], [2, 4], [4, 5], [1, 2], [6, 4]]
201
+
202
+ <em>Topological sort</em> is realized with as iterator:
203
+
204
+ irb> dg.topsort
205
+ => [1, 2, 3, 6, 4, 5]
206
+ irb> y=0; dg.topsort {|v| y+=v}; y
207
+ => 21
208
+
209
+ # Use DOT to visualize this graph:
210
+ irb> require 'gratr/dot'
211
+ irb> dg.write_to_graphic_file('jpg','visualize')
212
+ "graph.jpg"
213
+
214
+ The result: link:../examples/visualize.jpg
215
+
216
+ Here's an example showing the module inheritance hierarchy:
217
+
218
+ module_graph=Digraph.new
219
+ ObjectSpace.each_object(Module) do |m|
220
+ m.ancestors.each {|a| module_graph.add_edge!(m,a) if m != a}
221
+ end
222
+
223
+ gv = module_graph.vertices.select {|v| v.to_s.match(/GRATR/)}
224
+ module_graph.induced_subgraph(gv).write_to_graphic_file('jpg','module_graph')
225
+
226
+ The result: link:../examples/module_graph.jpg
227
+
228
+ Look for more in the examples directory.
229
+
230
+ == Credits
231
+
232
+ Many thanks to Robert Feldt which also worked on a graph library
233
+ (http://rockit.sf.net/subprojects/graphr) who pointed me to BGL and many other
234
+ graph resources. Manuel Simoni found a subtle bug in a preliminary version
235
+ announced at http://rubygarden.com/ruby?RubyAlgorithmPackage/Graph.
236
+
237
+ Robert kindly allowed to integrate his work on graphr, which I did not yet
238
+ succeed. Especially his work to output graphs for
239
+ GraphViz[http://www.research.att.com/sw/tools/graphviz/download.html] is much
240
+ more elaborated than the minimal support in dot.rb.
241
+
242
+ Jeremy Siek one of the authors of the nice book "The Boost Graph Library (BGL)"
243
+ (http://www.boost.org/libs/graph/doc) kindly allowed to use the
244
+ BGL documentation as a _cheap_ reference for GRATR. He and Robert also gave
245
+ feedback and many ideas for GRATR.
246
+
247
+ Dave Thomas for RDoc[http://rdoc.sourceforge.net] which generated what you read
248
+ and Matz for Ruby. Dave included in the latest version of RDoc (alpha9) the
249
+ module dot/dot.rb which I use instead of Roberts module to visualize graphs
250
+ (see gratr/dot.rb).
251
+
252
+ Horst Duchene for RGL which provided the basis for this library and his vision.
253
+
254
+ Rick Bradley who reworked the library and added many graph theoretic constructs.
255
+
256
+ == Known Bugs
257
+
258
+ * Some of the digraph distance algorithms need reworked to work for pseudo and multi graphs.
259
+
260
+ == To Do
261
+
262
+ * Primal Dual for combinatorial optimization problems
263
+ * Min-Max Flow
264
+ * Near optimal traveling salesman problem
265
+ * Orientation of undirected graphs
266
+
267
+ == Release Notes
268
+
269
+ The core interface is about to be updated to allow for cleaner dependency injects. Luke Kanies has also contributed
270
+ several optimizations for speed and logged some bugs. This will result in a 0.5 release coming soon.
271
+
272
+ === 0.4.3
273
+
274
+ * Fixed bug in dot output dependency.
275
+ * Changed method.call to send in a couple places.
276
+ * Fixed bug in unconnected vertices for reversal. Ticket #7237
277
+ * Fixed bugs in A* Search. Ticket #7250.
278
+
279
+ === 0.4.2
280
+
281
+ * Fixed bug in parallel edge adjacency detection.
282
+ * Fix to allow symbols to be passed through to dot for labels.
283
+ * Changed naming to use Arcs for Digraphs and Edges for Undirected Graphs.
284
+ * Added a gem release.
285
+
286
+ === 0.4.1
287
+
288
+ * Got reflection working for graphs
289
+ * Fixed major bugs in multi and pseudo graph handling
290
+
291
+ === 0.4.0
292
+
293
+ Initial release of fork from RGL library.
294
+
295
+ == Copying
296
+
297
+ Copyright (c) 2006 Shawn Patrick Garbett
298
+
299
+ Copyright (c) 2002,2004,2005 by Horst Duchene
300
+
301
+ Copyright (c) 2000,2001 Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
302
+
303
+ All rights reserved.
304
+
305
+ Jeremy Siek was one of the principal developers of the Boost Graph library.
306
+ Since this work is derivative, his name is included in the copyright list.
307
+
308
+ Redistribution and use in source and binary forms, with or without modification,
309
+ are permitted provided that the following conditions are met:
310
+
311
+ * Redistributions of source code must retain the above copyright notice(s),
312
+ this list of conditions and the following disclaimer.
313
+ * Redistributions in binary form must reproduce the above copyright notice,
314
+ this list of conditions and the following disclaimer in the documentation
315
+ and/or other materials provided with the distribution.
316
+ * Neither the name of the Shawn Garbett nor the names of its contributors
317
+ may be used to endorse or promote products derived from this software
318
+ without specific prior written permission.
319
+
320
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
321
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
322
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
323
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
324
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
325
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
326
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
327
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
328
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
329
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
330
+
331
+ == Support
332
+
333
+ Please contact me at mailto:shawn@garbett.org with bug reports
334
+ suggestions, and other comments. If you send patches, it would help if
335
+ they were generated using "diff -u".
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/ruby -I../lib
2
+
3
+ require 'gratr/import'
4
+ require 'gratr/dot'
5
+
6
+ # This program gives an example of dynamic analysis of a program's call stack,
7
+ # that exports to dot and creates a jpg visualization of the call diagram.
8
+
9
+ class GraphSelf
10
+
11
+ # Setup some data to call Dijkstra's Algorithm
12
+ def initialize
13
+ @d = Digraph[ [:a,:b] => 9, [:a,:e] => 3,
14
+ [:b,:c] => 2, [:b,:e] => 6,
15
+ [:c,:d] => 1,
16
+ [:d,:c] => 2,
17
+ [:e,:b] => 2, [:e,:f] => 1,
18
+ [:f,:c] => 2, [:f,:d] => 7, [:f,:e] => 2 ]
19
+
20
+ @call_stack = []
21
+ @call_graph = Digraph.new
22
+ end
23
+
24
+ # Get the call graph variable
25
+ def call_graph() @call_graph; end
26
+
27
+ # Turn capturing of call graph on
28
+ def capture_func
29
+ Proc.new do |event, f, l, id, b, klass|
30
+ # Only interested in the GRATR library itself
31
+ if ( klass.to_s =~ /GRATR/ )
32
+ case event.to_s
33
+ when /call/
34
+ method = "#{klass.to_s.split('::')[1]}.#{id}" # Removes GRATR::
35
+ @call_graph.add_edge!(@call_stack[-1],method) if @call_stack[-1]
36
+ @call_stack.push(method)
37
+ when /return/ : @call_stack.pop
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ # Run a capture of the call graph for Dijkstra's algorithm
44
+ def run
45
+ set_trace_func capture_func
46
+ @d.dijkstras_algorithm(:a)
47
+ set_trace_func nil
48
+ self
49
+ end
50
+
51
+ end
52
+
53
+ # Run a capture and generate the resulting jpg file
54
+ GraphSelf.new.run.call_graph.write_to_graphic_file('jpg','self_graph')
Binary file
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/ruby -I../lib
2
+
3
+ require 'gratr/import'
4
+ require 'gratr/dot'
5
+
6
+ module_graph=Digraph.new
7
+ ObjectSpace.each_object(Module) do |m|
8
+ m.ancestors.each {|a| module_graph.add_edge!(m,a) if m != a}
9
+ end
10
+
11
+ gv = module_graph.vertices.select {|v| v.to_s.match(/GRATR/)}
12
+ module_graph.induced_subgraph(gv).write_to_graphic_file('jpg','module_graph')
Binary file
Binary file
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/ruby -I../lib
2
+
3
+ require 'gratr/import'
4
+ require 'gratr/dot'
5
+
6
+ dg = Digraph[1,2, 2,3, 2,4, 4,5, 6,4, 1,6]
7
+
8
+ dg.write_to_graphic_file('jpg','visualize')
@@ -0,0 +1,49 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require 'getoptlong'
4
+ require 'rbconfig'
5
+ require 'ftools'
6
+ require 'find'
7
+
8
+ SRC_BASE = 'lib'
9
+ SRC = 'gratr'
10
+
11
+
12
+ INSTDIR = File.join Config::CONFIG['sitedir']
13
+ DESTDIR = File.join INSTDIR, SRC
14
+
15
+ opts = GetoptLong.new( [ "--uninstall", "-u", GetoptLong::NO_ARGUMENT ] )
16
+
17
+ def install
18
+ begin
19
+ File.makedirs( DESTDIR )
20
+ pwd = Dir.pwd
21
+ Dir.chdir(SRC_BASE)
22
+ Dir['*.rb'].each do |file|
23
+ dst = File.join( INSTDIR, file )
24
+ File.install(file, dst, 0644, true)
25
+ end
26
+ Find.find(SRC) do |file|
27
+ dst = File.join( INSTDIR, file )
28
+ File.install(file, dst, 0644, true) if file =~ /.rb$/
29
+ end
30
+ Dir.chdir(pwd)
31
+ rescue
32
+ puts $!
33
+ end
34
+ end
35
+
36
+ def uninstall
37
+ begin
38
+ puts "Deleting:"
39
+ Find.find(DESTDIR) { |file| File.rm_f file,true }
40
+ Dir.delete DESTDIR
41
+ rescue
42
+ end
43
+ end
44
+
45
+ if (opt = opts.get) and opt[0] =~ /^-?-u/
46
+ uninstall
47
+ else
48
+ install
49
+ end