Skip to content

Commit ed9fb94

Browse files
authored
Merge pull request #263 from JuliaRobotics/feature/20Q1/getSubgraphAroundNode
Abstract getSubgraphAroundNode
2 parents bea5266 + 6962aec commit ed9fb94

File tree

8 files changed

+119
-77
lines changed

8 files changed

+119
-77
lines changed

src/DFGPlots/DFGPlots.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ More information at [GraphPlot.jl](https://github.com/JuliaGraphs/GraphPlot.jl)
8888
function dfgplot(dfg::AbstractDFG, p::DFGPlotProps = DFGPlotProps())
8989
# TODO implement convert functions
9090
@warn "TODO Implement convert"
91-
ldfg = LightDFG{AbstractParams}()
91+
ldfg = LightDFG{NoSolverParams}()
9292
DistributedFactorGraphs._copyIntoGraph!(dfg, ldfg, union(getVariableIds(dfg), getFactorIds(dfg)), true, copyGraphMetadata=false)
9393

9494
dfgplot(ldfg, p)

src/DistributedFactorGraphs.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export timestamp # DEPRECATED
2626
export label, getTimestamp, setTimestamp!, tags, setTags!, estimates, estimate, data, softtype, solverData, getData, solverDataDict, setSolverData, setSolverData!, internalId, smallData, setSmallData!, bigData
2727
export DFGVariableSummary, DFGFactorSummary, AbstractDFGSummary
2828
export addBigDataEntry!, getBigDataEntry, updateBigDataEntry!, deleteBigDataEntry!, getBigDataEntries, getBigDataKeys
29+
export getNeighborhood, getSubgraph, getSubgraphAroundNode
2930

3031
#Skeleton types
3132
export SkeletonDFGVariable, SkeletonDFGFactor

src/GraphsDFG/services/GraphsDFG.jl

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -327,40 +327,41 @@ function getNeighbors(dfg::GraphsDFG, label::Symbol; solvable::Int=0)::Vector{Sy
327327
return map(n -> n.dfgNode.label, neighbors)
328328
end
329329

330-
"""
331-
$(SIGNATURES)
332-
Retrieve a deep subgraph copy around a given variable or factor.
333-
Optionally provide a distance to specify the number of edges should be followed.
334-
Optionally provide an existing subgraph addToDFG, the extracted nodes will be copied into this graph. By default a new subgraph will be created.
335-
Note: By default orphaned factors (where the subgraph does not contain all the related variables) are not returned. Set includeOrphanFactors to return the orphans irrespective of whether the subgraph contains all the variables.
336-
"""
337-
function getSubgraphAroundNode(dfg::GraphsDFG{P}, node::T, distance::Int64=1, includeOrphanFactors::Bool=false, addToDFG::GraphsDFG=GraphsDFG{P}(); solvable::Int=0)::GraphsDFG where {P <: AbstractParams, T <: DFGNode}
338-
if !haskey(dfg.labelDict, node.label)
339-
error("Variable/factor with label '$(node.label)' does not exist in the factor graph")
340-
end
341-
342-
# Build a list of all unique neighbors inside 'distance'
343-
neighborList = Dict{Symbol, Any}()
344-
push!(neighborList, node.label => dfg.g.vertices[dfg.labelDict[node.label]])
345-
curList = Dict{Symbol, Any}(node.label => dfg.g.vertices[dfg.labelDict[node.label]])
346-
for dist in 1:distance
347-
newNeighbors = Dict{Symbol, Any}()
348-
for (key, node) in curList
349-
neighbors = in_neighbors(node, dfg.g) #Don't use out_neighbors! It enforces directiveness even if we don't want it
350-
for neighbor in neighbors
351-
if !haskey(neighborList, neighbor.dfgNode.label) && (isSolvable(neighbor.dfgNode) >= solvable)
352-
push!(neighborList, neighbor.dfgNode.label => neighbor)
353-
push!(newNeighbors, neighbor.dfgNode.label => neighbor)
354-
end
355-
end
356-
end
357-
curList = newNeighbors
358-
end
359-
360-
# Copy the section of graph we want
361-
_copyIntoGraph!(dfg, addToDFG, collect(keys(neighborList)), includeOrphanFactors)
362-
return addToDFG
363-
end
330+
#NOTE Replaced by abstract function in services/AbstractDFG.jl
331+
# """
332+
# $(SIGNATURES)
333+
# Retrieve a deep subgraph copy around a given variable or factor.
334+
# Optionally provide a distance to specify the number of edges should be followed.
335+
# Optionally provide an existing subgraph addToDFG, the extracted nodes will be copied into this graph. By default a new subgraph will be created.
336+
# Note: By default orphaned factors (where the subgraph does not contain all the related variables) are not returned. Set includeOrphanFactors to return the orphans irrespective of whether the subgraph contains all the variables.
337+
# """
338+
# function getSubgraphAroundNode(dfg::GraphsDFG{P}, node::T, distance::Int64=1, includeOrphanFactors::Bool=false, addToDFG::GraphsDFG=GraphsDFG{P}(); solvable::Int=0)::GraphsDFG where {P <: AbstractParams, T <: DFGNode}
339+
# if !haskey(dfg.labelDict, node.label)
340+
# error("Variable/factor with label '$(node.label)' does not exist in the factor graph")
341+
# end
342+
#
343+
# # Build a list of all unique neighbors inside 'distance'
344+
# neighborList = Dict{Symbol, Any}()
345+
# push!(neighborList, node.label => dfg.g.vertices[dfg.labelDict[node.label]])
346+
# curList = Dict{Symbol, Any}(node.label => dfg.g.vertices[dfg.labelDict[node.label]])
347+
# for dist in 1:distance
348+
# newNeighbors = Dict{Symbol, Any}()
349+
# for (key, node) in curList
350+
# neighbors = in_neighbors(node, dfg.g) #Don't use out_neighbors! It enforces directiveness even if we don't want it
351+
# for neighbor in neighbors
352+
# if !haskey(neighborList, neighbor.dfgNode.label) && (isSolvable(neighbor.dfgNode) >= solvable)
353+
# push!(neighborList, neighbor.dfgNode.label => neighbor)
354+
# push!(newNeighbors, neighbor.dfgNode.label => neighbor)
355+
# end
356+
# end
357+
# end
358+
# curList = newNeighbors
359+
# end
360+
#
361+
# # Copy the section of graph we want
362+
# _copyIntoGraph!(dfg, addToDFG, collect(keys(neighborList)), includeOrphanFactors)
363+
# return addToDFG
364+
# end
364365

365366
"""
366367
$(SIGNATURES)

src/LightDFG/entities/LightDFG.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ function LightDFG{T,V,F}(g::FactorGraph{Int,V,F}=FactorGraph{Int,V,F}();
3636
userData::Dict{Symbol, String} = Dict{Symbol, String}(),
3737
robotData::Dict{Symbol, String} = Dict{Symbol, String}(),
3838
sessionData::Dict{Symbol, String} = Dict{Symbol, String}(),
39-
params::T=NoSolverParams()) where {T <: AbstractParams, V <:AbstractDFGVariable, F<:AbstractDFGFactor}
39+
params::T=T()) where {T <: AbstractParams, V <:AbstractDFGVariable, F<:AbstractDFGFactor}
4040

4141
LightDFG{T,V,F}(g, description, userId, robotId, sessionId, userData, robotData, sessionData, Symbol[], params)
4242
end

src/SymbolDFG/services/SymbolDFG.jl

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -360,44 +360,44 @@ function _copyIntoGraph!(sourceDFG::SymbolDFG, destDFG::SymbolDFG, labels::Vecto
360360
return nothing
361361
end
362362

363-
364-
"""
365-
$(SIGNATURES)
366-
Retrieve a deep subgraph copy around a given variable or factor.
367-
Optionally provide a distance to specify the number of edges should be followed.
368-
Optionally provide an existing subgraph addToDFG, the extracted nodes will be copied into this graph. By default a new subgraph will be created.
369-
Note: By default orphaned factors (where the subgraph does not contain all the related variables) are not returned. Set includeOrphanFactors to return the orphans irrespective of whether the subgraph contains all the variables.
370-
"""
371-
function getSubgraphAroundNode(dfg::SymbolDFG, node::DFGNode, distance::Int64=1, includeOrphanFactors::Bool=false, addToDFG::SymbolDFG=SymbolDFG{AbstractParams}(); solvable::Int=0)::SymbolDFG
372-
if !exists(dfg,node.label)
373-
error("Variable/factor with label '$(node.label)' does not exist in the factor graph")
374-
end
375-
376-
nodelabel = node.label
377-
# Build a list of all unique neighbors inside 'distance'
378-
neighborList = Symbol[nodelabel]
379-
380-
curList = Symbol[nodelabel]
381-
382-
for dist in 1:distance
383-
newNeighbors = Symbol[]
384-
for cl in curList
385-
neighbors = outneighbors(dfg.g, cl)
386-
for neighbor in neighbors
387-
if !(neighbor in neighborList) && _isSolvable(dfg, neighbor, solvable)
388-
push!(neighborList, neighbor)
389-
push!(newNeighbors, neighbor)
390-
end
391-
end
392-
end
393-
curList = newNeighbors
394-
end
395-
396-
397-
# _copyIntoGraph!(dfg, addToDFG, map(n->get_prop(dfg.g, n, :label), ns), includeOrphanFactors)
398-
_copyIntoGraph!(dfg, addToDFG, neighborList, includeOrphanFactors)
399-
return addToDFG
400-
end
363+
# moved to abstract
364+
# """
365+
# $(SIGNATURES)
366+
# Retrieve a deep subgraph copy around a given variable or factor.
367+
# Optionally provide a distance to specify the number of edges should be followed.
368+
# Optionally provide an existing subgraph addToDFG, the extracted nodes will be copied into this graph. By default a new subgraph will be created.
369+
# Note: By default orphaned factors (where the subgraph does not contain all the related variables) are not returned. Set includeOrphanFactors to return the orphans irrespective of whether the subgraph contains all the variables.
370+
# """
371+
# function getSubgraphAroundNode(dfg::SymbolDFG, node::DFGNode, distance::Int64=1, includeOrphanFactors::Bool=false, addToDFG::SymbolDFG=SymbolDFG{AbstractParams}(); solvable::Int=0)::SymbolDFG
372+
# if !exists(dfg,node.label)
373+
# error("Variable/factor with label '$(node.label)' does not exist in the factor graph")
374+
# end
375+
#
376+
# nodelabel = node.label
377+
# # Build a list of all unique neighbors inside 'distance'
378+
# neighborList = Symbol[nodelabel]
379+
#
380+
# curList = Symbol[nodelabel]
381+
#
382+
# for dist in 1:distance
383+
# newNeighbors = Symbol[]
384+
# for cl in curList
385+
# neighbors = outneighbors(dfg.g, cl)
386+
# for neighbor in neighbors
387+
# if !(neighbor in neighborList) && _isSolvable(dfg, neighbor, solvable)
388+
# push!(neighborList, neighbor)
389+
# push!(newNeighbors, neighbor)
390+
# end
391+
# end
392+
# end
393+
# curList = newNeighbors
394+
# end
395+
#
396+
#
397+
# # _copyIntoGraph!(dfg, addToDFG, map(n->get_prop(dfg.g, n, :label), ns), includeOrphanFactors)
398+
# _copyIntoGraph!(dfg, addToDFG, neighborList, includeOrphanFactors)
399+
# return addToDFG
400+
# end
401401

402402

403403
"""

src/needsahome.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ function buildSubgraphFromLabels!(dfg::G,
2525
syms::Vector{Symbol};
2626
subfg::AbstractDFG=(G <: InMemoryDFGTypes ? G : GraphsDFG)(params=getSolverParams(dfg)),
2727
solvable::Int=0,
28-
allowedFactors::Union{Nothing, Vector{Symbol}}=nothing )::G where G <: AbstractDFG
28+
allowedFactors::Union{Nothing, Vector{Symbol}}=nothing )::AbstractDFG where G <: AbstractDFG
2929
#
3030

3131
# add a little too many variables (since we need the factors)

src/services/AbstractDFG.jl

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,30 @@ end
418418

419419
# TODO: NEED TO FIGURE OUT SIGNATURE FOR DEFAULT ARGS
420420

421+
422+
# TODO export, test and overwrite in LightGraphs and CloudGraphsDFG
423+
"""
424+
$(SIGNATURES)
425+
Build a list of all unique neighbors inside 'distance'
426+
"""
427+
function getNeighborhood(dfg::AbstractDFG, label::Symbol, distance::Int)::Vector{Symbol}
428+
neighborList = Set{Symbol}([label])
429+
curList = Set{Symbol}([label])
430+
431+
for dist in 1:distance
432+
newNeighbors = Set{Symbol}()
433+
for node in curList
434+
neighbors = getNeighbors(dfg, node)
435+
for neighbor in neighbors
436+
push!(neighborList, neighbor)
437+
push!(newNeighbors, neighbor)
438+
end
439+
end
440+
curList = newNeighbors
441+
end
442+
return collect(neighborList)
443+
end
444+
421445
"""
422446
$(SIGNATURES)
423447
Retrieve a deep subgraph copy around a given variable or factor.
@@ -426,8 +450,20 @@ Optionally provide an existing subgraph addToDFG, the extracted nodes will be co
426450
Note: By default orphaned factors (where the subgraph does not contain all the related variables) are not returned. Set includeOrphanFactors to return the orphans irrespective of whether the subgraph contains all the variables.
427451
Note: Always returns the node at the center, but filters around it if solvable is set.
428452
"""
429-
function getSubgraphAroundNode(dfg::G, node::T, distance::Int64=1, includeOrphanFactors::Bool=false, addToDFG::H=_getDuplicatedEmptyDFG(dfg); solvable::Int=0)::G where {G <: AbstractDFG, H <: AbstractDFG, P <: AbstractParams, T <: DFGNode}
430-
error("getSubgraphAroundNode not implemented for $(typeof(dfg))")
453+
function getSubgraphAroundNode(dfg::AbstractDFG, node::DFGNode, distance::Int=1, includeOrphanFactors::Bool=false, addToDFG::AbstractDFG=_getDuplicatedEmptyDFG(dfg); solvable::Int=0)::AbstractDFG
454+
455+
if !exists(dfg, node.label)
456+
error("Variable/factor with label '$(node.label)' does not exist in the factor graph")
457+
end
458+
459+
neighbors = getNeighborhood(dfg, node.label, distance)
460+
461+
# for some reason: always returns the node at the center with || (nlbl == node.label)
462+
solvable != 0 && filter!(nlbl -> (getSolvable(dfg, nlbl) >= solvable) || (nlbl == node.label), neighbors)
463+
464+
# Copy the section of graph we want
465+
_copyIntoGraph!(dfg, addToDFG, neighbors, includeOrphanFactors)
466+
return addToDFG
431467
end
432468

433469
"""

test/interfaceTests.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,10 @@ end
416416
# Filter - always returns the node you start at but filters around that.
417417
dfgSubgraph = getSubgraphAroundNode(dfg, getFactor(dfg, :x7x8f1), 1, true, solvable=1)
418418
@test symdiff([:x7x8f1, :x7], [ls(dfgSubgraph)..., lsf(dfgSubgraph)...]) == []
419+
# Test for distance = 2, should return orphans
420+
#:x7x8f1 is not solvable
421+
dfgSubgraph = getSubgraphAroundNode(dfg, getVariable(dfg, :x8), 2, true, solvable=1)
422+
@test symdiff([:x8, :x7], [ls(dfgSubgraph)..., lsf(dfgSubgraph)...]) == []
419423

420424
# DFG issue #95 - confirming that getSubgraphAroundNode retains order
421425
# REF: https://github.com/JuliaRobotics/DistributedFactorGraphs.jl/issues/95

0 commit comments

Comments
 (0)