From 9b437370add932cf7dc74e55d26615a2dc54d9ab Mon Sep 17 00:00:00 2001 From: Alexandre Schulz Date: Thu, 29 Jun 2023 16:49:53 +0200 Subject: [PATCH 01/15] added bidijkstra_shortest_path (documentation and test needed) --- Project.toml | 2 + src/shortestpaths/dijkstra.jl | 88 +++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/Project.toml b/Project.toml index fc44c0c0c..2e58d6a0e 100644 --- a/Project.toml +++ b/Project.toml @@ -7,6 +7,7 @@ ArnoldiMethod = "ec485272-7323-5ecc-a04f-4719b315124d" Compat = "34da2185-b29b-5c13-b0c7-acf172513d20" DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b" +Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" Inflate = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" @@ -14,6 +15,7 @@ SharedArrays = "1a1011a3-84de-559e-8e89-a11a2f7dc383" SimpleTraits = "699a6c99-e7fa-54fc-8d76-47d257e15c1d" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd" [compat] Aqua = "0.5" diff --git a/src/shortestpaths/dijkstra.jl b/src/shortestpaths/dijkstra.jl index 3afb5941a..807785a2c 100644 --- a/src/shortestpaths/dijkstra.jl +++ b/src/shortestpaths/dijkstra.jl @@ -162,3 +162,91 @@ function dijkstra_shortest_paths( g, [src;], distmx; allpaths=allpaths, trackvertices=trackvertices ) end + +function relax(u::U, + v::U, + distmx::AbstractMatrix{T}, + dists::Vector{T}, + parents::Vector{U}, + visited::Vector{Bool}, + Q::PriorityQueue{U,T} +) where {T<:Real} where {U<:Integer} + alt = dists[u] + distmx[u, v] + + if !visited[v] + visited[v] = true + dists[v] = alt + parents[v] = u + Q[v] = alt + elseif alt < dists[v] + dists[v] = alt + parents[v] = u + Q[v] = alt + end +end + +function bidijkstra_shortest_path( + g::AbstractGraph, + src::U, + dst::U, + distmx::AbstractMatrix{T}=weights(g) +) where {T<:Real} where {U<:Integer} + if src == dst + return Int64[] + end + # keep weight of the best seen path and the midpoint vertex + mu, mid_v = typemax(T), -1 + + nvg = nv(g) + dists_f, dists_b= fill(typemax(T), nvg), fill(typemax(T), nvg) + + parents_f, parents_b= zeros(U, nvg), zeros(U, nvg) + + visited_f, visited_b = zeros(Bool, nvg),zeros(Bool, nvg) + + preds_f, preds_b = fill(Vector{U}(), nvg), fill(Vector{U}(), nvg) + + Qf, Qb = PriorityQueue{U,T}(), PriorityQueue{U,T}() + + dists_f[src] = zero(T) + visited_f[src] = true + Qf[src] = zero(T) + + dists_b[dst] = zero(T) + visited_b[dst] = true + Qb[dst] = zero(T) + + while !isempty(Qf) && !isempty(Qb) + uf, ub = dequeue!(Qf), dequeue!(Qb) + + for v in outneighbors(g, uf) + relax(uf, v, distmx, dists_f, parents_f, visited_f, Qf) + if visited_b[v] && (dists_f[uf]+distmx[uf,v]+dists_b[v]) < mu + # we have found an edge between the forward and backward exploration + mu = dists_f[uf]+distmx[uf,v]+dists_b[v] + mid_v = v + end + end + + for v in inneighbors(g, ub) + relax(ub, v, distmx, dists_b, parents_b, visited_b, Qb) + if visited_f[v] && (dists_f[v]+distmx[v,ub]+dists_b[ub]) < mu + # we have found an edge between the forward and backward exploration + mu = dists_f[v]+distmx[v,ub]+dists_b[ub] + mid_v = v + end + end + if dists_f[uf]+dists_b[ub] >= mu + break + end + end + if mid_v == -1 + # no path exists between source and destination + return Int64[] + end + ds_f = DijkstraState{T,U}(parents_f, dists_f, preds_f, zeros(nvg), Vector{U}()) + ds_b = DijkstraState{T,U}(parents_b, dists_b, preds_b, zeros(nvg), Vector{U}()) + path = vcat(enumerate_paths(ds_f, mid_v), reverse(enumerate_paths(ds_b, mid_v)[1:end-1])) + return path +end + From b37aefd7835a74748d3582d3528fce43e1588fbd Mon Sep 17 00:00:00 2001 From: Alexandre Schulz Date: Thu, 29 Jun 2023 16:49:53 +0200 Subject: [PATCH 02/15] added bidijkstra_shortest_path (documentation and test needed) --- Project.toml | 2 + src/shortestpaths/dijkstra.jl | 88 +++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/Project.toml b/Project.toml index 9dee36b4d..169b5d928 100644 --- a/Project.toml +++ b/Project.toml @@ -7,6 +7,7 @@ ArnoldiMethod = "ec485272-7323-5ecc-a04f-4719b315124d" Compat = "34da2185-b29b-5c13-b0c7-acf172513d20" DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b" +Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" Inflate = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" @@ -14,6 +15,7 @@ SharedArrays = "1a1011a3-84de-559e-8e89-a11a2f7dc383" SimpleTraits = "699a6c99-e7fa-54fc-8d76-47d257e15c1d" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd" [compat] Aqua = "0.6" diff --git a/src/shortestpaths/dijkstra.jl b/src/shortestpaths/dijkstra.jl index 39d58559b..7e8bacc85 100644 --- a/src/shortestpaths/dijkstra.jl +++ b/src/shortestpaths/dijkstra.jl @@ -169,3 +169,91 @@ function dijkstra_shortest_paths( g, [src;], distmx; allpaths=allpaths, trackvertices=trackvertices, maxdist=maxdist ) end + +function relax(u::U, + v::U, + distmx::AbstractMatrix{T}, + dists::Vector{T}, + parents::Vector{U}, + visited::Vector{Bool}, + Q::PriorityQueue{U,T} +) where {T<:Real} where {U<:Integer} + alt = dists[u] + distmx[u, v] + + if !visited[v] + visited[v] = true + dists[v] = alt + parents[v] = u + Q[v] = alt + elseif alt < dists[v] + dists[v] = alt + parents[v] = u + Q[v] = alt + end +end + +function bidijkstra_shortest_path( + g::AbstractGraph, + src::U, + dst::U, + distmx::AbstractMatrix{T}=weights(g) +) where {T<:Real} where {U<:Integer} + if src == dst + return Int64[] + end + # keep weight of the best seen path and the midpoint vertex + mu, mid_v = typemax(T), -1 + + nvg = nv(g) + dists_f, dists_b= fill(typemax(T), nvg), fill(typemax(T), nvg) + + parents_f, parents_b= zeros(U, nvg), zeros(U, nvg) + + visited_f, visited_b = zeros(Bool, nvg),zeros(Bool, nvg) + + preds_f, preds_b = fill(Vector{U}(), nvg), fill(Vector{U}(), nvg) + + Qf, Qb = PriorityQueue{U,T}(), PriorityQueue{U,T}() + + dists_f[src] = zero(T) + visited_f[src] = true + Qf[src] = zero(T) + + dists_b[dst] = zero(T) + visited_b[dst] = true + Qb[dst] = zero(T) + + while !isempty(Qf) && !isempty(Qb) + uf, ub = dequeue!(Qf), dequeue!(Qb) + + for v in outneighbors(g, uf) + relax(uf, v, distmx, dists_f, parents_f, visited_f, Qf) + if visited_b[v] && (dists_f[uf]+distmx[uf,v]+dists_b[v]) < mu + # we have found an edge between the forward and backward exploration + mu = dists_f[uf]+distmx[uf,v]+dists_b[v] + mid_v = v + end + end + + for v in inneighbors(g, ub) + relax(ub, v, distmx, dists_b, parents_b, visited_b, Qb) + if visited_f[v] && (dists_f[v]+distmx[v,ub]+dists_b[ub]) < mu + # we have found an edge between the forward and backward exploration + mu = dists_f[v]+distmx[v,ub]+dists_b[ub] + mid_v = v + end + end + if dists_f[uf]+dists_b[ub] >= mu + break + end + end + if mid_v == -1 + # no path exists between source and destination + return Int64[] + end + ds_f = DijkstraState{T,U}(parents_f, dists_f, preds_f, zeros(nvg), Vector{U}()) + ds_b = DijkstraState{T,U}(parents_b, dists_b, preds_b, zeros(nvg), Vector{U}()) + path = vcat(enumerate_paths(ds_f, mid_v), reverse(enumerate_paths(ds_b, mid_v)[1:end-1])) + return path +end + From a2d65d4c94032c744ea505fdab9cbcb8f3bb1ea6 Mon Sep 17 00:00:00 2001 From: Alexandre Schulz Date: Fri, 30 Jun 2023 09:08:12 +0200 Subject: [PATCH 03/15] exporting bidijkstra_shortest_path --- src/Graphs.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Graphs.jl b/src/Graphs.jl index c8d209cf5..18729063d 100644 --- a/src/Graphs.jl +++ b/src/Graphs.jl @@ -248,6 +248,7 @@ export transitivereduction, yen_k_shortest_paths, desopo_pape_shortest_paths, + bidijkstra_shortest_path, # centrality betweenness_centrality, From d28db696ed90026f879a942aeac650a3eb6845c7 Mon Sep 17 00:00:00 2001 From: Alexandre Schulz Date: Fri, 30 Jun 2023 09:08:39 +0200 Subject: [PATCH 04/15] simple test for bidijkstra_shortest_path function --- test/shortestpaths/dijkstra.jl | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/shortestpaths/dijkstra.jl b/test/shortestpaths/dijkstra.jl index 5a47f9128..bf64b6789 100644 --- a/test/shortestpaths/dijkstra.jl +++ b/test/shortestpaths/dijkstra.jl @@ -111,4 +111,20 @@ ds = @inferred(dijkstra_shortest_paths(g, 3, m;maxdist=3.0)) @test ds.dists == [2, 1, 0, Inf, Inf, 3] end + + # bidijkstra_shortest_path + g4 = path_digraph(5) + 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]) + 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])) + + for g in testdigraphs(g4) + x = @inferred(dijkstra_shortest_paths(g, 2, d1)) + p = enumerate_paths(x, 4) + y = @inferred(bidijkstra_shortest_path(g, 2, 4, d1)) + z = @inferred(bidijkstra_shortest_path(g, 2, 4, d2)) + + @test p == y == z + end + + end From 515091c5f4d49fd1fd451aab9c712a80e1a8ad2f Mon Sep 17 00:00:00 2001 From: Alexandre Schulz Date: Fri, 30 Jun 2023 09:17:12 +0200 Subject: [PATCH 05/15] bidijkstra_shortest_path documentation --- src/shortestpaths/dijkstra.jl | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/shortestpaths/dijkstra.jl b/src/shortestpaths/dijkstra.jl index 7e8bacc85..541f8a1ab 100644 --- a/src/shortestpaths/dijkstra.jl +++ b/src/shortestpaths/dijkstra.jl @@ -192,6 +192,30 @@ function relax(u::U, end end +""" + bidijkstra_shortest_paths(g, src, dst, distmx=weights(g)); + +Perform [Bidirectional Dijkstra's algorithm](https://www.homepages.ucl.ac.uk/~ucahmto/math/2020/05/30/bidirectional-dijkstra.html) +on a graph, computing the shortest path between `src` and `dst`. + +# Examples +```jldoctest +julia> using Graphs + +julia> bidijkstra_shortest_path(cycle_graph(5), 1, 4); +3-element Vector{Int64}: + 1 + 5 + 4 + +julia> bidijkstra_shortest_path(path_graph(5), 1, 4); +4-element Vector{Int64}: + 1 + 2 + 3 + 4 +``` +""" function bidijkstra_shortest_path( g::AbstractGraph, src::U, From 20b5bb8f92c2d96eebf03fd521a58a939eba6238 Mon Sep 17 00:00:00 2001 From: Alexandre Schulz Date: Mon, 3 Jul 2023 11:17:14 +0200 Subject: [PATCH 06/15] removed undesired dependencies Distributions, StatsPlots --- Project.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/Project.toml b/Project.toml index 169b5d928..9dee36b4d 100644 --- a/Project.toml +++ b/Project.toml @@ -7,7 +7,6 @@ ArnoldiMethod = "ec485272-7323-5ecc-a04f-4719b315124d" Compat = "34da2185-b29b-5c13-b0c7-acf172513d20" DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b" -Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" Inflate = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" @@ -15,7 +14,6 @@ SharedArrays = "1a1011a3-84de-559e-8e89-a11a2f7dc383" SimpleTraits = "699a6c99-e7fa-54fc-8d76-47d257e15c1d" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" -StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd" [compat] Aqua = "0.6" From 2abd6b79a285f4169d0a63b9f7addce9955dd511 Mon Sep 17 00:00:00 2001 From: Alexandre Schulz Date: Mon, 3 Jul 2023 11:26:55 +0200 Subject: [PATCH 07/15] removed spaces, Int64[]->Int[] --- src/shortestpaths/dijkstra.jl | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/shortestpaths/dijkstra.jl b/src/shortestpaths/dijkstra.jl index 541f8a1ab..f81eb27d1 100644 --- a/src/shortestpaths/dijkstra.jl +++ b/src/shortestpaths/dijkstra.jl @@ -223,29 +223,20 @@ function bidijkstra_shortest_path( distmx::AbstractMatrix{T}=weights(g) ) where {T<:Real} where {U<:Integer} if src == dst - return Int64[] + return Int[] end # keep weight of the best seen path and the midpoint vertex mu, mid_v = typemax(T), -1 - nvg = nv(g) dists_f, dists_b= fill(typemax(T), nvg), fill(typemax(T), nvg) - parents_f, parents_b= zeros(U, nvg), zeros(U, nvg) - visited_f, visited_b = zeros(Bool, nvg),zeros(Bool, nvg) - preds_f, preds_b = fill(Vector{U}(), nvg), fill(Vector{U}(), nvg) - Qf, Qb = PriorityQueue{U,T}(), PriorityQueue{U,T}() - dists_f[src] = zero(T) - visited_f[src] = true - Qf[src] = zero(T) - - dists_b[dst] = zero(T) - visited_b[dst] = true - Qb[dst] = zero(T) + dists_f[src], dists_b[dst]= zero(T), zero(T) + visited_f[src], visited_b[dst]= true, true + Qf[src], Qb[dst] = zero(T), zero(T) while !isempty(Qf) && !isempty(Qb) uf, ub = dequeue!(Qf), dequeue!(Qb) @@ -273,7 +264,7 @@ function bidijkstra_shortest_path( end if mid_v == -1 # no path exists between source and destination - return Int64[] + return Int[] end ds_f = DijkstraState{T,U}(parents_f, dists_f, preds_f, zeros(nvg), Vector{U}()) ds_b = DijkstraState{T,U}(parents_b, dists_b, preds_b, zeros(nvg), Vector{U}()) From 7504b6dc99a6d83a3cef209305cc7a96e58390f0 Mon Sep 17 00:00:00 2001 From: Alexandre Schulz Date: Mon, 3 Jul 2023 11:51:44 +0200 Subject: [PATCH 08/15] using relax in dijkstra_shortest_paths --- src/shortestpaths/dijkstra.jl | 86 ++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 41 deletions(-) diff --git a/src/shortestpaths/dijkstra.jl b/src/shortestpaths/dijkstra.jl index f81eb27d1..d6f0d35c1 100644 --- a/src/shortestpaths/dijkstra.jl +++ b/src/shortestpaths/dijkstra.jl @@ -83,7 +83,7 @@ function dijkstra_shortest_paths( parents = zeros(U, nvg) visited = zeros(Bool, nvg) - pathcounts = zeros(nvg) + pathcounts = zeros(Int, nvg) preds = fill(Vector{U}(), nvg) H = PriorityQueue{U,T}() # fill creates only one array. @@ -110,33 +110,12 @@ function dijkstra_shortest_paths( alt = d + distmx[u, v] alt > maxdist && continue - - if !visited[v] - visited[v] = true - dists[v] = alt - parents[v] = u - - pathcounts[v] += pathcounts[u] - if allpaths - preds[v] = [u;] - end - H[v] = alt - elseif alt < dists[v] - dists[v] = alt - parents[v] = u - #615 - pathcounts[v] = pathcounts[u] - if allpaths - resize!(preds[v], 1) - preds[v][1] = u - end - H[v] = alt - elseif alt == dists[v] - pathcounts[v] += pathcounts[u] - if allpaths - push!(preds[v], u) - end - end + + relax(u,v,distmx,dists,parents,visited,H; + allpaths=allpaths, + pathcounts=pathcounts, + preds=preds + ) end end @@ -176,20 +155,45 @@ function relax(u::U, dists::Vector{T}, parents::Vector{U}, visited::Vector{Bool}, - Q::PriorityQueue{U,T} + Q::PriorityQueue{U,T}; + allpaths=false, + pathcounts=nothing, + preds=nothing ) where {T<:Real} where {U<:Integer} - alt = dists[u] + distmx[u, v] - - if !visited[v] - visited[v] = true - dists[v] = alt - parents[v] = u - Q[v] = alt - elseif alt < dists[v] - dists[v] = alt - parents[v] = u - Q[v] = alt - end + alt = dists[u] + distmx[u, v] + + if !visited[v] + visited[v] = true + dists[v] = alt + parents[v] = u + + if !isnothing(pathcounts) + pathcounts[v] += pathcounts[u] + end + if allpaths + preds[v] = [u;] + end + Q[v] = alt + elseif alt < dists[v] + dists[v] = alt + parents[v] = u + #615 + if !isnothing(pathcounts) + pathcounts[v] = pathcounts[u] + end + if allpaths + resize!(preds[v], 1) + preds[v][1] = u + end + Q[v] = alt + elseif alt == dists[v] + if !isnothing(pathcounts) + pathcounts[v] += pathcounts[u] + end + if allpaths + push!(preds[v], u) + end + end end """ From 806593da7bfeef11cbf0d8057b71de0dc27996ab Mon Sep 17 00:00:00 2001 From: Alexandre Schulz Date: Mon, 3 Jul 2023 14:40:08 +0200 Subject: [PATCH 09/15] relax arguments u,v now untyped --- src/shortestpaths/dijkstra.jl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/shortestpaths/dijkstra.jl b/src/shortestpaths/dijkstra.jl index d6f0d35c1..9e021d30b 100644 --- a/src/shortestpaths/dijkstra.jl +++ b/src/shortestpaths/dijkstra.jl @@ -110,7 +110,6 @@ function dijkstra_shortest_paths( alt = d + distmx[u, v] alt > maxdist && continue - relax(u,v,distmx,dists,parents,visited,H; allpaths=allpaths, pathcounts=pathcounts, @@ -149,8 +148,8 @@ function dijkstra_shortest_paths( ) end -function relax(u::U, - v::U, +function relax(u, + v, distmx::AbstractMatrix{T}, dists::Vector{T}, parents::Vector{U}, From 0de4e9287c699a8cb525f58002813eb19aa3f0cf Mon Sep 17 00:00:00 2001 From: Alexandre Schulz Date: Mon, 3 Jul 2023 14:40:49 +0200 Subject: [PATCH 10/15] bidijkstra_shortest_path tests --- test/runtests.jl | 1 + test/shortestpaths/bidijkstra.jl | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 test/shortestpaths/bidijkstra.jl diff --git a/test/runtests.jl b/test/runtests.jl index cbb8763bb..2ca2272c2 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -105,6 +105,7 @@ tests = [ "shortestpaths/bellman-ford", "shortestpaths/desopo-pape", "shortestpaths/dijkstra", + "shortestpaths/bidijkstra", "shortestpaths/johnson", "shortestpaths/floyd-warshall", "shortestpaths/yen", diff --git a/test/shortestpaths/bidijkstra.jl b/test/shortestpaths/bidijkstra.jl new file mode 100644 index 000000000..6c3005d6f --- /dev/null +++ b/test/shortestpaths/bidijkstra.jl @@ -0,0 +1,19 @@ +@testset "Bidijkstra" begin + g3 = path_graph(5) + g4 = path_digraph(5) + + 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]) + 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])) + for g in testgraphs(g3), dg in testdigraphs(g4) + @test @inferred(bidijkstra_shortest_path(g, 1, 4, d1)) == + @inferred(bidijkstra_shortest_path(dg, 1, 4, d1)) == + @inferred(bidijkstra_shortest_path(g, 1, 4, d2)) + @test isempty(@inferred(bidijkstra_shortest_path(dg, 4, 1))) + end + + # test for #1258 + g = complete_graph(4) + w = float([1 1 1 4; 1 1 1 1; 1 1 1 1; 4 1 1 1]) + ds = dijkstra_shortest_paths(g, 1, w) + @test length(bidijkstra_shortest_path(g, 1, 4, w)) == 3 # path is a sequence of vertices +end From cb9eebef0e59b11df6d02229a53a20f50e173cd8 Mon Sep 17 00:00:00 2001 From: Alexandre Schulz Date: Mon, 3 Jul 2023 14:52:55 +0200 Subject: [PATCH 11/15] cosmetic mu to \mu --- src/shortestpaths/dijkstra.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/shortestpaths/dijkstra.jl b/src/shortestpaths/dijkstra.jl index 9e021d30b..730dd576e 100644 --- a/src/shortestpaths/dijkstra.jl +++ b/src/shortestpaths/dijkstra.jl @@ -229,7 +229,7 @@ function bidijkstra_shortest_path( return Int[] end # keep weight of the best seen path and the midpoint vertex - mu, mid_v = typemax(T), -1 + μ, mid_v = typemax(T), -1 nvg = nv(g) dists_f, dists_b= fill(typemax(T), nvg), fill(typemax(T), nvg) parents_f, parents_b= zeros(U, nvg), zeros(U, nvg) @@ -246,22 +246,22 @@ function bidijkstra_shortest_path( for v in outneighbors(g, uf) relax(uf, v, distmx, dists_f, parents_f, visited_f, Qf) - if visited_b[v] && (dists_f[uf]+distmx[uf,v]+dists_b[v]) < mu + if visited_b[v] && (dists_f[uf]+distmx[uf,v]+dists_b[v]) < μ # we have found an edge between the forward and backward exploration - mu = dists_f[uf]+distmx[uf,v]+dists_b[v] + μ = dists_f[uf]+distmx[uf,v]+dists_b[v] mid_v = v end end for v in inneighbors(g, ub) relax(ub, v, distmx, dists_b, parents_b, visited_b, Qb) - if visited_f[v] && (dists_f[v]+distmx[v,ub]+dists_b[ub]) < mu + if visited_f[v] && (dists_f[v]+distmx[v,ub]+dists_b[ub]) < μ # we have found an edge between the forward and backward exploration - mu = dists_f[v]+distmx[v,ub]+dists_b[ub] + μ = dists_f[v]+distmx[v,ub]+dists_b[ub] mid_v = v end end - if dists_f[uf]+dists_b[ub] >= mu + if dists_f[uf]+dists_b[ub] >= μ break end end From 40bb78a1541e3eccb47f7316f5ad6414b932ad1c Mon Sep 17 00:00:00 2001 From: Alexandre Schulz Date: Wed, 5 Jul 2023 16:23:40 +0200 Subject: [PATCH 12/15] docstring correction --- src/shortestpaths/dijkstra.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shortestpaths/dijkstra.jl b/src/shortestpaths/dijkstra.jl index 730dd576e..4a5ad2486 100644 --- a/src/shortestpaths/dijkstra.jl +++ b/src/shortestpaths/dijkstra.jl @@ -205,13 +205,13 @@ on a graph, computing the shortest path between `src` and `dst`. ```jldoctest julia> using Graphs -julia> bidijkstra_shortest_path(cycle_graph(5), 1, 4); +julia> bidijkstra_shortest_path(cycle_graph(5), 1, 4) 3-element Vector{Int64}: 1 5 4 -julia> bidijkstra_shortest_path(path_graph(5), 1, 4); +julia> bidijkstra_shortest_path(path_graph(5), 1, 4) 4-element Vector{Int64}: 1 2 From 3b2d21a2b79d5ceb8ba747524778de28a2170f9c Mon Sep 17 00:00:00 2001 From: Alexandre Schulz Date: Sun, 9 Jul 2023 08:30:25 +0200 Subject: [PATCH 13/15] solved issue when dealing with directed graphs --- src/shortestpaths/dijkstra.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/shortestpaths/dijkstra.jl b/src/shortestpaths/dijkstra.jl index 4a5ad2486..e2c0c8b75 100644 --- a/src/shortestpaths/dijkstra.jl +++ b/src/shortestpaths/dijkstra.jl @@ -157,9 +157,10 @@ function relax(u, Q::PriorityQueue{U,T}; allpaths=false, pathcounts=nothing, - preds=nothing + preds=nothing, + forward=true ) where {T<:Real} where {U<:Integer} - alt = dists[u] + distmx[u, v] + alt = dists[u] + (forward ? distmx[u, v] : distmx[v, u]) if !visited[v] visited[v] = true @@ -254,7 +255,7 @@ function bidijkstra_shortest_path( end for v in inneighbors(g, ub) - relax(ub, v, distmx, dists_b, parents_b, visited_b, Qb) + relax(ub, v, distmx, dists_b, parents_b, visited_b, Qb; forward=false) if visited_f[v] && (dists_f[v]+distmx[v,ub]+dists_b[ub]) < μ # we have found an edge between the forward and backward exploration μ = dists_f[v]+distmx[v,ub]+dists_b[ub] From 313c464fbd8f00721e9c27ed4020d413d69545a8 Mon Sep 17 00:00:00 2001 From: Alexandre Schulz Date: Wed, 18 Oct 2023 12:30:32 +0200 Subject: [PATCH 14/15] error in building path when midpoint corresponds to either source or destination of the shortest path --- src/shortestpaths/dijkstra.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/shortestpaths/dijkstra.jl b/src/shortestpaths/dijkstra.jl index e2c0c8b75..aa967cba7 100644 --- a/src/shortestpaths/dijkstra.jl +++ b/src/shortestpaths/dijkstra.jl @@ -272,7 +272,11 @@ function bidijkstra_shortest_path( end ds_f = DijkstraState{T,U}(parents_f, dists_f, preds_f, zeros(nvg), Vector{U}()) ds_b = DijkstraState{T,U}(parents_b, dists_b, preds_b, zeros(nvg), Vector{U}()) - path = vcat(enumerate_paths(ds_f, mid_v), reverse(enumerate_paths(ds_b, mid_v)[1:end-1])) - return path + if mid_v == src + return reverse(enumerate_paths(ds_b, mid_v)) + elseif mid_v ==dst + return enumerate_paths(ds_f, mid_v) + end + return vcat(enumerate_paths(ds_f, mid_v), reverse(enumerate_paths(ds_b, mid_v)[1:end-1])) end From 08d696aa054279834bc00961f9c6aa2dec183e2a Mon Sep 17 00:00:00 2001 From: Alexandre Schulz Date: Wed, 18 Oct 2023 18:29:43 +0200 Subject: [PATCH 15/15] reverting to old dijkstra implementation (not relying on relax function), tests now work --- src/shortestpaths/dijkstra.jl | 41 ++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/src/shortestpaths/dijkstra.jl b/src/shortestpaths/dijkstra.jl index aa967cba7..e43d311c1 100644 --- a/src/shortestpaths/dijkstra.jl +++ b/src/shortestpaths/dijkstra.jl @@ -75,15 +75,14 @@ function dijkstra_shortest_paths( distmx::AbstractMatrix{T}=weights(g); allpaths=false, trackvertices=false, - maxdist=typemax(T) - ) where T <: Real where U <: Integer - + maxdist=typemax(T), +) where {T<:Real} where {U<:Integer} nvg = nv(g) dists = fill(typemax(T), nvg) parents = zeros(U, nvg) visited = zeros(Bool, nvg) - pathcounts = zeros(Int, nvg) + pathcounts = zeros(nvg) preds = fill(Vector{U}(), nvg) H = PriorityQueue{U,T}() # fill creates only one array. @@ -110,11 +109,33 @@ function dijkstra_shortest_paths( alt = d + distmx[u, v] alt > maxdist && continue - relax(u,v,distmx,dists,parents,visited,H; - allpaths=allpaths, - pathcounts=pathcounts, - preds=preds - ) + + if !visited[v] + visited[v] = true + dists[v] = alt + parents[v] = u + + pathcounts[v] += pathcounts[u] + if allpaths + preds[v] = [u;] + end + H[v] = alt + elseif alt < dists[v] + dists[v] = alt + parents[v] = u + #615 + pathcounts[v] = pathcounts[u] + if allpaths + resize!(preds[v], 1) + preds[v][1] = u + end + H[v] = alt + elseif alt == dists[v] + pathcounts[v] += pathcounts[u] + if allpaths + push!(preds[v], u) + end + end end end @@ -141,7 +162,7 @@ function dijkstra_shortest_paths( distmx::AbstractMatrix=weights(g); allpaths=false, trackvertices=false, - maxdist=typemax(eltype(distmx)) + maxdist=typemax(eltype(distmx)), ) return dijkstra_shortest_paths( g, [src;], distmx; allpaths=allpaths, trackvertices=trackvertices, maxdist=maxdist