rgl 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. data/ChangeLog +74 -0
  2. data/Makefile +72 -0
  3. data/README +240 -0
  4. data/Rakefile +210 -0
  5. data/TAGS +209 -0
  6. data/examples/canvas.rb +103 -0
  7. data/examples/codegraph +238 -0
  8. data/examples/example.jpg +0 -0
  9. data/examples/examples.rb +112 -0
  10. data/examples/graph.dot +54 -0
  11. data/examples/graph.png +0 -0
  12. data/examples/module_graph.jpg +0 -0
  13. data/examples/north.rb +12 -0
  14. data/examples/north/Graph.log +128 -0
  15. data/examples/north/g.10.0.graphml +28 -0
  16. data/examples/north/g.10.1.graphml +28 -0
  17. data/examples/north/g.10.11.graphml +31 -0
  18. data/examples/north/g.10.12.graphml +27 -0
  19. data/examples/north/g.10.13.graphml +27 -0
  20. data/examples/north/g.10.14.graphml +27 -0
  21. data/examples/north/g.10.15.graphml +26 -0
  22. data/examples/north/g.10.16.graphml +26 -0
  23. data/examples/north/g.10.17.graphml +26 -0
  24. data/examples/north/g.10.19.graphml +37 -0
  25. data/examples/north/g.10.2.graphml +28 -0
  26. data/examples/north/g.10.20.graphml +38 -0
  27. data/examples/north/g.10.22.graphml +43 -0
  28. data/examples/north/g.10.24.graphml +30 -0
  29. data/examples/north/g.10.25.graphml +45 -0
  30. data/examples/north/g.10.27.graphml +38 -0
  31. data/examples/north/g.10.28.graphml +30 -0
  32. data/examples/north/g.10.29.graphml +38 -0
  33. data/examples/north/g.10.3.graphml +26 -0
  34. data/examples/north/g.10.30.graphml +34 -0
  35. data/examples/north/g.10.31.graphml +42 -0
  36. data/examples/north/g.10.34.graphml +42 -0
  37. data/examples/north/g.10.37.graphml +28 -0
  38. data/examples/north/g.10.38.graphml +38 -0
  39. data/examples/north/g.10.39.graphml +36 -0
  40. data/examples/north/g.10.4.graphml +26 -0
  41. data/examples/north/g.10.40.graphml +37 -0
  42. data/examples/north/g.10.41.graphml +37 -0
  43. data/examples/north/g.10.42.graphml +26 -0
  44. data/examples/north/g.10.45.graphml +28 -0
  45. data/examples/north/g.10.46.graphml +32 -0
  46. data/examples/north/g.10.5.graphml +31 -0
  47. data/examples/north/g.10.50.graphml +30 -0
  48. data/examples/north/g.10.56.graphml +29 -0
  49. data/examples/north/g.10.57.graphml +32 -0
  50. data/examples/north/g.10.58.graphml +32 -0
  51. data/examples/north/g.10.6.graphml +26 -0
  52. data/examples/north/g.10.60.graphml +32 -0
  53. data/examples/north/g.10.61.graphml +34 -0
  54. data/examples/north/g.10.62.graphml +34 -0
  55. data/examples/north/g.10.68.graphml +30 -0
  56. data/examples/north/g.10.69.graphml +32 -0
  57. data/examples/north/g.10.7.graphml +29 -0
  58. data/examples/north/g.10.70.graphml +26 -0
  59. data/examples/north/g.10.71.graphml +27 -0
  60. data/examples/north/g.10.72.graphml +28 -0
  61. data/examples/north/g.10.74.graphml +29 -0
  62. data/examples/north/g.10.75.graphml +29 -0
  63. data/examples/north/g.10.78.graphml +27 -0
  64. data/examples/north/g.10.79.graphml +34 -0
  65. data/examples/north/g.10.8.graphml +29 -0
  66. data/examples/north/g.10.80.graphml +34 -0
  67. data/examples/north/g.10.82.graphml +35 -0
  68. data/examples/north/g.10.83.graphml +32 -0
  69. data/examples/north/g.10.85.graphml +34 -0
  70. data/examples/north/g.10.86.graphml +34 -0
  71. data/examples/north/g.10.88.graphml +37 -0
  72. data/examples/north/g.10.89.graphml +29 -0
  73. data/examples/north/g.10.9.graphml +26 -0
  74. data/examples/north/g.10.90.graphml +32 -0
  75. data/examples/north/g.10.91.graphml +31 -0
  76. data/examples/north/g.10.92.graphml +26 -0
  77. data/examples/north/g.10.93.graphml +32 -0
  78. data/examples/north/g.10.94.graphml +34 -0
  79. data/examples/north/g.12.8.graphml +40 -0
  80. data/examples/north/g.14.9.graphml +36 -0
  81. data/examples/north2.rb +21 -0
  82. data/examples/rdep-rgl.rb +395 -0
  83. data/install.rb +49 -0
  84. data/lib/rgl/adjacency.rb +151 -0
  85. data/lib/rgl/base.rb +299 -0
  86. data/lib/rgl/connected_components.rb +125 -0
  87. data/lib/rgl/dot.rb +63 -0
  88. data/lib/rgl/graphxml.rb +52 -0
  89. data/lib/rgl/implicit.rb +151 -0
  90. data/lib/rgl/mutable.rb +54 -0
  91. data/lib/rgl/rdot.rb +264 -0
  92. data/lib/rgl/topsort.rb +61 -0
  93. data/lib/rgl/transitiv_closure.rb +34 -0
  94. data/lib/rgl/traversal.rb +296 -0
  95. data/tests/TestComponents.rb +67 -0
  96. data/tests/TestDirectedGraph.rb +100 -0
  97. data/tests/TestEdge.rb +33 -0
  98. data/tests/TestGraphXML.rb +57 -0
  99. data/tests/TestImplicit.rb +52 -0
  100. data/tests/TestTransitiveClosure.rb +29 -0
  101. data/tests/TestTraversal.rb +222 -0
  102. data/tests/TestUnDirectedGraph.rb +98 -0
  103. metadata +163 -0
@@ -0,0 +1,67 @@
1
+ require 'test/unit'
2
+
3
+ require 'rgl/connected_components'
4
+ require 'rgl/adjacency'
5
+
6
+ class Array
7
+ alias add push
8
+ end
9
+
10
+ include RGL
11
+
12
+ def graph_from_string(s)
13
+ g = DirectedAdjacencyGraph.new(Array)
14
+ s.split(/\n/).collect{|x| x.split(/->/)}.each do |a|
15
+ from = a[0].strip
16
+ a[1].split.each do |to|
17
+ g.add_edge from,to
18
+ end
19
+ end
20
+ g
21
+ end
22
+
23
+ class TestComponents < Test::Unit::TestCase
24
+
25
+ def setup
26
+ @dg = DirectedAdjacencyGraph.new(Array)
27
+ edges = [[1,2],[2,3],[2,4],[4,5],[1,6],[6,4]]
28
+ edges.each do |(src,target)|
29
+ @dg.add_edge(src, target)
30
+ end
31
+ @bfs = @dg.bfs_iterator(1)
32
+ @dfs = @dg.dfs_iterator(1)
33
+
34
+ @ug = AdjacencyGraph.new(Array)
35
+ @ug.add_edges(*edges)
36
+
37
+ @dg2 = graph_from_string(
38
+ "a -> b f h
39
+ b -> c a
40
+ c -> d b
41
+ d -> e
42
+ e -> d
43
+ f -> g
44
+ g -> f d
45
+ h -> i
46
+ i -> h j e c")
47
+ end
48
+
49
+ def test_connected_components
50
+ ccs = []
51
+ @ug.each_connected_component { |c| ccs << c }
52
+ assert_equal(1,ccs.size)
53
+
54
+ ccs = []
55
+ @ug.add_edge 10,11
56
+ @ug.add_edge 33,44
57
+ @ug.each_connected_component { |c| ccs << c.sort }
58
+ assert_equal([[10, 11], [1, 2, 3, 4, 5, 6], [33,44]].sort,ccs.sort)
59
+ end
60
+
61
+ def test_strong_components
62
+ vis = @dg2.strongly_connected_components
63
+
64
+ assert_equal(4,vis.num_comp)
65
+ assert_equal([["a", 3], ["b", 3], ["c", 3], ["d", 0], ["e", 0], ["f", 1], ["g", 1], ["h", 3], ["i", 3], ["j", 2]],vis.comp_map.to_a)
66
+ end
67
+ end
@@ -0,0 +1,100 @@
1
+ require 'test/unit'
2
+ require 'rgl/adjacency'
3
+
4
+ include RGL
5
+ include RGL::Edge
6
+
7
+ class TestDirectedGraph < Test::Unit::TestCase
8
+ def setup
9
+ @dg = DirectedAdjacencyGraph.new
10
+ [[1,2],[2,3],[3,2],[2,4]].each do |(src,target)|
11
+ @dg.add_edge(src, target)
12
+ end
13
+ end
14
+
15
+ def test_empty_graph
16
+ dg = DirectedAdjacencyGraph.new
17
+ assert(dg.empty?)
18
+ assert(dg.directed?)
19
+ assert(!dg.has_edge?(2,1))
20
+ assert(!dg.has_vertex?(3))
21
+ # Non existend vertex result in a Name Error because each_key is
22
+ # called for nil
23
+ assert_raises(NoVertexError) {dg.out_degree(3)}
24
+ assert_equal([],dg.vertices)
25
+ assert_equal(0,dg.size)
26
+ assert_equal(0,dg.num_vertices)
27
+ assert_equal(0,dg.num_edges)
28
+ assert_equal(DirectedEdge,dg.edge_class)
29
+ assert([].eql?(dg.edges))
30
+ end
31
+
32
+ def test_add
33
+ dg = DirectedAdjacencyGraph.new
34
+ dg.add_edge(1,2)
35
+ assert(!dg.empty?)
36
+ assert(dg.has_edge?(1,2))
37
+ assert(!dg.has_edge?(2,1))
38
+ assert(dg.has_vertex?(1) && dg.has_vertex?(2))
39
+ assert(!dg.has_vertex?(3))
40
+
41
+ assert_equal([1,2],dg.vertices.sort)
42
+ assert([DirectedEdge.new(1,2)].eql?(dg.edges))
43
+ assert_equal("(1-2)",dg.edges.to_s)
44
+
45
+ assert_equal([2],dg.adjacent_vertices(1))
46
+ assert_equal([],dg.adjacent_vertices(2))
47
+
48
+ assert_equal(1,dg.out_degree(1))
49
+ assert_equal(0,dg.out_degree(2))
50
+ end
51
+
52
+ def test_edges
53
+ assert_equal(4, @dg.edges.length)
54
+ assert_equal([1,2,2,3], @dg.edges.map {|l| l.source}.sort)
55
+ assert_equal([2,2,3,4], @dg.edges.map {|l| l.target}.sort)
56
+ assert_equal("(1-2)(2-3)(2-4)(3-2)", @dg.edges.map {|l| l.to_s}.sort.join)
57
+ # assert_equal([0,1,2,3], @dg.edges.map {|l| l.info}.sort)
58
+ end
59
+
60
+ def test_vertices
61
+ assert_equal([1,2,3,4], @dg.vertices.sort)
62
+ end
63
+
64
+ def test_edges_from_to?
65
+ assert @dg.has_edge?(1,2)
66
+ assert @dg.has_edge?(2,3)
67
+ assert @dg.has_edge?(3,2)
68
+ assert @dg.has_edge?(2,4)
69
+ assert !@dg.has_edge?(2,1)
70
+ assert !@dg.has_edge?(3,1)
71
+ assert !@dg.has_edge?(4,1)
72
+ assert !@dg.has_edge?(4,2)
73
+ end
74
+
75
+ def test_remove_edges
76
+ @dg.remove_edge 1,2
77
+ assert !@dg.has_edge?(1,2)
78
+ @dg.remove_edge 1,2
79
+ assert !@dg.has_edge?(1,2)
80
+ @dg.remove_vertex 3
81
+ assert !@dg.has_vertex?(3)
82
+ assert !@dg.has_edge?(2,3)
83
+ assert_equal("(2-4)",@dg.to_s)
84
+ end
85
+
86
+ def test_add_vertices
87
+ dg = DirectedAdjacencyGraph.new
88
+ dg.add_vertices 1,3,2,4
89
+ assert_equal dg.vertices.sort, [1,2,3,4]
90
+
91
+ dg.remove_vertices 1,3
92
+ assert_equal dg.vertices.sort, [2,4]
93
+ end
94
+
95
+ def test_creating_from_array
96
+ dg = DirectedAdjacencyGraph[1, 2, 3, 4]
97
+ assert_equal(dg.vertices.sort, [1,2,3,4])
98
+ assert_equal(dg.edges.to_s, "(1-2)(3-4)")
99
+ end
100
+ end
@@ -0,0 +1,33 @@
1
+ require 'test/unit'
2
+ require 'rgl/base'
3
+
4
+ include RGL::Edge
5
+
6
+ class TestEdge < Test::Unit::TestCase
7
+
8
+ def test_directed_edge
9
+ assert_raises(ArgumentError) {DirectedEdge.new}
10
+ e = DirectedEdge.new 1,2
11
+ assert_equal(1,e.source)
12
+ assert_equal(2,e.target)
13
+ assert_equal([1,2],e.to_a)
14
+ assert_equal("(1-2)",e.to_s)
15
+ assert_equal([1,2],[e[0],e[1]])
16
+ assert(DirectedEdge.new(1,2).eql?(DirectedEdge.new(1,2)))
17
+ assert(!DirectedEdge.new(1,2).eql?(DirectedEdge.new(1,3)))
18
+ assert(!DirectedEdge.new(2,1).eql?(DirectedEdge.new(1,2)))
19
+ end
20
+
21
+ def test_undirected_edge
22
+ assert_raises(ArgumentError) {UnDirectedEdge.new}
23
+ e = UnDirectedEdge.new 1,2
24
+ assert_equal(1,e.source)
25
+ assert_equal(2,e.target)
26
+ assert_equal([1,2],e.to_a)
27
+ assert_equal("(1=2)",e.to_s)
28
+ assert(UnDirectedEdge.new(1,2).eql?(UnDirectedEdge.new(2,1)))
29
+ assert(!UnDirectedEdge.new(1,3).eql?(UnDirectedEdge.new(2,1)))
30
+ assert_equal(UnDirectedEdge.new(1,2).hash,UnDirectedEdge.new(1,2).hash)
31
+ end
32
+
33
+ end
@@ -0,0 +1,57 @@
1
+ require 'test/unit'
2
+ require 'rgl/graphxml'
3
+ require 'rgl/adjacency'
4
+ require 'rgl/topsort'
5
+ require 'rgl/connected_components'
6
+ require 'rgl/dot'
7
+
8
+ include RGL
9
+
10
+ class TestGraphXML < Test::Unit::TestCase
11
+ NORTH_DIR = './examples/north/'
12
+
13
+ def setup
14
+ @stream = File.new(NORTH_DIR + "g.10.0.graphml")
15
+ end
16
+
17
+ def tear_down
18
+ @stream.close
19
+ end
20
+
21
+ def test_graphxml
22
+ @dg = DirectedAdjacencyGraph.from_graphxml(@stream).to_s
23
+ assert_equal("(n0-n1)(n0-n2)(n0-n9)(n3-n4)(n4-n5)(n5-n7)(n8-n0)(n8-n3)(n8-n4)(n8-n5)(n8-n6)",@dg.to_s)
24
+ end
25
+
26
+ def test_north_graphs
27
+ name,nnodes,nedges = '',0,0
28
+ IO.foreach(NORTH_DIR + '/Graph.log') {
29
+ |line|
30
+ if /name:\s*(.*)\sformat: graphml\s+nodes: (\d+)\s+edges: (\d+)/ =~ line
31
+ name,nnodes,nedges = $1,$2.to_i,$3.to_i
32
+ end
33
+ if name && /directed: (\w+).*acyclic: (\w+).*connected: (\w+).*biconnected: (\w+)\s+/ =~ line
34
+ directed, acyclic, connected, biconnected = $1,$2,$3,$4
35
+ File.open(NORTH_DIR + name + '.graphml') {
36
+ |file|
37
+ print '.'; $stdout.flush
38
+ graph = (directed == 'true' ? DirectedAdjacencyGraph : AdjacencyGraph).from_graphxml(file)
39
+ #graph.write_to_graphic_file
40
+ assert_equal(nnodes,graph.num_vertices)
41
+ assert_equal(nedges,graph.num_edges)
42
+ assert_equal(acyclic,graph.acyclic?.to_s)
43
+
44
+ num_comp = 0
45
+ graph.to_undirected.each_connected_component {|x| num_comp += 1}
46
+ assert_equal(connected,(num_comp == 1).to_s)
47
+
48
+ # if graph.directed?
49
+ # num_comp = graph.strongly_connected_components.num_comp
50
+ # #puts num_comp
51
+ # assert_equal(biconnected, (num_comp == 1).to_s)
52
+ # end
53
+ }
54
+ end
55
+ }
56
+ end
57
+ end
@@ -0,0 +1,52 @@
1
+ require 'test/unit'
2
+ require 'rgl/implicit'
3
+ require 'rgl/adjacency'
4
+
5
+ include RGL
6
+
7
+ class TestImplicit < Test::Unit::TestCase
8
+ def setup
9
+ @dg = DirectedAdjacencyGraph.new
10
+ [[1,2],[2,3],[2,4],[4,5],[1,6],[6,4]].each do |(src,target)|
11
+ @dg.add_edge(src, target)
12
+ end
13
+
14
+ @cycle = ImplicitGraph.new { |g|
15
+ g.vertex_iterator { |b| 0.upto(4,&b) }
16
+ g.adjacent_iterator { |x, b| b.call((x+1)%5) }
17
+ g.directed = true
18
+ }
19
+ end
20
+
21
+ def test_empty
22
+ empty = ImplicitGraph.new
23
+ assert(empty.empty?)
24
+ assert_equal([],empty.edges)
25
+ assert_equal([],empty.vertices)
26
+ end
27
+
28
+ def test_cycle
29
+ assert(!@cycle.empty?)
30
+ assert_equal([0, 1, 2, 3, 4],@cycle.vertices.sort)
31
+ assert_equal("(0-1)(1-2)(2-3)(3-4)(4-0)",@cycle.edges.sort.to_s)
32
+ end
33
+
34
+ def test_vertex_filtered_graph
35
+ fg = @cycle.vertices_filtered_by {|v| v%2 == 0}
36
+ assert_equal([0, 2, 4],fg.vertices.sort)
37
+ assert_equal("(4-0)",fg.edges.sort.to_s)
38
+ assert(fg.directed?)
39
+
40
+ fg = @dg.vertices_filtered_by {|v| v%2 == 0}
41
+ assert_equal([2, 4, 6],fg.vertices.sort)
42
+ assert_equal("(2-4)(6-4)",fg.edges.sort.to_s)
43
+ assert(fg.directed?)
44
+ end
45
+
46
+ def test_edge_filtered_graph
47
+ fg = @cycle.edges_filtered_by {|u,v| u+v > 3}
48
+ assert_equal(@cycle.vertices.sort,fg.vertices.sort)
49
+ assert_equal("(2-3)(3-4)(4-0)",fg.edges.sort.to_s)
50
+ assert(fg.directed?)
51
+ end
52
+ end
@@ -0,0 +1,29 @@
1
+ require 'test/unit'
2
+ require 'rgl/transitiv_closure'
3
+
4
+ include RGL
5
+
6
+ class Array
7
+ alias add push
8
+ end
9
+
10
+ class TestTransitiveClosure < Test::Unit::TestCase
11
+
12
+ def setup
13
+ @dg = DirectedAdjacencyGraph.new(Array)
14
+ edges = [[1,2],[2,3],[2,4],[4,5],[1,6],[6,4]]
15
+ edges.each do |(src,target)|
16
+ @dg.add_edge(src, target)
17
+ end
18
+ end
19
+
20
+ def test_transitive_closure
21
+ assert_equal("(1-2)(1-3)(1-4)(1-6)(2-3)(2-4)(2-5)(4-5)(6-4)(6-5)",
22
+ @dg.transitive_closure.to_s)
23
+ end
24
+
25
+ def test_transitive_closure_undirected
26
+ assert_raises(NotDirectedError) {AdjacencyGraph.new.transitive_closure}
27
+ end
28
+ end
29
+
@@ -0,0 +1,222 @@
1
+ require 'test/unit'
2
+ require 'rgl/adjacency'
3
+ require 'rgl/traversal'
4
+ require 'rgl/topsort'
5
+ require 'rgl/implicit'
6
+
7
+ class Array
8
+ alias add push
9
+ end
10
+
11
+ include RGL
12
+
13
+ class TestTraversal < Test::Unit::TestCase
14
+
15
+ def setup
16
+ @dg = DirectedAdjacencyGraph.new(Array)
17
+ edges = [[1,2],[2,3],[2,4],[4,5],[1,6],[6,4]]
18
+ edges.each do |(src,target)|
19
+ @dg.add_edge(src, target)
20
+ end
21
+ @bfs = @dg.bfs_iterator(1)
22
+ @dfs = @dg.dfs_iterator(1)
23
+
24
+ @ug = AdjacencyGraph.new(Array)
25
+ @ug.add_edges(*edges)
26
+ end
27
+
28
+ def test_bfs_iterator_creation
29
+ assert(@bfs.at_beginning?)
30
+ assert(!@bfs.at_end?)
31
+ assert_equal(1,@bfs.start_vertex)
32
+ assert_equal(@dg,@bfs.graph)
33
+ end
34
+
35
+ def test_bfs_visiting
36
+ expected = [1, 2, 6, 3, 4, 5]
37
+ assert_equal(expected,@bfs.to_a)
38
+ assert_equal(expected,@ug.bfs_iterator(1).to_a)
39
+ assert_equal([2, 1, 3, 4, 6, 5],@ug.bfs_iterator(2).to_a)
40
+ end
41
+
42
+ def test_bfs_event_handlers
43
+ expected =
44
+ 'tree_edge : -1
45
+ examine_vertex : 1
46
+ examine_edge : 1-2
47
+ tree_edge : 1-2
48
+ examine_edge : 1-6
49
+ tree_edge : 1-6
50
+ finished_vertex: 1
51
+ examine_vertex : 2
52
+ examine_edge : 2-3
53
+ tree_edge : 2-3
54
+ examine_edge : 2-4
55
+ tree_edge : 2-4
56
+ finished_vertex: 2
57
+ examine_vertex : 6
58
+ examine_edge : 6-4
59
+ back_edge : 6-4
60
+ finished_vertex: 6
61
+ examine_vertex : 3
62
+ finished_vertex: 3
63
+ examine_vertex : 4
64
+ examine_edge : 4-5
65
+ tree_edge : 4-5
66
+ finished_vertex: 4
67
+ examine_vertex : 5
68
+ examine_edge : 5-3
69
+ forward_edge : 5-3
70
+ finished_vertex: 5
71
+ '
72
+ s = ''
73
+ @dg.add_edge 5,3 # for the forward_edge 5-3
74
+ @bfs.set_examine_vertex_event_handler { |v| s << "examine_vertex : #{v}\n"}
75
+ @bfs.set_examine_edge_event_handler { |u,v| s << "examine_edge : #{u}-#{v}\n"}
76
+ @bfs.set_tree_edge_event_handler { |u,v| s << "tree_edge : #{u}-#{v}\n"}
77
+ @bfs.set_back_edge_event_handler { |u,v| s << "back_edge : #{u}-#{v}\n"}
78
+ @bfs.set_forward_edge_event_handler { |u,v| s << "forward_edge : #{u}-#{v}\n"}
79
+
80
+ @bfs.each {|v| s << "finished_vertex: #{v}\n"}
81
+ puts "BFS: ", s if $DEBUG
82
+ assert_equal(expected,s)
83
+ end
84
+
85
+ def test_dfs_visiting
86
+ assert_equal([1, 6, 4, 5, 2, 3],@dg.dfs_iterator(1).to_a)
87
+ assert_equal([2, 4, 5, 3],@dg.dfs_iterator(2).to_a)
88
+ end
89
+
90
+ def test_dfs_event_handlers
91
+ expected =
92
+ 'tree_edge : -1
93
+ examine_vertex : 1
94
+ examine_edge : 1-2
95
+ tree_edge : 1-2
96
+ examine_edge : 1-6
97
+ tree_edge : 1-6
98
+ finished_vertex: 1
99
+ examine_vertex : 6
100
+ examine_edge : 6-4
101
+ tree_edge : 6-4
102
+ finished_vertex: 6
103
+ examine_vertex : 4
104
+ examine_edge : 4-5
105
+ tree_edge : 4-5
106
+ finished_vertex: 4
107
+ examine_vertex : 5
108
+ examine_edge : 5-3
109
+ tree_edge : 5-3
110
+ finished_vertex: 5
111
+ examine_vertex : 3
112
+ finished_vertex: 3
113
+ examine_vertex : 2
114
+ examine_edge : 2-3
115
+ forward_edge : 2-3
116
+ examine_edge : 2-4
117
+ forward_edge : 2-4
118
+ finished_vertex: 2
119
+ '
120
+ s = ''
121
+ @dg.add_edge 5,3
122
+ @dfs.set_examine_vertex_event_handler { |v| s << "examine_vertex : #{v}\n"}
123
+ @dfs.set_examine_edge_event_handler { |u,v| s << "examine_edge : #{u}-#{v}\n"}
124
+ @dfs.set_tree_edge_event_handler { |u,v| s << "tree_edge : #{u}-#{v}\n"}
125
+ @dfs.set_back_edge_event_handler { |u,v| s << "back_edge : #{u}-#{v}\n"}
126
+ @dfs.set_forward_edge_event_handler { |u,v| s << "forward_edge : #{u}-#{v}\n"}
127
+
128
+ @dfs.each {|v| s << "finished_vertex: #{v}\n"}
129
+ puts "DFS: ", s if $DEBUG
130
+ assert_equal(expected,s)
131
+ end
132
+
133
+ def test_bfs_search_tree
134
+ assert_equal("(1-2)(1-6)(2-3)(2-4)(4-5)",@dg.bfs_search_tree_from(1).edges.sort.to_s)
135
+ end
136
+
137
+ def aux(it)
138
+ it.attach_distance_map
139
+ it.set_to_end
140
+ it.graph.vertices.sort.collect {|v|
141
+ "#{v}-#{it.distance_to_root(v)}"
142
+ }.join(', ')
143
+ end
144
+ def test_distance_map
145
+ assert_equal("1-0, 2-1, 3-2, 4-2, 5-3, 6-1",aux(@bfs))
146
+ @dg.add_edge 5,3
147
+ assert_equal("1-0, 2-1, 3-4, 4-2, 5-3, 6-1",aux(@dfs))
148
+ end
149
+
150
+ def test_topsort
151
+ ts_it = @dg.topsort_iterator
152
+ assert(ts_it.at_beginning?)
153
+ assert_equal(@dg,ts_it.graph)
154
+ assert(!ts_it.at_end?)
155
+ ts_order = ts_it.to_a # do the traversal
156
+ assert_equal(@dg.num_vertices,ts_order.size)
157
+
158
+ # Check topsort contraint:
159
+ @dg.each_edge { |u,v|
160
+ assert(ts_order.index(u) < ts_order.index(v))
161
+ }
162
+ ts_it.set_to_begin
163
+ assert(ts_it.at_beginning?)
164
+
165
+ # Topsort on undirected graphs is empty
166
+ assert(@ug.topsort_iterator.at_end?)
167
+ end
168
+
169
+ # depth_first_search can also be used to compute a topsort!
170
+ def test_dfs_search_as_topsort
171
+ ts_order = []
172
+ @dg.depth_first_search { |v| ts_order << v }
173
+ ts_order = ts_order.reverse
174
+ @dg.each_edge { |u,v|
175
+ assert(ts_order.index(u) < ts_order.index(v))
176
+ }
177
+ end
178
+
179
+ def test_acyclic
180
+ assert(@dg.acyclic?)
181
+ @dg.add_edge 5,2 # add cycle
182
+ assert(!@dg.acyclic?)
183
+ end
184
+
185
+ def test_dfs_visit
186
+ a = []
187
+ @dg.depth_first_visit(1) { |x| a << x }
188
+ assert_equal([3, 5, 4, 2, 6, 1],a)
189
+
190
+ a = []
191
+ @dg.add_edge 10,11
192
+ @dg.depth_first_visit(10) { |x| a << x }
193
+ assert_equal([11, 10],a)
194
+ end
195
+
196
+ def test_dfs_visit_with_parens
197
+ a = ""
198
+ vis = DFSVisitor.new(@dg)
199
+ vis.set_examine_vertex_event_handler {|v| a << "(#{v} "}
200
+ vis.set_finish_vertex_event_handler {|v| a << " #{v})"}
201
+ @dg.depth_first_visit(1,vis) { |x| }
202
+ assert_equal("(1 (2 (3 3)(4 (5 5) 4) 2)(6 6) 1)",a)
203
+ end
204
+
205
+ def test_depth_first_search_with_parens
206
+ @dg.add_edge 10,11
207
+ # We must ensure, that the order of the traversal is not dependend on the
208
+ # order of the each iterator in the hash map of the adjacency graph. Therefor we
209
+ # wrap the graph with an implicit graph that simply ensures a sort order on
210
+ # the vertices.
211
+ dg = @dg.implicit_graph {
212
+ | g |
213
+ g.vertex_iterator { |b| @dg.vertices.sort.each(&b)}
214
+ }
215
+ a = ""
216
+ vis = DFSVisitor.new(dg)
217
+ vis.set_examine_vertex_event_handler {|v| a << "(#{v} "}
218
+ vis.set_finish_vertex_event_handler {|v| a << " #{v})"}
219
+ dg.depth_first_search(vis) { |x| }
220
+ assert_equal("(1 (2 (3 3)(4 (5 5) 4) 2)(6 6) 1)(10 (11 11) 10)",a)
221
+ end
222
+ end