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.
- data/ChangeLog +19 -10
- data/Gemfile +3 -0
- data/{README → README.rdoc} +70 -98
- data/Rakefile +44 -150
- data/examples/canvas.rb +63 -64
- data/examples/examples.rb +42 -42
- data/examples/graph.dot +46 -0
- data/examples/images/example.jpg +0 -0
- data/examples/images/module_graph.jpg +0 -0
- data/examples/images/rgl_modules.png +0 -0
- data/examples/{insel-der-tausend-gefahren.rb → insel_der_tausend_gefahren.rb} +18 -19
- data/examples/north.rb +2 -2
- data/examples/north2.rb +11 -11
- data/examples/rdep-rgl.rb +218 -222
- data/lib/rgl/adjacency.rb +78 -74
- data/lib/rgl/base.rb +160 -78
- data/lib/rgl/bellman_ford.rb +115 -0
- data/lib/rgl/bidirectional.rb +17 -10
- data/lib/rgl/bipartite.rb +87 -0
- data/lib/rgl/condensation.rb +13 -4
- data/lib/rgl/connected_components.rb +38 -30
- data/lib/rgl/dijkstra.rb +158 -0
- data/lib/rgl/dijkstra_visitor.rb +42 -0
- data/lib/rgl/dot.rb +40 -32
- data/lib/rgl/edge_properties_map.rb +55 -0
- data/lib/rgl/edmonds_karp.rb +136 -0
- data/lib/rgl/enumerable_ext.rb +4 -1
- data/lib/rgl/graph_iterator.rb +15 -0
- data/lib/rgl/graph_visitor.rb +138 -0
- data/lib/rgl/graph_wrapper.rb +15 -0
- data/lib/rgl/graphxml.rb +20 -10
- data/lib/rgl/implicit.rb +68 -66
- data/lib/rgl/mutable.rb +37 -31
- data/lib/rgl/path_builder.rb +40 -0
- data/lib/rgl/prim.rb +52 -0
- data/lib/rgl/rdot.rb +411 -374
- data/lib/rgl/topsort.rb +23 -16
- data/lib/rgl/transitivity.rb +29 -27
- data/lib/rgl/traversal.rb +67 -205
- data/rakelib/dep_graph.rake +4 -3
- data/test/bellman_ford_test.rb +187 -0
- data/test/bipartite_test.rb +47 -0
- data/test/components_test.rb +80 -0
- data/test/cycles_test.rb +60 -0
- data/test/dijkstra_test.rb +148 -0
- data/test/directed_graph_test.rb +118 -0
- data/test/dot_test.rb +26 -0
- data/test/edge_properties_map_test.rb +63 -0
- data/test/edge_test.rb +35 -0
- data/test/edmonds_karp_test.rb +105 -0
- data/{tests/TestGraph.rb → test/graph_test.rb} +6 -6
- data/test/graph_xml_test.rb +57 -0
- data/test/implicit_test.rb +53 -0
- data/test/prim_test.rb +98 -0
- data/{tests/TestRdot.rb → test/rdot_test.rb} +309 -308
- data/{tests → test}/test_helper.rb +4 -1
- data/{tests/TestTransitivity.rb → test/transitivity_test.rb} +43 -43
- data/test/traversal_test.rb +221 -0
- data/test/undirected_graph_test.rb +103 -0
- metadata +226 -145
- data/examples/example.jpg +0 -0
- data/examples/module_graph.jpg +0 -0
- data/install.rb +0 -49
- data/tests/TestComponents.rb +0 -65
- data/tests/TestCycles.rb +0 -61
- data/tests/TestDirectedGraph.rb +0 -125
- data/tests/TestDot.rb +0 -18
- data/tests/TestEdge.rb +0 -34
- data/tests/TestGraphXML.rb +0 -57
- data/tests/TestImplicit.rb +0 -52
- data/tests/TestTraversal.rb +0 -220
- data/tests/TestUnDirectedGraph.rb +0 -102
data/examples/canvas.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# From c.l.r SNIP IT: bond TkCanvas with RubyGraphLibrary
|
2
2
|
# author: Phlip (see also
|
3
|
-
# http://www.rubygarden.org/ruby?RubyAlgorithmPackage/TkCanvasSample)
|
4
|
-
#
|
3
|
+
# http://www.rubygarden.org/ruby?RubyAlgorithmPackage/TkCanvasSample)
|
4
|
+
#
|
5
5
|
# put a GraphViz graph into a TkCanvas, and make nodes
|
6
6
|
# selectable. Illustrates a bug in GraphViz
|
7
7
|
|
@@ -19,83 +19,82 @@ puts 'Displaying ' + filename
|
|
19
19
|
# ruby canvas.rb north/g.14.9.graphml &
|
20
20
|
|
21
21
|
File.open(filename) { |file|
|
22
|
-
graph = DirectedAdjacencyGraph.from_graphxml(file)
|
22
|
+
graph = DirectedAdjacencyGraph.from_graphxml(file)
|
23
23
|
graph.write_to_graphic_file('gif', filename)
|
24
24
|
graph.write_to_graphic_file('plain', filename)
|
25
|
-
root = TkRoot.new{title "Ex1"}
|
26
|
-
|
27
|
-
canvas = TkCanvas.new(root)
|
28
|
-
|
29
|
-
|
25
|
+
root = TkRoot.new { title "Ex1" }
|
26
|
+
|
27
|
+
canvas = TkCanvas.new(root) {
|
28
|
+
width 400
|
29
|
+
height 600
|
30
30
|
}
|
31
31
|
canvas.pack()
|
32
32
|
ovals = []
|
33
33
|
|
34
34
|
TkcImage.new(canvas, 0, 0) {
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
35
|
+
anchor 'nw'
|
36
|
+
|
37
|
+
image TkPhotoImage.new() {
|
38
|
+
file filename + '.gif'
|
39
|
+
}
|
40
40
|
}
|
41
41
|
|
42
42
|
# read the 'plain' file, and for each node put an invisible
|
43
43
|
# oval over its image
|
44
|
-
|
45
|
-
File.open(filename + '.plain')
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
end
|
44
|
+
|
45
|
+
File.open(filename + '.plain') { |f|
|
46
|
+
graphLine = f.readline()
|
47
|
+
graphStats = graphLine.split()
|
48
|
+
graphHeight = graphStats[3].to_f()
|
49
|
+
nodeLine = f.readline()
|
50
|
+
fields = nodeLine.split()
|
51
|
+
|
52
|
+
while fields[0] == 'node'
|
53
|
+
namer = fields[1]
|
54
|
+
|
55
|
+
# the following crud is because GraphViz has no system to
|
56
|
+
# emit a "plain" format in pixels that exactly match the
|
57
|
+
# locations of objects in dot's raster output
|
58
|
+
|
59
|
+
# furtherless, the current GraphViz seems to be centering
|
60
|
+
# the raster output but not the 'plain' output. Hence on
|
61
|
+
# g.10.8.graphml the X fudge factor must be 45. >sigh<
|
62
|
+
|
63
|
+
# YMMV, based on your system's opinion of the size of an inch
|
64
|
+
|
65
|
+
exx = fields[2].to_f * 96 - 20 # 45
|
66
|
+
why = (graphHeight - fields[3].to_f) * 96 - 20
|
67
|
+
widt = fields[4].to_f() * 90
|
68
|
+
hite = fields[5].to_f() * 90
|
69
|
+
|
70
|
+
ov = TkcOval.new(canvas, exx, why, exx + widt, why + hite) {
|
71
|
+
state 'hidden'
|
72
|
+
width 4
|
73
|
+
outline 'green'
|
74
|
+
tags namer
|
75
|
+
}
|
76
|
+
ovals.push(ov)
|
77
|
+
nodeLine = f.readline()
|
78
|
+
fields = nodeLine.split()
|
79
|
+
end
|
81
80
|
}
|
82
81
|
lastOval = ovals[0]
|
83
82
|
|
84
83
|
# at click time, search for an oval in range and display it
|
85
|
-
|
86
|
-
canvas.bind('Button-1')
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
84
|
+
|
85
|
+
canvas.bind('Button-1') do |event|
|
86
|
+
x, y = canvas.canvasx(event.x), canvas.canvasy(event.y)
|
87
|
+
|
88
|
+
ovals.each { |r|
|
89
|
+
x1, y1, x2, y2 = r.coords()
|
90
|
+
|
91
|
+
if x >= x1 and x <= x2 and y >= y1 and y <= y2
|
92
|
+
lastOval.configure('state' => 'hidden')
|
93
|
+
lastOval = r
|
94
|
+
lastOval.configure('state' => 'normal')
|
95
|
+
break
|
96
|
+
end
|
97
|
+
}
|
99
98
|
end
|
100
99
|
|
101
100
|
Tk.mainloop
|
data/examples/examples.rb
CHANGED
@@ -4,12 +4,12 @@ require 'rgl/adjacency'
|
|
4
4
|
require 'rgl/implicit'
|
5
5
|
|
6
6
|
# partite 8, 5
|
7
|
-
def partite(n,m)
|
7
|
+
def partite(n, m)
|
8
8
|
result = RGL::DirectedAdjacencyGraph.new
|
9
9
|
1.upto(n) { |i|
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
1.upto(m) { |j|
|
11
|
+
result.add_edge('a' + i.to_s, 'b' + j.to_s)
|
12
|
+
}
|
13
13
|
}
|
14
14
|
result
|
15
15
|
end
|
@@ -18,8 +18,8 @@ end
|
|
18
18
|
def modulo (n, m)
|
19
19
|
result = RGL::AdjacencyGraph.new
|
20
20
|
1.upto(n) { |x|
|
21
|
-
1.upto(n) {|y|
|
22
|
-
result.add_edge x,y if x != y && x%m == y%m }
|
21
|
+
1.upto(n) { |y|
|
22
|
+
result.add_edge x, y if x != y && x % m == y % m }
|
23
23
|
}
|
24
24
|
result
|
25
25
|
end
|
@@ -27,9 +27,9 @@ end
|
|
27
27
|
# Cyclic graph with _n_ vertices
|
28
28
|
def cycle (n)
|
29
29
|
RGL::ImplicitGraph.new { |g|
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
g.vertex_iterator { |b| 0.upto(n - 1, &b) }
|
31
|
+
g.adjacent_iterator { |x, b| b.call((x + 1) % n) }
|
32
|
+
g.directed = true
|
33
33
|
}
|
34
34
|
end
|
35
35
|
|
@@ -37,40 +37,40 @@ end
|
|
37
37
|
def complete (n)
|
38
38
|
set = n.integer? ? (1..n) : n
|
39
39
|
RGL::ImplicitGraph.new { |g|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
40
|
+
g.vertex_iterator { |b| set.each(&b) }
|
41
|
+
g.adjacent_iterator { |x, b|
|
42
|
+
set.each { |y| b.call(y) unless x == y }
|
43
|
+
}
|
44
44
|
}
|
45
45
|
end
|
46
46
|
|
47
47
|
# Directed graph of ruby modules. Edges are defined by the method _ancestors_
|
48
48
|
def module_graph
|
49
49
|
RGL::ImplicitGraph.new { |g|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
50
|
+
g.vertex_iterator { |b|
|
51
|
+
ObjectSpace.each_object(Module, &b)
|
52
|
+
}
|
53
|
+
g.adjacent_iterator { |x, b|
|
54
|
+
x.ancestors.each { |y|
|
55
|
+
b.call(y) unless x == y || y == Kernel || y == Object
|
56
|
+
}
|
57
|
+
}
|
58
|
+
g.directed = true
|
59
59
|
}
|
60
60
|
end
|
61
61
|
|
62
62
|
# Shows graph of divisors of all integers from 2 to _n_.
|
63
63
|
def divisors(n)
|
64
64
|
RGL::ImplicitGraph.new { |g|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
65
|
+
g.vertex_iterator { |b| 2.upto(n, &b) }
|
66
|
+
g.adjacent_iterator { |x, b|
|
67
|
+
n.downto(x + 1) { |y| b.call(y) if y % x == 0 }
|
68
|
+
}
|
69
|
+
g.directed = true
|
70
70
|
}
|
71
71
|
end
|
72
72
|
|
73
|
-
def bfs_example(g=cycle(5), start=g.detect {|x| true})
|
73
|
+
def bfs_example(g = cycle(5), start = g.detect { |x| true })
|
74
74
|
require 'rgl/traversal'
|
75
75
|
|
76
76
|
g.bfs_search_tree_from(start)
|
@@ -81,15 +81,15 @@ def graph_from_dotfile (file)
|
|
81
81
|
g = RGL::AdjacencyGraph.new
|
82
82
|
pattern = /\s*([^\"]+)[\"\s]*--[\"\s]*([^\"\[\;]+)/ # ugly but works
|
83
83
|
IO.foreach(file) { |line|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
84
|
+
case line
|
85
|
+
when /^digraph/
|
86
|
+
g = RGL::DirectedAdjacencyGraph.new
|
87
|
+
pattern = /\s*([^\"]+)[\"\s]*->[\"\s]*([^\"\[\;]+)/
|
88
|
+
when pattern
|
89
|
+
g.add_edge $1, $2
|
90
|
+
else
|
91
|
+
nil
|
92
|
+
end
|
93
93
|
}
|
94
94
|
g
|
95
95
|
end
|
@@ -99,15 +99,15 @@ end
|
|
99
99
|
if $0 == __FILE__
|
100
100
|
require 'rgl/dot'
|
101
101
|
|
102
|
-
dg = RGL::DirectedAdjacencyGraph[1,2
|
102
|
+
dg = RGL::DirectedAdjacencyGraph[1,2, 2,3, 2,4, 4,5, 6,4, 1,6]
|
103
103
|
dg.dotty
|
104
104
|
dg.write_to_graphic_file
|
105
|
-
bfs_example(dg,1).dotty
|
106
|
-
bfs_example(graph_from_dotfile('dot/unix.dot'), 'Interdata').dotty({'label'=>'Interdata Nachfolger', 'fontsize' => 12})
|
105
|
+
bfs_example(dg, 1).dotty
|
106
|
+
bfs_example(graph_from_dotfile('dot/unix.dot'), 'Interdata').dotty({ 'label' => 'Interdata Nachfolger', 'fontsize' => 12 })
|
107
107
|
|
108
108
|
g = module_graph
|
109
|
-
tree = bfs_example(module_graph,RGL::AdjacencyGraph)
|
110
|
-
g = g.vertices_filtered_by {|v| tree.has_vertex? v}
|
109
|
+
tree = bfs_example(module_graph, RGL::AdjacencyGraph)
|
110
|
+
g = g.vertices_filtered_by { |v| tree.has_vertex? v }
|
111
111
|
g.write_to_graphic_file
|
112
112
|
g.dotty
|
113
113
|
end
|
data/examples/graph.dot
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
subgraph RGL__AdjacencyGraph {
|
2
|
+
0 [
|
3
|
+
fontsize = 8,
|
4
|
+
label = 0
|
5
|
+
]
|
6
|
+
|
7
|
+
1 [
|
8
|
+
fontsize = 8,
|
9
|
+
label = 1
|
10
|
+
]
|
11
|
+
|
12
|
+
2 [
|
13
|
+
fontsize = 8,
|
14
|
+
label = 2
|
15
|
+
]
|
16
|
+
|
17
|
+
3 [
|
18
|
+
fontsize = 8,
|
19
|
+
label = 3
|
20
|
+
]
|
21
|
+
|
22
|
+
4 [
|
23
|
+
fontsize = 8,
|
24
|
+
label = 4
|
25
|
+
]
|
26
|
+
|
27
|
+
0 -- 1 [
|
28
|
+
fontsize = 8
|
29
|
+
]
|
30
|
+
|
31
|
+
0 -- 4 [
|
32
|
+
fontsize = 8
|
33
|
+
]
|
34
|
+
|
35
|
+
1 -- 2 [
|
36
|
+
fontsize = 8
|
37
|
+
]
|
38
|
+
|
39
|
+
2 -- 3 [
|
40
|
+
fontsize = 8
|
41
|
+
]
|
42
|
+
|
43
|
+
3 -- 4 [
|
44
|
+
fontsize = 8
|
45
|
+
]
|
46
|
+
}
|
Binary file
|
Binary file
|
Binary file
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# Die Insel der 1000 Gefahren
|
2
2
|
# http://www.amazon.de/1000-Gefahren-Die-Insel/dp/3473520225/ref=pd_sim_b?ie=UTF8&qid=1203279845&sr=8-3
|
3
3
|
|
4
|
-
require 'rubygems' rescue nil
|
5
4
|
require 'rgl/adjacency'
|
6
5
|
require 'rgl/implicit'
|
7
6
|
require 'rgl/dot'
|
@@ -18,16 +17,16 @@ g = RGL::DirectedAdjacencyGraph[
|
|
18
17
|
|
19
18
|
11, 15,
|
20
19
|
11, 16,
|
21
|
-
|
20
|
+
|
22
21
|
12, 17,
|
23
|
-
12, 18,
|
22
|
+
12, 18,
|
24
23
|
|
25
|
-
13, 19,
|
24
|
+
13, 19,
|
26
25
|
13, 20,
|
27
26
|
|
28
27
|
14, 21,
|
29
28
|
14, 22,
|
30
|
-
|
29
|
+
|
31
30
|
15, 23,
|
32
31
|
15, 24,
|
33
32
|
|
@@ -38,12 +37,12 @@ g = RGL::DirectedAdjacencyGraph[
|
|
38
37
|
17, 28,
|
39
38
|
|
40
39
|
18, 29,
|
41
|
-
18, 30,
|
40
|
+
18, 30,
|
42
41
|
|
43
42
|
18, 31,
|
44
43
|
18, 32,
|
45
44
|
|
46
|
-
19, 31,
|
45
|
+
19, 31,
|
47
46
|
19, 32,
|
48
47
|
|
49
48
|
20, 33,
|
@@ -58,7 +57,7 @@ g = RGL::DirectedAdjacencyGraph[
|
|
58
57
|
23, 39,
|
59
58
|
23, 40,
|
60
59
|
|
61
|
-
24, 41,
|
60
|
+
24, 41,
|
62
61
|
24, 42,
|
63
62
|
|
64
63
|
25, 43,
|
@@ -71,29 +70,29 @@ g = RGL::DirectedAdjacencyGraph[
|
|
71
70
|
27, 48,
|
72
71
|
|
73
72
|
28, 49,
|
74
|
-
28, 50,
|
73
|
+
28, 50,
|
75
74
|
|
76
75
|
29, 51,
|
77
|
-
29, 52,
|
76
|
+
29, 52,
|
78
77
|
|
79
78
|
30, 53,
|
80
79
|
30, 54,
|
81
|
-
|
80
|
+
|
82
81
|
31, 55,
|
83
|
-
31, 56,
|
84
|
-
|
82
|
+
31, 56,
|
83
|
+
|
85
84
|
32, 57,
|
86
85
|
32, 58,
|
87
86
|
|
88
87
|
33, 59,
|
89
88
|
33, 60,
|
90
|
-
|
89
|
+
|
91
90
|
34, 61,
|
92
91
|
34, 62,
|
93
92
|
|
94
93
|
35, 63,
|
95
94
|
35, 64,
|
96
|
-
|
95
|
+
|
97
96
|
36, 65,
|
98
97
|
36, 66,
|
99
98
|
|
@@ -135,9 +134,9 @@ g = RGL::DirectedAdjacencyGraph[
|
|
135
134
|
53, 91,
|
136
135
|
|
137
136
|
55, 93,
|
138
|
-
55, 94,
|
137
|
+
55, 94,
|
138
|
+
|
139
139
|
|
140
|
-
|
141
140
|
57, 92,
|
142
141
|
|
143
142
|
|
@@ -155,7 +154,7 @@ g = RGL::DirectedAdjacencyGraph[
|
|
155
154
|
61, 103,
|
156
155
|
|
157
156
|
62, 104,
|
158
|
-
62, 105,
|
157
|
+
62, 105,
|
159
158
|
|
160
159
|
64, 88,
|
161
160
|
|
@@ -168,7 +167,7 @@ g = RGL::DirectedAdjacencyGraph[
|
|
168
167
|
67, 109,
|
169
168
|
|
170
169
|
75, 9,
|
171
|
-
|
170
|
+
|
172
171
|
78, 26,
|
173
172
|
|
174
173
|
86, 30,
|