Skip to content

add non-allocating enumerate_paths! #428

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
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
43 changes: 33 additions & 10 deletions src/shortestpaths/bellman-ford.jl
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,41 @@ to all other vertices. In addition, `enumerate_paths(state, v, d)` will return
a vector representing the path from vertex `v` to vertex `d`.
"""
function enumerate_paths(state::AbstractPathState, vs::AbstractVector{<:Integer})
parents = state.parents
T = eltype(parents)
T = eltype(state.parents)
all_paths = Vector{T}[Vector{eltype(state.parents)}() for _ in 1:length(vs)]
enumerate_paths!(all_paths, state, vs)
end

enumerate_paths(state::AbstractPathState, v::Integer) = enumerate_paths(state, v:v)[1]
function enumerate_paths(state::AbstractPathState)
return enumerate_paths(state, 1:length(state.parents))
end

"""
enumerate_paths!(paths::AbstractVector{<:AbstractVector}, state, vs::AbstractVector{Int})

In-place version of [`enumerate_paths`](@ref).

`paths` must be a `Vector{Vectors{eltype(state.parents)}}`

`enumerate_paths!` should be more efficient when used in a loop,
as the same memory can be used for each iteration.
"""
function enumerate_paths!(
all_paths::AbstractVector{<:AbstractVector},
state::AbstractPathState,
vs::AbstractVector{<:Integer}
)
Base.require_one_based_indexing(all_paths)
Base.require_one_based_indexing(vs)
@assert length(all_paths) == length(vs)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the documentation:

Warning

An assert might be disabled at some optimization levels.
Assert should therefore only be used as a debugging tool and
not used for authentication verification (e.g., verifying
passwords or checking array bounds). The code must not rely
on the side effects of running cond for the correct behavior
of a function.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok this is now an ArgumentError instead, and I've tested expliticly calling enumerate_paths! with both correct and incorrect length inputs so its also tested


parents = state.parents
T = eltype(state.parents)
num_vs = length(vs)
all_paths = Vector{Vector{T}}(undef, num_vs)

for i in 1:num_vs
all_paths[i] = Vector{T}()
empty!(all_paths[i])
index = T(vs[i])
if parents[index] != 0 || parents[index] == index
while parents[index] != 0
Expand All @@ -134,9 +162,4 @@ function enumerate_paths(state::AbstractPathState, vs::AbstractVector{<:Integer}
end
end
return all_paths
end

enumerate_paths(state::AbstractPathState, v::Integer) = enumerate_paths(state, [v])[1]
function enumerate_paths(state::AbstractPathState)
return enumerate_paths(state, [1:length(state.parents);])
end
end