gratr19 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/README +335 -0
  2. data/examples/graph_self.rb +54 -0
  3. data/examples/module_graph.jpg +0 -0
  4. data/examples/module_graph.rb +12 -0
  5. data/examples/self_graph.jpg +0 -0
  6. data/examples/visualize.jpg +0 -0
  7. data/examples/visualize.rb +8 -0
  8. data/install.rb +49 -0
  9. data/lib/gratr.rb +42 -0
  10. data/lib/gratr/adjacency_graph.rb +230 -0
  11. data/lib/gratr/base.rb +34 -0
  12. data/lib/gratr/biconnected.rb +116 -0
  13. data/lib/gratr/chinese_postman.rb +123 -0
  14. data/lib/gratr/common.rb +74 -0
  15. data/lib/gratr/comparability.rb +92 -0
  16. data/lib/gratr/digraph.rb +115 -0
  17. data/lib/gratr/digraph_distance.rb +185 -0
  18. data/lib/gratr/dot.rb +90 -0
  19. data/lib/gratr/edge.rb +145 -0
  20. data/lib/gratr/graph.rb +314 -0
  21. data/lib/gratr/graph_api.rb +82 -0
  22. data/lib/gratr/import.rb +44 -0
  23. data/lib/gratr/labels.rb +103 -0
  24. data/lib/gratr/maximum_flow.rb +107 -0
  25. data/lib/gratr/rdot.rb +332 -0
  26. data/lib/gratr/search.rb +422 -0
  27. data/lib/gratr/strong_components.rb +127 -0
  28. data/lib/gratr/undirected_graph.rb +153 -0
  29. data/lib/gratr/version.rb +6 -0
  30. data/lib/priority-queue/benchmark/dijkstra.rb +171 -0
  31. data/lib/priority-queue/compare_comments.rb +49 -0
  32. data/lib/priority-queue/ext/priority_queue/CPriorityQueue/extconf.rb +2 -0
  33. data/lib/priority-queue/lib/priority_queue.rb +14 -0
  34. data/lib/priority-queue/lib/priority_queue/c_priority_queue.rb +1 -0
  35. data/lib/priority-queue/lib/priority_queue/poor_priority_queue.rb +46 -0
  36. data/lib/priority-queue/lib/priority_queue/ruby_priority_queue.rb +525 -0
  37. data/lib/priority-queue/setup.rb +1551 -0
  38. data/lib/priority-queue/test/priority_queue_test.rb +371 -0
  39. data/tests/TestBiconnected.rb +53 -0
  40. data/tests/TestChinesePostman.rb +53 -0
  41. data/tests/TestComplement.rb +54 -0
  42. data/tests/TestDigraph.rb +333 -0
  43. data/tests/TestDigraphDistance.rb +138 -0
  44. data/tests/TestDot.rb +75 -0
  45. data/tests/TestEdge.rb +171 -0
  46. data/tests/TestInspection.rb +57 -0
  47. data/tests/TestMultiEdge.rb +57 -0
  48. data/tests/TestNeighborhood.rb +64 -0
  49. data/tests/TestProperties.rb +160 -0
  50. data/tests/TestSearch.rb +277 -0
  51. data/tests/TestStrongComponents.rb +85 -0
  52. data/tests/TestTriagulated.rb +137 -0
  53. data/tests/TestUndirectedGraph.rb +219 -0
  54. metadata +152 -0
@@ -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