rgl 0.2.2

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