Skip to content

Commit 039b4cb

Browse files
Tortargdalle
andauthored
Create some new options for BFSIterator (#389)
* Create some new options for BFSIterator * Update runtests.jl * use neighbors_type * Update bfs.jl * Update bfs.jl * Update src/iterators/bfs.jl Co-authored-by: Guillaume Dalle <[email protected]> * Update bfs.jl * Update bfs.jl --------- Co-authored-by: Guillaume Dalle <[email protected]>
1 parent 34fd1dc commit 039b4cb

File tree

2 files changed

+28
-10
lines changed

2 files changed

+28
-10
lines changed

src/iterators/bfs.jl

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
"""
2-
BFSIterator
2+
BFSIterator(graph, source; depth_limit=nothing, neighbors_type=outneighbors)
33
4-
`BFSIterator` is used to iterate through graph vertices using a breadth-first search.
5-
A source node(s) is optionally supplied as an `Int` or an array-like type that can be
6-
indexed if supplying multiple sources.
4+
`BFSIterator` is used to iterate through graph vertices using a breadth-first search.
5+
A source node(s) must be supplied as an `Int` or an array-like type that can be
6+
indexed if supplying multiple sources. It is also possible to specify a `depth_limit`
7+
which will stop the search once all nodes at that depth are visited and a `neighbors_type`
8+
which specifies what kind of neighbors of a node should be considered when exploring the graph.
79
810
# Examples
911
```julia-repl
@@ -20,14 +22,18 @@ julia> for node in BFSIterator(g,3)
2022
2
2123
```
2224
"""
23-
struct BFSIterator{S,G<:AbstractGraph}
25+
struct BFSIterator{S,G<:AbstractGraph,F}
2426
graph::G
2527
source::S
26-
function BFSIterator(graph::G, source::S) where {S,G}
28+
depth_limit::Int
29+
neighbors_type::F
30+
function BFSIterator(
31+
graph::G, source::S; depth_limit=typemax(Int64), neighbors_type::F=outneighbors
32+
) where {S,G,F}
2733
if any(node -> !has_vertex(graph, node), source)
2834
error("Some source nodes for the iterator are not in the graph")
2935
end
30-
return new{S,G}(graph, source)
36+
return new{S,G,F}(graph, source, depth_limit, neighbors_type)
3137
end
3238
end
3339

@@ -46,6 +52,7 @@ mutable struct BFSVertexIteratorState
4652
next_level::Vector{Int}
4753
node_idx::Int
4854
n_visited::Int
55+
n_level::Int
4956
end
5057

5158
Base.IteratorSize(::BFSIterator) = Base.SizeUnknown()
@@ -59,7 +66,7 @@ First iteration to visit vertices in a graph using breadth-first search.
5966
function Base.iterate(t::BFSIterator{<:Integer})
6067
visited = falses(nv(t.graph))
6168
visited[t.source] = true
62-
state = BFSVertexIteratorState(visited, [t.source], Int[], 0, 0)
69+
state = BFSVertexIteratorState(visited, [t.source], Int[], 0, 0, 0)
6370
return Base.iterate(t, state)
6471
end
6572

@@ -68,7 +75,7 @@ function Base.iterate(t::BFSIterator{<:AbstractArray})
6875
curr_level = unique(s for s in t.source)
6976
sort!(curr_level)
7077
visited[curr_level] .= true
71-
state = BFSVertexIteratorState(visited, curr_level, Int[], 0, 0)
78+
state = BFSVertexIteratorState(visited, curr_level, Int[], 0, 0, 0)
7279
return Base.iterate(t, state)
7380
end
7481

@@ -80,10 +87,13 @@ Iterator to visit vertices in a graph using breadth-first search.
8087
function Base.iterate(t::BFSIterator, state::BFSVertexIteratorState)
8188
# we fill nodes in this level
8289
if state.node_idx == length(state.curr_level)
90+
state.n_level == t.depth_limit && return nothing
91+
state.n_level += 1
8392
state.n_visited += length(state.curr_level)
8493
state.n_visited == nv(t.graph) && return nothing
94+
neighbors_type = t.neighbors_type
8595
@inbounds for node in state.curr_level
86-
for adj_node in outneighbors(t.graph, node)
96+
for adj_node in neighbors_type(t.graph, node)
8797
if !state.visited[adj_node]
8898
push!(state.next_level, adj_node)
8999
state.visited[adj_node] = true

test/iterators/bfs.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,12 @@
4545
@test sort(nodes_visited[1:3]) == sort(levels[1])
4646
@test sort(nodes_visited[4:8]) == sort(levels[2])
4747
@test sort(nodes_visited[9:end]) == sort(levels[3])
48+
49+
nodes_visited = collect(BFSIterator(g2, [8, 1, 6]; depth_limit=1))
50+
@test sort(nodes_visited[1:3]) == sort(levels[1])
51+
@test sort(nodes_visited[4:end]) == sort(levels[2])
52+
53+
g = path_digraph(7)
54+
nodes_visited = collect(BFSIterator(g, 7; neighbors_type=inneighbors))
55+
@test nodes_visited == collect(7:-1:1)
4856
end

0 commit comments

Comments
 (0)