gratr 0.4.2

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 (45) hide show
  1. data/Grater.xcf +0 -0
  2. data/README +328 -0
  3. data/Rakefile +220 -0
  4. data/examples/graph_self.rb +54 -0
  5. data/examples/module_graph.jpg +0 -0
  6. data/examples/module_graph.rb +12 -0
  7. data/examples/self_graph.jpg +0 -0
  8. data/examples/visualize.jpg +0 -0
  9. data/examples/visualize.rb +8 -0
  10. data/install.rb +49 -0
  11. data/lib/gratr.rb +33 -0
  12. data/lib/gratr/adjacency_graph.rb +230 -0
  13. data/lib/gratr/base.rb +34 -0
  14. data/lib/gratr/biconnected.rb +116 -0
  15. data/lib/gratr/chinese_postman.rb +123 -0
  16. data/lib/gratr/common.rb +73 -0
  17. data/lib/gratr/comparability.rb +92 -0
  18. data/lib/gratr/digraph.rb +113 -0
  19. data/lib/gratr/digraph_distance.rb +185 -0
  20. data/lib/gratr/dot.rb +90 -0
  21. data/lib/gratr/edge.rb +145 -0
  22. data/lib/gratr/graph.rb +315 -0
  23. data/lib/gratr/graph_api.rb +82 -0
  24. data/lib/gratr/import.rb +44 -0
  25. data/lib/gratr/labels.rb +103 -0
  26. data/lib/gratr/maximum_flow.rb +107 -0
  27. data/lib/gratr/rdot.rb +326 -0
  28. data/lib/gratr/search.rb +409 -0
  29. data/lib/gratr/strong_components.rb +127 -0
  30. data/lib/gratr/undirected_graph.rb +153 -0
  31. data/tests/TestBiconnected.rb +53 -0
  32. data/tests/TestChinesePostman.rb +53 -0
  33. data/tests/TestComplement.rb +54 -0
  34. data/tests/TestDigraph.rb +333 -0
  35. data/tests/TestDigraphDistance.rb +138 -0
  36. data/tests/TestEdge.rb +171 -0
  37. data/tests/TestInspection.rb +57 -0
  38. data/tests/TestMultiEdge.rb +57 -0
  39. data/tests/TestNeighborhood.rb +64 -0
  40. data/tests/TestProperties.rb +160 -0
  41. data/tests/TestSearch.rb +257 -0
  42. data/tests/TestStrongComponents.rb +85 -0
  43. data/tests/TestTriagulated.rb +137 -0
  44. data/tests/TestUndirectedGraph.rb +219 -0
  45. metadata +92 -0
Binary file
data/README ADDED
@@ -0,0 +1,328 @@
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.2
273
+
274
+ * Fixed bug in parallel edge adjacency detection.
275
+ * Fix to allow symbols to be passed through to dot for labels.
276
+ * Changed naming to use Arcs for Digraphs and Edges for Undirected Graphs.
277
+ * Added a gem release.
278
+
279
+ === 0.4.1
280
+
281
+ * Got reflection working for graphs
282
+ * Fixed major bugs in multi and pseudo graph handling
283
+
284
+ === 0.4.0
285
+
286
+ Initial release of fork from RGL library.
287
+
288
+ == Copying
289
+
290
+ Copyright (c) 2006 Shawn Patrick Garbett
291
+
292
+ Copyright (c) 2002,2004,2005 by Horst Duchene
293
+
294
+ Copyright (c) 2000,2001 Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
295
+
296
+ All rights reserved.
297
+
298
+ Jeremy Siek was one of the principal developers of the Boost Graph library.
299
+ Since this work is derivative, his name is included in the copyright list.
300
+
301
+ Redistribution and use in source and binary forms, with or without modification,
302
+ are permitted provided that the following conditions are met:
303
+
304
+ * Redistributions of source code must retain the above copyright notice(s),
305
+ this list of conditions and the following disclaimer.
306
+ * Redistributions in binary form must reproduce the above copyright notice,
307
+ this list of conditions and the following disclaimer in the documentation
308
+ and/or other materials provided with the distribution.
309
+ * Neither the name of the Shawn Garbett nor the names of its contributors
310
+ may be used to endorse or promote products derived from this software
311
+ without specific prior written permission.
312
+
313
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
314
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
315
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
316
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
317
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
318
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
319
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
320
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
321
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
322
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
323
+
324
+ == Support
325
+
326
+ Please contact me at mailto:shawn@garbett.org with bug reports
327
+ suggestions, and other comments. If you send patches, it would help if
328
+ they were generated using "diff -u".
@@ -0,0 +1,220 @@
1
+ # Rakefile for GRATR -*- ruby -*-
2
+ begin
3
+ require 'rubygems'
4
+ require 'rake/gempackagetask'
5
+ rescue Exception
6
+ nil
7
+ end
8
+
9
+ require 'rake/clean'
10
+ require 'rake/testtask'
11
+ require 'rake/rdoctask'
12
+
13
+ # Determine the current version of the software
14
+
15
+ if `ruby -Ilib -rgratr/base -e'puts GRATR_VERSION'` =~ /\S+$/
16
+ PKG_VERSION = $&
17
+ else
18
+ PKG_VERSION = "0.0.0"
19
+ end
20
+
21
+ SUMMARY = "Graph Theory Ruby library"
22
+ SOURCES = FileList['lib/**/*.rb']
23
+ RDOC_DIR = './gratr'
24
+
25
+ # The default task is run if rake is given no explicit arguments.
26
+
27
+ desc "Default Task"
28
+ task :default => :test
29
+
30
+ # Define a test task.
31
+
32
+ Rake::TestTask.new { |t|
33
+ t.libs << "tests"
34
+ t.pattern = 'tests/Test*.rb'
35
+ t.verbose = true
36
+ }
37
+
38
+ task :test
39
+
40
+ # Define a test that will run all the test targets.
41
+ desc "Run all test targets"
42
+ task :testall => [:test ]
43
+
44
+ # Install gratr using the standard install.rb script.
45
+
46
+ desc "Install the application"
47
+ task :install do
48
+ ruby "install.rb"
49
+ end
50
+
51
+ # CVS Tasks ----------------------------------------------------------
52
+
53
+ desc "Tag all the CVS files with the latest release number (TAG=x)"
54
+ task :tag do
55
+ rel = "REL_" + PKG_VERSION.gsub(/\./, '_')
56
+ rel << ENV['TAG'] if ENV['TAG']
57
+ puts rel
58
+ sh %{cvs commit -m 'pre-tag commit'}
59
+ sh %{cvs tag #{rel}}
60
+ end
61
+
62
+ # Create a task to build the RDOC documentation tree.
63
+
64
+ rd = Rake::RDocTask.new("rdoc") { |rdoc|
65
+ rdoc.rdoc_dir = RDOC_DIR
66
+ rdoc.title = SUMMARY
67
+ rdoc.options << '--line-numbers' << '--inline-source' <<
68
+ '--main' << 'README'
69
+ rdoc.rdoc_files.include(SOURCES, 'README' ) #, 'examples/examples.rb')
70
+ }
71
+
72
+ # ====================================================================
73
+ # Create a task that will package the gratr software into distributable
74
+ # tar, zip and gem files.
75
+
76
+ PKG_FILES = FileList[
77
+ 'install.rb',
78
+ '[A-Z]*',
79
+ 'tests/**/*.rb',
80
+ 'examples/**/*'
81
+ ] + SOURCES
82
+
83
+ if ! defined?(Gem)
84
+ puts "Package Target requires RubyGEMs"
85
+ else
86
+ spec = Gem::Specification.new do |s|
87
+
88
+ #### Basic information.
89
+
90
+ s.name = 'gratr'
91
+ s.version = PKG_VERSION
92
+ s.summary = SUMMARY
93
+
94
+ s.description = <<-EOF
95
+ GRATR is a framework for graph data structures and algorithms.
96
+
97
+ This library is a fork of RGL. This version utilizes
98
+ Ruby blocks and duck typing to greatly simplfy the code. It also supports
99
+ export to DOT format for display as graphics.
100
+
101
+ GRATR currently contains a core set of algorithm patterns:
102
+
103
+ * Breadth First Search
104
+ * Depth First Search
105
+ * A* Search
106
+ * Floyd-Warshall
107
+ * Best First Search
108
+ * Djikstra's Algorithm
109
+ * Lexicographic Search
110
+
111
+ The algorithm patterns by themselves do not compute any meaningful quantities
112
+ over graphs, they are merely building blocks for constructing graph
113
+ algorithms. The graph algorithms in GRATR currently include:
114
+
115
+ * Topological Sort
116
+ * Strongly Connected Components
117
+ * Transitive Closure
118
+ * Rural Chinese Postman
119
+ * Biconnected
120
+ EOF
121
+
122
+ #### Which files are to be included in this gem? Everything! (Except CVS directories.)
123
+ s.files = PKG_FILES.to_a
124
+
125
+ #### Load-time details: library and application (you will need one or both).
126
+
127
+ s.require_path = 'lib' # Use these for libraries.
128
+ s.autorequire = 'gratr'
129
+
130
+ #### Documentation and testing.
131
+
132
+ s.has_rdoc = true
133
+ s.extra_rdoc_files = ['README']
134
+ s.rdoc_options <<
135
+ '--title' << 'GRATR - Ruby Graph Library' <<
136
+ '--main' << 'README' <<
137
+ '--line-numbers'
138
+
139
+ #### Author and project details.
140
+ s.author = "Shawn Garbett"
141
+ s.email = "shawn@garbett.org"
142
+ s.homepage = "http://gratr.rubyforge.org"
143
+ s.rubyforge_project = "gratr"
144
+
145
+ end
146
+
147
+ Rake::GemPackageTask.new(spec) do |pkg|
148
+ #pkg.need_zip = true
149
+ pkg.need_tar = true
150
+ end
151
+ end
152
+
153
+ # TAGS ---------------------------------------------------------------
154
+
155
+ file 'tags' => SOURCES do
156
+ print "Running ctags..."
157
+ sh %{ctags #{SOURCES.join(' ')}} # vi tags
158
+ puts "done."
159
+ end
160
+
161
+ file 'TAGS' => SOURCES do
162
+ sh %{ctags -e #{SOURCES.join(' ')}} # emacs TAGS
163
+ end
164
+
165
+ # Misc tasks =========================================================
166
+
167
+ def count_lines(filename)
168
+ lines = 0
169
+ codelines = 0
170
+ open(filename) { |f|
171
+ f.each do |line|
172
+ lines += 1
173
+ next if line =~ /^\s*$/
174
+ next if line =~ /^\s*#/
175
+ codelines += 1
176
+ end
177
+ }
178
+ [lines, codelines]
179
+ end
180
+
181
+ def show_line(msg, lines, loc)
182
+ printf "%6s %6s %s\n", lines.to_s, loc.to_s, msg
183
+ end
184
+
185
+ desc "Count lines in the main files"
186
+ task :lines do
187
+ total_lines = 0
188
+ total_code = 0
189
+ show_line("File Name", "LINES", "LOC")
190
+ SOURCES.each do |fn|
191
+ lines, codelines = count_lines(fn)
192
+ show_line(fn, lines, codelines)
193
+ total_lines += lines
194
+ total_code += codelines
195
+ end
196
+ show_line("TOTAL", total_lines, total_code)
197
+ end
198
+
199
+ ARCHIVEDIR = '/mnt/flash'
200
+
201
+ task :archive => [:package] do
202
+ cp FileList["pkg/*.tgz", "pkg/*.zip", "pkg/*.gem"], ARCHIVEDIR
203
+ end
204
+
205
+ desc "Copy rdoc html to rubyforge"
206
+ task :rdoc2rf => [:rdoc] do
207
+ sh "scp -r #{RDOC_DIR} monora@rubyforge.org:/var/www/gforge-projects/gratr"
208
+ sh "scp examples/*.jpg monora@rubyforge.org:/var/www/gforge-projects/gratr/examples"
209
+ end
210
+
211
+ STATS_DIRECTORIES = [
212
+ %w(Libraries lib/gratr),
213
+ %w(Unit\ tests tests),
214
+ ].collect { |name, dir| [ name, "./#{dir}" ] }.select { |name, dir| File.directory?(dir) }
215
+
216
+ desc "Report code statistics (KLOCs, etc) from the application"
217
+ task :stats do
218
+ require 'stats/code_statistics'
219
+ CodeStatistics.new(*STATS_DIRECTORIES).to_s
220
+ end