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)
20222
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
3238end
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
4956end
5057
5158Base. IteratorSize (:: BFSIterator ) = Base. SizeUnknown ()
@@ -59,7 +66,7 @@ First iteration to visit vertices in a graph using breadth-first search.
5966function 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)
6471end
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)
7380end
7481
@@ -80,10 +87,13 @@ Iterator to visit vertices in a graph using breadth-first search.
8087function 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
0 commit comments