From 7acc706125efabf3f0197e4a6217c5eed23f393a Mon Sep 17 00:00:00 2001 From: Tortar Date: Wed, 26 Jun 2024 21:44:59 +0200 Subject: [PATCH 1/5] Create some new options for BFSIterator --- src/iterators/bfs.jl | 28 +++++++++++++++++++--------- test/iterators/bfs.jl | 8 ++++++++ test/runtests.jl | 2 +- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/iterators/bfs.jl b/src/iterators/bfs.jl index d45f77933..a3db0cc17 100644 --- a/src/iterators/bfs.jl +++ b/src/iterators/bfs.jl @@ -1,9 +1,11 @@ """ - BFSIterator + BFSIterator(graph::G, source::S; depth_limit=nothing, neighbor_func=outneighbors) `BFSIterator` is used to iterate through graph vertices using a breadth-first search. -A source node(s) is optionally supplied as an `Int` or an array-like type that can be -indexed if supplying multiple sources. +A source node(s) must be supplied as an `Int` or an array-like type that can be +indexed if supplying multiple sources. It is also possible to specify a `depth_limit` +which will stop the search after it is reached and a `neighbor_func` which specifies +what kind of neighbors of a node should be considered when exploring the graph. # Examples ```julia-repl @@ -20,14 +22,18 @@ julia> for node in BFSIterator(g,3) 2 ``` """ -struct BFSIterator{S,G<:AbstractGraph} +struct BFSIterator{S,G<:AbstractGraph,F<:Function} graph::G source::S - function BFSIterator(graph::G, source::S) where {S,G} + depth_limit::Int + neighbor_func::F + function BFSIterator( + graph::G, source::S; depth_limit=typemax(Int64), neighbor_func::F=outneighbors + ) where {S,G,F} if any(node -> !has_vertex(graph, node), source) error("Some source nodes for the iterator are not in the graph") end - return new{S,G}(graph, source) + return new{S,G,F}(graph, source, depth_limit, neighbor_func) end end @@ -46,6 +52,7 @@ mutable struct BFSVertexIteratorState next_level::Vector{Int} node_idx::Int n_visited::Int + n_level::Int end Base.IteratorSize(::BFSIterator) = Base.SizeUnknown() @@ -59,7 +66,7 @@ First iteration to visit vertices in a graph using breadth-first search. function Base.iterate(t::BFSIterator{<:Integer}) visited = falses(nv(t.graph)) visited[t.source] = true - state = BFSVertexIteratorState(visited, [t.source], Int[], 0, 0) + state = BFSVertexIteratorState(visited, [t.source], Int[], 0, 0, 0) return Base.iterate(t, state) end @@ -68,7 +75,7 @@ function Base.iterate(t::BFSIterator{<:AbstractArray}) curr_level = unique(s for s in t.source) sort!(curr_level) visited[curr_level] .= true - state = BFSVertexIteratorState(visited, curr_level, Int[], 0, 0) + state = BFSVertexIteratorState(visited, curr_level, Int[], 0, 0, 0) return Base.iterate(t, state) end @@ -80,10 +87,13 @@ Iterator to visit vertices in a graph using breadth-first search. function Base.iterate(t::BFSIterator, state::BFSVertexIteratorState) # we fill nodes in this level if state.node_idx == length(state.curr_level) + state.n_level == t.depth_limit && return nothing + state.n_level += 1 state.n_visited += length(state.curr_level) state.n_visited == nv(t.graph) && return nothing + neighbor_func = t.neighbor_func @inbounds for node in state.curr_level - for adj_node in outneighbors(t.graph, node) + for adj_node in neighbor_func(t.graph, node) if !state.visited[adj_node] push!(state.next_level, adj_node) state.visited[adj_node] = true diff --git a/test/iterators/bfs.jl b/test/iterators/bfs.jl index f459eafa0..d6fa03f52 100644 --- a/test/iterators/bfs.jl +++ b/test/iterators/bfs.jl @@ -45,4 +45,12 @@ @test sort(nodes_visited[1:3]) == sort(levels[1]) @test sort(nodes_visited[4:8]) == sort(levels[2]) @test sort(nodes_visited[9:end]) == sort(levels[3]) + + nodes_visited = collect(BFSIterator(g2, [8, 1, 6]; depth_limit=1)) + @test sort(nodes_visited[1:3]) == sort(levels[1]) + @test sort(nodes_visited[4:end]) == sort(levels[2]) + + g = path_digraph(7) + nodes_visited = collect(BFSIterator(g, 7; neighbor_func=inneighbors)) + @test nodes_visited == collect(7:-1:1) end diff --git a/test/runtests.jl b/test/runtests.jl index 83644faff..29bacdd73 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -164,7 +164,7 @@ tests = [ end @testset "Code formatting (JuliaFormatter.jl)" begin - @test format(Graphs; verbose=false, overwrite=false) + @test format(Graphs; verbose=false, overwrite=true) end doctest(Graphs) From a3aa9931d7685fae192dab0e8dbc762c90f4eba8 Mon Sep 17 00:00:00 2001 From: Tortar <68152031+Tortar@users.noreply.github.com> Date: Wed, 26 Jun 2024 21:51:24 +0200 Subject: [PATCH 2/5] Update runtests.jl --- test/runtests.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runtests.jl b/test/runtests.jl index 29bacdd73..83644faff 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -164,7 +164,7 @@ tests = [ end @testset "Code formatting (JuliaFormatter.jl)" begin - @test format(Graphs; verbose=false, overwrite=true) + @test format(Graphs; verbose=false, overwrite=false) end doctest(Graphs) From f07098384315730803db77903a2d6ea47e0913fe Mon Sep 17 00:00:00 2001 From: Tortar <68152031+Tortar@users.noreply.github.com> Date: Wed, 26 Jun 2024 22:43:56 +0200 Subject: [PATCH 3/5] use neighbors_type --- src/iterators/bfs.jl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/iterators/bfs.jl b/src/iterators/bfs.jl index a3db0cc17..746edc8fc 100644 --- a/src/iterators/bfs.jl +++ b/src/iterators/bfs.jl @@ -1,10 +1,10 @@ """ - BFSIterator(graph::G, source::S; depth_limit=nothing, neighbor_func=outneighbors) + BFSIterator(graph::G, source::S; depth_limit=nothing, neighbors_type=outneighbors) `BFSIterator` is used to iterate through graph vertices using a breadth-first search. A source node(s) must be supplied as an `Int` or an array-like type that can be indexed if supplying multiple sources. It is also possible to specify a `depth_limit` -which will stop the search after it is reached and a `neighbor_func` which specifies +which will stop the search after it is reached and a `neighbors_type` which specifies what kind of neighbors of a node should be considered when exploring the graph. # Examples @@ -26,14 +26,14 @@ struct BFSIterator{S,G<:AbstractGraph,F<:Function} graph::G source::S depth_limit::Int - neighbor_func::F + neighbors_type::F function BFSIterator( - graph::G, source::S; depth_limit=typemax(Int64), neighbor_func::F=outneighbors + graph::G, source::S; depth_limit=typemax(Int64), neighbors_type::F=outneighbors ) where {S,G,F} if any(node -> !has_vertex(graph, node), source) error("Some source nodes for the iterator are not in the graph") end - return new{S,G,F}(graph, source, depth_limit, neighbor_func) + return new{S,G,F}(graph, source, depth_limit, neighbors_type) end end @@ -91,9 +91,9 @@ function Base.iterate(t::BFSIterator, state::BFSVertexIteratorState) state.n_level += 1 state.n_visited += length(state.curr_level) state.n_visited == nv(t.graph) && return nothing - neighbor_func = t.neighbor_func + neighbors_type = t.neighbors_type @inbounds for node in state.curr_level - for adj_node in neighbor_func(t.graph, node) + for adj_node in neighbors_type(t.graph, node) if !state.visited[adj_node] push!(state.next_level, adj_node) state.visited[adj_node] = true From 9e9046a99a18b06ae3001b613de57b01d47f26bb Mon Sep 17 00:00:00 2001 From: Tortar <68152031+Tortar@users.noreply.github.com> Date: Wed, 26 Jun 2024 22:45:36 +0200 Subject: [PATCH 4/5] Update bfs.jl --- test/iterators/bfs.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/iterators/bfs.jl b/test/iterators/bfs.jl index d6fa03f52..00e9fd026 100644 --- a/test/iterators/bfs.jl +++ b/test/iterators/bfs.jl @@ -51,6 +51,6 @@ @test sort(nodes_visited[4:end]) == sort(levels[2]) g = path_digraph(7) - nodes_visited = collect(BFSIterator(g, 7; neighbor_func=inneighbors)) + nodes_visited = collect(BFSIterator(g, 7; neighbors_type=inneighbors)) @test nodes_visited == collect(7:-1:1) end From b67e871fdf963cd7e17a57766d987fdd5beb0a77 Mon Sep 17 00:00:00 2001 From: Tortar <68152031+Tortar@users.noreply.github.com> Date: Wed, 26 Jun 2024 23:08:27 +0200 Subject: [PATCH 5/5] Update bfs.jl --- src/iterators/bfs.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/iterators/bfs.jl b/src/iterators/bfs.jl index 746edc8fc..316e5cec1 100644 --- a/src/iterators/bfs.jl +++ b/src/iterators/bfs.jl @@ -1,5 +1,5 @@ """ - BFSIterator(graph::G, source::S; depth_limit=nothing, neighbors_type=outneighbors) + BFSIterator(graph, source; depth_limit=nothing, neighbors_type=outneighbors) `BFSIterator` is used to iterate through graph vertices using a breadth-first search. A source node(s) must be supplied as an `Int` or an array-like type that can be