Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/src/algorithms/shortestpaths.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Shortest paths

*Graphs.jl* includes standard algorithms for [shortest paths](https://en.wikipedia.org/wiki/Shortest_path_problem).
*Graphs.jl* includes standard algorithms for [shortest paths](https://en.wikipedia.org/wiki/Shortest_path_problem) and longest paths.

## Index

Expand All @@ -19,6 +19,7 @@ Pages = [
"shortestpaths/dijkstra.jl",
"shortestpaths/floyd-warshall.jl",
"shortestpaths/johnson.jl",
"shortestpaths/longest_path.jl",
"shortestpaths/spfa.jl",
"shortestpaths/yen.jl",
]
Expand Down
7 changes: 6 additions & 1 deletion src/Graphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,10 @@ export
independent_set,

# vertexcover
vertex_cover
vertex_cover,

# longestpaths
dag_longest_path

"""
Graphs
Expand Down Expand Up @@ -496,6 +499,7 @@ include("traversals/eulerian.jl")
include("connectivity.jl")
include("distance.jl")
include("editdist.jl")
include("shortestpaths/utils.jl")
include("shortestpaths/astar.jl")
include("shortestpaths/bellman-ford.jl")
include("shortestpaths/dijkstra.jl")
Expand All @@ -504,6 +508,7 @@ include("shortestpaths/desopo-pape.jl")
include("shortestpaths/floyd-warshall.jl")
include("shortestpaths/yen.jl")
include("shortestpaths/spfa.jl")
include("shortestpaths/longest_path.jl")
include("linalg/LinAlg.jl")
include("operators.jl")
include("persistence/common.jl")
Expand Down
35 changes: 35 additions & 0 deletions src/shortestpaths/longest_path.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""
dag_longest_path(g, distmx=weights(g); topological_order=topological_sort_by_dfs(g))

Return a longest path within the directed acyclic graph `g`, with distance matrix `distmx` and using `topological_order` to iterate on vertices.
"""
function dag_longest_path end

@traitfn function dag_longest_path(
g::::IsDirected,
distmx::AbstractMatrix=weights(g);
topological_order=topological_sort_by_dfs(g),
)
U = eltype(g)
T = eltype(distmx)

dists = zeros(T, nv(g))
parents = zeros(U, nv(g))

for v in topological_order
for u in inneighbors(g, v)
newdist = dists[u] + distmx[u, v]
if newdist > dists[v]
dists[v] = newdist
parents[v] = u
end
end
end

if isempty(dists)
return U[]
else
v = argmax(dists)
return path_from_parents(v, parents)
end
end
9 changes: 9 additions & 0 deletions src/shortestpaths/utils.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
function path_from_parents(target::Integer, parents::AbstractVector)
v = target
path = [v]
while parents[v] != v && parents[v] != zero(v)
v = parents[v]
pushfirst!(path, v)
end
return path
end
2 changes: 2 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ tests = [
"edit_distance",
"connectivity",
"persistence/persistence",
"shortestpaths/utils",
"shortestpaths/astar",
"shortestpaths/bellman-ford",
"shortestpaths/desopo-pape",
Expand All @@ -111,6 +112,7 @@ tests = [
"shortestpaths/floyd-warshall",
"shortestpaths/yen",
"shortestpaths/spfa",
"shortestpaths/longest_path",
"traversals/bfs",
"traversals/bipartition",
"traversals/greedy_color",
Expand Down
20 changes: 20 additions & 0 deletions test/shortestpaths/longest_path.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
@testset "Longest path" begin
# empty DAG
g = DiGraph()
@test dag_longest_path(g) == Int[]

# unweighted DAG
g = SimpleDiGraphFromIterator(Edge.([(1, 2), (2, 3), (2, 4), (3, 5), (5, 6), (3, 7)]))
@test dag_longest_path(g) == [1, 2, 3, 5, 6]

# weighted DAG
n = 6
g = DiGraph(n)
A = [(1, 2, -5), (2, 3, 1), (3, 4, 1), (4, 5, 0), (3, 5, 4), (1, 6, 2)]
distmx = fill(NaN, n, n)
for (i, j, dist) in A
add_edge!(g, (i, j))
distmx[i, j] = dist
end
@test dag_longest_path(g, distmx) == [2, 3, 5]
end
9 changes: 9 additions & 0 deletions test/shortestpaths/utils.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@testset "Path from parents" begin
using Graphs: path_from_parents
parents = [3, 0, 2, 5, 5]
@test path_from_parents(1, parents) == [2, 3, 1]
@test path_from_parents(2, parents) == [2]
@test path_from_parents(3, parents) == [2, 3]
@test path_from_parents(4, parents) == [5, 4]
@test path_from_parents(5, parents) == [5]
end