Skip to content
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

All simple paths (refresh #20) #353

Merged
merged 16 commits into from
Apr 5, 2024
Prev Previous commit
Next Next commit
more updates from code-review
thchr committed Apr 5, 2024
commit c9953b5a98654fc668a102c921a1c39abce20858
11 changes: 6 additions & 5 deletions src/traversals/all_simple_paths.jl
Original file line number Diff line number Diff line change
@@ -33,7 +33,8 @@ julia> collect(spi)
[1, 3, 4]
[1, 4]
```
We can restrict the search to paths of length less than or equal to a specified cut-off (here, 2 edges):
We can restrict the search to path lengths less than or equal to a specified cut-off (here,
2 edges):
```jldoctest allsimplepaths; setup = :(using Graphs)
julia> collect(all_simple_paths(g, 1, 4; cutoff=2))
3-element Vector{Vector{Int64}}:
@@ -43,7 +44,7 @@ julia> collect(all_simple_paths(g, 1, 4; cutoff=2))
```
"""
function all_simple_paths(
g::AbstractGraph{T}, u::T, vs; cutoff::T=nv(g) - 1
g::AbstractGraph{T}, u::T, vs; cutoff::T=nv(g) - one(T)
) where {T<:Integer}
vs = vs isa Set{T} ? vs : Set{T}(vs)
return SimplePathIterator(g, u, vs, cutoff)
@@ -73,7 +74,7 @@ Base.IteratorSize(::Type{<:SimplePathIterator}) = Base.SizeUnknown()
Base.eltype(::SimplePathIterator{T}) where {T} = Vector{T}

mutable struct SimplePathIteratorState{T<:Integer}
stack::Stack{Tuple{T,T}} # used to restore iteration of child vertices: elements are
stack::Stack{Tuple{T,T}} # used to restore iteration of child vertices: elements are
# (parent vertex, index of children)
visited::Stack{T} # current path candidate
queued::Vector{T} # remaining targets if path length reached cutoff
@@ -116,8 +117,8 @@ function Base.iterate(
end

child = children[next_child_index]
next_child_index′ = pop!(state.stack)[2] # move child index forward
push!(state.stack, (parent_node, next_child_index′ + one(T))) #
next_child_index_tmp = pop!(state.stack)[2] # move child
push!(state.stack, (parent_node, next_child_index_tmp + one(T))) # index forward
child in state.visited && continue

if length(state.visited) == spi.cutoff