rgl 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,
|