Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
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
44 changes: 34 additions & 10 deletions src/GraphsDFG/services/graph_ops.jl
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,42 @@ function DFG.listNeighborhood(
whereSolvable = >=(solvable)
end

# find neighbors at distance to add
nbhood = Int[]

for l in variableFactorLabels
union!(nbhood, neighborhood(dfg.g, dfg.g.labels[l], distance))
# Filter-aware BFS: listNeighbors applies filterDFG! so filtered-out nodes are
# never added to the frontier, consistently breaking the traversal chain.
# Fast path (no filters): neighborhood() from the graph library is used directly.
allvarfacs = if isnothing(whereSolvable) && isnothing(whereTags)
nbhood = Int[]
for l in variableFactorLabels
union!(nbhood, neighborhood(dfg.g, dfg.g.labels[l], distance))
end
[dfg.g.labels[id] for id in nbhood]
else
visited = Set{Symbol}(variableFactorLabels)
included = copy(variableFactorLabels)
frontier = Symbol[]
# Seed frontier with starting nodes that pass the filter (they are always
# expansion roots regardless, but only passed to listNeighbors if they exist).
filterDFG!(included, whereSolvable, l -> getSolvable(dfg, l))
filterDFG!(included, whereTags, l -> listTags(dfg, l))
append!(frontier, included)

for _ = 1:distance
isempty(frontier) && break
next_frontier = Symbol[]
for node in frontier
for nl in listNeighbors(dfg, node; whereSolvable, whereTags)
if !(nl in visited)
push!(visited, nl)
push!(included, nl)
push!(next_frontier, nl)
end
end
end
frontier = next_frontier
end
included
end

allvarfacs = [dfg.g.labels[id] for id in nbhood]

filterDFG!(allvarfacs, whereSolvable, l -> getSolvable(dfg, l))
filterDFG!(allvarfacs, whereTags, l -> listTags(dfg, l))

variableLabels = intersect(listVariables(dfg), allvarfacs)
factorLabels = intersect(listFactors(dfg), allvarfacs)

Expand Down
7 changes: 5 additions & 2 deletions src/services/discovery.jl
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,11 @@ end
"""
$(SIGNATURES)
Build a list of all unique neighbors inside 'distance'. Neighbors can be filtered by using keyword arguments, eg. [`whereTags`] and [`whereSolvable`].
Filters are applied to final neighborhood result.
Filters break the traversal chain: nodes that do not pass the filter are excluded from the result and their neighbors are not explored further.

Notes
- Returns a tuple `(variableLabels, factorLabels)`, where each element is a `Vector{Symbol}`.
- The starting `label` itself is subject to filtering.

Related:
- [`getSubgraph`](@ref)
Expand All @@ -134,7 +135,9 @@ function listNeighborhood(dfg::AbstractDFG, label::Symbol, distance::Int; filter
for dist = 1:distance
newNeighbors = Set{Symbol}()
for node in curList
neighbors = listNeighbors(dfg, node)
# Apply filters during traversal so that filtered-out nodes break the chain:
# only neighbors passing the filter are added to the result and frontier.
neighbors = listNeighbors(dfg, node; filters...)
union!(neighborList, neighbors)
union!(newNeighbors, neighbors)
end
Expand Down
10 changes: 10 additions & 0 deletions test/testBlocks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1541,6 +1541,16 @@ function GettingNeighbors(testDFGAPI; VARTYPE = VariableDFG, FACTYPE = FactorDFG

# Solvable
#TODO if not a GraphsDFG with and summary or skeleton
if VARTYPE == VariableDFG
# Chain-breaking: x7x8f1 is solvable=0; x8x9f1 is only reachable through x8 (solvable=0).
# With the filter applied during traversal, x8x9f1 must NOT appear in the result.
varnh, facnh = listNeighborhood(dfg, [:x7], 4; whereSolvable = >=(1))
@test issetequal(varnh, [:x5, :x6, :x7])
@test issetequal(facnh, [:x5x6f1, :x6x7f1])
@test :x8x9f1 ∉ facnh # chain-breaking: not reachable through solvable=0 x7x8f1/x8
@test :x8 ∉ varnh
end

if VARTYPE == VariableDFG
@test listNeighbors(dfg, :x5; whereSolvable = >=(2)) == Symbol[]
@test issetequal(listNeighbors(dfg, :x5; whereSolvable = >=(0)), [:x4x5f1, :x5x6f1])
Expand Down
Loading