plexus 0.5.4 → 0.5.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/Gemfile +3 -0
  2. data/LICENSE +37 -0
  3. data/README.md +208 -0
  4. data/Rakefile +25 -0
  5. data/lib/plexus.rb +90 -0
  6. data/lib/plexus/adjacency_graph.rb +225 -0
  7. data/lib/plexus/arc.rb +60 -0
  8. data/lib/plexus/arc_number.rb +50 -0
  9. data/lib/plexus/biconnected.rb +84 -0
  10. data/lib/plexus/chinese_postman.rb +91 -0
  11. data/lib/plexus/classes/graph_classes.rb +28 -0
  12. data/lib/plexus/common.rb +63 -0
  13. data/lib/plexus/comparability.rb +63 -0
  14. data/lib/plexus/directed_graph.rb +78 -0
  15. data/lib/plexus/directed_graph/algorithms.rb +95 -0
  16. data/lib/plexus/directed_graph/distance.rb +167 -0
  17. data/lib/plexus/dot.rb +94 -0
  18. data/lib/plexus/edge.rb +38 -0
  19. data/lib/plexus/ext.rb +79 -0
  20. data/lib/plexus/graph.rb +628 -0
  21. data/lib/plexus/graph_api.rb +35 -0
  22. data/lib/plexus/labels.rb +112 -0
  23. data/lib/plexus/maximum_flow.rb +77 -0
  24. data/lib/plexus/ruby_compatibility.rb +17 -0
  25. data/lib/plexus/search.rb +510 -0
  26. data/lib/plexus/strong_components.rb +93 -0
  27. data/lib/plexus/support/support.rb +9 -0
  28. data/lib/plexus/undirected_graph.rb +56 -0
  29. data/lib/plexus/undirected_graph/algorithms.rb +90 -0
  30. data/lib/plexus/version.rb +6 -0
  31. data/spec/biconnected_spec.rb +27 -0
  32. data/spec/chinese_postman_spec.rb +27 -0
  33. data/spec/community_spec.rb +44 -0
  34. data/spec/complement_spec.rb +27 -0
  35. data/spec/digraph_distance_spec.rb +121 -0
  36. data/spec/digraph_spec.rb +339 -0
  37. data/spec/dot_spec.rb +48 -0
  38. data/spec/edge_spec.rb +158 -0
  39. data/spec/inspection_spec.rb +38 -0
  40. data/spec/multi_edge_spec.rb +32 -0
  41. data/spec/neighborhood_spec.rb +36 -0
  42. data/spec/properties_spec.rb +146 -0
  43. data/spec/search_spec.rb +227 -0
  44. data/spec/spec.opts +4 -0
  45. data/spec/spec_helper.rb +59 -0
  46. data/spec/strong_components_spec.rb +61 -0
  47. data/spec/triangulated_spec.rb +125 -0
  48. data/spec/undirected_graph_spec.rb +220 -0
  49. data/vendor/priority-queue/CHANGELOG +33 -0
  50. data/vendor/priority-queue/Makefile +140 -0
  51. data/vendor/priority-queue/README +133 -0
  52. data/vendor/priority-queue/benchmark/dijkstra.rb +171 -0
  53. data/vendor/priority-queue/compare_comments.rb +49 -0
  54. data/vendor/priority-queue/doc/c-vs-rb.png +0 -0
  55. data/vendor/priority-queue/doc/compare_big.gp +14 -0
  56. data/vendor/priority-queue/doc/compare_big.png +0 -0
  57. data/vendor/priority-queue/doc/compare_small.gp +15 -0
  58. data/vendor/priority-queue/doc/compare_small.png +0 -0
  59. data/vendor/priority-queue/doc/results.csv +37 -0
  60. data/vendor/priority-queue/ext/priority_queue/CPriorityQueue/extconf.rb +2 -0
  61. data/vendor/priority-queue/ext/priority_queue/CPriorityQueue/priority_queue.c +947 -0
  62. data/vendor/priority-queue/lib/priority_queue.rb +14 -0
  63. data/vendor/priority-queue/lib/priority_queue/c_priority_queue.rb +1 -0
  64. data/vendor/priority-queue/lib/priority_queue/poor_priority_queue.rb +46 -0
  65. data/vendor/priority-queue/lib/priority_queue/ruby_priority_queue.rb +526 -0
  66. data/vendor/priority-queue/priority_queue.so +0 -0
  67. data/vendor/priority-queue/setup.rb +1551 -0
  68. data/vendor/priority-queue/test/priority_queue_test.rb +371 -0
  69. data/vendor/rdot.rb +360 -0
  70. metadata +100 -10
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Inspection" do # :nodoc:
4
+ before do
5
+ @dg = DirectedMultiGraph[
6
+ [0,0,1] => 1,
7
+ [1,2,2] => 2,
8
+ [1,3,3] => 4,
9
+ [1,4,4] => nil,
10
+ [4,1,5] => 8,
11
+ [1,2,6] => 16,
12
+ [3,3,7] => 32,
13
+ [3,3,8] => 64
14
+ ]
15
+ @dg[3] = 128
16
+ @dg[0] = 256
17
+ end
18
+
19
+ describe "inspection_without_labels" do
20
+ it do
21
+ @dg = Digraph[1,2,3,4,5,6]
22
+ reflect = eval @dg.inspect
23
+ reflect.should == @dg
24
+ end
25
+ end
26
+
27
+ describe "inspection_with_labels" do
28
+ it do
29
+ inspect = @dg.inspect
30
+ @dg.vertices.inject(0) {|a,v| a += (@dg[v] || 0)}.should == 384
31
+ @dg.edges.inject(0) {|a,e| a += (@dg[e] || 0)}.should == 127
32
+ reflect = eval inspect
33
+ reflect.should == @dg
34
+ reflect.edges.inject(0) { |a,e| a += (reflect[e] || 0)}.should == 127
35
+ reflect.vertices.inject(0) {|a,v| a += (reflect[v] || 0)}.should == 384
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,32 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe "MultiArc" do # :nodoc:
4
+
5
+ describe "directed_pseudo_graph" do
6
+ it do
7
+ dpg = DirectedPseudoGraph[ :a,:b,
8
+ :a,:b,
9
+ :a,:b ]
10
+ dpg.edges.size.should == 3
11
+ x = 0
12
+ dpg.edges.each {|e| dpg[e] = (x+=1)}
13
+ dpg.edges.inject(0) {|a,v| a+=dpg[v]}.should == 6
14
+ end
15
+ end
16
+
17
+ describe "directed_multi_graph" do
18
+ it do
19
+ dmg = DirectedMultiGraph[ :a,:a,
20
+ :a,:a,
21
+ :a,:b,
22
+ :a,:b,
23
+ :b,:b,
24
+ :b,:b ]
25
+ dmg.edges.size.should == 6
26
+ x = 0
27
+ dmg.edges.each { |e| dmg[e] = (x+=1) }
28
+ dmg.edges.inject(0) {|a,v| a+=dmg[v]}.should == 21
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,36 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe "Neighborhood" do
4
+ before do
5
+ @d = Digraph[:a,:b, :a,:f,
6
+ :b,:g,
7
+ :c,:b, :c,:g,
8
+ :d,:c, :d,:g,
9
+ :e,:d,
10
+ :f,:e, :f,:g,
11
+ :g,:a, :g,:e]
12
+ @w = [:a,:b]
13
+ end
14
+
15
+ describe "open_out_neighborhood" do
16
+ it do
17
+ @d.set_neighborhood([:a], :in).should == [:g]
18
+ ([:f,:g] - @d.set_neighborhood(@w, :out)).should == []
19
+ (@w - @d.open_pth_neighborhood(@w, 0, :out)).should == []
20
+ ([:f, :g] - @d.open_pth_neighborhood(@w, 1, :out)).should == []
21
+ ([:e] - @d.open_pth_neighborhood(@w, 2, :out)).should == []
22
+ ([:d] - @d.open_pth_neighborhood(@w, 3, :out)).should == []
23
+ ([:c] - @d.open_pth_neighborhood(@w, 4, :out)).should == []
24
+ end
25
+ end
26
+
27
+ describe "closed_out_neighborhood" do
28
+ it do
29
+ (@w - @d.closed_pth_neighborhood(@w, 0, :out)).should == []
30
+ ([:a,:b,:f,:g] - @d.closed_pth_neighborhood(@w, 1, :out)).should == []
31
+ ([:a,:b,:e,:f,:g] - @d.closed_pth_neighborhood(@w, 2, :out)).should == []
32
+ ([:a,:b,:d,:e,:f,:g] - @d.closed_pth_neighborhood(@w, 3, :out)).should == []
33
+ ([:a,:b,:c,:d,:e,:f,:g] - @d.closed_pth_neighborhood(@w, 4, :out)).should == []
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,146 @@
1
+
2
+ require File.join(File.dirname(__FILE__), 'spec_helper')
3
+ require 'plexus/dot'
4
+
5
+ # This test runs the classes from Appendix F in
6
+ # _Algorithmic_Graph_Theory_and_Perfect_Graphs,
7
+ # by Martin Charles Golumbic
8
+ describe "Properties" do # :nodoc:
9
+
10
+ describe "g1" do
11
+ it do
12
+ g1 = UndirectedGraph[ :a,:b, :a,:d, :a,:e, :a,:i, :a,:g, :a,:h,
13
+ :b,:c, :b,:f,
14
+ :c,:d, :c,:h,
15
+ :d,:h, :d,:e,
16
+ :e,:f,
17
+ :f,:g, :f,:h, :f,:i,
18
+ :h,:i ]
19
+
20
+ g1.should_not be_triangulated
21
+ g1.complement.should_not be_triangulated # Disagrees with Golumbic!
22
+ g1.should_not be_comparability
23
+ g1.complement.should_not be_comparability
24
+ g1.should_not be_interval
25
+ g1.complement.should_not be_interval
26
+ g1.should_not be_permutation
27
+ g1.should_not be_split
28
+
29
+ # g1.write_to_graphic_file('jpg','g1')
30
+ # g1.complement.write_to_graphic_file('jpg','g1_complement')
31
+ end
32
+ end
33
+
34
+ describe "g2" do
35
+ it do
36
+ g2 = UndirectedGraph[ :a,:b, :a,:e,
37
+ :b,:c, :b,:e, :b,:f,
38
+ :c,:d, :c,:f, :c,:g,
39
+ :d,:g,
40
+ :e,:f,
41
+ :f,:g]
42
+
43
+ g2.should be_triangulated
44
+ g2.complement.should_not be_triangulated
45
+ g2.should_not be_comparability
46
+ g2.complement.should be_comparability
47
+ g2.should be_interval
48
+ g2.complement.should_not be_interval
49
+ g2.should_not be_permutation
50
+ g2.should_not be_split
51
+ end
52
+ end
53
+
54
+ describe "g3" do
55
+ it do
56
+ g3 = UndirectedGraph[ :a,:c,
57
+ :b,:e,
58
+ :c,:d, :c,:f,
59
+ :d,:f, :d,:g, :d,:e,
60
+ :e,:g,
61
+ :f,:g ]
62
+ g3.should be_triangulated
63
+ g3.complement.should_not be_triangulated
64
+ g3.should_not be_comparability
65
+ g3.complement.should be_comparability
66
+ g3.should be_interval
67
+ g3.complement.should_not be_interval
68
+ g3.should_not be_permutation
69
+ g3.should_not be_split
70
+ end
71
+ end
72
+
73
+ describe "g4" do
74
+ it do
75
+ g4 = UndirectedGraph[ :a,:b,
76
+ :b,:c,
77
+ :c,:d, :c,:e,
78
+ :d,:f,
79
+ :e,:g]
80
+ g4.should be_triangulated
81
+ g4.complement.should_not be_triangulated
82
+ g4.should be_comparability
83
+ g4.complement.should_not be_comparability
84
+ g4.should_not be_interval
85
+ g4.complement.should_not be_interval
86
+ g4.should_not be_permutation
87
+ g4.should_not be_split
88
+ end
89
+ end
90
+
91
+ describe "g5" do
92
+ it do
93
+ g5 = UndirectedGraph[ :a,:b, :a,:c,
94
+ :b,:c, :b,:d, :b,:f, :b,:g,
95
+ :c,:e, :c,:f, :c,:g,
96
+ :d,:f,
97
+ :e,:g,
98
+ :f,:g]
99
+ g5.should be_triangulated
100
+ g5.complement.should be_triangulated
101
+ g5.should be_comparability
102
+ g5.complement.should_not be_comparability
103
+ g5.should_not be_interval
104
+ g5.complement.should be_interval
105
+ g5.should_not be_permutation
106
+ g5.should be_split
107
+ end
108
+ end
109
+
110
+ describe "g6" do
111
+ it do
112
+ g6 = UndirectedGraph[ :a,:c, :a,:d,
113
+ :b,:c,
114
+ :c,:f,
115
+ :d,:e, :d,:f]
116
+ g6.should_not be_triangulated
117
+ g6.complement.should_not be_triangulated
118
+ g6.should be_comparability
119
+ g6.complement.should be_comparability
120
+ g6.should_not be_interval
121
+ g6.complement.should_not be_interval
122
+ g6.should be_permutation
123
+ g6.should_not be_split
124
+ end
125
+ end
126
+
127
+ describe "g7" do
128
+ it do
129
+ g7 = UndirectedGraph[ :a,:b, :a,:c,
130
+ :b,:c, :b,:d, :b,:e,
131
+ :c,:e, :c,:f,
132
+ :d,:e,
133
+ :e,:f]
134
+ g7.should be_triangulated
135
+ g7.complement.should be_triangulated
136
+ g7.should_not be_comparability
137
+ g7.complement.should_not be_comparability
138
+ g7.should_not be_interval
139
+ g7.complement.should_not be_interval
140
+ g7.should_not be_permutation
141
+ g7.should be_split
142
+ end
143
+
144
+ end
145
+
146
+ end
@@ -0,0 +1,227 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe "Search" do # :nodoc:
4
+
5
+ before do
6
+ @directed = Digraph[1,2, 2,3, 2,4, 4,5, 1,6, 6,4]
7
+ @undirected = UndirectedGraph[1,2, 2,3, 2,4, 4,5, 1,6]
8
+ @tree = Digraph[ 1,2, 1,3, 1,4, 2,5, 2,4, 2,6, 6,7, 23,24 ]
9
+ end
10
+
11
+ # "Algorithmic Graph Theory and Perfect Graphs", Martin Charles
12
+ # Golumbic, 1980, Academic Press, page 39, Propery (D1) and (D2) of
13
+ # depth first search
14
+ describe "dfs_properties" do
15
+ it do
16
+ dfs = {}
17
+ father = {}
18
+ @directed.each do |vertex|
19
+ assign_dfsnumber_ancestry(@directed, dfs, father, vertex)
20
+ # Property (D1)
21
+ father.keys.each {|v| dfs[father[v]].should be < dfs[v] }
22
+ # Property (D2)
23
+ # FIXME: Huh? Doesn't work
24
+ #@directed.edges.each {|e| related?(father, e.source, e.target).should be_true }
25
+ #@directed.edges.each {|e| dfs[e.source].should be < dfs[e.target] }
26
+ end
27
+ @directed.dfs.size.should == 6
28
+ @directed.dfs.sort.should == @directed.vertices.sort
29
+ end
30
+ end
31
+
32
+ # "Algorithmic Graph Theory and Perfect Graphs", Martin Charles
33
+ # Golumbic, 1980, Academic Press, page 40, Propery (B1), (B2) and (B3) of
34
+ # breadth first search
35
+ describe "bfs_properties" do
36
+ it do
37
+ level = {}
38
+ father = {}
39
+ bfs = {}
40
+ @directed.each do |vertex|
41
+ assign_bfsnumber_ancestry(@directed, bfs, level, father, vertex)
42
+ # Property (B1)
43
+ father.keys.each do |v|
44
+ bfs[father[v]].should be < bfs[v]
45
+ end
46
+ # Property (B2)
47
+ @directed.edges.each do |e|
48
+ (level[e.source]-level[e.target]).abs.should be < 2
49
+ end
50
+ # Property (B3)
51
+ # FIXME: How can one test this?
52
+ # @directed.vertex.each { |e| (level[e.source]-level[e.target]).abs.should be < 2 }
53
+ end
54
+ @directed.dfs.size.should == 6
55
+ @directed.dfs.sort.should == @directed.vertices.sort
56
+ end
57
+ end
58
+
59
+ describe "cyclic" do
60
+ it do
61
+ @directed.should be_acyclic
62
+ @undirected.should be_acyclic
63
+ @directed.should_not be_cyclic
64
+ @undirected.should_not be_cyclic
65
+ @undirected.add_edge!(4,6)
66
+ @directed.add_edge!(3,1)
67
+ @directed.should_not be_acyclic
68
+ @undirected.should_not be_acyclic
69
+ @directed.should be_cyclic
70
+ @undirected.should be_cyclic
71
+
72
+ # Test empty graph
73
+ x = Digraph.new
74
+ x.should_not be_cyclic
75
+ x.should be_acyclic
76
+ end
77
+ end
78
+
79
+ describe "astar" do
80
+ it do
81
+ # Graph from "Artificial Intelligence: A Modern Approach" by Stuart
82
+ # Russell ande Peter Norvig, Prentice-Hall 2nd Edition, pg 63
83
+ romania = UndirectedGraph.new.
84
+ add_edge!('Oradea', 'Zerind', 71).
85
+ add_edge!('Oradea', 'Sibiu', 151).
86
+ add_edge!('Zerind', 'Arad', 75).
87
+ add_edge!('Arad', 'Sibiu', 99).
88
+ add_edge!('Arad', 'Timisoara', 138).
89
+ add_edge!('Timisoara', 'Lugoj', 111).
90
+ add_edge!('Lugoj', 'Mehadia', 70).
91
+ add_edge!('Mehadia', 'Dobreta', 75).
92
+ add_edge!('Dobreta', 'Craiova', 120).
93
+ add_edge!('Sibiu', 'Fagaras', 99).
94
+ add_edge!('Fagaras', 'Bucharest', 211).
95
+ add_edge!('Sibiu', 'Rimnicu Vilcea', 80).
96
+ add_edge!('Rimnicu Vilcea', 'Craiova', 146).
97
+ add_edge!('Rimnicu Vilcea', 'Pitesti', 97).
98
+ add_edge!('Craiova', 'Pitesti', 138).
99
+ add_edge!('Pitesti', 'Bucharest', 101).
100
+ add_edge!('Bucharest', 'Giurgin', 90).
101
+ add_edge!('Bucharest', 'Urzieni', 85).
102
+ add_edge!('Urzieni', 'Hirsova', 98).
103
+ add_edge!('Urzieni', 'Vaslui', 142).
104
+ add_edge!('Hirsova', 'Eforie', 86).
105
+ add_edge!('Vaslui', 'Iasi', 92).
106
+ add_edge!('Iasi', 'Neamt', 87)
107
+
108
+ # Heuristic from "Artificial Intelligence: A Modern Approach" by Stuart
109
+ # Russell ande Peter Norvig, Prentice-Hall 2nd Edition, pg 95
110
+ straight_line_to_Bucharest =
111
+ {
112
+ 'Arad' => 366,
113
+ 'Bucharest' => 0,
114
+ 'Craiova' => 160,
115
+ 'Dobreta' => 242,
116
+ 'Eforie' => 161,
117
+ 'Fagaras' => 176,
118
+ 'Giurgiu' => 77,
119
+ 'Hirsova' => 151,
120
+ 'Iasi' => 226,
121
+ 'Lugoj' => 244,
122
+ 'Mehadia' => 241,
123
+ 'Neamt' => 234,
124
+ 'Oradea' => 380,
125
+ 'Pitesti' => 100,
126
+ 'Rimnicu Vilcea' => 193,
127
+ 'Sibiu' => 253,
128
+ 'Timisoara' => 329,
129
+ 'Urziceni' => 80,
130
+ 'Vaslui' => 199,
131
+ 'Zerind' => 374
132
+ }
133
+
134
+ # Heuristic is distance as crow flies, always under estimates costs.
135
+ h = Proc.new {|v| straight_line_to_Bucharest[v]}
136
+
137
+ list = []
138
+
139
+ dv = Proc.new {|v| list << "dv #{v}" }
140
+ ev = Proc.new {|v| list << "ev #{v}" }
141
+ bt = Proc.new {|v| list << "bt #{v}" }
142
+ fv = Proc.new {|v| list << "fv #{v}" }
143
+ er = Proc.new {|e| list << "er #{e}" }
144
+ enr = Proc.new {|e| list << "enr #{e}" }
145
+
146
+ options = { :discover_vertex => dv,
147
+ :examine_vertex => ev,
148
+ :black_target => bt,
149
+ :finish_vertex => fv,
150
+ :edge_relaxed => er,
151
+ :edge_not_relaxed => enr }
152
+
153
+ result = romania.astar('Arad', 'Bucharest', h, options)
154
+
155
+ result.should == ["Arad", "Sibiu", "Rimnicu Vilcea", "Pitesti", "Bucharest"]
156
+ # This isn't the greatest test since the exact ordering is not
157
+ # not specified by the algorithm. If someone has a better idea, please fix
158
+ list.should == ["ev Arad",
159
+ "er (Arad=Sibiu '99')",
160
+ "dv Sibiu",
161
+ "er (Arad=Timisoara '138')",
162
+ "dv Timisoara",
163
+ "er (Arad=Zerind '75')",
164
+ "dv Zerind",
165
+ "fv Arad",
166
+ "ev Sibiu",
167
+ "er (Rimnicu Vilcea=Sibiu '80')",
168
+ "dv Rimnicu Vilcea",
169
+ "er (Fagaras=Sibiu '99')",
170
+ "dv Fagaras",
171
+ "er (Oradea=Sibiu '151')",
172
+ "dv Oradea",
173
+ "enr (Arad=Sibiu '99')",
174
+ "fv Sibiu",
175
+ "ev Rimnicu Vilcea",
176
+ "enr (Rimnicu Vilcea=Sibiu '80')",
177
+ "er (Craiova=Rimnicu Vilcea '146')",
178
+ "dv Craiova",
179
+ "er (Pitesti=Rimnicu Vilcea '97')",
180
+ "dv Pitesti",
181
+ "fv Rimnicu Vilcea",
182
+ "ev Fagaras",
183
+ "enr (Fagaras=Sibiu '99')",
184
+ "er (Bucharest=Fagaras '211')",
185
+ "dv Bucharest",
186
+ "fv Fagaras",
187
+ "ev Pitesti",
188
+ "enr (Pitesti=Rimnicu Vilcea '97')",
189
+ "er (Bucharest=Pitesti '101')",
190
+ "enr (Craiova=Pitesti '138')",
191
+ "fv Pitesti",
192
+ "ev Bucharest"]
193
+ end
194
+ end
195
+
196
+ describe "bfs_spanning_forest" do
197
+ it do
198
+ predecessor, roots = @tree.bfs_spanning_forest(1)
199
+ predecessor.should == {2=>1, 3=>1, 4=>1, 5=>2, 6=>2, 7=>6, 24=>23}
200
+ roots.sort.should == [1,23]
201
+ predecessor, roots = @tree.bfs_spanning_forest(3)
202
+ predecessor.should == {7=>6, 24=>23, 2=>1, 4=>1}
203
+ roots.sort.should == [1,3,5,6,23]
204
+ end
205
+ end
206
+
207
+ describe "dfs_spanning_forest" do
208
+ it do
209
+ predecessor, roots = @tree.dfs_spanning_forest(1)
210
+ predecessor.should == {5=>2, 6=>2, 7=>6, 24=>23, 2=>1, 3=>1, 4=>2}
211
+ roots.sort.should == [1,23]
212
+ predecessor, roots = @tree.dfs_spanning_forest(3)
213
+ predecessor.should == {7=>6, 24=>23, 2=>1, 4=>2}
214
+ roots.sort.should == [1,3,5,6,23]
215
+ end
216
+ end
217
+
218
+ describe "tree_from_vertex" do
219
+ it do
220
+ @tree.bfs_tree_from_vertex(1).should == {5=>2, 6=>2, 7=>6, 2=>1, 3=>1, 4=>1}
221
+ @tree.bfs_tree_from_vertex(3).should == {}
222
+ @tree.dfs_tree_from_vertex(1).should == {5=>2, 6=>2, 7=>6, 2=>1, 3=>1, 4=>2}
223
+ @tree.dfs_tree_from_vertex(3).should == {}
224
+ end
225
+ end
226
+
227
+ end