rgl 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/ChangeLog +19 -10
  2. data/Gemfile +3 -0
  3. data/{README → README.rdoc} +70 -98
  4. data/Rakefile +44 -150
  5. data/examples/canvas.rb +63 -64
  6. data/examples/examples.rb +42 -42
  7. data/examples/graph.dot +46 -0
  8. data/examples/images/example.jpg +0 -0
  9. data/examples/images/module_graph.jpg +0 -0
  10. data/examples/images/rgl_modules.png +0 -0
  11. data/examples/{insel-der-tausend-gefahren.rb → insel_der_tausend_gefahren.rb} +18 -19
  12. data/examples/north.rb +2 -2
  13. data/examples/north2.rb +11 -11
  14. data/examples/rdep-rgl.rb +218 -222
  15. data/lib/rgl/adjacency.rb +78 -74
  16. data/lib/rgl/base.rb +160 -78
  17. data/lib/rgl/bellman_ford.rb +115 -0
  18. data/lib/rgl/bidirectional.rb +17 -10
  19. data/lib/rgl/bipartite.rb +87 -0
  20. data/lib/rgl/condensation.rb +13 -4
  21. data/lib/rgl/connected_components.rb +38 -30
  22. data/lib/rgl/dijkstra.rb +158 -0
  23. data/lib/rgl/dijkstra_visitor.rb +42 -0
  24. data/lib/rgl/dot.rb +40 -32
  25. data/lib/rgl/edge_properties_map.rb +55 -0
  26. data/lib/rgl/edmonds_karp.rb +136 -0
  27. data/lib/rgl/enumerable_ext.rb +4 -1
  28. data/lib/rgl/graph_iterator.rb +15 -0
  29. data/lib/rgl/graph_visitor.rb +138 -0
  30. data/lib/rgl/graph_wrapper.rb +15 -0
  31. data/lib/rgl/graphxml.rb +20 -10
  32. data/lib/rgl/implicit.rb +68 -66
  33. data/lib/rgl/mutable.rb +37 -31
  34. data/lib/rgl/path_builder.rb +40 -0
  35. data/lib/rgl/prim.rb +52 -0
  36. data/lib/rgl/rdot.rb +411 -374
  37. data/lib/rgl/topsort.rb +23 -16
  38. data/lib/rgl/transitivity.rb +29 -27
  39. data/lib/rgl/traversal.rb +67 -205
  40. data/rakelib/dep_graph.rake +4 -3
  41. data/test/bellman_ford_test.rb +187 -0
  42. data/test/bipartite_test.rb +47 -0
  43. data/test/components_test.rb +80 -0
  44. data/test/cycles_test.rb +60 -0
  45. data/test/dijkstra_test.rb +148 -0
  46. data/test/directed_graph_test.rb +118 -0
  47. data/test/dot_test.rb +26 -0
  48. data/test/edge_properties_map_test.rb +63 -0
  49. data/test/edge_test.rb +35 -0
  50. data/test/edmonds_karp_test.rb +105 -0
  51. data/{tests/TestGraph.rb → test/graph_test.rb} +6 -6
  52. data/test/graph_xml_test.rb +57 -0
  53. data/test/implicit_test.rb +53 -0
  54. data/test/prim_test.rb +98 -0
  55. data/{tests/TestRdot.rb → test/rdot_test.rb} +309 -308
  56. data/{tests → test}/test_helper.rb +4 -1
  57. data/{tests/TestTransitivity.rb → test/transitivity_test.rb} +43 -43
  58. data/test/traversal_test.rb +221 -0
  59. data/test/undirected_graph_test.rb +103 -0
  60. metadata +226 -145
  61. data/examples/example.jpg +0 -0
  62. data/examples/module_graph.jpg +0 -0
  63. data/install.rb +0 -49
  64. data/tests/TestComponents.rb +0 -65
  65. data/tests/TestCycles.rb +0 -61
  66. data/tests/TestDirectedGraph.rb +0 -125
  67. data/tests/TestDot.rb +0 -18
  68. data/tests/TestEdge.rb +0 -34
  69. data/tests/TestGraphXML.rb +0 -57
  70. data/tests/TestImplicit.rb +0 -52
  71. data/tests/TestTraversal.rb +0 -220
  72. data/tests/TestUnDirectedGraph.rb +0 -102
@@ -1,65 +0,0 @@
1
- require 'test/unit'
2
-
3
- require 'rgl/traversal'
4
- require 'rgl/connected_components'
5
- require 'rgl/adjacency'
6
- require 'test_helper'
7
-
8
- include RGL
9
-
10
- def graph_from_string(s)
11
- g = DirectedAdjacencyGraph.new(Array)
12
- s.split(/\n/).collect{|x| x.split(/->/)}.each do |a|
13
- from = a[0].strip
14
- a[1].split.each do |to|
15
- g.add_edge from,to
16
- end
17
- end
18
- g
19
- end
20
-
21
- class TestComponents < Test::Unit::TestCase
22
-
23
- def setup
24
- @dg = DirectedAdjacencyGraph.new(Array)
25
- edges = [[1,2],[2,3],[2,4],[4,5],[1,6],[6,4]]
26
- edges.each do |(src,target)|
27
- @dg.add_edge(src, target)
28
- end
29
- @bfs = @dg.bfs_iterator(1)
30
- @dfs = @dg.dfs_iterator(1)
31
-
32
- @ug = AdjacencyGraph.new(Array)
33
- @ug.add_edges(*edges)
34
-
35
- @dg2 = graph_from_string(
36
- "a -> b f h
37
- b -> c a
38
- c -> d b
39
- d -> e
40
- e -> d
41
- f -> g
42
- g -> f d
43
- h -> i
44
- i -> h j e c")
45
- end
46
-
47
- def test_connected_components
48
- ccs = []
49
- @ug.each_connected_component { |c| ccs << c }
50
- assert_equal(1,ccs.size)
51
-
52
- ccs = []
53
- @ug.add_edge 10,11
54
- @ug.add_edge 33,44
55
- @ug.each_connected_component { |c| ccs << c.sort }
56
- assert_equal([[10, 11], [1, 2, 3, 4, 5, 6], [33,44]].sort,ccs.sort)
57
- end
58
-
59
- def test_strong_components
60
- vis = @dg2.strongly_connected_components
61
-
62
- assert_equal(4,vis.num_comp)
63
- 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)
64
- end
65
- end
@@ -1,61 +0,0 @@
1
- $LOAD_PATH << "../lib"
2
- require 'test/unit'
3
- require 'rgl/adjacency'
4
- require 'test_helper'
5
-
6
- include RGL
7
-
8
- class TestCycles < Test::Unit::TestCase
9
-
10
- def setup
11
- @dg = DirectedAdjacencyGraph.new(Array)
12
- edges = [[1,2],[2,2],[2,3],[3,4],[4,5],[5,1],[6,4],[6,6],[1,4],[7,7],[7,7]]
13
- edges.each do |(src,target)|
14
- @dg.add_edge(src, target)
15
- end
16
-
17
- @ug = AdjacencyGraph.new(Array)
18
- @ug.add_edges(*edges)
19
- end
20
-
21
- # Helper for testing for different permutations of a cycle
22
- def contains_cycle?(cycles,cycle)
23
- cycle.size.times do |i|
24
- return true if cycles.include?(cycle)
25
- cycle = cycle[1..-1] + [cycle[0]]
26
- end
27
- end
28
-
29
- def test_cycles
30
- d_cycles = @dg.cycles
31
- assert_equal 6, d_cycles.size
32
- assert d_cycles.include?([6])
33
- assert d_cycles.include?([7])
34
- assert d_cycles.include?([2])
35
- assert contains_cycle?(d_cycles, [1,4,5])
36
- assert contains_cycle?(d_cycles, [1,2,3,4,5])
37
-
38
- assert_equal 5, DirectedAdjacencyGraph.new(Set, @dg).cycles.size
39
-
40
- u_cycles = AdjacencyGraph.new(Set, @dg).cycles.sort
41
-
42
- assert u_cycles.include?([2])
43
- assert u_cycles.include?([6])
44
- assert u_cycles.include?([7])
45
- assert contains_cycle?(u_cycles, [1,2,3,4,5])
46
- assert contains_cycle?(u_cycles, [1,5,4,3,2])
47
- assert contains_cycle?(u_cycles, [1,4,3,2])
48
- assert contains_cycle?(u_cycles, [1,4,5])
49
- assert contains_cycle?(u_cycles, [1,5,4])
50
- assert contains_cycle?(u_cycles, [1,5])
51
- assert contains_cycle?(u_cycles, [1,2])
52
- assert contains_cycle?(u_cycles, [1,2,3,4])
53
- assert contains_cycle?(u_cycles, [2,3])
54
- assert contains_cycle?(u_cycles, [1,4])
55
- assert contains_cycle?(u_cycles, [3,4])
56
- assert contains_cycle?(u_cycles, [4,5])
57
- assert contains_cycle?(u_cycles, [4,6])
58
- assert_equal 16, u_cycles.size
59
- end
60
-
61
- end
@@ -1,125 +0,0 @@
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
-
101
- def test_reverse
102
- reverted = @dg.reverse
103
- @dg.each_edge do |u,v|
104
- assert(reverted.has_edge?(v,u))
105
- end
106
- end
107
-
108
- def test_reverse
109
- # Add isolated vertex
110
- @dg.add_vertex(42)
111
- reverted = @dg.reverse
112
-
113
- @dg.each_edge do |u,v|
114
- assert(reverted.has_edge?(v,u))
115
- end
116
-
117
- assert(reverted.has_vertex?(42),
118
- "Reverted graph should contain isolated Vertex 42")
119
- end
120
-
121
- def test_to_undirected
122
- undirected = @dg.to_undirected
123
- assert_equal undirected.edges.sort.to_s, "(1=2)(2=3)(2=4)"
124
- end
125
- end
@@ -1,18 +0,0 @@
1
- require 'test/unit'
2
- require 'rgl/dot'
3
-
4
- class TestDot < Test::Unit::TestCase
5
-
6
- def test_to_dot_graph
7
- graph = RGL::DirectedAdjacencyGraph[1,2]
8
- dot = graph.to_dot_graph.to_s
9
- assert_match(dot, /\{[^}]*\}/) # {...}
10
- assert_match(dot, /1\s*\[/) # node 1
11
- assert_match(dot, /2\s*\[/) # node 2
12
- assert_match(dot, /1\s*->\s*2/) # edge
13
- end
14
-
15
- def assert_match(dot, pattern)
16
- assert(!(dot =~ pattern).nil?, "#{dot} doesn't match #{pattern}")
17
- end
18
- end
@@ -1,34 +0,0 @@
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("(2-1)",e.reverse.to_s)
16
- assert_equal([1,2],[e[0],e[1]])
17
- assert(DirectedEdge[1,2].eql?(DirectedEdge.new(1,2)))
18
- assert(!DirectedEdge[1,2].eql?(DirectedEdge.new(1,3)))
19
- assert(!DirectedEdge[2,1].eql?(DirectedEdge.new(1,2)))
20
- end
21
-
22
- def test_undirected_edge
23
- assert_raises(ArgumentError) {UnDirectedEdge.new}
24
- e = UnDirectedEdge.new 1,2
25
- assert_equal(1,e.source)
26
- assert_equal(2,e.target)
27
- assert_equal([1,2],e.to_a)
28
- assert_equal("(1=2)",e.to_s)
29
- assert(UnDirectedEdge.new(1,2).eql?(UnDirectedEdge.new(2,1)))
30
- assert(!UnDirectedEdge.new(1,3).eql?(UnDirectedEdge.new(2,1)))
31
- assert_equal(UnDirectedEdge.new(1,2).hash,UnDirectedEdge.new(1,2).hash)
32
- end
33
-
34
- end
@@ -1,57 +0,0 @@
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.new.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).new.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
@@ -1,52 +0,0 @@
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
@@ -1,220 +0,0 @@
1
- require 'test/unit'
2
- require 'rgl/adjacency'
3
- require 'rgl/traversal'
4
- require 'rgl/topsort'
5
- require 'rgl/implicit'
6
-
7
- require 'test_helper'
8
-
9
- include RGL
10
-
11
- class TestTraversal < Test::Unit::TestCase
12
-
13
- def setup
14
- @dg = DirectedAdjacencyGraph.new(Array)
15
- edges = [[1,2],[2,3],[2,4],[4,5],[1,6],[6,4]]
16
- edges.each do |(src,target)|
17
- @dg.add_edge(src, target)
18
- end
19
- @bfs = @dg.bfs_iterator(1)
20
- @dfs = @dg.dfs_iterator(1)
21
-
22
- @ug = AdjacencyGraph.new(Array)
23
- @ug.add_edges(*edges)
24
- end
25
-
26
- def test_bfs_iterator_creation
27
- assert(@bfs.at_beginning?)
28
- assert(!@bfs.at_end?)
29
- assert_equal(1,@bfs.start_vertex)
30
- assert_equal(@dg,@bfs.graph)
31
- end
32
-
33
- def test_bfs_visiting
34
- expected = [1, 2, 6, 3, 4, 5]
35
- assert_equal(expected,@bfs.to_a)
36
- assert_equal(expected,@ug.bfs_iterator(1).to_a)
37
- assert_equal([2, 1, 3, 4, 6, 5],@ug.bfs_iterator(2).to_a)
38
- end
39
-
40
- def test_bfs_event_handlers
41
- expected =
42
- 'tree_edge : -1
43
- examine_vertex : 1
44
- examine_edge : 1-2
45
- tree_edge : 1-2
46
- examine_edge : 1-6
47
- tree_edge : 1-6
48
- finished_vertex: 1
49
- examine_vertex : 2
50
- examine_edge : 2-3
51
- tree_edge : 2-3
52
- examine_edge : 2-4
53
- tree_edge : 2-4
54
- finished_vertex: 2
55
- examine_vertex : 6
56
- examine_edge : 6-4
57
- back_edge : 6-4
58
- finished_vertex: 6
59
- examine_vertex : 3
60
- finished_vertex: 3
61
- examine_vertex : 4
62
- examine_edge : 4-5
63
- tree_edge : 4-5
64
- finished_vertex: 4
65
- examine_vertex : 5
66
- examine_edge : 5-3
67
- forward_edge : 5-3
68
- finished_vertex: 5
69
- '
70
- s = ''
71
- @dg.add_edge 5,3 # for the forward_edge 5-3
72
- @bfs.set_examine_vertex_event_handler { |v| s << "examine_vertex : #{v}\n"}
73
- @bfs.set_examine_edge_event_handler { |u,v| s << "examine_edge : #{u}-#{v}\n"}
74
- @bfs.set_tree_edge_event_handler { |u,v| s << "tree_edge : #{u}-#{v}\n"}
75
- @bfs.set_back_edge_event_handler { |u,v| s << "back_edge : #{u}-#{v}\n"}
76
- @bfs.set_forward_edge_event_handler { |u,v| s << "forward_edge : #{u}-#{v}\n"}
77
-
78
- @bfs.each {|v| s << "finished_vertex: #{v}\n"}
79
- puts "BFS: ", s if $DEBUG
80
- assert_equal(expected,s)
81
- end
82
-
83
- def test_dfs_visiting
84
- assert_equal([1, 6, 4, 5, 2, 3],@dg.dfs_iterator(1).to_a)
85
- assert_equal([2, 4, 5, 3],@dg.dfs_iterator(2).to_a)
86
- end
87
-
88
- def test_dfs_event_handlers
89
- expected =
90
- 'tree_edge : -1
91
- examine_vertex : 1
92
- examine_edge : 1-2
93
- tree_edge : 1-2
94
- examine_edge : 1-6
95
- tree_edge : 1-6
96
- finished_vertex: 1
97
- examine_vertex : 6
98
- examine_edge : 6-4
99
- tree_edge : 6-4
100
- finished_vertex: 6
101
- examine_vertex : 4
102
- examine_edge : 4-5
103
- tree_edge : 4-5
104
- finished_vertex: 4
105
- examine_vertex : 5
106
- examine_edge : 5-3
107
- tree_edge : 5-3
108
- finished_vertex: 5
109
- examine_vertex : 3
110
- finished_vertex: 3
111
- examine_vertex : 2
112
- examine_edge : 2-3
113
- forward_edge : 2-3
114
- examine_edge : 2-4
115
- forward_edge : 2-4
116
- finished_vertex: 2
117
- '
118
- s = ''
119
- @dg.add_edge 5,3
120
- @dfs.set_examine_vertex_event_handler { |v| s << "examine_vertex : #{v}\n"}
121
- @dfs.set_examine_edge_event_handler { |u,v| s << "examine_edge : #{u}-#{v}\n"}
122
- @dfs.set_tree_edge_event_handler { |u,v| s << "tree_edge : #{u}-#{v}\n"}
123
- @dfs.set_back_edge_event_handler { |u,v| s << "back_edge : #{u}-#{v}\n"}
124
- @dfs.set_forward_edge_event_handler { |u,v| s << "forward_edge : #{u}-#{v}\n"}
125
-
126
- @dfs.each {|v| s << "finished_vertex: #{v}\n"}
127
- puts "DFS: ", s if $DEBUG
128
- assert_equal(expected,s)
129
- end
130
-
131
- def test_bfs_search_tree
132
- assert_equal("(1-2)(1-6)(2-3)(2-4)(4-5)",@dg.bfs_search_tree_from(1).edges.sort.to_s)
133
- end
134
-
135
- def aux(it)
136
- it.attach_distance_map
137
- it.set_to_end
138
- it.graph.vertices.sort.collect {|v|
139
- "#{v}-#{it.distance_to_root(v)}"
140
- }.join(', ')
141
- end
142
- def test_distance_map
143
- assert_equal("1-0, 2-1, 3-2, 4-2, 5-3, 6-1",aux(@bfs))
144
- @dg.add_edge 5,3
145
- assert_equal("1-0, 2-1, 3-4, 4-2, 5-3, 6-1",aux(@dfs))
146
- end
147
-
148
- def test_topsort
149
- ts_it = @dg.topsort_iterator
150
- assert(ts_it.at_beginning?)
151
- assert_equal(@dg,ts_it.graph)
152
- assert(!ts_it.at_end?)
153
- ts_order = ts_it.to_a # do the traversal
154
- assert_equal(@dg.num_vertices,ts_order.size)
155
-
156
- # Check topsort contraint:
157
- @dg.each_edge { |u,v|
158
- assert(ts_order.index(u) < ts_order.index(v))
159
- }
160
- ts_it.set_to_begin
161
- assert(ts_it.at_beginning?)
162
-
163
- # Topsort on undirected graphs is empty
164
- assert(@ug.topsort_iterator.at_end?)
165
- end
166
-
167
- # depth_first_search can also be used to compute a topsort!
168
- def test_dfs_search_as_topsort
169
- ts_order = []
170
- @dg.depth_first_search { |v| ts_order << v }
171
- ts_order = ts_order.reverse
172
- @dg.each_edge { |u,v|
173
- assert(ts_order.index(u) < ts_order.index(v))
174
- }
175
- end
176
-
177
- def test_acyclic
178
- assert(@dg.acyclic?)
179
- @dg.add_edge 5,2 # add cycle
180
- assert(!@dg.acyclic?)
181
- end
182
-
183
- def test_dfs_visit
184
- a = []
185
- @dg.depth_first_visit(1) { |x| a << x }
186
- assert_equal([3, 5, 4, 2, 6, 1],a)
187
-
188
- a = []
189
- @dg.add_edge 10,11
190
- @dg.depth_first_visit(10) { |x| a << x }
191
- assert_equal([11, 10],a)
192
- end
193
-
194
- def test_dfs_visit_with_parens
195
- a = ""
196
- vis = DFSVisitor.new(@dg)
197
- vis.set_examine_vertex_event_handler {|v| a << "(#{v} "}
198
- vis.set_finish_vertex_event_handler {|v| a << " #{v})"}
199
- @dg.depth_first_visit(1,vis) { |x| }
200
- assert_equal("(1 (2 (3 3)(4 (5 5) 4) 2)(6 6) 1)",a)
201
- end
202
-
203
- def test_depth_first_search_with_parens
204
- @dg.add_edge 10,11
205
- # We must ensure, that the order of the traversal is not dependend on the
206
- # order of the each iterator in the hash map of the adjacency graph. Therefor we
207
- # wrap the graph with an implicit graph that simply ensures a sort order on
208
- # the vertices.
209
- dg = @dg.implicit_graph {
210
- | g |
211
- g.vertex_iterator { |b| @dg.vertices.sort.each(&b)}
212
- }
213
- a = ""
214
- vis = DFSVisitor.new(dg)
215
- vis.set_examine_vertex_event_handler {|v| a << "(#{v} "}
216
- vis.set_finish_vertex_event_handler {|v| a << " #{v})"}
217
- dg.depth_first_search(vis) { |x| }
218
- assert_equal("(1 (2 (3 3)(4 (5 5) 4) 2)(6 6) 1)(10 (11 11) 10)",a)
219
- end
220
- end