Skip to content

Commit 794beff

Browse files
Use GenericGraph for testing shortestpaths algorithms (#275)
1 parent ab2056a commit 794beff

File tree

11 files changed

+85
-66
lines changed

11 files changed

+85
-66
lines changed

src/shortestpaths/bellman-ford.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ function bellman_ford_shortest_paths(
4848
for i in vertices(graph)
4949
no_changes = true
5050
new_active .= false
51-
for u in vertices(graph)[active]
51+
for u in vertices(graph)
52+
active[u] || continue
5253
for v in outneighbors(graph, u)
5354
relax_dist = distmx[u, v] + dists[u]
5455
if dists[v] > relax_dist
@@ -80,9 +81,10 @@ function has_negative_edge_cycle(
8081
g::AbstractGraph{U}, distmx::AbstractMatrix{T}
8182
) where {T<:Real} where {U<:Integer}
8283
try
83-
bellman_ford_shortest_paths(g, vertices(g), distmx)
84+
bellman_ford_shortest_paths(g, collect_if_not_vector(vertices(g)), distmx)
8485
catch e
8586
isa(e, NegativeCycleError) && return true
87+
rethrow()
8688
end
8789
return false
8890
end

src/shortestpaths/johnson.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ function johnson_shortest_paths(
2828
nvg = nv(g)
2929
type_distmx = typeof(distmx)
3030
# Change when parallel implementation of Bellman Ford available
31-
wt_transform = bellman_ford_shortest_paths(g, vertices(g), distmx).dists
31+
wt_transform = bellman_ford_shortest_paths(g, collect_if_not_vector(vertices(g)), distmx).dists
3232

3333
@compat if !ismutable(distmx) && type_distmx != Graphs.DefaultDistance
3434
distmx = sparse(distmx) # Change reference, not value

src/shortestpaths/yen.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# TODO this algorithm does not work with abitrary AbstractGraph yet,
2+
# as it relies on rem_edge! and deepcopy
3+
4+
15
"""
26
struct YenState{T, U}
37

test/shortestpaths/astar.jl

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,21 @@
44

55
d1 = float([0 1 2 3 4; 5 0 6 7 8; 9 10 0 11 12; 13 14 15 0 16; 17 18 19 20 0])
66
d2 = sparse(float([0 1 2 3 4; 5 0 6 7 8; 9 10 0 11 12; 13 14 15 0 16; 17 18 19 20 0]))
7-
for g in testgraphs(g3), dg in testdigraphs(g4)
7+
@testset "SimpleGraph and SimpleDiGraph" for g in testgraphs(g3), dg in testdigraphs(g4)
88
@test @inferred(a_star(g, 1, 4, d1)) ==
99
@inferred(a_star(dg, 1, 4, d1)) ==
1010
@inferred(a_star(g, 1, 4, d2))
1111
@test isempty(@inferred(a_star(dg, 4, 1)))
1212
end
13+
@testset "GenericGraph and GenricDiGraph with SimpleEdge" for g in test_generic_graphs(g3), dg in test_generic_graphs(g4)
14+
zero_heuristic = n -> 0
15+
Eg = SimpleEdge{eltype(g)}
16+
Edg = SimpleEdge{eltype(dg)}
17+
@test @inferred(a_star(g, 1, 4, d1, zero_heuristic, Eg)) ==
18+
@inferred(a_star(dg, 1, 4, d1, zero_heuristic, Edg)) ==
19+
@inferred(a_star(g, 1, 4, d2, zero_heuristic, Eg))
20+
@test isempty(@inferred(a_star(dg, 4, 1, weights(dg), zero_heuristic, Edg)))
21+
end
1322

1423
# test for #1258
1524
g = complete_graph(4)
@@ -21,5 +30,5 @@
2130
s::Int
2231
d::Int
2332
end
24-
@test eltype(a_star(g, 1, 4, w, n -> 0, MyFavoriteEdgeType)) == MyFavoriteEdgeType
33+
@test eltype(a_star(GenericGraph(g), 1, 4, w, n -> 0, MyFavoriteEdgeType)) == MyFavoriteEdgeType
2534
end

test/shortestpaths/bellman-ford.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
d1 = float([0 1 2 3 4; 5 0 6 7 8; 9 10 0 11 12; 13 14 15 0 16; 17 18 19 20 0])
55
d2 = sparse(float([0 1 2 3 4; 5 0 6 7 8; 9 10 0 11 12; 13 14 15 0 16; 17 18 19 20 0]))
6-
for g in testdigraphs(g4)
6+
for g in test_generic_graphs(g4)
77
y = @inferred(bellman_ford_shortest_paths(g, 2, d1))
88
z = @inferred(bellman_ford_shortest_paths(g, 2, d2))
99
@test y.dists == z.dists == [Inf, 0, 6, 17, 33]
@@ -24,7 +24,7 @@
2424

2525
# Negative Cycle
2626
gx = complete_graph(3)
27-
for g in testgraphs(gx)
27+
for g in test_generic_graphs(gx)
2828
d = [1 -3 1; -3 1 1; 1 1 1]
2929
@test_throws Graphs.NegativeCycleError bellman_ford_shortest_paths(g, 1, d)
3030
@test has_negative_edge_cycle(g, d)
@@ -37,7 +37,7 @@
3737
# Negative cycle of length 3 in graph of diameter 4
3838
gx = complete_graph(4)
3939
d = [1 -1 1 1; 1 1 1 -1; 1 1 1 1; 1 1 1 1]
40-
for g in testgraphs(gx)
40+
for g in test_generic_graphs(gx)
4141
@test_throws Graphs.NegativeCycleError bellman_ford_shortest_paths(g, 1, d)
4242
@test has_negative_edge_cycle(g, d)
4343
end
@@ -56,7 +56,7 @@
5656

5757
d3 = [CustomReal(i, 3) for i in d1]
5858
d4 = sparse(d3)
59-
for g in testdigraphs(g4)
59+
for g in test_generic_graphs(g4)
6060
y = @inferred(bellman_ford_shortest_paths(g, 2, d3))
6161
z = @inferred(bellman_ford_shortest_paths(g, 2, d4))
6262
@test getfield.(y.dists, :val) == getfield.(z.dists, :val) == [Inf, 0, 6, 17, 33]

test/shortestpaths/desopo-pape.jl

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
g4 = path_digraph(5)
33
d1 = float([0 1 2 3 4; 5 0 6 7 8; 9 10 0 11 12; 13 14 15 0 16; 17 18 19 20 0])
44
d2 = sparse(float([0 1 2 3 4; 5 0 6 7 8; 9 10 0 11 12; 13 14 15 0 16; 17 18 19 20 0]))
5-
@testset "generic tests: $g" for g in testdigraphs(g4)
5+
@testset "generic tests: $(typeof(g))" for g in test_generic_graphs(g4)
66
y = @inferred(desopo_pape_shortest_paths(g, 2, d1))
77
z = @inferred(desopo_pape_shortest_paths(g, 2, d2))
88
@test y.parents == z.parents == [0, 0, 2, 3, 4]
@@ -13,7 +13,7 @@
1313
add_edge!(gx, 2, 4)
1414
d = ones(Int, 5, 5)
1515
d[2, 3] = 100
16-
@testset "cycles: $g" for g in testgraphs(gx)
16+
@testset "cycles: $(typeof(g))" for g in test_generic_graphs(gx)
1717
z = @inferred(desopo_pape_shortest_paths(g, 1, d))
1818
@test z.dists == [0, 1, 3, 2, 3]
1919
@test z.parents == [0, 1, 4, 2, 4]
@@ -28,7 +28,7 @@
2828
add_edge!(G, 3, 4)
2929
add_edge!(G, 4, 5)
3030

31-
@testset "more cycles: $g" for g in testgraphs(G)
31+
@testset "more cycles: $(typeof(g))" for g in test_generic_graphs(G)
3232
y = @inferred(desopo_pape_shortest_paths(g, 1, m))
3333
@test y.parents == [0, 1, 1, 3, 3]
3434
@test y.dists == [0, 2, 2, 3, 4]
@@ -43,7 +43,7 @@
4343
add_edge!(G, 2, 4)
4444
add_edge!(G, 4, 5)
4545
m = [0 10 2 0 15; 10 9 0 1 0; 2 0 1 0 0; 0 1 0 0 2; 15 0 0 2 0]
46-
@testset "self loops: $g" for g in testgraphs(G)
46+
@testset "self loops: $(typeof(g))" for g in test_generic_graphs(G)
4747
z = @inferred(desopo_pape_shortest_paths(g, 1, m))
4848
y = @inferred(dijkstra_shortest_paths(g, 1, m))
4949
@test isapprox(z.dists, y.dists)
@@ -54,15 +54,15 @@
5454
add_edge!(G, 1, 3)
5555
add_edge!(G, 4, 5)
5656
inf = typemax(eltype(G))
57-
@testset "disconnected: $g" for g in testgraphs(G)
57+
@testset "disconnected: $(typeof(G))" for g in test_generic_graphs(G)
5858
z = @inferred(desopo_pape_shortest_paths(g, 1))
5959
@test z.dists == [0, 1, 1, inf, inf]
6060
@test z.parents == [0, 1, 1, 0, 0]
6161
end
6262

6363
G = SimpleGraph(3)
6464
inf = typemax(eltype(G))
65-
@testset "empty: $g" for g in testgraphs(G)
65+
@testset "empty: $(typeof(g))" for g in test_generic_graphs(G)
6666
z = @inferred(desopo_pape_shortest_paths(g, 1))
6767
@test z.dists == [0, inf, inf]
6868
@test z.parents == [0, 0, 0]
@@ -73,7 +73,7 @@
7373
rng = StableRNG(seed)
7474
nvg = Int(ceil(250 * rand(rng)))
7575
neg = Int(floor((nvg * (nvg - 1) / 2) * rand(rng)))
76-
g = SimpleGraph(nvg, neg; rng=rng)
76+
g = GenericGraph(SimpleGraph(nvg, neg; rng=rng))
7777
z = desopo_pape_shortest_paths(g, 1)
7878
y = dijkstra_shortest_paths(g, 1)
7979
@test isapprox(z.dists, y.dists)
@@ -85,50 +85,50 @@
8585
rng = StableRNG(seed)
8686
nvg = Int(ceil(250 * rand(rng)))
8787
neg = Int(floor((nvg * (nvg - 1) / 2) * rand(rng)))
88-
g = SimpleDiGraph(nvg, neg; rng=rng)
88+
g = GenericDiGraph(SimpleDiGraph(nvg, neg; rng=rng))
8989
z = desopo_pape_shortest_paths(g, 1)
9090
y = dijkstra_shortest_paths(g, 1)
9191
@test isapprox(z.dists, y.dists)
9292
end
9393
end
9494

9595
@testset "misc graphs" begin
96-
G = complete_graph(9)
96+
G = GenericGraph(complete_graph(9))
9797
z = desopo_pape_shortest_paths(G, 1)
9898
y = dijkstra_shortest_paths(G, 1)
9999
@test isapprox(z.dists, y.dists)
100100

101-
G = complete_digraph(9)
101+
G = GenericDiGraph(complete_digraph(9))
102102
z = desopo_pape_shortest_paths(G, 1)
103103
y = dijkstra_shortest_paths(G, 1)
104104
@test isapprox(z.dists, y.dists)
105105

106-
G = cycle_graph(9)
106+
G = GenericGraph(cycle_graph(9))
107107
z = desopo_pape_shortest_paths(G, 1)
108108
y = dijkstra_shortest_paths(G, 1)
109109
@test isapprox(z.dists, y.dists)
110110

111-
G = cycle_digraph(9)
111+
G = GenericDiGraph(cycle_digraph(9))
112112
z = desopo_pape_shortest_paths(G, 1)
113113
y = dijkstra_shortest_paths(G, 1)
114114
@test isapprox(z.dists, y.dists)
115115

116-
G = star_graph(9)
116+
G = GenericGraph(star_graph(9))
117117
z = desopo_pape_shortest_paths(G, 1)
118118
y = dijkstra_shortest_paths(G, 1)
119119
@test isapprox(z.dists, y.dists)
120120

121-
G = wheel_graph(9)
121+
G = GenericGraph(wheel_graph(9))
122122
z = desopo_pape_shortest_paths(G, 1)
123123
y = dijkstra_shortest_paths(G, 1)
124124
@test isapprox(z.dists, y.dists)
125125

126-
G = roach_graph(9)
126+
G = GenericGraph(roach_graph(9))
127127
z = desopo_pape_shortest_paths(G, 1)
128128
y = dijkstra_shortest_paths(G, 1)
129129
@test isapprox(z.dists, y.dists)
130130

131-
G = clique_graph(5, 19)
131+
G = GenericGraph(clique_graph(5, 19))
132132
z = desopo_pape_shortest_paths(G, 1)
133133
y = dijkstra_shortest_paths(G, 1)
134134
@test isapprox(z.dists, y.dists)
@@ -158,16 +158,17 @@
158158
:truncatedtetrahedron,
159159
:truncatedtetrahedron_dir,
160160
]
161-
G = smallgraph(s)
162-
z = desopo_pape_shortest_paths(G, 1)
163-
y = dijkstra_shortest_paths(G, 1)
161+
GS = smallgraph(s)
162+
GG = is_directed(GS) ? GenericDiGraph(GS) : GenericGraph(GS)
163+
z = desopo_pape_shortest_paths(GG, 1)
164+
y = dijkstra_shortest_paths(GG, 1)
164165
@test isapprox(z.dists, y.dists)
165166
end
166167

167168
@testset "errors" begin
168-
g = Graph()
169+
g = GenericGraph(Graph())
169170
@test_throws DomainError desopo_pape_shortest_paths(g, 1)
170-
g = Graph(5)
171+
g = GenericGraph(Graph(5))
171172
@test_throws DomainError desopo_pape_shortest_paths(g, 6)
172173
end
173174
end

test/shortestpaths/dijkstra.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
d1 = float([0 1 2 3 4; 5 0 6 7 8; 9 10 0 11 12; 13 14 15 0 16; 17 18 19 20 0])
44
d2 = sparse(float([0 1 2 3 4; 5 0 6 7 8; 9 10 0 11 12; 13 14 15 0 16; 17 18 19 20 0]))
55

6-
for g in testdigraphs(g4)
6+
for g in test_generic_graphs(g4)
77
y = @inferred(dijkstra_shortest_paths(g, 2, d1))
88
z = @inferred(dijkstra_shortest_paths(g, 2, d2))
99

@@ -28,7 +28,7 @@
2828
add_edge!(gx, 2, 4)
2929
d = ones(Int, 5, 5)
3030
d[2, 3] = 100
31-
for g in testgraphs(gx)
31+
for g in test_generic_graphs(gx)
3232
z = @inferred(dijkstra_shortest_paths(g, 1, d))
3333
@test z.dists == [0, 1, 3, 2, 3]
3434
@test z.parents == [0, 1, 4, 2, 4]
@@ -59,7 +59,7 @@
5959
1.0 0.0 3.0 0.0
6060
]
6161

62-
for g in testgraphs(G)
62+
for g in test_generic_graphs(G)
6363
ds = @inferred(dijkstra_shortest_paths(g, 2, w))
6464
# this loop reconstructs the shortest path for vertices 1, 3 and 4
6565
@test spaths(ds, [1, 3, 4], 2) == Array[[2 1], [2 3], [2 1 4]]
@@ -81,7 +81,7 @@
8181
add_edge!(G, 3, 5)
8282
add_edge!(G, 3, 4)
8383
add_edge!(G, 4, 5)
84-
for g in testgraphs(G)
84+
for g in test_generic_graphs(G)
8585
ds = @inferred(dijkstra_shortest_paths(g, 1, m; allpaths=true))
8686
@test ds.pathcounts == [1.0, 1.0, 1.0, 1.0, 2.0]
8787
@test ds.predecessors == [[], [1], [1], [3], [3, 4]]
@@ -97,7 +97,7 @@
9797
add_edge!(G, 1, 2)
9898
add_edge!(G, 1, 3)
9999
add_edge!(G, 4, 5)
100-
for g in testgraphs(G)
100+
for g in test_generic_graphs(G)
101101
dm = @inferred(dijkstra_shortest_paths(g, 1; allpaths=true, trackvertices=true))
102102
@test dm.closest_vertices == [1, 2, 3, 4, 5]
103103
end
@@ -107,7 +107,7 @@
107107
add_edge!(G, 1, 3)
108108
m = float([0 2 2 0 0 1; 2 0 1 0 0 0; 2 1 0 4 0 0; 0 0 4 0 1 0; 0 0 0 1 0 1; 1 0 0 0 1 0])
109109

110-
for g in testgraphs(G)
110+
for g in test_generic_graphs(G)
111111
ds = @inferred(dijkstra_shortest_paths(g, 3, m;maxdist=3.0))
112112
@test ds.dists == [2, 1, 0, Inf, Inf, 3]
113113
end

test/shortestpaths/floyd-warshall.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
@testset "Floyd Warshall" begin
22
g3 = path_graph(5)
33
d = [0 1 2 3 4; 5 0 6 7 8; 9 10 0 11 12; 13 14 15 0 16; 17 18 19 20 0]
4-
for g in testgraphs(g3)
4+
for g in test_generic_graphs(g3)
55
z = @inferred(floyd_warshall_shortest_paths(g, d))
66
@test z.dists[3, :][:] == [7, 6, 0, 11, 27]
77
@test z.parents[3, :][:] == [2, 3, 0, 3, 4]
@@ -14,7 +14,7 @@
1414
end
1515
g4 = path_digraph(4)
1616
d = ones(4, 4)
17-
for g in testdigraphs(g4)
17+
for g in test_generic_graphs(g4)
1818
z = @inferred(floyd_warshall_shortest_paths(g, d))
1919
@test length(enumerate_paths(z, 4, 3)) == 0
2020
@test length(enumerate_paths(z, 4, 1)) == 0
@@ -23,7 +23,7 @@
2323

2424
g5 = DiGraph([1 1 1 0 1; 0 1 0 1 1; 0 1 1 0 0; 1 0 1 1 0; 0 0 0 1 1])
2525
d = [0 3 8 0 -4; 0 0 0 1 7; 0 4 0 0 0; 2 0 -5 0 0; 0 0 0 6 0]
26-
for g in testdigraphs(g5)
26+
for g in test_generic_graphs(g5)
2727
z = @inferred(floyd_warshall_shortest_paths(g, d))
2828
@test z.dists == [0 1 -3 2 -4; 3 0 -4 1 -1; 7 4 0 5 3; 2 -1 -5 0 -2; 8 5 1 6 0]
2929
end
@@ -32,15 +32,15 @@
3232
g = SimpleGraph(2)
3333
add_edge!(g, 1, 2)
3434
add_edge!(g, 2, 2)
35-
@test enumerate_paths(floyd_warshall_shortest_paths(g)) ==
35+
@test enumerate_paths(floyd_warshall_shortest_paths(GenericGraph(g))) ==
3636
Vector{Vector{Int}}[[[], [1, 2]], [[2, 1], []]]
3737

3838
g = SimpleDiGraph(2)
3939
add_edge!(g, 1, 1)
4040
add_edge!(g, 1, 2)
4141
add_edge!(g, 2, 1)
4242
add_edge!(g, 2, 2)
43-
@test enumerate_paths(floyd_warshall_shortest_paths(g)) ==
43+
@test enumerate_paths(floyd_warshall_shortest_paths(GenericDiGraph(g))) ==
4444
Vector{Vector{Int}}[[[], [1, 2]], [[2, 1], []]]
4545
end
4646
end

test/shortestpaths/johnson.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
@testset "Johnson" begin
22
g3 = path_graph(5)
33
d = Symmetric([0 1 2 3 4; 1 0 6 7 8; 2 6 0 11 12; 3 7 11 0 16; 4 8 12 16 0])
4-
for g in testgraphs(g3)
4+
for g in test_generic_graphs(g3)
55
z = @inferred(johnson_shortest_paths(g, d))
66
@test z.dists[3, :][:] == [7, 6, 0, 11, 27]
77
@test z.parents[3, :][:] == [2, 3, 0, 3, 4]
@@ -14,7 +14,7 @@
1414
end
1515

1616
g4 = path_digraph(4)
17-
for g in testdigraphs(g4)
17+
for g in test_generic_graphs(g4)
1818
z = @inferred(johnson_shortest_paths(g))
1919
@test length(enumerate_paths(z, 4, 3)) == 0
2020
@test length(enumerate_paths(z, 4, 1)) == 0
@@ -23,7 +23,7 @@
2323

2424
g5 = DiGraph([1 1 1 0 1; 0 1 0 1 1; 0 1 1 0 0; 1 0 1 1 0; 0 0 0 1 1])
2525
d = [0 3 8 0 -4; 0 0 0 1 7; 0 4 0 0 0; 2 0 -5 0 0; 0 0 0 6 0]
26-
for g in testdigraphs(g5)
26+
for g in test_generic_graphs(g5)
2727
z = @inferred(johnson_shortest_paths(g, d))
2828
@test z.dists == [0 1 -3 2 -4; 3 0 -4 1 -1; 7 4 0 5 3; 2 -1 -5 0 -2; 8 5 1 6 0]
2929
end

0 commit comments

Comments
 (0)