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.
- data/ChangeLog +19 -10
- data/Gemfile +3 -0
- data/{README → README.rdoc} +70 -98
- data/Rakefile +44 -150
- data/examples/canvas.rb +63 -64
- data/examples/examples.rb +42 -42
- data/examples/graph.dot +46 -0
- data/examples/images/example.jpg +0 -0
- data/examples/images/module_graph.jpg +0 -0
- data/examples/images/rgl_modules.png +0 -0
- data/examples/{insel-der-tausend-gefahren.rb → insel_der_tausend_gefahren.rb} +18 -19
- data/examples/north.rb +2 -2
- data/examples/north2.rb +11 -11
- data/examples/rdep-rgl.rb +218 -222
- data/lib/rgl/adjacency.rb +78 -74
- data/lib/rgl/base.rb +160 -78
- data/lib/rgl/bellman_ford.rb +115 -0
- data/lib/rgl/bidirectional.rb +17 -10
- data/lib/rgl/bipartite.rb +87 -0
- data/lib/rgl/condensation.rb +13 -4
- data/lib/rgl/connected_components.rb +38 -30
- data/lib/rgl/dijkstra.rb +158 -0
- data/lib/rgl/dijkstra_visitor.rb +42 -0
- data/lib/rgl/dot.rb +40 -32
- data/lib/rgl/edge_properties_map.rb +55 -0
- data/lib/rgl/edmonds_karp.rb +136 -0
- data/lib/rgl/enumerable_ext.rb +4 -1
- data/lib/rgl/graph_iterator.rb +15 -0
- data/lib/rgl/graph_visitor.rb +138 -0
- data/lib/rgl/graph_wrapper.rb +15 -0
- data/lib/rgl/graphxml.rb +20 -10
- data/lib/rgl/implicit.rb +68 -66
- data/lib/rgl/mutable.rb +37 -31
- data/lib/rgl/path_builder.rb +40 -0
- data/lib/rgl/prim.rb +52 -0
- data/lib/rgl/rdot.rb +411 -374
- data/lib/rgl/topsort.rb +23 -16
- data/lib/rgl/transitivity.rb +29 -27
- data/lib/rgl/traversal.rb +67 -205
- data/rakelib/dep_graph.rake +4 -3
- data/test/bellman_ford_test.rb +187 -0
- data/test/bipartite_test.rb +47 -0
- data/test/components_test.rb +80 -0
- data/test/cycles_test.rb +60 -0
- data/test/dijkstra_test.rb +148 -0
- data/test/directed_graph_test.rb +118 -0
- data/test/dot_test.rb +26 -0
- data/test/edge_properties_map_test.rb +63 -0
- data/test/edge_test.rb +35 -0
- data/test/edmonds_karp_test.rb +105 -0
- data/{tests/TestGraph.rb → test/graph_test.rb} +6 -6
- data/test/graph_xml_test.rb +57 -0
- data/test/implicit_test.rb +53 -0
- data/test/prim_test.rb +98 -0
- data/{tests/TestRdot.rb → test/rdot_test.rb} +309 -308
- data/{tests → test}/test_helper.rb +4 -1
- data/{tests/TestTransitivity.rb → test/transitivity_test.rb} +43 -43
- data/test/traversal_test.rb +221 -0
- data/test/undirected_graph_test.rb +103 -0
- metadata +226 -145
- data/examples/example.jpg +0 -0
- data/examples/module_graph.jpg +0 -0
- data/install.rb +0 -49
- data/tests/TestComponents.rb +0 -65
- data/tests/TestCycles.rb +0 -61
- data/tests/TestDirectedGraph.rb +0 -125
- data/tests/TestDot.rb +0 -18
- data/tests/TestEdge.rb +0 -34
- data/tests/TestGraphXML.rb +0 -57
- data/tests/TestImplicit.rb +0 -52
- data/tests/TestTraversal.rb +0 -220
- data/tests/TestUnDirectedGraph.rb +0 -102
data/tests/TestComponents.rb
DELETED
@@ -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
|
data/tests/TestCycles.rb
DELETED
@@ -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
|
data/tests/TestDirectedGraph.rb
DELETED
@@ -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
|
data/tests/TestDot.rb
DELETED
@@ -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
|
data/tests/TestEdge.rb
DELETED
@@ -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
|
data/tests/TestGraphXML.rb
DELETED
@@ -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
|
data/tests/TestImplicit.rb
DELETED
@@ -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
|
data/tests/TestTraversal.rb
DELETED
@@ -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
|