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.
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