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
@@ -13,9 +13,10 @@ end
13
13
  desc "Generate dependency graph of rake tasks"
14
14
  task :dep_graph do |task|
15
15
  this_task = task.name
16
- dep = RGL::ImplicitGraph.new { |g|
16
+
17
+ dep = RGL::ImplicitGraph.new do |g|
17
18
  # vertices of the graph are all defined tasks without this task
18
- g.vertex_iterator do |b|
19
+ g.vertex_iterator do |b|
19
20
  Rake::Task.tasks.each do |t|
20
21
  b.call(t) unless t.name == this_task
21
22
  end
@@ -23,7 +24,7 @@ task :dep_graph do |task|
23
24
  # neighbors of task t are its prerequisites
24
25
  g.adjacent_iterator { |t, b| t.prerequisites.each(&b) }
25
26
  g.directed = true
26
- }
27
+ end
27
28
 
28
29
  dep.write_to_graphic_file('png', this_task)
29
30
  puts "Wrote dependency graph to #{this_task}.png."
@@ -0,0 +1,187 @@
1
+ require 'test_helper'
2
+
3
+ require 'rgl/bellman_ford'
4
+ require 'rgl/adjacency'
5
+
6
+ include RGL
7
+
8
+ class TestBellmanFord < Test::Unit::TestCase
9
+
10
+ def setup
11
+ @graph = AdjacencyGraph[1,2, 1,3, 2,3, 2,4, 3,4]
12
+
13
+ @edge_weights = {
14
+ [1, 2] => 10,
15
+ [1, 3] => 1,
16
+ [2, 3] => 1,
17
+ [2, 4] => 1,
18
+ [3, 4] => 10
19
+ }
20
+
21
+ @edge_weights_lambda = lambda { |edge| @edge_weights[edge] }
22
+ end
23
+
24
+ def test_shortest_paths_search
25
+ assert_equal(
26
+ {
27
+ 1 => [1],
28
+ 2 => [1, 3, 2],
29
+ 3 => [1, 3],
30
+ 4 => [1, 3, 2, 4]
31
+ },
32
+ shortest_paths(1)
33
+ )
34
+ end
35
+
36
+ def test_shortest_paths_search_with_lambda
37
+ assert_equal(
38
+ {
39
+ 1 => [1],
40
+ 2 => [1, 3, 2],
41
+ 3 => [1, 3],
42
+ 4 => [1, 3, 2, 4]
43
+ },
44
+ shortest_paths(1, @edge_weights_lambda)
45
+ )
46
+ end
47
+
48
+ def test_shortest_paths_search_with_unreachable_vertex
49
+ @graph.add_vertex(5)
50
+
51
+ assert_equal(
52
+ {
53
+ 1 => [1],
54
+ 2 => [1, 3, 2],
55
+ 3 => [1, 3],
56
+ 4 => [1, 3, 2, 4],
57
+ 5 => nil
58
+ },
59
+ shortest_paths(1)
60
+ )
61
+ end
62
+
63
+ def test_shortest_paths_with_negative_weights
64
+ # can't use an undirected graph with a negative weighted edge here, because a negative weighted undirected edge is
65
+ # already a negative weighted cycle and therefore Bellman-Ford can't be applied for such graph
66
+ @graph = DirectedAdjacencyGraph[1,2, 1,3, 2,3, 2,4, 3,2, 3,4]
67
+ @edge_weights[[3, 2]] = 1
68
+ @edge_weights[[3, 4]] = -1
69
+
70
+ assert_equal(
71
+ {
72
+ 1 => [1],
73
+ 2 => [1, 3, 2],
74
+ 3 => [1, 3],
75
+ 4 => [1, 3, 4]
76
+ },
77
+ shortest_paths(1)
78
+ )
79
+ end
80
+
81
+ def test_missing_edge_weight
82
+ @edge_weights.delete([2, 3])
83
+ assert_raises(ArgumentError, 'weight of edge (2, 3) is not defined') { shortest_paths(1) }
84
+ end
85
+
86
+ def test_negative_cycles
87
+ @graph = DirectedAdjacencyGraph[1,2, 1,3, 2,3, 2,4, 3,4, 4,2]
88
+ @edge_weights[[4, 2]] = 1
89
+ @edge_weights[[3, 4]] = -3 # cycle 2-3-4-2 has negative weight
90
+
91
+ assert_raises(ArgumentError, 'there is a negative-weight cycle including edge (3, 4)') { shortest_paths(1) }
92
+ end
93
+
94
+ def test_visitor
95
+ visitor = BellmanFordVisitor.new(@graph)
96
+
97
+ events = []
98
+
99
+ %w[examine_edge edge_relaxed edge_not_relaxed edge_minimized edge_not_minimized].each do |event|
100
+ visitor.send("set_#{event}_event_handler") { |*args| events << { event.to_sym => args } }
101
+ end
102
+
103
+ @graph.bellman_ford_shortest_paths(@edge_weights, 1, visitor)
104
+
105
+ assert_equal(
106
+ [
107
+ # first iteration
108
+ { :examine_edge => [1, 2] },
109
+ { :edge_relaxed => [1, 2] },
110
+ { :examine_edge => [2, 1] },
111
+ { :edge_not_relaxed => [2, 1] },
112
+ { :examine_edge => [1, 3] },
113
+ { :edge_relaxed => [1, 3] },
114
+ { :examine_edge => [3, 1] },
115
+ { :edge_not_relaxed => [3, 1] },
116
+ { :examine_edge => [2, 3] },
117
+ { :edge_not_relaxed => [2, 3] },
118
+ { :examine_edge => [3, 2] },
119
+ { :edge_relaxed => [3, 2] },
120
+ { :examine_edge => [2, 4] },
121
+ { :edge_relaxed => [2, 4] },
122
+ { :examine_edge => [4, 2] },
123
+ { :edge_not_relaxed => [4, 2] },
124
+ { :examine_edge => [3, 4] },
125
+ { :edge_not_relaxed => [3, 4] },
126
+ { :examine_edge => [4, 3] },
127
+ { :edge_not_relaxed => [4, 3] },
128
+ # second iteration
129
+ { :examine_edge => [1, 2] },
130
+ { :edge_not_relaxed => [1, 2] },
131
+ { :examine_edge => [2, 1] },
132
+ { :edge_not_relaxed => [2, 1] },
133
+ { :examine_edge => [1, 3] },
134
+ { :edge_not_relaxed => [1, 3] },
135
+ { :examine_edge => [3, 1] },
136
+ { :edge_not_relaxed => [3, 1] },
137
+ { :examine_edge => [2, 3] },
138
+ { :edge_not_relaxed => [2, 3] },
139
+ { :examine_edge => [3, 2] },
140
+ { :edge_not_relaxed => [3, 2] },
141
+ { :examine_edge => [2, 4] },
142
+ { :edge_not_relaxed => [2, 4] },
143
+ { :examine_edge => [4, 2] },
144
+ { :edge_not_relaxed => [4, 2] },
145
+ { :examine_edge => [3, 4] },
146
+ { :edge_not_relaxed => [3, 4] },
147
+ { :examine_edge => [4, 3] },
148
+ { :edge_not_relaxed => [4, 3] },
149
+ # thirds iteration
150
+ { :examine_edge => [1, 2] },
151
+ { :edge_not_relaxed => [1, 2] },
152
+ { :examine_edge => [2, 1] },
153
+ { :edge_not_relaxed => [2, 1] },
154
+ { :examine_edge => [1, 3] },
155
+ { :edge_not_relaxed => [1, 3] },
156
+ { :examine_edge => [3, 1] },
157
+ { :edge_not_relaxed => [3, 1] },
158
+ { :examine_edge => [2, 3] },
159
+ { :edge_not_relaxed => [2, 3] },
160
+ { :examine_edge => [3, 2] },
161
+ { :edge_not_relaxed => [3, 2] },
162
+ { :examine_edge => [2, 4] },
163
+ { :edge_not_relaxed => [2, 4] },
164
+ { :examine_edge => [4, 2] },
165
+ { :edge_not_relaxed => [4, 2] },
166
+ { :examine_edge => [3, 4] },
167
+ { :edge_not_relaxed => [3, 4] },
168
+ { :examine_edge => [4, 3] },
169
+ { :edge_not_relaxed => [4, 3] },
170
+ # post-iteration check
171
+ { :edge_minimized => [1, 2] },
172
+ { :edge_minimized => [1, 3] },
173
+ { :edge_minimized => [2, 3] },
174
+ { :edge_minimized => [2, 4] },
175
+ { :edge_minimized => [3, 4] }
176
+ ],
177
+ events
178
+ )
179
+ end
180
+
181
+ private
182
+
183
+ def shortest_paths(source, edge_weights = @edge_weights)
184
+ @graph.bellman_ford_shortest_paths(edge_weights, source)
185
+ end
186
+
187
+ end
@@ -0,0 +1,47 @@
1
+ require 'test_helper'
2
+
3
+ require 'rgl/bipartite'
4
+ require 'rgl/adjacency'
5
+
6
+ include RGL
7
+
8
+ class TestBipartite < Test::Unit::TestCase
9
+
10
+ def test_bipartite_sets
11
+ assert_equal([[1, 2, 3], [4, 5, 6]], bipartite_sets(AdjacencyGraph[1,5, 1,6, 2,4, 2,5, 3,4, 3,5, 3,6]))
12
+ end
13
+
14
+ def test_bipartite_sets_for_non_bipartite_graph
15
+ assert_equal(nil, bipartite_sets(AdjacencyGraph[1,4, 1,5, 2,3, 2,4, 2,5, 3,5]))
16
+ end
17
+
18
+ def test_bipartite_sets_for_directed_graph
19
+ assert_raise(NotUndirectedError, 'bipartite sets can only be found for an undirected graph') do
20
+ DirectedAdjacencyGraph.new.bipartite_sets
21
+ end
22
+ end
23
+
24
+ def test_bipartite_sets_for_bipartite_disconnected_graph
25
+ assert_equal([[1, 3], [2, 4]], bipartite_sets(AdjacencyGraph[1,2, 3,4]))
26
+ end
27
+
28
+ def test_bipartite_sets_for_non_bipartite_disconnected_graph
29
+ assert_equal(nil, bipartite_sets(AdjacencyGraph[1,2, 3,4, 4,5, 5,3]))
30
+ end
31
+
32
+ def test_bipartite
33
+ assert(AdjacencyGraph[1,2, 2,3].bipartite?)
34
+ end
35
+
36
+ def test_not_bipartite
37
+ assert(!AdjacencyGraph[1,2, 2,3, 3,1].bipartite?)
38
+ end
39
+
40
+ private
41
+
42
+ def bipartite_sets(graph)
43
+ sets = graph.bipartite_sets
44
+ sets && sets.map { |set| set.sort }.sort
45
+ end
46
+
47
+ end
@@ -0,0 +1,80 @@
1
+ require 'test_helper'
2
+
3
+ require 'rgl/connected_components'
4
+ require 'rgl/adjacency'
5
+
6
+ include RGL
7
+
8
+ def graph_from_string(s)
9
+ g = DirectedAdjacencyGraph.new(Array)
10
+ s.split(/\n/).collect { |x| x.split(/->/) }.each do |a|
11
+ from = a[0].strip
12
+ a[1].split.each do |to|
13
+ g.add_edge from, to
14
+ end
15
+ end
16
+ g
17
+ end
18
+
19
+ class TestComponents < Test::Unit::TestCase
20
+
21
+ def setup
22
+ @dg = DirectedAdjacencyGraph.new(Array)
23
+ edges = [[1, 2], [2, 3], [2, 4], [4, 5], [1, 6], [6, 4]]
24
+ edges.each do |(src, target)|
25
+ @dg.add_edge(src, target)
26
+ end
27
+ @bfs = @dg.bfs_iterator(1)
28
+ @dfs = @dg.dfs_iterator(1)
29
+
30
+ @ug = AdjacencyGraph.new(Array)
31
+ @ug.add_edges(*edges)
32
+
33
+ @dg2 = graph_from_string(<<-END
34
+ a -> b f h
35
+ b -> c a
36
+ c -> d b
37
+ d -> e
38
+ e -> d
39
+ f -> g
40
+ g -> f d
41
+ h -> i
42
+ i -> h j e c
43
+ END
44
+ )
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
+
64
+ res = vis.comp_map.to_a.sort.reduce({}) { |res, a|
65
+ if res.key?(a[1])
66
+ res[a[1]] << a[0]
67
+ else
68
+ res[a[1]] = [a[0]]
69
+ end
70
+ res
71
+ }
72
+
73
+ std_res = res.to_a.map {
74
+ |a|
75
+ [a[1][0], a[1]]
76
+ }.sort
77
+
78
+ assert_equal([["a", ["a", "b", "c", "h", "i"]], ["d", ["d", "e"]], ["f", ["f", "g"]], ["j", ["j"]]], std_res)
79
+ end
80
+ end
@@ -0,0 +1,60 @@
1
+ require 'test_helper'
2
+
3
+ require 'rgl/adjacency'
4
+
5
+ include RGL
6
+
7
+ class TestCycles < Test::Unit::TestCase
8
+
9
+ def setup
10
+ @dg = DirectedAdjacencyGraph.new(Array)
11
+ edges = [[1, 2], [2, 2], [2, 3], [3, 4], [4, 5], [5, 1], [6, 4], [6, 6], [1, 4], [7, 7], [7, 7]]
12
+ edges.each do |(src, target)|
13
+ @dg.add_edge(src, target)
14
+ end
15
+
16
+ @ug = AdjacencyGraph.new(Array)
17
+ @ug.add_edges(*edges)
18
+ end
19
+
20
+ # Helper for testing for different permutations of a cycle
21
+ def contains_cycle?(cycles, cycle)
22
+ cycle.size.times do |i|
23
+ return true if cycles.include?(cycle)
24
+ cycle = cycle[1..-1] + [cycle[0]]
25
+ end
26
+ end
27
+
28
+ def test_cycles
29
+ d_cycles = @dg.cycles
30
+ assert_equal 6, d_cycles.size
31
+ assert d_cycles.include?([6])
32
+ assert d_cycles.include?([7])
33
+ assert d_cycles.include?([2])
34
+ assert contains_cycle?(d_cycles, [1, 4, 5])
35
+ assert contains_cycle?(d_cycles, [1, 2, 3, 4, 5])
36
+
37
+ assert_equal 5, DirectedAdjacencyGraph.new(Set, @dg).cycles.size
38
+
39
+ u_cycles = AdjacencyGraph.new(Set, @dg).cycles.sort
40
+
41
+ assert u_cycles.include?([2])
42
+ assert u_cycles.include?([6])
43
+ assert u_cycles.include?([7])
44
+ assert contains_cycle?(u_cycles, [1, 2, 3, 4, 5])
45
+ assert contains_cycle?(u_cycles, [1, 5, 4, 3, 2])
46
+ assert contains_cycle?(u_cycles, [1, 4, 3, 2])
47
+ assert contains_cycle?(u_cycles, [1, 4, 5])
48
+ assert contains_cycle?(u_cycles, [1, 5, 4])
49
+ assert contains_cycle?(u_cycles, [1, 5])
50
+ assert contains_cycle?(u_cycles, [1, 2])
51
+ assert contains_cycle?(u_cycles, [1, 2, 3, 4])
52
+ assert contains_cycle?(u_cycles, [2, 3])
53
+ assert contains_cycle?(u_cycles, [1, 4])
54
+ assert contains_cycle?(u_cycles, [3, 4])
55
+ assert contains_cycle?(u_cycles, [4, 5])
56
+ assert contains_cycle?(u_cycles, [4, 6])
57
+ assert_equal 16, u_cycles.size
58
+ end
59
+
60
+ end
@@ -0,0 +1,148 @@
1
+ require 'test_helper'
2
+
3
+ require 'rgl/dijkstra'
4
+ require 'rgl/adjacency'
5
+
6
+ include RGL
7
+
8
+ class TestDijkstra < Test::Unit::TestCase
9
+
10
+ def setup
11
+ @graph = AdjacencyGraph[1,2, 1,3, 2,3, 2,4, 3,4]
12
+
13
+ @edge_weights = {
14
+ [1, 2] => 10,
15
+ [1, 3] => 1,
16
+ [2, 3] => 1,
17
+ [2, 4] => 1,
18
+ [3, 4] => 10
19
+ }
20
+
21
+ @edge_weights_lambda = lambda { |edge| @edge_weights[edge] }
22
+ end
23
+
24
+ def test_shortest_path_search
25
+ assert_equal([1, 3, 2, 4], shortest_path(1, 4))
26
+ end
27
+
28
+ def test_shortest_path_search_with_lambda
29
+ assert_equal([1, 3, 2, 4], shortest_path(1, 4, @edge_weights_lambda))
30
+ end
31
+
32
+ def test_shortest_path_to_the_source
33
+ assert_equal([1], shortest_path(1, 1))
34
+ end
35
+
36
+ def test_path_for_unreachable_vertex
37
+ @graph.add_vertex(5)
38
+ assert_equal(nil, shortest_path(1, 5))
39
+ end
40
+
41
+ def test_shortest_paths_search
42
+ assert_equal(
43
+ {
44
+ 1 => [1],
45
+ 2 => [1, 3, 2],
46
+ 3 => [1, 3],
47
+ 4 => [1, 3, 2, 4]
48
+ },
49
+ shortest_paths(1)
50
+ )
51
+ end
52
+
53
+ def test_shortest_paths_search_with_lambda
54
+ assert_equal(
55
+ {
56
+ 1 => [1],
57
+ 2 => [1, 3, 2],
58
+ 3 => [1, 3],
59
+ 4 => [1, 3, 2, 4]
60
+ },
61
+ shortest_paths(1, @edge_weights_lambda)
62
+ )
63
+ end
64
+
65
+ def test_shortest_paths_search_with_unreachable_vertex
66
+ @graph.add_vertex(5)
67
+
68
+ assert_equal(
69
+ {
70
+ 1 => [1],
71
+ 2 => [1, 3, 2],
72
+ 3 => [1, 3],
73
+ 4 => [1, 3, 2, 4],
74
+ 5 => nil
75
+ },
76
+ shortest_paths(1)
77
+ )
78
+ end
79
+
80
+ def test_visitor
81
+ visitor = DijkstraVisitor.new(@graph)
82
+
83
+ events = []
84
+
85
+ %w[examine_vertex examine_edge edge_relaxed edge_not_relaxed finish_vertex].each do |event|
86
+ visitor.send("set_#{event}_event_handler") { |*args| events << { event.to_sym => args } }
87
+ end
88
+
89
+ @graph.dijkstra_shortest_paths(@edge_weights, 1, visitor)
90
+
91
+ assert_equal(
92
+ [
93
+ { :examine_vertex => [1] },
94
+ { :examine_edge => [1, 2] },
95
+ { :edge_relaxed => [1, 2] },
96
+ { :examine_edge => [1, 3] },
97
+ { :edge_relaxed => [1, 3] },
98
+ { :finish_vertex => [1] },
99
+ { :examine_vertex => [3] },
100
+ { :examine_edge => [3, 2] },
101
+ { :edge_relaxed => [3, 2] },
102
+ { :examine_edge => [3, 4] },
103
+ { :edge_relaxed => [3, 4] },
104
+ { :finish_vertex => [3] },
105
+ { :examine_vertex => [2] },
106
+ { :examine_edge => [2, 4] },
107
+ { :edge_relaxed => [2, 4] },
108
+ { :finish_vertex => [2] },
109
+ { :examine_vertex => [4] },
110
+ { :finish_vertex => [4] },
111
+ ],
112
+ events
113
+ )
114
+ end
115
+
116
+ def test_negative_edge_weight
117
+ @edge_weights[[2, 3]] = -7
118
+ assert_raises(ArgumentError, 'weight of edge (2, 3) is negative') { shortest_path(1, 5) }
119
+ end
120
+
121
+ def test_negative_edge_weight_with_lambda
122
+ @edge_weights[[2, 3]] = -7
123
+ assert_raises(ArgumentError, 'weight of edge (2, 3) is negative') { shortest_path(1, 5, @edge_weights_lambda) }
124
+ end
125
+
126
+ def test_missing_edge_weight
127
+ @edge_weights.delete([2, 3])
128
+ assert_raises(ArgumentError, 'weight of edge (2, 3) is not defined') { shortest_path(1, 5) }
129
+ end
130
+
131
+ def test_edge_weights_map_object_in_argument
132
+ weights_map = EdgePropertiesMap.new(@edge_weights, @graph.directed?)
133
+ dijkstra = DijkstraAlgorithm.new(@graph, weights_map, DijkstraVisitor.new(@graph))
134
+
135
+ assert_equal([1, 3, 2, 4], dijkstra.shortest_path(1, 4))
136
+ end
137
+
138
+ private
139
+
140
+ def shortest_path(source, target, edge_weights = @edge_weights)
141
+ @graph.dijkstra_shortest_path(edge_weights, source, target)
142
+ end
143
+
144
+ def shortest_paths(source, edge_weights = @edge_weights)
145
+ @graph.dijkstra_shortest_paths(edge_weights, source)
146
+ end
147
+
148
+ end