Skip to content

Commit 2fb8edc

Browse files
committed
Connectivity
1 parent 872bc12 commit 2fb8edc

File tree

3 files changed

+95
-62
lines changed

3 files changed

+95
-62
lines changed

src/SymbolDFG/SymbolDFG.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import ...DistributedFactorGraphs: setSolverParams,
2929
isFullyConnected,
3030
hasOrphans,
3131
getNeighbors,
32+
getSubgraphAroundNode,
33+
getSubgraph,
3234
getAdjacencyMatrix
3335

3436
include("SymbolFactorGraphs/SymbolFactorGraphs.jl")

src/SymbolDFG/SymbolFactorGraphs/SymbolFactorGraphs.jl

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ module SymbolFactorGraphs
22

33
using LightGraphs
44

5-
import LightGraphs: nv, ne, vertices, is_directed, has_edge, edges, inneighbors, outneighbors, rem_vertex!, neighbors
5+
import LightGraphs: nv, ne, vertices, is_directed, has_edge, edges, inneighbors, outneighbors, rem_vertex!, neighbors, connected_components
66

77
import ...DistributedFactorGraphs: DFGNode
88

@@ -422,6 +422,50 @@ function rem_vertex!(g::SymbolFactorGraph, v::Symbol)
422422
return true
423423
end
424424

425+
function _connected_components!(label::Dict{Symbol, T}, g::SymbolFactorGraph) where T <: UnionNothingSymbol
426+
nvg = nv(g)
427+
428+
for u in vertices(g)
429+
label[u] != nothing && continue
430+
label[u] = u
431+
Q = Vector{T}()
432+
push!(Q, u)
433+
while !isempty(Q)
434+
src = popfirst!(Q)
435+
for vertex in neighbors(g, src)
436+
if label[vertex] == zero(T)
437+
push!(Q, vertex)
438+
label[vertex] = u
439+
end
440+
end
441+
end
442+
end
443+
return label
444+
end
445+
446+
function _components(labels::Dict{Symbol, UnionNothingSymbol})
447+
448+
d = Dict{Symbol,Int}()
449+
c = Vector{Vector{Symbol}}()
450+
i = 1 #one(T)
451+
for (v, l) in enumerate(labels)
452+
index = get!(d, l.second, i)
453+
if length(c) >= index
454+
push!(c[index], l.first)
455+
else
456+
push!(c, [l.first])
457+
i += 1
458+
end
459+
end
460+
return c, d
461+
end
425462

463+
function connected_components(g::SymbolFactorGraph)
464+
# label = zeros(T, nv(g))
465+
label = Dict{Symbol, UnionNothingSymbol}(l=>nothing for l in vertices(g))
466+
_connected_components!(label, g)
467+
c, d = _components(label)
468+
return c
469+
end
426470

427471
end

src/SymbolDFG/services/SymbolDFG.jl

Lines changed: 48 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,18 @@ end
1717
$(SIGNATURES)
1818
True if the variable or factor exists in the graph.
1919
"""
20-
function exists(dfg::SymbolDFG{P,V,F}, node::N) where {P <:AbstractParams, V <: DFGNode, F <: DFGNode, N <: DFGNode}
21-
# TODO just checking for key, maybe check equallity?
22-
if N == V
23-
return haskey(dfg.g.variables, node.label)
24-
elseif N == F
25-
return haskey(dfg.g.variables, node.label)
26-
else
27-
@error "Node $(N) not a variable or a factor of type $(V),$(F)"
28-
return false
29-
end
20+
function exists(dfg::SymbolDFG{P,V,F}, node::V) where {P <:AbstractParams, V <: DFGNode, F <: DFGNode, N <: DFGNode}
21+
return haskey(dfg.g.variables, node.label)
22+
end
3023

24+
function exists(dfg::SymbolDFG{P,V,F}, node::F) where {P <:AbstractParams, V <: DFGNode, F <: DFGNode, N <: DFGNode}
25+
return haskey(dfg.g.factors, node.label)
3126
end
27+
3228
exists(dfg::SymbolDFG, nId::Symbol) = haskey(dfg.g.fadjdict, nId)
3329

30+
exists(dfg::SymbolDFG, node::DFGNode) = exists(dfg, node.label)
31+
3432

3533

3634
"""
@@ -365,47 +363,34 @@ function ls(dfg::SymbolDFG, label::Symbol)::Vector{Symbol} where T <: DFGNode
365363
return getNeighbors(dfg, label)
366364
end
367365

368-
#=
369-
function _copyIntoGraph!(sourceDFG::SymbolDFG, destDFG::SymbolDFG, ns::Vector{Int}, includeOrphanFactors::Bool=false)::Nothing
370-
# Split into variables and factors
371-
subgraph = sourceDFG.g[ns]
372-
sourceVariableIds = collect(filter_vertices(subgraph, :variable))
373-
sourceFactorIds = collect(filter_vertices(subgraph, :factor))
374-
# or copy out of sourceDFG.
375-
# sourceFactorIds = intersect(ns, collect(filter_vertices(sourceDFG.g, :factor)))
376-
377-
#get factor and variable nodes
378-
variables = map(vId->getVariable(subgraph, vId), sourceVariableIds)
379-
factors = map(fId->getFactor(subgraph, fId), sourceFactorIds)
380-
381-
# Now we have to add all variables first,
382-
for v in variables
383-
if !haskey(destDFG.g.metaindex[:label], v.label)
384-
addVariable!(destDFG, deepcopy(v))
366+
# function _copyIntoGraph!(sourceDFG{AbstractParam,DFGVariable,DFGFactor}::SymbolDFG, destDFG{AbstractParam,DFGVariable,DFGFactor}::SymbolDFG, labels::Vector{Symbol}, includeOrphanFactors::Bool=false)::Nothing
367+
function _copyIntoGraph!(sourceDFG::SymbolDFG, destDFG::SymbolDFG, labels::Vector{Symbol}, includeOrphanFactors::Bool=false)::Nothing
368+
369+
# Add all variables first,
370+
for v in values(sourceDFG.g.variables)
371+
if v.label in labels
372+
exists(destDFG, v) ? (@warn "_copyIntoGraph $(v.label) exists, ignoring") : addVariable!(destDFG, deepcopy(v))
385373
end
386374
end
387375

388376
# And then all factors to the destDFG.
389-
for f in factors
390-
if !haskey(destDFG.g.metaindex[:label], f.label)
377+
for f in values(sourceDFG.g.factors)
378+
if f.label in labels
391379
# Get the original factor variables (we need them to create it)
392-
# variables = in_neighbors(factor, sourceDFG.g)
393-
# variables = getNeighbors(sourceDFG, f)
394-
varIds = LightGraphs.neighbors(sourceDFG.g, sourceDFG.g[f.label,:label])
395-
variables = map(vId->getVariable(sourceDFG.g, vId), varIds)
380+
neigh_labels = outneighbors(sourceDFG.g, f.label)
396381

397382
# Find the labels and associated variables in our new subgraph
398383
factVariables = DFGVariable[]
399-
for v in variables
400-
if haskey(destDFG.g.metaindex[:label], v.label)
401-
push!(factVariables, getVariable(destDFG, v.label))
384+
for v_lab in neigh_labels
385+
if haskey(destDFG.g.variables, v_lab)
386+
push!(factVariables, getVariable(destDFG, v_lab))
402387
#otherwise ignore
403388
end
404389
end
405390

406391
# Only if we have all of them should we add it (otherwise strange things may happen on evaluation)
407-
if includeOrphanFactors || length(factVariables) == length(variables)
408-
addFactor!(destDFG, factVariables, deepcopy(f))
392+
if includeOrphanFactors || length(factVariables) == length(neigh_labels)
393+
exists(destDFG, f.label) ? (@warn "_copyIntoGraph $(f.label) exists, ignoring") : addFactor!(destDFG, factVariables, deepcopy(f))
409394
end
410395
end
411396
end
@@ -420,32 +405,34 @@ Optionally provide a distance to specify the number of edges should be followed.
420405
Optionally provide an existing subgraph addToDFG, the extracted nodes will be copied into this graph. By default a new subgraph will be created.
421406
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.
422407
"""
423-
function getSubgraphAroundNode(dfg::SymbolDFG{P}, node::T, distance::Int64=1, includeOrphanFactors::Bool=false, addToDFG::SymbolDFG=SymbolDFG{P}())::SymbolDFG where {P <: AbstractParams, T <: DFGNode}
424-
if !haskey(dfg.g.metaindex[:label], node.label)
408+
function getSubgraphAroundNode(dfg::SymbolDFG, node::DFGNode, distance::Int64=1, includeOrphanFactors::Bool=false, addToDFG::SymbolDFG=SymbolDFG{AbstractParams}())::SymbolDFG
409+
if !exists(dfg,node.label)
425410
error("Variable/factor with label '$(node.label)' does not exist in the factor graph")
426411
end
427412

428-
# Get a list of all unique neighbors inside 'distance'
429-
ns = neighborhood(dfg.g, dfg.g[node.label,:label], distance)
430-
431-
# Copy the section of graph we want
432-
# _copyIntoGraph!(dfg, addToDFG, map(n->get_prop(dfg.g, n, :label), ns), includeOrphanFactors)
433-
_copyIntoGraph!(dfg, addToDFG, ns, includeOrphanFactors)
434-
return addToDFG
435-
end
436-
437-
438-
function getSubgraphAroundNode(dfg::SymbolDFG{<:AbstractParams}, node::DFGNode, distance::Int64=1, includeOrphanFactors::Bool=false, addToDFG::AbstractDFG=SymbolDFG{AbstractParams}())::AbstractDFG
439-
if !haskey(dfg.g.metaindex[:label], node.label)
440-
error("Variable/factor with label '$(node.label)' does not exist in the factor graph")
441-
end
413+
nodelabel = node.label
414+
# Build a list of all unique neighbors inside 'distance'
415+
neighborList = Symbol[nodelabel]
416+
417+
curList = Symbol[nodelabel]
418+
419+
for dist in 1:distance
420+
newNeighbors = Symbol[]
421+
for cl in curList
422+
neighbors = outneighbors(dfg.g, cl)
423+
for neighbor in neighbors
424+
if !(neighbor in neighborList)
425+
push!(neighborList, neighbor)
426+
push!(newNeighbors, neighbor)
427+
end
428+
end
429+
end
430+
curList = newNeighbors
431+
end
442432

443-
# Get a list of all unique neighbors inside 'distance'
444-
ns = neighborhood(dfg.g, dfg.g[node.label,:label], distance)
445433

446-
# Copy the section of graph we want
447-
_copyIntoGraph!(dfg, addToDFG, map(n->get_prop(dfg.g, n, :label), ns), includeOrphanFactors)
448-
# _copyIntoGraph!(dfg, addToDFG, ns, includeOrphanFactors)
434+
# _copyIntoGraph!(dfg, addToDFG, map(n->get_prop(dfg.g, n, :label), ns), includeOrphanFactors)
435+
_copyIntoGraph!(dfg, addToDFG, neighborList, includeOrphanFactors)
449436
return addToDFG
450437
end
451438

@@ -458,15 +445,15 @@ Note: By default orphaned factors (where the subgraph does not contain all the r
458445
"""
459446
function getSubgraph(dfg::SymbolDFG, variableFactorLabels::Vector{Symbol}, includeOrphanFactors::Bool=false, addToDFG::SymbolDFG=SymbolDFG{AbstractParams}())::SymbolDFG
460447
for label in variableFactorLabels
461-
if !haskey(dfg.g.metaindex[:label], label)
448+
if !exists(dfg, label)
462449
error("Variable/factor with label '$(label)' does not exist in the factor graph")
463450
end
464451
end
465452

466453
_copyIntoGraph!(dfg, addToDFG, variableFactorLabels, includeOrphanFactors)
467454
return addToDFG
468455
end
469-
=#
456+
470457
"""
471458
$(SIGNATURES)
472459
Get an adjacency matrix for the DFG, returned as a Matrix{Union{Nothing, Symbol}}.

0 commit comments

Comments
 (0)