rgl 0.4.0 → 0.5.0

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