rgl 0.5.1 → 0.5.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.
- checksums.yaml +7 -0
- data/ChangeLog +18 -5
- data/Gemfile +1 -3
- data/README.md +252 -0
- data/Rakefile +1 -15
- data/lib/rgl/base.rb +4 -1
- data/lib/rgl/bellman_ford.rb +1 -2
- data/lib/rgl/dijkstra.rb +3 -29
- data/lib/rgl/dot.rb +7 -3
- data/lib/rgl/traversal.rb +4 -0
- data/test/dijkstra_issue24_test.rb +23 -0
- data/test/dot_test.rb +10 -6
- data/test/graph_test.rb +5 -0
- data/test/test_helper.rb +3 -0
- metadata +20 -40
- data/README.rdoc +0 -248
- data/examples/images/example.jpg +0 -0
- data/examples/images/module_graph.jpg +0 -0
- data/examples/images/rgl_modules.png +0 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d301ca82307bce4dd2de05303de4bc633f92dbf4
|
4
|
+
data.tar.gz: a133f96bc69d3baa7a790674fd9d6e08a8b93d83
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 88d2fcb68bfc33c482cc11d0c82ac8c143ac9d2fcd1f4c287f3392944fc7ca212dd9f93bed4654a243c4ab9d73038d9c3c34dcd84e1521923756e8833e69963d
|
7
|
+
data.tar.gz: ffe9faef0d0e4f77cef5c830a3ef0a86b2fe61bb8ad7e8f62c272c9360d550e24aca23c5aaf392f9f6990cdf1e36e9d631dab7d982ff1c8b89823eecc4c39042
|
data/ChangeLog
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
2016-05 Release 0.5.2
|
2
|
+
|
3
|
+
Horst Duchene <monora@gmail.com>
|
4
|
+
* Issue #21: Use new method vertex_id instead of object_id to identify vertices in dot export. (fa7592)
|
5
|
+
* Integrate Code Climate's test coverage reporting (0ab722)
|
6
|
+
* Clarify traversal order of DFS search (see #20). (afa788)
|
7
|
+
Chase Gilliam <chase.gilliam@gmail.com>
|
8
|
+
* drop 1.9.3 add newer jruby and rubinius (fad333)
|
9
|
+
Matías Battocchia <matias@riseup.net>
|
10
|
+
* Switched to a different heap implementation. (bd7c13)
|
11
|
+
gorn <j@kub.cz>
|
12
|
+
* Adding failing test for issue #24 (1f6204)
|
13
|
+
|
1
14
|
2015-12 Release 0.5.1
|
2
15
|
|
3
16
|
Horst Duchene <monora@gmail.com>
|
@@ -21,7 +34,7 @@ Chase <chase.gilliam@gmail.com>
|
|
21
34
|
* updated algorithms to 6.1 and added test unit to support newer rubies (fbd874)
|
22
35
|
Louis Rose <louismrose@gmail.com>
|
23
36
|
* Fix #15. Use object IDs rather than labels to identify vertexs in DOT graph to ensure that distinct nodes that share a label are shown. (33206f)
|
24
|
-
|
37
|
+
* Issue #15. Fix tests. (4fc455)
|
25
38
|
|
26
39
|
|
27
40
|
2014-12 Release 0.5.0
|
@@ -29,13 +42,13 @@ Horst Duchene <monora@gmail.com>
|
|
29
42
|
* Changed edge sequence to match example picture (daa88e)
|
30
43
|
* Fixed comment (6a6c93)
|
31
44
|
* Fixed spelling (7ca281)
|
32
|
-
Horst Duchêne <monora@gmail.com>
|
33
45
|
Chase <chase.gilliam@gmail.com>
|
34
46
|
* updated algorithms to 6.1 and added test unit to support newer rubies (fbd874)
|
35
47
|
Louis Rose <louismrose@gmail.com>
|
36
|
-
* Fix #15. Use object IDs rather than labels to identify vertexs
|
37
|
-
|
38
|
-
|
48
|
+
* Fix #15. Use object IDs rather than labels to identify vertexs
|
49
|
+
in DOT graph to ensure that distinct nodes that share a label are
|
50
|
+
shown. (33206f)
|
51
|
+
* Issue #15. Fix tests. (4fc455)
|
39
52
|
|
40
53
|
2014-12 Release 0.5.0
|
41
54
|
|
data/Gemfile
CHANGED
data/README.md
ADDED
@@ -0,0 +1,252 @@
|
|
1
|
+
# Ruby Graph Library (RGL) [<img src="https://secure.travis-ci.org/monora/rgl.png?branch=master" alt="Build Status" />](https://travis-ci.org/monora/rgl) [<img src="https://codeclimate.com/github/monora/rgl/badges/coverage.svg" />](https://codeclimate.com/github/monora/rgl/coverage)
|
2
|
+
|
3
|
+
RGL is a framework for graph data structures and algorithms.
|
4
|
+
|
5
|
+
The design of the library is much influenced by the Boost Graph Library (BGL)
|
6
|
+
which is written in C++. Refer to http://www.boost.org/libs/graph/doc for
|
7
|
+
further links and documentation on graph data structures and algorithms and
|
8
|
+
the design rationales of BGL.
|
9
|
+
|
10
|
+
A comprehensive summary of graph terminology can be found in the graph section
|
11
|
+
of the *Dictionary of Algorithms and Data Structures* at
|
12
|
+
http://www.nist.gov/dads/HTML/graph.html or
|
13
|
+
[Wikipedia](https://en.wikipedia.org/wiki/Graph_%28discrete_mathematics%29).
|
14
|
+
|
15
|
+
## Documentation
|
16
|
+
|
17
|
+
* RGL's [API Reference](http://www.rubydoc.info/github/monora/rgl) at
|
18
|
+
http://rubydoc.info
|
19
|
+
|
20
|
+
|
21
|
+
## Design principles
|
22
|
+
|
23
|
+
This document concentrates on the special issues of the implementation in
|
24
|
+
Ruby. The main design goals directly taken from the BGL design are:
|
25
|
+
|
26
|
+
* An interface for how the structure of a graph can be accessed using a
|
27
|
+
generic interface that hides the details of the graph data structure
|
28
|
+
implementation. This interface is defined by the module {RGL::Graph},
|
29
|
+
which should be included in concrete classes.
|
30
|
+
|
31
|
+
* A standardized generic interface for traversing graphs
|
32
|
+
{RGL::GraphIterator}
|
33
|
+
|
34
|
+
|
35
|
+
RGL provides some general purpose graph classes that conform to this
|
36
|
+
interface, but they are not meant to be the **only** graph classes. As in BGL
|
37
|
+
I believe that the main contribution of the RGL is the formulation of this
|
38
|
+
interface.
|
39
|
+
|
40
|
+
The BGL graph interface and graph components are generic in the sense of the
|
41
|
+
C++ Standard Template Library (STL). In Ruby other techniques are available to
|
42
|
+
express the generic character of the algorithms and data structures mainly
|
43
|
+
using mixins and iterators. The BGL documentation mentions three means to
|
44
|
+
achieve genericity:
|
45
|
+
|
46
|
+
* Algorithm/Data-Structure Interoperability
|
47
|
+
* Extension through Function Objects and Visitors
|
48
|
+
* Element Type Parameterization
|
49
|
+
* Vertex and Edge Property Multi-Parameterization
|
50
|
+
|
51
|
+
|
52
|
+
The first is easily achieved in RGL using mixins, which of course is not as
|
53
|
+
efficient than C++ templates (but much more readable :-). The second one is
|
54
|
+
even more easily implemented using standard iterators with blocks or using the
|
55
|
+
[stream](http://www.rubydoc.info/github/monora/stream) module. The third one
|
56
|
+
is no issue since Ruby is dynamically typed: Each object can be a graph
|
57
|
+
vertex. There is no need for a vertex (or even edge type). In the current
|
58
|
+
version of RGL properties of vertices are simply attached using hashes. At
|
59
|
+
first there seems to be not much need for the graph property machinery.
|
60
|
+
|
61
|
+
### Algorithms
|
62
|
+
|
63
|
+
RGL current contains a core set of algorithm patterns:
|
64
|
+
|
65
|
+
* Breadth First Search {RGL::BFSIterator}
|
66
|
+
* Depth First Search {RGL::DFSIterator}
|
67
|
+
|
68
|
+
|
69
|
+
The algorithm patterns by themselves do not compute any meaningful quantities
|
70
|
+
over graphs, they are merely building blocks for constructing graph
|
71
|
+
algorithms. The graph algorithms in RGL currently include:
|
72
|
+
|
73
|
+
* Topological Sort {RGL::TopsortIterator}
|
74
|
+
* Connected Components {RGL::Graph#each_connected_component}
|
75
|
+
* Strongly Connected Components {RGL::Graph#strongly_connected_components}
|
76
|
+
* Transitive Closure {RGL::Graph#transitive_closure}
|
77
|
+
* Dijkstras Shortest Path Algorithm {RGL::DijkstraAlgorithm}
|
78
|
+
* Bellman Ford Algorithm {RGL::BellmanFordAlgorithm}
|
79
|
+
|
80
|
+
|
81
|
+
### Data Structures
|
82
|
+
|
83
|
+
RGL currently provides two graph classes that implement a generalized
|
84
|
+
adjacency list and an edge list adaptor.
|
85
|
+
|
86
|
+
* {RGL::AdjacencyGraph}
|
87
|
+
* {RGL::ImplicitGraph}
|
88
|
+
|
89
|
+
|
90
|
+
The AdjacencyGraph class is the general purpose _swiss army knife_ of graph
|
91
|
+
classes. It is highly parameterized so that it can be optimized for different
|
92
|
+
situations: the graph is directed or undirected, allow or disallow parallel
|
93
|
+
edges, efficient access to just the out-edges, fast vertex insertion and
|
94
|
+
removal at the cost of extra space overhead, etc.
|
95
|
+
|
96
|
+
### Differences to BGL
|
97
|
+
|
98
|
+
The concepts of IncidenceGraph, AdjacencyGraph and VertexListGraph (see
|
99
|
+
http://www.boost.org/libs/graph/doc/IncidenceGraph.html) are here bundled in
|
100
|
+
the base graph module. Most methods of IncidenceGraph should be standard in
|
101
|
+
the base module Graph. The complexity guarantees can not necessarily provided.
|
102
|
+
See http://www.boost.org/libs/graph/doc/graph_concepts.html.
|
103
|
+
|
104
|
+
## Installation
|
105
|
+
|
106
|
+
% gem install rgl
|
107
|
+
|
108
|
+
or download the latest sources from the git repository
|
109
|
+
http://github.com/monora/rgl.
|
110
|
+
|
111
|
+
## Running tests
|
112
|
+
|
113
|
+
Checkout RGL git repository and go to the project directory. First, install
|
114
|
+
RGL dependencies with bundler:
|
115
|
+
|
116
|
+
% bundle install
|
117
|
+
|
118
|
+
After that you can run the tests:
|
119
|
+
|
120
|
+
% rake test
|
121
|
+
|
122
|
+
## Example irb session with RGL
|
123
|
+
|
124
|
+
irb> require 'rgl/adjacency'
|
125
|
+
irb> dg=RGL::DirectedAdjacencyGraph[1,2 ,2,3 ,2,4, 4,5, 6,4, 1,6]
|
126
|
+
# Use DOT to visualize this graph:
|
127
|
+
irb> require 'rgl/dot'
|
128
|
+
irb> dg.write_to_graphic_file('jpg')
|
129
|
+
"graph.jpg"
|
130
|
+
|
131
|
+
The result:
|
132
|
+
|
133
|
+

|
134
|
+
|
135
|
+
irb> dg.directed?
|
136
|
+
true
|
137
|
+
irb> dg.vertices
|
138
|
+
[5, 6, 1, 2, 3, 4]
|
139
|
+
irb> dg.has_vertex? 4
|
140
|
+
true
|
141
|
+
|
142
|
+
Every object could be a vertex (there is no class Vertex), even the class
|
143
|
+
object *Object*:
|
144
|
+
|
145
|
+
irb> dg.has_vertex? Object
|
146
|
+
false
|
147
|
+
irb> dg.edges.sort.to_s
|
148
|
+
"(1-2)(1-6)(2-3)(2-4)(4-5)(6-4)"
|
149
|
+
irb> dg.to_undirected.edges.sort.to_s
|
150
|
+
"(1=2)(1=6)(2=3)(2=4)(5=4)(6=4)"
|
151
|
+
|
152
|
+
Add inverse edge (4-2) to directed graph:
|
153
|
+
|
154
|
+
irb> dg.add_edge 4,2
|
155
|
+
|
156
|
+
(4-2) == (2-4) in the undirected graph:
|
157
|
+
|
158
|
+
irb> dg.to_undirected.edges.sort.to_s
|
159
|
+
"(1=2)(1=6)(2=3)(2=4)(5=4)(6=4)"
|
160
|
+
|
161
|
+
(4-2) != (2-4) in directed graphs:
|
162
|
+
|
163
|
+
irb> dg.edges.sort.to_s
|
164
|
+
"(1-2)(1-6)(2-3)(2-4)(4-2)(4-5)(6-4)"
|
165
|
+
irb> dg.remove_edge 4,2
|
166
|
+
true
|
167
|
+
|
168
|
+
*Topological sort* is implemented as an iterator:
|
169
|
+
|
170
|
+
require 'rgl/topsort'
|
171
|
+
irb> dg.topsort_iterator.to_a
|
172
|
+
[1, 2, 3, 6, 4, 5]
|
173
|
+
|
174
|
+
A more elaborated example showing *implicit graphs*:
|
175
|
+
|
176
|
+
require 'rgl/implicit'
|
177
|
+
def module_graph
|
178
|
+
RGL::ImplicitGraph.new { |g|
|
179
|
+
g.vertex_iterator { |b|
|
180
|
+
ObjectSpace.each_object(Module, &b)
|
181
|
+
}
|
182
|
+
g.adjacent_iterator { |x, b|
|
183
|
+
x.ancestors.each { |y|
|
184
|
+
b.call(y) unless x == y || y == Kernel || y == Object
|
185
|
+
}
|
186
|
+
}
|
187
|
+
g.directed = true
|
188
|
+
}
|
189
|
+
end
|
190
|
+
|
191
|
+
This function creates a directed graph, with vertices being all loaded
|
192
|
+
modules:
|
193
|
+
|
194
|
+
g = module_graph
|
195
|
+
|
196
|
+
We only want to see the ancestors of {RGL::AdjacencyGraph}:
|
197
|
+
|
198
|
+
require 'rgl/traversal'
|
199
|
+
tree = g.bfs_search_tree_from(RGL::AdjacencyGraph)
|
200
|
+
|
201
|
+
Now we want to visualize this component of g with DOT. We therefore create a
|
202
|
+
subgraph of the original graph, using a filtered graph:
|
203
|
+
|
204
|
+
g = g.vertices_filtered_by {|v| tree.has_vertex? v}
|
205
|
+
g.write_to_graphic_file('jpg')
|
206
|
+
|
207
|
+
creates the following graph image with DOT:
|
208
|
+
|
209
|
+

|
210
|
+
|
211
|
+
This graph shows all loaded RGL modules:
|
212
|
+
|
213
|
+

|
214
|
+
|
215
|
+
Look for more in
|
216
|
+
[examples](https://github.com/monora/rgl/tree/master/examples) directory.
|
217
|
+
|
218
|
+
I collect some links to stuff around RGL at http://del.icio.us/monora/rgl.
|
219
|
+
|
220
|
+
## Credits
|
221
|
+
|
222
|
+
Many thanks to Robert Feldt which also worked on a graph library
|
223
|
+
(http://rockit.sf.net/subprojects/graphr) who pointed me to BGL and many other
|
224
|
+
graph resources.
|
225
|
+
|
226
|
+
Robert kindly allowed to integrate his work on graphr, which I did not yet
|
227
|
+
succeed. Especially his work to output graphs for
|
228
|
+
[GraphViz](http://www.research.att.com/sw/tools/graphviz/download.html) is
|
229
|
+
much more elaborated than the minimal support in dot.rb.
|
230
|
+
|
231
|
+
Jeremy Siek one of the authors of the nice book [The Boost Graph
|
232
|
+
Library](http://www.boost.org/libs/graph/doc) kindly allowed to use the BGL
|
233
|
+
documentation as a *cheap* reference for RGL. He and Robert also gave feedback
|
234
|
+
and many ideas for RGL.
|
235
|
+
|
236
|
+
Dave Thomas for [RDoc](http://rdoc.sourceforge.net) which generated what you
|
237
|
+
read and matz for Ruby. Dave included in the latest version of RDoc (alpha9)
|
238
|
+
the module dot/dot.rb which I use instead of Roberts module to visualize
|
239
|
+
graphs (see rgl/dot.rb).
|
240
|
+
|
241
|
+
Jeremy Bopp, John Carter, Sascha Doerdelmann, Shawn Garbett, Andreas Schörk
|
242
|
+
and Kirill Lashuk for contributing additions, test cases and bugfixes.
|
243
|
+
|
244
|
+
Kirill Lashuk who started to take over further development in November 2012.
|
245
|
+
|
246
|
+
See also http://github.com/monora/rgl/contributors.
|
247
|
+
|
248
|
+
## Copying
|
249
|
+
|
250
|
+
RGL is Copyright (c) 2002,2004,2005,2008,2013,2015 by Horst Duchene. It is
|
251
|
+
free software, and may be redistributed under the terms specified in the
|
252
|
+
README file of the Ruby distribution.
|
data/Rakefile
CHANGED
@@ -6,12 +6,12 @@ require 'bundler/setup'
|
|
6
6
|
require 'rubygems/package_task'
|
7
7
|
|
8
8
|
require 'rake/testtask'
|
9
|
+
require 'rake/clean'
|
9
10
|
require 'yard'
|
10
11
|
|
11
12
|
$:.unshift File.join(File.dirname(__FILE__), 'lib')
|
12
13
|
require 'rgl/base' # require base module to get RGL_VERSION
|
13
14
|
|
14
|
-
SUMMARY = "Ruby Graph Library"
|
15
15
|
SOURCES = FileList['lib/**/*.rb']
|
16
16
|
|
17
17
|
# The default task is run if rake is given no explicit arguments.
|
@@ -26,20 +26,6 @@ Rake::TestTask.new do |t|
|
|
26
26
|
t.verbose = true
|
27
27
|
end
|
28
28
|
|
29
|
-
begin
|
30
|
-
require 'rcov/rcovtask'
|
31
|
-
|
32
|
-
desc "Calculate code coverage with rcov"
|
33
|
-
Rcov::RcovTask.new(:rcov) do |t|
|
34
|
-
t.libs << 'test'
|
35
|
-
t.pattern = 'test/*_test.rb'
|
36
|
-
t.verbose = true
|
37
|
-
t.rcov_opts += ['--exclude', 'test/,gems/']
|
38
|
-
end
|
39
|
-
rescue LoadError
|
40
|
-
nil # rcov is available only on Ruby 1.8
|
41
|
-
end
|
42
|
-
|
43
29
|
# Git tagging
|
44
30
|
|
45
31
|
desc "Commit all changes as a new version commit. Tag the commit with v<version> tag"
|
data/lib/rgl/base.rb
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
|
7
7
|
require 'rgl/enumerable_ext'
|
8
8
|
|
9
|
-
RGL_VERSION = "0.5.
|
9
|
+
RGL_VERSION = "0.5.2"
|
10
10
|
|
11
11
|
module RGL
|
12
12
|
class NotDirectedError < RuntimeError; end
|
@@ -77,6 +77,9 @@ module RGL
|
|
77
77
|
"(#{source}-#{target})"
|
78
78
|
end
|
79
79
|
|
80
|
+
# Since Ruby 2.0 #inspect no longer calls #to_s. So we alias it to to_s (fixes #22)
|
81
|
+
alias inspect to_s
|
82
|
+
|
80
83
|
# Returns the array [source,target].
|
81
84
|
#
|
82
85
|
def to_a
|
data/lib/rgl/bellman_ford.rb
CHANGED
data/lib/rgl/dijkstra.rb
CHANGED
@@ -2,8 +2,7 @@ require 'rgl/dijkstra_visitor'
|
|
2
2
|
require 'rgl/edge_properties_map'
|
3
3
|
require 'rgl/path_builder'
|
4
4
|
|
5
|
-
require '
|
6
|
-
require 'algorithms'
|
5
|
+
require 'lazy_priority_queue'
|
7
6
|
|
8
7
|
module RGL
|
9
8
|
|
@@ -55,7 +54,7 @@ module RGL
|
|
55
54
|
def init(source)
|
56
55
|
@visitor.set_source(source)
|
57
56
|
|
58
|
-
@queue =
|
57
|
+
@queue = MinPriorityQueue.new
|
59
58
|
@queue.push(source, 0)
|
60
59
|
end
|
61
60
|
|
@@ -82,8 +81,6 @@ module RGL
|
|
82
81
|
new_v_distance = @distance_combinator.call(@visitor.distance_map[u], @edge_weights_map.edge_property(u, v))
|
83
82
|
|
84
83
|
if new_v_distance < @visitor.distance_map[v]
|
85
|
-
old_v_distance = @visitor.distance_map[v]
|
86
|
-
|
87
84
|
@visitor.distance_map[v] = new_v_distance
|
88
85
|
@visitor.parents_map[v] = u
|
89
86
|
|
@@ -91,7 +88,7 @@ module RGL
|
|
91
88
|
@visitor.color_map[v] = :GRAY
|
92
89
|
@queue.push(v, new_v_distance)
|
93
90
|
elsif @visitor.color_map[v] == :GRAY
|
94
|
-
@queue.decrease_key(v,
|
91
|
+
@queue.decrease_key(v, new_v_distance)
|
95
92
|
end
|
96
93
|
|
97
94
|
@visitor.handle_edge_relaxed(u, v)
|
@@ -104,29 +101,6 @@ module RGL
|
|
104
101
|
edge_weights_map.is_a?(EdgePropertiesMap) ? edge_weights_map : NonNegativeEdgePropertiesMap.new(edge_weights_map, @graph.directed?)
|
105
102
|
end
|
106
103
|
|
107
|
-
class Queue < SimpleDelegator # :nodoc:
|
108
|
-
|
109
|
-
def initialize
|
110
|
-
@heap = Containers::Heap.new { |a, b| a.distance < b.distance }
|
111
|
-
super(@heap)
|
112
|
-
end
|
113
|
-
|
114
|
-
def push(vertex, distance)
|
115
|
-
@heap.push(vertex_key(vertex, distance), vertex)
|
116
|
-
end
|
117
|
-
|
118
|
-
def decrease_key(vertex, old_distance, new_distance)
|
119
|
-
@heap.change_key(vertex_key(vertex, old_distance), vertex_key(vertex, new_distance))
|
120
|
-
end
|
121
|
-
|
122
|
-
def vertex_key(vertex, distance)
|
123
|
-
VertexKey.new(vertex, distance)
|
124
|
-
end
|
125
|
-
|
126
|
-
VertexKey = Struct.new(:vertex, :distance)
|
127
|
-
|
128
|
-
end
|
129
|
-
|
130
104
|
end # class DijkstraAlgorithm
|
131
105
|
|
132
106
|
module Graph
|
data/lib/rgl/dot.rb
CHANGED
@@ -17,6 +17,10 @@ module RGL
|
|
17
17
|
v.to_s
|
18
18
|
end
|
19
19
|
|
20
|
+
def vertex_id(v)
|
21
|
+
v
|
22
|
+
end
|
23
|
+
|
20
24
|
# Return a RGL::DOT::Digraph for directed graphs or a DOT::Graph for an
|
21
25
|
# undirected Graph. _params_ can contain any graph property specified in
|
22
26
|
# rdot.rb.
|
@@ -29,7 +33,7 @@ module RGL
|
|
29
33
|
|
30
34
|
each_vertex do |v|
|
31
35
|
graph << DOT::Node.new(
|
32
|
-
'name' => v
|
36
|
+
'name' => vertex_id(v),
|
33
37
|
'fontsize' => fontsize,
|
34
38
|
'label' => vertex_label(v)
|
35
39
|
)
|
@@ -37,8 +41,8 @@ module RGL
|
|
37
41
|
|
38
42
|
each_edge do |u, v|
|
39
43
|
graph << edge_class.new(
|
40
|
-
'from' => u
|
41
|
-
'to' => v
|
44
|
+
'from' => vertex_id(u),
|
45
|
+
'to' => vertex_id(v),
|
42
46
|
'fontsize' => fontsize
|
43
47
|
)
|
44
48
|
end
|
data/lib/rgl/traversal.rb
CHANGED
@@ -169,6 +169,10 @@ module RGL
|
|
169
169
|
# it is called on each _finish_vertex_ event. See
|
170
170
|
# strongly_connected_components for an example usage.
|
171
171
|
#
|
172
|
+
# Note that this traversal does not garantee, that roots are at the top of
|
173
|
+
# each spanning subtree induced by the DFS search on a directed graph (see
|
174
|
+
# also the discussion in issue #20[https://github.com/monora/rgl/issues/20]).
|
175
|
+
#
|
172
176
|
def depth_first_search(vis = DFSVisitor.new(self), &b)
|
173
177
|
each_vertex do |u|
|
174
178
|
unless vis.finished_vertex?(u)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
require 'rgl/dijkstra'
|
4
|
+
require 'rgl/adjacency'
|
5
|
+
|
6
|
+
include RGL
|
7
|
+
|
8
|
+
class TestDijkstraIssue24 < Test::Unit::TestCase
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@graph = RGL::AdjacencyGraph[2,53, 2,3, 3,8, 3,28, 3,39, 29,58, 8,35, 12,39, 10,29, 62,15, 15,32, 32,58, 58,44, 44,53]
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_shortest_path_search
|
16
|
+
assert_equal([53, 44, 58, 32, 15, 62], shortest_path(53, 62))
|
17
|
+
end
|
18
|
+
|
19
|
+
def shortest_path(v,w)
|
20
|
+
@graph.dijkstra_shortest_path(Hash.new(1), v, w)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/test/dot_test.rb
CHANGED
@@ -10,25 +10,29 @@ class TestDot < Test::Unit::TestCase
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def test_to_dot_digraph
|
13
|
-
graph = RGL::DirectedAdjacencyGraph[
|
13
|
+
graph = RGL::DirectedAdjacencyGraph["a", "b"]
|
14
14
|
dot = graph.to_dot_graph.to_s
|
15
15
|
|
16
|
-
first_vertex_id =
|
17
|
-
second_vertex_id =
|
16
|
+
first_vertex_id = "a"
|
17
|
+
second_vertex_id = "b"
|
18
18
|
|
19
19
|
assert_match(dot, /\{[^}]*\}/) # {...}
|
20
20
|
assert_match(dot, /#{first_vertex_id}\s*\[/) # node 1
|
21
|
-
assert_match(dot, /label\s*=\s*
|
21
|
+
assert_match(dot, /label\s*=\s*a/) # node 1 label
|
22
22
|
assert_match(dot, /#{second_vertex_id}\s*\[/) # node 2
|
23
|
-
assert_match(dot, /label\s*=\s*
|
23
|
+
assert_match(dot, /label\s*=\s*b/) # node 2 label
|
24
24
|
assert_match(dot, /#{first_vertex_id}\s*->\s*#{second_vertex_id}/) # edge
|
25
25
|
end
|
26
26
|
|
27
27
|
def test_to_dot_graph
|
28
|
-
graph = RGL::AdjacencyGraph[
|
28
|
+
graph = RGL::AdjacencyGraph["a", "b"]
|
29
29
|
def graph.vertex_label(v)
|
30
30
|
"label-"+v.to_s
|
31
31
|
end
|
32
|
+
|
33
|
+
def graph.vertex_id(v)
|
34
|
+
"id-"+v.to_s
|
35
|
+
end
|
32
36
|
dot = graph.write_to_graphic_file
|
33
37
|
end
|
34
38
|
end
|
data/test/graph_test.rb
CHANGED
@@ -63,6 +63,11 @@ class TestGraph < Test::Unit::TestCase
|
|
63
63
|
assert_equal edges, @dg1.edges
|
64
64
|
end
|
65
65
|
|
66
|
+
# Test for issue #22
|
67
|
+
def test_edges_to_s
|
68
|
+
assert_equal @dg1.edges.sort.to_s, "[(1-2), (1-6), (2-3), (2-4), (4-5), (6-4)]"
|
69
|
+
end
|
70
|
+
|
66
71
|
def test_not_implemented
|
67
72
|
graph = NotImplementedGraph.new
|
68
73
|
assert_raise(NotImplementedError) { graph.each_vertex }
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rgl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
5
|
-
prerelease:
|
4
|
+
version: 0.5.2
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Horst Duchene
|
@@ -10,12 +9,11 @@ authors:
|
|
10
9
|
autorequire: rgl/base
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date:
|
12
|
+
date: 2016-05-09 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: stream
|
17
16
|
requirement: !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
17
|
requirements:
|
20
18
|
- - ~>
|
21
19
|
- !ruby/object:Gem::Version
|
@@ -23,73 +21,64 @@ dependencies:
|
|
23
21
|
type: :runtime
|
24
22
|
prerelease: false
|
25
23
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
none: false
|
27
24
|
requirements:
|
28
25
|
- - ~>
|
29
26
|
- !ruby/object:Gem::Version
|
30
27
|
version: 0.5.0
|
31
28
|
- !ruby/object:Gem::Dependency
|
32
|
-
name:
|
29
|
+
name: lazy_priority_queue
|
33
30
|
requirement: !ruby/object:Gem::Requirement
|
34
|
-
none: false
|
35
31
|
requirements:
|
36
32
|
- - ~>
|
37
33
|
- !ruby/object:Gem::Version
|
38
|
-
version: 0.
|
34
|
+
version: 0.1.0
|
39
35
|
type: :runtime
|
40
36
|
prerelease: false
|
41
37
|
version_requirements: !ruby/object:Gem::Requirement
|
42
|
-
none: false
|
43
38
|
requirements:
|
44
39
|
- - ~>
|
45
40
|
- !ruby/object:Gem::Version
|
46
|
-
version: 0.
|
41
|
+
version: 0.1.0
|
47
42
|
- !ruby/object:Gem::Dependency
|
48
43
|
name: rake
|
49
44
|
requirement: !ruby/object:Gem::Requirement
|
50
|
-
none: false
|
51
45
|
requirements:
|
52
|
-
- -
|
46
|
+
- - '>='
|
53
47
|
- !ruby/object:Gem::Version
|
54
48
|
version: '0'
|
55
49
|
type: :development
|
56
50
|
prerelease: false
|
57
51
|
version_requirements: !ruby/object:Gem::Requirement
|
58
|
-
none: false
|
59
52
|
requirements:
|
60
|
-
- -
|
53
|
+
- - '>='
|
61
54
|
- !ruby/object:Gem::Version
|
62
55
|
version: '0'
|
63
56
|
- !ruby/object:Gem::Dependency
|
64
57
|
name: yard
|
65
58
|
requirement: !ruby/object:Gem::Requirement
|
66
|
-
none: false
|
67
59
|
requirements:
|
68
|
-
- -
|
60
|
+
- - '>='
|
69
61
|
- !ruby/object:Gem::Version
|
70
62
|
version: '0'
|
71
63
|
type: :development
|
72
64
|
prerelease: false
|
73
65
|
version_requirements: !ruby/object:Gem::Requirement
|
74
|
-
none: false
|
75
66
|
requirements:
|
76
|
-
- -
|
67
|
+
- - '>='
|
77
68
|
- !ruby/object:Gem::Version
|
78
69
|
version: '0'
|
79
70
|
- !ruby/object:Gem::Dependency
|
80
71
|
name: test-unit
|
81
72
|
requirement: !ruby/object:Gem::Requirement
|
82
|
-
none: false
|
83
73
|
requirements:
|
84
|
-
- -
|
74
|
+
- - '>='
|
85
75
|
- !ruby/object:Gem::Version
|
86
76
|
version: '0'
|
87
77
|
type: :development
|
88
78
|
prerelease: false
|
89
79
|
version_requirements: !ruby/object:Gem::Requirement
|
90
|
-
none: false
|
91
80
|
requirements:
|
92
|
-
- -
|
81
|
+
- - '>='
|
93
82
|
- !ruby/object:Gem::Version
|
94
83
|
version: '0'
|
95
84
|
description: RGL is a framework for graph data structures and algorithms
|
@@ -97,7 +86,7 @@ email: monora@gmail.com
|
|
97
86
|
executables: []
|
98
87
|
extensions: []
|
99
88
|
extra_rdoc_files:
|
100
|
-
- README.
|
89
|
+
- README.md
|
101
90
|
files:
|
102
91
|
- lib/rgl/dijkstra.rb
|
103
92
|
- lib/rgl/edmonds_karp.rb
|
@@ -126,9 +115,6 @@ files:
|
|
126
115
|
- lib/rgl/graph_wrapper.rb
|
127
116
|
- lib/rgl/bipartite.rb
|
128
117
|
- ChangeLog
|
129
|
-
- examples/images/module_graph.jpg
|
130
|
-
- examples/images/example.jpg
|
131
|
-
- examples/images/rgl_modules.png
|
132
118
|
- examples/insel_der_tausend_gefahren.rb
|
133
119
|
- examples/rdep-rgl.rb
|
134
120
|
- examples/north2.rb
|
@@ -203,7 +189,6 @@ files:
|
|
203
189
|
- examples/north/g.10.2.graphml
|
204
190
|
- examples/examples.rb
|
205
191
|
- Gemfile
|
206
|
-
- README.rdoc
|
207
192
|
- Rakefile
|
208
193
|
- rakelib/dep_graph.rake
|
209
194
|
- test/dijkstra_test.rb
|
@@ -222,43 +207,38 @@ files:
|
|
222
207
|
- test/bellman_ford_test.rb
|
223
208
|
- test/rdot_test.rb
|
224
209
|
- test/cycles_test.rb
|
210
|
+
- test/dijkstra_issue24_test.rb
|
225
211
|
- test/test_helper.rb
|
226
212
|
- test/transitivity_test.rb
|
227
213
|
- test/bipartite_test.rb
|
214
|
+
- README.md
|
228
215
|
homepage: https://github.com/monora/rgl
|
229
216
|
licenses: []
|
217
|
+
metadata: {}
|
230
218
|
post_install_message:
|
231
219
|
rdoc_options:
|
232
220
|
- --title
|
233
221
|
- RGL - Ruby Graph Library
|
234
222
|
- --main
|
235
|
-
- README.
|
223
|
+
- README.md
|
236
224
|
- --line-numbers
|
237
225
|
require_paths:
|
238
226
|
- lib
|
239
227
|
required_ruby_version: !ruby/object:Gem::Requirement
|
240
|
-
none: false
|
241
228
|
requirements:
|
242
|
-
- -
|
229
|
+
- - '>='
|
243
230
|
- !ruby/object:Gem::Version
|
244
231
|
version: '0'
|
245
|
-
segments:
|
246
|
-
- 0
|
247
|
-
hash: 900116365
|
248
232
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
249
|
-
none: false
|
250
233
|
requirements:
|
251
|
-
- -
|
234
|
+
- - '>='
|
252
235
|
- !ruby/object:Gem::Version
|
253
236
|
version: '0'
|
254
|
-
segments:
|
255
|
-
- 0
|
256
|
-
hash: 900116365
|
257
237
|
requirements: []
|
258
238
|
rubyforge_project:
|
259
|
-
rubygems_version:
|
239
|
+
rubygems_version: 2.0.14
|
260
240
|
signing_key:
|
261
|
-
specification_version:
|
241
|
+
specification_version: 4
|
262
242
|
summary: Ruby Graph Library
|
263
243
|
test_files: []
|
264
244
|
has_rdoc: true
|
data/README.rdoc
DELETED
@@ -1,248 +0,0 @@
|
|
1
|
-
= Ruby Graph Library (RGL) {<img src="https://secure.travis-ci.org/monora/rgl.png?branch=master" alt="Build Status" />}[https://travis-ci.org/monora/rgl]
|
2
|
-
|
3
|
-
RGL is a framework for graph data structures and algorithms.
|
4
|
-
|
5
|
-
The design of the library is much influenced by the Boost Graph Library (BGL)
|
6
|
-
which is written in C++ heavily using its template mechanism. Refer to
|
7
|
-
http://www.boost.org/libs/graph/doc for further links and documentation on graph
|
8
|
-
data structures and algorithms and the design rationales of BGL.
|
9
|
-
|
10
|
-
A comprehensive summary of graph terminology can be found in the the graph
|
11
|
-
section of the <em>Dictionary of Algorithms and Data Structures</em> at
|
12
|
-
http://www.nist.gov/dads/HTML/graph.html.
|
13
|
-
|
14
|
-
== Design principles
|
15
|
-
|
16
|
-
This document concentrates on the special issues of the implementation in
|
17
|
-
Ruby. The main design goals directly taken from the BGL design are:
|
18
|
-
|
19
|
-
* An interface for how the structure of a graph can be accessed using a generic
|
20
|
-
interface that hides the details of the graph data structure
|
21
|
-
implementation. This interface is defined by the module {Graph}, which should be
|
22
|
-
included in concrete classes.
|
23
|
-
|
24
|
-
* A standardized generic interface for traversing graphs {RGL::GraphIterator}
|
25
|
-
|
26
|
-
RGL provides some general purpose graph classes that conform to this interface,
|
27
|
-
but they are not meant to be the *only* graph classes. As in BGL I believe that
|
28
|
-
the main contribution of the RGL is the formulation of this interface.
|
29
|
-
|
30
|
-
The BGL graph interface and graph components are generic in the sense of the C++
|
31
|
-
Standard Template Library (STL). In Ruby other techniques are available to
|
32
|
-
express the generic character of the algorithms and data structures mainly using
|
33
|
-
mixins and iterators. The BGL documentation mentions three means to achieve
|
34
|
-
genericity:
|
35
|
-
|
36
|
-
* Algorithm/Data-Structure Interoperability
|
37
|
-
* Extension through Function Objects and Visitors
|
38
|
-
* Element Type Parameterization
|
39
|
-
* Vertex and Edge Property Multi-Parameterization
|
40
|
-
|
41
|
-
The first is easily achieved in RGL using mixins, which of course is not as
|
42
|
-
efficient than C++ templates (but much more readable :-). The second one is even
|
43
|
-
more easily implemented using standard iterators with blocks or using the
|
44
|
-
{http://www.rubydoc.info/github/monora/stream stream module}. The third one is
|
45
|
-
no issue since Ruby is dynamically typed: Each object can be a graph vertex.
|
46
|
-
There is no need for a vertex (or even edge type). In the current version of RGL
|
47
|
-
properties of vertices are simply attached using hashes. At first there seems to
|
48
|
-
be not much need for the graph property machinery.
|
49
|
-
|
50
|
-
=== Algorithms
|
51
|
-
|
52
|
-
RGL current contains a core set of algorithm patterns:
|
53
|
-
|
54
|
-
* Breadth First Search {RGL::BFSIterator}
|
55
|
-
* Depth First Search {RGL::DFSIterator}
|
56
|
-
|
57
|
-
The algorithm patterns by themselves do not compute any meaningful quantities
|
58
|
-
over graphs, they are merely building blocks for constructing graph
|
59
|
-
algorithms. The graph algorithms in RGL currently include:
|
60
|
-
|
61
|
-
* Topological Sort {RGL::TopsortIterator}
|
62
|
-
* Connected Components {RGL::Graph#each_connected_component}
|
63
|
-
* Strongly Connected Components {RGL::Graph#strongly_connected_components}
|
64
|
-
* Transitive Closure {RGL::Graph#transitive_closure}
|
65
|
-
* Dijkstras Shortest Path Algorithm {RGL::DijkstraAlgorithm}
|
66
|
-
* Bellman Ford Algorithm {RGL::BellmanFordAlgorithm}
|
67
|
-
|
68
|
-
=== Data Structures
|
69
|
-
|
70
|
-
RGL currently provides two graph classes that implement a generalized adjacency
|
71
|
-
list and an edge list adaptor.
|
72
|
-
|
73
|
-
* {RGL::AdjacencyGraph}
|
74
|
-
* {RGL::ImplicitGraph}
|
75
|
-
|
76
|
-
The AdjacencyGraph class is the general purpose _swiss army knife_ of graph
|
77
|
-
classes. It is highly parameterized so that it can be optimized for different
|
78
|
-
situations: the graph is directed or undirected, allow or disallow parallel
|
79
|
-
edges, efficient access to just the out-edges, fast vertex insertion and removal
|
80
|
-
at the cost of extra space overhead, etc.
|
81
|
-
|
82
|
-
=== Differences to BGL
|
83
|
-
|
84
|
-
The concepts of IncidenceGraph, AdjacencyGraph and VertexListGraph (see
|
85
|
-
http://www.boost.org/libs/graph/doc/IncidenceGraph.html) are here bundled in the
|
86
|
-
base graph module. Most methods of IncidenceGraph should be standard in the base
|
87
|
-
module Graph. The complexity guarantees can not necessarily provided. See
|
88
|
-
http://www.boost.org/libs/graph/doc/graph_concepts.html.
|
89
|
-
|
90
|
-
== Installation
|
91
|
-
|
92
|
-
% gem install rgl
|
93
|
-
|
94
|
-
or download the latest sources from the git repository http://github.com/monora/rgl.
|
95
|
-
|
96
|
-
== Running tests
|
97
|
-
|
98
|
-
Checkout RGL git repository and go to the project directory. First, install RGL
|
99
|
-
dependencies with bundler:
|
100
|
-
|
101
|
-
% bundle install
|
102
|
-
|
103
|
-
After that you can run the tests:
|
104
|
-
|
105
|
-
% rake test
|
106
|
-
|
107
|
-
To see tests coverage run rcov[http://github.com/relevance/rcov] rake task:
|
108
|
-
|
109
|
-
% rake rcov
|
110
|
-
|
111
|
-
This command will generate tests coverage report in coverage/ directory.
|
112
|
-
|
113
|
-
<em>Node: rcov is not compatible with Ruby >= 1.9, so this rake task is
|
114
|
-
available only on Ruby 1.8.</em>
|
115
|
-
|
116
|
-
== Example irb session with RGL
|
117
|
-
|
118
|
-
|
119
|
-
irb> require 'rgl/adjacency'
|
120
|
-
irb> dg=RGL::DirectedAdjacencyGraph[1,2 ,2,3 ,2,4, 4,5, 6,4, 1,6]
|
121
|
-
# Use DOT to visualize this graph:
|
122
|
-
irb> require 'rgl/dot'
|
123
|
-
irb> dg.write_to_graphic_file('jpg')
|
124
|
-
"graph.jpg"
|
125
|
-
|
126
|
-
The result:
|
127
|
-
|
128
|
-
link:images/example.jpg
|
129
|
-
|
130
|
-
irb> dg.directed?
|
131
|
-
true
|
132
|
-
irb> dg.vertices
|
133
|
-
[5, 6, 1, 2, 3, 4]
|
134
|
-
irb> dg.has_vertex? 4
|
135
|
-
true
|
136
|
-
|
137
|
-
Every object could be a vertex (there is no class Vertex), even the class
|
138
|
-
object _Object_:
|
139
|
-
|
140
|
-
irb> dg.has_vertex? Object
|
141
|
-
false
|
142
|
-
irb> dg.edges.sort.to_s
|
143
|
-
"(1-2)(1-6)(2-3)(2-4)(4-5)(6-4)"
|
144
|
-
irb> dg.to_undirected.edges.sort.to_s
|
145
|
-
"(1=2)(1=6)(2=3)(2=4)(5=4)(6=4)"
|
146
|
-
|
147
|
-
Add inverse edge (4-2) to directed graph:
|
148
|
-
|
149
|
-
irb> dg.add_edge 4,2
|
150
|
-
|
151
|
-
(4-2) == (2-4) in the undirected graph:
|
152
|
-
|
153
|
-
irb> dg.to_undirected.edges.sort.to_s
|
154
|
-
"(1=2)(1=6)(2=3)(2=4)(5=4)(6=4)"
|
155
|
-
|
156
|
-
(4-2) != (2-4) in directed graphs:
|
157
|
-
|
158
|
-
irb> dg.edges.sort.to_s
|
159
|
-
"(1-2)(1-6)(2-3)(2-4)(4-2)(4-5)(6-4)"
|
160
|
-
irb> dg.remove_edge 4,2
|
161
|
-
true
|
162
|
-
|
163
|
-
<em>Topological sort</em> is implemented as an iterator:
|
164
|
-
|
165
|
-
require 'rgl/topsort'
|
166
|
-
irb> dg.topsort_iterator.to_a
|
167
|
-
[1, 2, 3, 6, 4, 5]
|
168
|
-
|
169
|
-
A more elaborated example showing <em>implicit graphs</em>:
|
170
|
-
|
171
|
-
require 'rgl/implicit'
|
172
|
-
def module_graph
|
173
|
-
RGL::ImplicitGraph.new { |g|
|
174
|
-
g.vertex_iterator { |b|
|
175
|
-
ObjectSpace.each_object(Module, &b)
|
176
|
-
}
|
177
|
-
g.adjacent_iterator { |x, b|
|
178
|
-
x.ancestors.each { |y|
|
179
|
-
b.call(y) unless x == y || y == Kernel || y == Object
|
180
|
-
}
|
181
|
-
}
|
182
|
-
g.directed = true
|
183
|
-
}
|
184
|
-
end
|
185
|
-
|
186
|
-
This function creates a directed graph, with vertices being all loaded modules:
|
187
|
-
|
188
|
-
g = module_graph
|
189
|
-
|
190
|
-
We only want to see the ancestors of {RGL::AdjacencyGraph}:
|
191
|
-
|
192
|
-
require 'rgl/traversal'
|
193
|
-
tree = g.bfs_search_tree_from(RGL::AdjacencyGraph)
|
194
|
-
|
195
|
-
Now we want to visualize this component of g with DOT. We therefore create a
|
196
|
-
subgraph of the original graph, using a filtered graph:
|
197
|
-
|
198
|
-
g = g.vertices_filtered_by {|v| tree.has_vertex? v}
|
199
|
-
g.write_to_graphic_file('jpg')
|
200
|
-
|
201
|
-
creates the following graph image with DOT:
|
202
|
-
|
203
|
-
link:images/module_graph.jpg
|
204
|
-
|
205
|
-
This graph shows all loaded RGL modules:
|
206
|
-
|
207
|
-
link:images/rgl_modules.png
|
208
|
-
|
209
|
-
Look for more in _examples_ directory (i.e. {file:examples/examples.rb}).
|
210
|
-
|
211
|
-
== My del.icio.us links concerning RGL
|
212
|
-
|
213
|
-
I collect some links to stuff around RGL at http://del.icio.us/monora/rgl.
|
214
|
-
|
215
|
-
== Credits
|
216
|
-
|
217
|
-
Many thanks to Robert Feldt which also worked on a graph library
|
218
|
-
(http://rockit.sf.net/subprojects/graphr) who pointed me to BGL and many other
|
219
|
-
graph resources.
|
220
|
-
|
221
|
-
Robert kindly allowed to integrate his work on graphr, which I did not yet
|
222
|
-
succeed. Especially his work to output graphs for
|
223
|
-
GraphViz[http://www.research.att.com/sw/tools/graphviz/download.html] is much
|
224
|
-
more elaborated than the minimal support in dot.rb.
|
225
|
-
|
226
|
-
Jeremy Siek one of the authors of the nice book "The Boost Graph Library (BGL)"
|
227
|
-
(http://www.boost.org/libs/graph/doc) kindly allowed to use the
|
228
|
-
BGL documentation as a _cheap_ reference for RGL. He and Robert also gave
|
229
|
-
feedback and many ideas for RGL.
|
230
|
-
|
231
|
-
Dave Thomas for RDoc[http://rdoc.sourceforge.net] which generated what you read
|
232
|
-
and matz for Ruby. Dave included in the latest version of RDoc (alpha9) the
|
233
|
-
module dot/dot.rb which I use instead of Roberts module to visualize graphs
|
234
|
-
(see rgl/dot.rb).
|
235
|
-
|
236
|
-
Jeremy Bopp, John Carter, Sascha Doerdelmann, Shawn Garbett, Andreas Schörk
|
237
|
-
and Kirill Lashuk for contributing additions, test cases and bugfixes.
|
238
|
-
|
239
|
-
Kirill Lashuk who started to take over further development in November 2012.
|
240
|
-
|
241
|
-
See also http://github.com/monora/rgl/contributors.
|
242
|
-
|
243
|
-
== Copying
|
244
|
-
|
245
|
-
RGL is Copyright (c) 2002,2004,2005,2008,2013,2015 by Horst Duchene. It is free software,
|
246
|
-
and may be redistributed under the terms specified in the README file of the
|
247
|
-
Ruby distribution.
|
248
|
-
|
data/examples/images/example.jpg
DELETED
Binary file
|
Binary file
|
Binary file
|