Skip to content

Commit e5405d1

Browse files
aurorarossigdalle
andauthored
Solved bug in yen.jl (#183)
* Add maxdist to dijkstra * Use new version of dijkstra in yen * Fix typo test yen * Add new test * Add test dijkstra * Fix type maxdist * Change type maxdist * Remove type `maxdist` docs Co-authored-by: Guillaume Dalle <[email protected]> * Remove type `maxdist` docs Co-authored-by: Guillaume Dalle <[email protected]> * Same for `yen` * Update docstring --------- Co-authored-by: Guillaume Dalle <[email protected]>
1 parent 11f54ad commit e5405d1

File tree

4 files changed

+41
-18
lines changed

4 files changed

+41
-18
lines changed

src/shortestpaths/dijkstra.jl

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,21 @@ Return a [`Graphs.DijkstraState`](@ref) that contains various traversal informat
2020
2121
2222
### Optional Arguments
23-
* `allpaths=false`: If true,
23+
* `allpaths=false`: If true,
2424
2525
`state.predecessors` holds a vector, indexed by vertex,
2626
of all the predecessors discovered during shortest-path calculations.
2727
This keeps track of all parents when there are multiple shortest paths available from the source.
2828
29-
`state.pathcounts` holds a vector, indexed by vertex, of the number of shortest paths from the source to that vertex.
29+
`state.pathcounts` holds a vector, indexed by vertex, of the number of shortest paths from the source to that vertex.
3030
The path count of a source vertex is always `1.0`. The path count of an unreached vertex is always `0.0`.
3131
32-
* `trackvertices=false`: If true,
32+
* `trackvertices=false`: If true,
3333
3434
`state.closest_vertices` holds a vector of all vertices in the graph ordered from closest to farthest.
3535
36+
* `maxdist` (default: `typemax(T)`) specifies the maximum path distance beyond which all path distances are assumed to be infinite (that is, they do not exist).
37+
3638
### Performance
3739
If using a sparse matrix for `distmx`, you *may* achieve better performance by passing in a transpose of its sparse transpose.
3840
That is, assuming `D` is the sparse distance matrix:
@@ -73,7 +75,9 @@ function dijkstra_shortest_paths(
7375
distmx::AbstractMatrix{T}=weights(g);
7476
allpaths=false,
7577
trackvertices=false,
76-
) where {T<:Real} where {U<:Integer}
78+
maxdist=typemax(T)
79+
) where T <: Real where U <: Integer
80+
7781
nvg = nv(g)
7882
dists = fill(typemax(T), nvg)
7983
parents = zeros(U, nvg)
@@ -105,6 +109,8 @@ function dijkstra_shortest_paths(
105109
for v in outneighbors(g, u)
106110
alt = d + distmx[u, v]
107111

112+
alt > maxdist && continue
113+
108114
if !visited[v]
109115
visited[v] = true
110116
dists[v] = alt
@@ -157,8 +163,9 @@ function dijkstra_shortest_paths(
157163
distmx::AbstractMatrix=weights(g);
158164
allpaths=false,
159165
trackvertices=false,
166+
maxdist=typemax(eltype(distmx))
160167
)
161168
return dijkstra_shortest_paths(
162-
g, [src;], distmx; allpaths=allpaths, trackvertices=trackvertices
169+
g, [src;], distmx; allpaths=allpaths, trackvertices=trackvertices, maxdist=maxdist
163170
)
164171
end

src/shortestpaths/yen.jl

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ struct YenState{T,U<:Integer} <: AbstractPathState
99
end
1010

1111
"""
12-
yen_k_shortest_paths(g, source, target, distmx=weights(g), K=1; maxdist=Inf);
12+
yen_k_shortest_paths(g, source, target, distmx=weights(g), K=1; maxdist=typemax(T));
1313
1414
Perform [Yen's algorithm](http://en.wikipedia.org/wiki/Yen%27s_algorithm)
1515
on a graph, computing k-shortest distances between `source` and `target` other vertices.
@@ -21,11 +21,11 @@ function yen_k_shortest_paths(
2121
target::U,
2222
distmx::AbstractMatrix{T}=weights(g),
2323
K::Int=1;
24-
maxdist=Inf,
25-
) where {T<:Real} where {U<:Integer}
24+
maxdist=typemax(T)) where {T<:Real} where {U<:Integer}
25+
2626
source == target && return YenState{T,U}([U(0)], [[source]])
2727

28-
dj = dijkstra_shortest_paths(g, source, distmx)
28+
dj = dijkstra_shortest_paths(g, source, distmx; maxdist)
2929
path = enumerate_paths(dj)[target]
3030
isempty(path) && return YenState{T,U}(Vector{T}(), Vector{Vector{U}}())
3131

@@ -35,7 +35,7 @@ function yen_k_shortest_paths(
3535
B = PriorityQueue()
3636
gcopy = deepcopy(g)
3737

38-
for k in 1:(K - 1)
38+
for k in 1:(K-1)
3939
for j in 1:length(A[k])
4040
# Spur node is retrieved from the previous k-shortest path, k − 1
4141
spurnode = A[k][j]
@@ -48,7 +48,7 @@ function yen_k_shortest_paths(
4848
for ppath in A
4949
if length(ppath) > j && rootpath == ppath[1:j]
5050
u = ppath[j]
51-
v = ppath[j + 1]
51+
v = ppath[j+1]
5252
if has_edge(gcopy, u, v)
5353
rem_edge!(gcopy, u, v)
5454
push!(edgesremoved, (u, v))
@@ -58,7 +58,7 @@ function yen_k_shortest_paths(
5858

5959
# Remove node of root path and calculate dist of it
6060
distrootpath = zero(T)
61-
for n in 1:(length(rootpath) - 1)
61+
for n in 1:(length(rootpath)-1)
6262
u = rootpath[n]
6363
nei = copy(neighbors(gcopy, u))
6464
for v in nei
@@ -67,7 +67,7 @@ function yen_k_shortest_paths(
6767
end
6868

6969
# Evaluate distance of root path
70-
v = rootpath[n + 1]
70+
v = rootpath[n+1]
7171
distrootpath += distmx[u, v]
7272
end
7373

@@ -76,7 +76,7 @@ function yen_k_shortest_paths(
7676
spurpath = enumerate_paths(djspur)[target]
7777
if !isempty(spurpath)
7878
# Entire path is made up of the root path and spur path
79-
pathtotal = [rootpath[1:(end - 1)]; spurpath]
79+
pathtotal = [rootpath[1:(end-1)]; spurpath]
8080
distpath = distrootpath + djspur.dists[target]
8181
# Add the potential k-shortest path to the heap
8282
if !haskey(B, pathtotal)

test/shortestpaths/dijkstra.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,14 @@
101101
dm = @inferred(dijkstra_shortest_paths(g, 1; allpaths=true, trackvertices=true))
102102
@test dm.closest_vertices == [1, 2, 3, 4, 5]
103103
end
104+
105+
#maximum distance setting limits paths found
106+
G = cycle_graph(6)
107+
add_edge!(G, 1, 3)
108+
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])
109+
110+
for g in testgraphs(G)
111+
ds = @inferred(dijkstra_shortest_paths(g, 3, m;maxdist=3.0))
112+
@test ds.dists == [2, 1, 0, Inf, Inf, 3]
113+
end
104114
end

test/shortestpaths/yen.jl

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,16 @@
111111
w[1, 4] = 3
112112
w[4, 1] = 3
113113
for g in testdigraphs(G)
114-
ds = @inferred(yen_k_shortest_paths(G, 1, 6, w, 100))
114+
ds = @inferred(yen_k_shortest_paths(g, 1, 6, w, 100))
115115
@test ds.dists == [4.0, 5.0, 7.0, 7.0, 8.0, 8.0, 8.0, 11.0, 11.0]
116-
117-
ds = @inferred(yen_k_shortest_paths(G, 1, 6, w, 100, maxdist=7))
116+
117+
ds = @inferred(yen_k_shortest_paths(g, 1, 6, w, 100, maxdist=7.))
118118
@test ds.dists == [4.0, 5.0, 7.0, 7.0]
119-
end
119+
end
120+
121+
# Test that no paths are returned if every path is longer than maxdist
122+
for g in testdigraphs(cycle_digraph(10))
123+
ds = @inferred(yen_k_shortest_paths(g, 2, 1, weights(g), 2, maxdist=2))
124+
@test isempty(ds.paths)
125+
end
120126
end

0 commit comments

Comments
 (0)