gratr19 0.4.4
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/README +335 -0
- data/examples/graph_self.rb +54 -0
- data/examples/module_graph.jpg +0 -0
- data/examples/module_graph.rb +12 -0
- data/examples/self_graph.jpg +0 -0
- data/examples/visualize.jpg +0 -0
- data/examples/visualize.rb +8 -0
- data/install.rb +49 -0
- data/lib/gratr.rb +42 -0
- data/lib/gratr/adjacency_graph.rb +230 -0
- data/lib/gratr/base.rb +34 -0
- data/lib/gratr/biconnected.rb +116 -0
- data/lib/gratr/chinese_postman.rb +123 -0
- data/lib/gratr/common.rb +74 -0
- data/lib/gratr/comparability.rb +92 -0
- data/lib/gratr/digraph.rb +115 -0
- data/lib/gratr/digraph_distance.rb +185 -0
- data/lib/gratr/dot.rb +90 -0
- data/lib/gratr/edge.rb +145 -0
- data/lib/gratr/graph.rb +314 -0
- data/lib/gratr/graph_api.rb +82 -0
- data/lib/gratr/import.rb +44 -0
- data/lib/gratr/labels.rb +103 -0
- data/lib/gratr/maximum_flow.rb +107 -0
- data/lib/gratr/rdot.rb +332 -0
- data/lib/gratr/search.rb +422 -0
- data/lib/gratr/strong_components.rb +127 -0
- data/lib/gratr/undirected_graph.rb +153 -0
- data/lib/gratr/version.rb +6 -0
- data/lib/priority-queue/benchmark/dijkstra.rb +171 -0
- data/lib/priority-queue/compare_comments.rb +49 -0
- data/lib/priority-queue/ext/priority_queue/CPriorityQueue/extconf.rb +2 -0
- data/lib/priority-queue/lib/priority_queue.rb +14 -0
- data/lib/priority-queue/lib/priority_queue/c_priority_queue.rb +1 -0
- data/lib/priority-queue/lib/priority_queue/poor_priority_queue.rb +46 -0
- data/lib/priority-queue/lib/priority_queue/ruby_priority_queue.rb +525 -0
- data/lib/priority-queue/setup.rb +1551 -0
- data/lib/priority-queue/test/priority_queue_test.rb +371 -0
- data/tests/TestBiconnected.rb +53 -0
- data/tests/TestChinesePostman.rb +53 -0
- data/tests/TestComplement.rb +54 -0
- data/tests/TestDigraph.rb +333 -0
- data/tests/TestDigraphDistance.rb +138 -0
- data/tests/TestDot.rb +75 -0
- data/tests/TestEdge.rb +171 -0
- data/tests/TestInspection.rb +57 -0
- data/tests/TestMultiEdge.rb +57 -0
- data/tests/TestNeighborhood.rb +64 -0
- data/tests/TestProperties.rb +160 -0
- data/tests/TestSearch.rb +277 -0
- data/tests/TestStrongComponents.rb +85 -0
- data/tests/TestTriagulated.rb +137 -0
- data/tests/TestUndirectedGraph.rb +219 -0
- metadata +152 -0
data/tests/TestSearch.rb
ADDED
@@ -0,0 +1,277 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2006 Shawn Patrick Garbett
|
3
|
+
# Copyright (c) 2002,2004,2005 by Horst Duchene
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
6
|
+
# are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice(s),
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
# * Neither the name of the Shawn Garbett nor the names of its contributors
|
14
|
+
# may be used to endorse or promote products derived from this software
|
15
|
+
# without specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
18
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
19
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
20
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
21
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
23
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
24
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
25
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
26
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
#++
|
28
|
+
|
29
|
+
|
30
|
+
require 'test/unit'
|
31
|
+
require 'gratr/import'
|
32
|
+
|
33
|
+
class TestSearch < Test::Unit::TestCase # :nodoc:
|
34
|
+
|
35
|
+
def setup
|
36
|
+
@directed = Digraph[1,2, 2,3, 2,4, 4,5, 1,6, 6,4]
|
37
|
+
@undirected = UndirectedGraph[1,2, 2,3, 2,4, 4,5, 1,6]
|
38
|
+
@tree = Digraph[ 1,2, 1,3, 1,4, 2,5, 2,4, 2,6, 6,7, 23,24 ]
|
39
|
+
end
|
40
|
+
|
41
|
+
# "Algorithmic Graph Theory and Perfect Graphs", Martin Charles
|
42
|
+
# Golumbic, 1980, Academic Press, page 38, Figure 2.6
|
43
|
+
def assign_dfsnumber_ancestry(graph, dfsnumber, father, start)
|
44
|
+
i = 0
|
45
|
+
dfsnumber.clear
|
46
|
+
father.clear
|
47
|
+
ev = Proc.new {|v| dfsnumber[v] = (i+=1) }
|
48
|
+
te = Proc.new {|e| father[e.target] = e.source }
|
49
|
+
graph.dfs({:enter_vertex => ev, :tree_edge => te, :start => start})
|
50
|
+
end
|
51
|
+
|
52
|
+
# Is v an ancestor of u
|
53
|
+
def ancestor?(father, u, v)
|
54
|
+
i = 1
|
55
|
+
while v
|
56
|
+
return i if father[v] == u
|
57
|
+
v = father[v]
|
58
|
+
i += 1
|
59
|
+
end; nil
|
60
|
+
end
|
61
|
+
|
62
|
+
# Is there any relationship?
|
63
|
+
def related?(father,u,v) ancestor?(father,u,v) or ancestor?(father,v,u); end
|
64
|
+
|
65
|
+
# "Algorithmic Graph Theory and Perfect Graphs", Martin Charles
|
66
|
+
# Golumbic, 1980, Academic Press, page 39, Propery (D1) and (D2) of
|
67
|
+
# depth first search
|
68
|
+
def test_dfs_properties
|
69
|
+
dfs = {}
|
70
|
+
father = {}
|
71
|
+
@directed.each do |vertex|
|
72
|
+
assign_dfsnumber_ancestry(@directed, dfs, father, vertex)
|
73
|
+
# Property (D1)
|
74
|
+
father.keys.each {|v| assert(dfs[father[v]] < dfs[v])}
|
75
|
+
# Property (D2)
|
76
|
+
# FIXME: Huh? Doesn't work
|
77
|
+
#@directed.edges.each {|e| assert(related?(father, e.source, e.target))}
|
78
|
+
#@directed.edges.each {|e| assert(dfs[e.source] < dfs[e.target])}
|
79
|
+
end
|
80
|
+
assert_equal 6, @directed.dfs.size
|
81
|
+
assert_equal @directed.vertices.sort, @directed.dfs.sort
|
82
|
+
end
|
83
|
+
|
84
|
+
# "Algorithmic Graph Theory and Perfect Graphs", Martin Charles
|
85
|
+
# Golumbic, 1980, Academic Press, page 40, Figure 2.7
|
86
|
+
def assign_bfsnumber_ancestry(graph, bfsnum, level, father, start)
|
87
|
+
i = 0
|
88
|
+
bfsnum.clear
|
89
|
+
level.clear
|
90
|
+
father.clear
|
91
|
+
rt = Proc.new {|v| level[v] = 0 }
|
92
|
+
ev = Proc.new {|v| bfsnum[v]=(i+=1);level[v]=(level[father[v]]+1) if father[v]}
|
93
|
+
te = Proc.new {|e| father[e.target] = e.source }
|
94
|
+
graph.dfs({:enter_vertex => ev, :tree_edge => te,
|
95
|
+
:root_vertex => rt, :start => start})
|
96
|
+
end
|
97
|
+
|
98
|
+
# "Algorithmic Graph Theory and Perfect Graphs", Martin Charles
|
99
|
+
# Golumbic, 1980, Academic Press, page 40, Propery (B1), (B2) and (B3) of
|
100
|
+
# breadth first search
|
101
|
+
def test_bfs_properties
|
102
|
+
level = {}
|
103
|
+
father = {}
|
104
|
+
bfs = {}
|
105
|
+
@directed.each do |vertex|
|
106
|
+
assign_bfsnumber_ancestry(@directed, bfs, level, father, vertex)
|
107
|
+
# Property (B1)
|
108
|
+
father.keys.each {|v| assert(bfs[father[v]] < bfs[v])}
|
109
|
+
# Property (B2)
|
110
|
+
@directed.edges.each {|e| assert((level[e.source]-level[e.target]).abs<2)}
|
111
|
+
# Property (B3)
|
112
|
+
# FIXME: How can one test this?
|
113
|
+
#@directed.vertex.each {|v| assert((level[e.source]-level[e.target]).abs<2)}
|
114
|
+
end
|
115
|
+
assert_equal 6, @directed.dfs.size
|
116
|
+
assert_equal @directed.vertices.sort, @directed.dfs.sort
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_cyclic
|
120
|
+
assert @directed.acyclic?
|
121
|
+
assert @undirected.acyclic?
|
122
|
+
assert !@directed.cyclic?
|
123
|
+
assert !@undirected.cyclic?
|
124
|
+
@undirected.add_edge!(4,6)
|
125
|
+
@directed.add_edge!(3,1)
|
126
|
+
assert !@directed.acyclic?
|
127
|
+
assert !@undirected.acyclic?
|
128
|
+
assert @directed.cyclic?
|
129
|
+
assert @undirected.cyclic?
|
130
|
+
|
131
|
+
# Test empty graph
|
132
|
+
x = Digraph.new
|
133
|
+
assert !x.cyclic?
|
134
|
+
assert x.acyclic?
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_astar
|
138
|
+
# Graph from "Artificial Intelligence: A Modern Approach" by Stuart
|
139
|
+
# Russell ande Peter Norvig, Prentice-Hall 2nd Edition, pg 63
|
140
|
+
romania = UndirectedGraph.new.
|
141
|
+
add_edge!('Oradea', 'Zerind', 71).
|
142
|
+
add_edge!('Oradea', 'Sibiu', 151).
|
143
|
+
add_edge!('Zerind', 'Arad', 75).
|
144
|
+
add_edge!('Arad', 'Sibiu', 99).
|
145
|
+
add_edge!('Arad', 'Timisoara', 138).
|
146
|
+
add_edge!('Timisoara', 'Lugoj', 111).
|
147
|
+
add_edge!('Lugoj', 'Mehadia', 70).
|
148
|
+
add_edge!('Mehadia', 'Dobreta', 75).
|
149
|
+
add_edge!('Dobreta', 'Craiova', 120).
|
150
|
+
add_edge!('Sibiu', 'Fagaras', 99).
|
151
|
+
add_edge!('Fagaras', 'Bucharest', 211).
|
152
|
+
add_edge!('Sibiu', 'Rimnicu Vilcea', 80).
|
153
|
+
add_edge!('Rimnicu Vilcea', 'Craiova', 146).
|
154
|
+
add_edge!('Rimnicu Vilcea', 'Pitesti', 97).
|
155
|
+
add_edge!('Craiova', 'Pitesti', 138).
|
156
|
+
add_edge!('Pitesti', 'Bucharest', 101).
|
157
|
+
add_edge!('Bucharest', 'Giurgin', 90).
|
158
|
+
add_edge!('Bucharest', 'Urzieni', 85).
|
159
|
+
add_edge!('Urzieni', 'Hirsova', 98).
|
160
|
+
add_edge!('Urzieni', 'Vaslui', 142).
|
161
|
+
add_edge!('Hirsova', 'Eforie', 86).
|
162
|
+
add_edge!('Vaslui', 'Iasi', 92).
|
163
|
+
add_edge!('Iasi', 'Neamt', 87)
|
164
|
+
|
165
|
+
# Heuristic from "Artificial Intelligence: A Modern Approach" by Stuart
|
166
|
+
# Russell ande Peter Norvig, Prentice-Hall 2nd Edition, pg 95
|
167
|
+
straight_line_to_Bucharest =
|
168
|
+
{
|
169
|
+
'Arad' => 366,
|
170
|
+
'Bucharest' => 0,
|
171
|
+
'Craiova' => 160,
|
172
|
+
'Dobreta' => 242,
|
173
|
+
'Eforie' => 161,
|
174
|
+
'Fagaras' => 176,
|
175
|
+
'Giurgiu' => 77,
|
176
|
+
'Hirsova' => 151,
|
177
|
+
'Iasi' => 226,
|
178
|
+
'Lugoj' => 244,
|
179
|
+
'Mehadia' => 241,
|
180
|
+
'Neamt' => 234,
|
181
|
+
'Oradea' => 380,
|
182
|
+
'Pitesti' => 100,
|
183
|
+
'Rimnicu Vilcea' => 193,
|
184
|
+
'Sibiu' => 253,
|
185
|
+
'Timisoara' => 329,
|
186
|
+
'Urziceni' => 80,
|
187
|
+
'Vaslui' => 199,
|
188
|
+
'Zerind' => 374
|
189
|
+
}
|
190
|
+
|
191
|
+
# Heuristic is distance as crow flies, always under estimates costs.
|
192
|
+
h = Proc.new {|v| straight_line_to_Bucharest[v]}
|
193
|
+
|
194
|
+
list = []
|
195
|
+
|
196
|
+
dv = Proc.new {|v| list << "dv #{v}" }
|
197
|
+
ev = Proc.new {|v| list << "ev #{v}" }
|
198
|
+
bt = Proc.new {|v| list << "bt #{v}" }
|
199
|
+
fv = Proc.new {|v| list << "fv #{v}" }
|
200
|
+
er = Proc.new {|e| list << "er #{e}" }
|
201
|
+
enr = Proc.new {|e| list << "enr #{e}" }
|
202
|
+
|
203
|
+
options = { :discover_vertex => dv,
|
204
|
+
:examine_vertex => ev,
|
205
|
+
:black_target => bt,
|
206
|
+
:finish_vertex => fv,
|
207
|
+
:edge_relaxed => er,
|
208
|
+
:edge_not_relaxed => enr }
|
209
|
+
|
210
|
+
result = romania.astar('Arad', 'Bucharest', h, options)
|
211
|
+
|
212
|
+
assert_equal ["Arad", "Sibiu", "Rimnicu Vilcea", "Pitesti", "Bucharest"], result
|
213
|
+
# This isn't the greatest test since the exact ordering is not
|
214
|
+
# not specified by the algorithm. If someone has a better idea, please fix
|
215
|
+
assert_equal ["ev Arad",
|
216
|
+
"er (Arad=Sibiu '99')",
|
217
|
+
"dv Sibiu",
|
218
|
+
"er (Arad=Timisoara '138')",
|
219
|
+
"dv Timisoara",
|
220
|
+
"er (Arad=Zerind '75')",
|
221
|
+
"dv Zerind",
|
222
|
+
"fv Arad",
|
223
|
+
"ev Sibiu",
|
224
|
+
"er (Rimnicu Vilcea=Sibiu '80')",
|
225
|
+
"dv Rimnicu Vilcea",
|
226
|
+
"er (Fagaras=Sibiu '99')",
|
227
|
+
"dv Fagaras",
|
228
|
+
"er (Oradea=Sibiu '151')",
|
229
|
+
"dv Oradea",
|
230
|
+
"enr (Arad=Sibiu '99')",
|
231
|
+
"fv Sibiu",
|
232
|
+
"ev Rimnicu Vilcea",
|
233
|
+
"enr (Rimnicu Vilcea=Sibiu '80')",
|
234
|
+
"er (Craiova=Rimnicu Vilcea '146')",
|
235
|
+
"dv Craiova",
|
236
|
+
"er (Pitesti=Rimnicu Vilcea '97')",
|
237
|
+
"dv Pitesti",
|
238
|
+
"fv Rimnicu Vilcea",
|
239
|
+
"ev Fagaras",
|
240
|
+
"enr (Fagaras=Sibiu '99')",
|
241
|
+
"er (Bucharest=Fagaras '211')",
|
242
|
+
"dv Bucharest",
|
243
|
+
"fv Fagaras",
|
244
|
+
"ev Pitesti",
|
245
|
+
"enr (Pitesti=Rimnicu Vilcea '97')",
|
246
|
+
"er (Bucharest=Pitesti '101')",
|
247
|
+
"enr (Craiova=Pitesti '138')",
|
248
|
+
"fv Pitesti",
|
249
|
+
"ev Bucharest"], list
|
250
|
+
end
|
251
|
+
|
252
|
+
def test_bfs_spanning_forest
|
253
|
+
predecessor, roots = @tree.bfs_spanning_forest(1)
|
254
|
+
assert_equal({2=>1, 3=>1, 4=>1, 5=>2, 6=>2, 7=>6, 24=>23}, predecessor)
|
255
|
+
assert_equal [1,23], roots.sort
|
256
|
+
predecessor, roots = @tree.bfs_spanning_forest(3)
|
257
|
+
assert_equal({7=>6, 24=>23, 2=>1, 4=>1}, predecessor)
|
258
|
+
assert_equal [1,3,5,6,23], roots.sort
|
259
|
+
end
|
260
|
+
|
261
|
+
def test_dfs_spanning_forest
|
262
|
+
predecessor, roots = @tree.dfs_spanning_forest(1)
|
263
|
+
assert_equal({5=>2, 6=>2, 7=>6, 24=>23, 2=>1, 3=>1, 4=>2}, predecessor)
|
264
|
+
assert_equal [1,23], roots.sort
|
265
|
+
predecessor, roots = @tree.dfs_spanning_forest(3)
|
266
|
+
assert_equal({7=>6, 24=>23, 2=>1, 4=>2}, predecessor)
|
267
|
+
assert_equal [1,3,5,6,23], roots.sort
|
268
|
+
end
|
269
|
+
|
270
|
+
def test_tree_from_vertex
|
271
|
+
assert_equal({5=>2, 6=>2, 7=>6, 2=>1, 3=>1, 4=>1}, @tree.bfs_tree_from_vertex(1))
|
272
|
+
assert_equal({}, @tree.bfs_tree_from_vertex(3))
|
273
|
+
assert_equal({5=>2, 6=>2, 7=>6, 2=>1, 3=>1, 4=>2}, @tree.dfs_tree_from_vertex(1))
|
274
|
+
assert_equal({}, @tree.dfs_tree_from_vertex(3))
|
275
|
+
end
|
276
|
+
|
277
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2006 Shawn Patrick Garbett
|
3
|
+
#
|
4
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
5
|
+
# are permitted provided that the following conditions are met:
|
6
|
+
#
|
7
|
+
# * Redistributions of source code must retain the above copyright notice(s),
|
8
|
+
# this list of conditions and the following disclaimer.
|
9
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
10
|
+
# this list of conditions and the following disclaimer in the documentation
|
11
|
+
# and/or other materials provided with the distribution.
|
12
|
+
# * Neither the name of the Shawn Garbett nor the names of its contributors
|
13
|
+
# may be used to endorse or promote products derived from this software
|
14
|
+
# without specific prior written permission.
|
15
|
+
#
|
16
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
17
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
19
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
20
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
21
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
22
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
23
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
24
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
25
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
26
|
+
#++
|
27
|
+
|
28
|
+
|
29
|
+
require 'test/unit'
|
30
|
+
require 'gratr/import'
|
31
|
+
|
32
|
+
class TestStrongComponents < Test::Unit::TestCase # :nodoc:
|
33
|
+
# Test from boost strong_components.cpp
|
34
|
+
# Original Copyright 1997-2001, University of Notre Dame.
|
35
|
+
# Original Authors: Andrew Lumsdaine, Lie-Quan Lee, Jermey G. Siek
|
36
|
+
def test_boost
|
37
|
+
g = Digraph[ 'a', 'b', 'a', 'f', 'a', 'h',
|
38
|
+
'b', 'c', 'b', 'a',
|
39
|
+
'c', 'd', 'c', 'b',
|
40
|
+
'd', 'e',
|
41
|
+
'e', 'd',
|
42
|
+
'f', 'g',
|
43
|
+
'g', 'f', 'g', 'd',
|
44
|
+
'h', 'i',
|
45
|
+
'i', 'h', 'i', 'j', 'i', 'e', 'i', 'c']
|
46
|
+
|
47
|
+
c = g.strong_components.map {|x| x.sort}
|
48
|
+
assert_equal 10, g.vertices.size
|
49
|
+
assert_equal 4, c.size
|
50
|
+
assert c.include?(['d','e'])
|
51
|
+
assert c.include?(['f','g'])
|
52
|
+
assert c.include?(['j'])
|
53
|
+
assert c.include?(['a','b','c','h','i'])
|
54
|
+
|
55
|
+
cg = g.condensation
|
56
|
+
cg_vertices = cg.map {|v| v.sort}
|
57
|
+
assert_equal 4, cg_vertices.size
|
58
|
+
assert cg_vertices.include?(['j'])
|
59
|
+
assert cg_vertices.include?(['d','e'])
|
60
|
+
assert cg_vertices.include?(['f', 'g'])
|
61
|
+
assert cg_vertices.include?(['a', 'b', 'c', 'h', 'i'])
|
62
|
+
assert cg.edges.map {|e| [e.source.sort.join, e.target.sort.join] }.sort ==
|
63
|
+
[['abchi','de'], ['abchi', 'fg'], ['abchi', 'j'], ['fg', 'de']]
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
# Figure #3, from 'Depth-First Search and Linear Graph Algorithms'
|
68
|
+
# by Robert Tarjan, SIAM J. Comput. Vol 1, No.2, June 1972
|
69
|
+
def test_tarjan_fig_3
|
70
|
+
g = Digraph[ 1,2,
|
71
|
+
2,3, 2,8,
|
72
|
+
3,4, 3,7,
|
73
|
+
4,5,
|
74
|
+
5,3, 5,6,
|
75
|
+
7,4, 7,6,
|
76
|
+
8,1, 8,7 ]
|
77
|
+
|
78
|
+
c = g.strong_components.map {|x| x.sort}
|
79
|
+
assert_equal 8, g.vertices.size
|
80
|
+
assert_equal 3, c.size
|
81
|
+
assert c.include?([6])
|
82
|
+
assert c.include?([1,2,8])
|
83
|
+
assert c.include?([3,4,5,7])
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2006 Shawn Patrick Garbett
|
3
|
+
#
|
4
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
5
|
+
# are permitted provided that the following conditions are met:
|
6
|
+
#
|
7
|
+
# * Redistributions of source code must retain the above copyright notice(s),
|
8
|
+
# this list of conditions and the following disclaimer.
|
9
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
10
|
+
# this list of conditions and the following disclaimer in the documentation
|
11
|
+
# and/or other materials provided with the distribution.
|
12
|
+
# * Neither the name of the Shawn Garbett nor the names of its contributors
|
13
|
+
# may be used to endorse or promote products derived from this software
|
14
|
+
# without specific prior written permission.
|
15
|
+
#
|
16
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
17
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
19
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
20
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
21
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
22
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
23
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
24
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
25
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
26
|
+
#++
|
27
|
+
|
28
|
+
|
29
|
+
require 'test/unit'
|
30
|
+
require 'gratr/import'
|
31
|
+
|
32
|
+
class TestTriagulated < Test::Unit::TestCase #:nodoc:
|
33
|
+
|
34
|
+
def test_berge_mystery
|
35
|
+
berge_mystery = UndirectedGraph[
|
36
|
+
:abe, :eddie,
|
37
|
+
:abe, :burt,
|
38
|
+
:abe, :desmond,
|
39
|
+
:eddie, :burt,
|
40
|
+
:eddie, :ida,
|
41
|
+
:eddie, :charlotte,
|
42
|
+
:charlotte, :ida,
|
43
|
+
:charlotte, :desmond,
|
44
|
+
:burt, :ida,
|
45
|
+
:ida, :desmond]
|
46
|
+
|
47
|
+
assert !berge_mystery.triangulated?
|
48
|
+
berge_mystery.remove_vertex!(:desmond)
|
49
|
+
assert berge_mystery.triangulated?
|
50
|
+
|
51
|
+
assert 3, berge_mystery.chromatic_number
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_house
|
55
|
+
house = UndirectedGraph[
|
56
|
+
:roof, :left_gutter,
|
57
|
+
:roof, :right_gutter,
|
58
|
+
:left_gutter, :left_foundation,
|
59
|
+
:right_gutter, :right_foundation,
|
60
|
+
:left_foundation, :right_foundation
|
61
|
+
]
|
62
|
+
assert !house.triangulated?
|
63
|
+
house.remove_vertex!(:left_foundation) # Becomes a bulls head graph
|
64
|
+
assert house.triangulated?
|
65
|
+
assert 3, house.chromatic_number
|
66
|
+
end
|
67
|
+
|
68
|
+
# A triangulated, but not interval graph test
|
69
|
+
def test_non_interval
|
70
|
+
non_interval = UndirectedGraph[
|
71
|
+
:ao, :ai,
|
72
|
+
:ai, :bi,
|
73
|
+
:ai, :ci,
|
74
|
+
:bo, :bi,
|
75
|
+
:bi, :ci,
|
76
|
+
:co, :ci
|
77
|
+
]
|
78
|
+
assert non_interval.triangulated?
|
79
|
+
assert 3, non_interval.chromatic_number
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_simple
|
83
|
+
simple = UndirectedGraph[
|
84
|
+
:a, :b,
|
85
|
+
:b, :c,
|
86
|
+
:c, :d,
|
87
|
+
:d, :e,
|
88
|
+
:e, :f,
|
89
|
+
:f, :g,
|
90
|
+
:g, :a,
|
91
|
+
:g, :b,
|
92
|
+
:b, :f,
|
93
|
+
:f, :c,
|
94
|
+
]
|
95
|
+
assert !simple.triangulated?
|
96
|
+
simple.add_edge!(:c, :e)
|
97
|
+
assert simple.triangulated?
|
98
|
+
assert 3, simple.chromatic_number
|
99
|
+
assert 2, UndirectedGraph[:a, :b].chromatic_number
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_simple2
|
103
|
+
simple2 = UndirectedGraph[
|
104
|
+
:x, :p,
|
105
|
+
:p, :z,
|
106
|
+
:z, :r,
|
107
|
+
:r, :x,
|
108
|
+
:p, :y,
|
109
|
+
:y, :r,
|
110
|
+
:y, :q,
|
111
|
+
:q, :z]
|
112
|
+
assert !simple2.triangulated?
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_lexicographic_queue
|
116
|
+
q = UndirectedGraph::LexicographicQueue.new([1,2,3,4,5,6,7,8,9])
|
117
|
+
assert_equal 9, q.pop
|
118
|
+
q.add_lexeme([3,4,5,6,7,8])
|
119
|
+
assert_equal 8, q.pop
|
120
|
+
q.add_lexeme([2,6,7,9])
|
121
|
+
assert_equal 7, q.pop
|
122
|
+
q.add_lexeme([8,9])
|
123
|
+
assert_equal 6, q.pop
|
124
|
+
q.add_lexeme([1,5,8,9])
|
125
|
+
assert_equal 5, q.pop
|
126
|
+
q.add_lexeme([6,9])
|
127
|
+
assert_equal 4, q.pop
|
128
|
+
q.add_lexeme([3,9])
|
129
|
+
assert_equal 3, q.pop
|
130
|
+
q.add_lexeme([4,9])
|
131
|
+
assert_equal 2, q.pop
|
132
|
+
q.add_lexeme([8])
|
133
|
+
assert_equal 1, q.pop
|
134
|
+
assert_equal nil, q.pop
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|