Skip to content

Commit 7fc3638

Browse files
committed
Neighbours
1 parent 130a161 commit 7fc3638

File tree

4 files changed

+84
-58
lines changed

4 files changed

+84
-58
lines changed

src/SymbolDFG/SymbolDFG.jl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,20 @@ import ...DistributedFactorGraphs: setSolverParams,
1515
addFactor!,
1616
getSolverParams,
1717
exists,
18-
getDescription
18+
getDescription,
19+
updateVariable!,
20+
updateFactor!,
21+
deleteVariable!,
22+
deleteFactor!,
23+
getVariables,
24+
getVariableIds,
25+
ls,
26+
getFactors,
27+
getFactorIds,
28+
lsf,
29+
isFullyConnected,
30+
hasOrphans,
31+
getNeighbors
1932

2033
include("SymbolFactorGraphs/SymbolFactorGraphs.jl")
2134
using .SymbolFactorGraphs

src/SymbolDFG/SymbolFactorGraphs/SymbolFactorGraphs.jl

Lines changed: 11 additions & 4 deletions
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!
5+
import LightGraphs: nv, ne, vertices, is_directed, has_edge, edges, inneighbors, outneighbors, rem_vertex!, neighbors
66

77
import ...DistributedFactorGraphs: DFGNode
88

@@ -17,6 +17,11 @@ export
1717

1818
const AbstractNodeType = DFGNode
1919

20+
import Base: zero
21+
const UnionNothingSymbol = Union{Nothing, Symbol}
22+
zero(UnionNothingSymbol) = nothing
23+
24+
2025
include("symboledge.jl")
2126

2227

@@ -25,7 +30,7 @@ include("symboledge.jl")
2530
2631
A type representing an undirected bipartite factor graph based on `label::Symbol`.
2732
"""
28-
mutable struct SymbolFactorGraph{V <: AbstractNodeType, F <: AbstractNodeType} <: AbstractGraph{Int}
33+
mutable struct SymbolFactorGraph{V <: AbstractNodeType, F <: AbstractNodeType} <: AbstractGraph{UnionNothingSymbol}
2934
ne::Int
3035
fadjdict::Dict{Symbol,Vector{Symbol}} # [variable src id]: (dst, dst, dst)
3136
variables::Dict{Symbol,V}
@@ -40,9 +45,11 @@ ne(g::SymbolFactorGraph) = g.ne
4045

4146
vertices(g::SymbolFactorGraph) = keys(g.fadjdict)
4247

43-
inneighbors(g::SymbolFactorGraph, v::Symbol) = badj(g, v)
48+
inneighbors(g::SymbolFactorGraph, v::Symbol) = copy(badj(g, v))
49+
50+
outneighbors(g::SymbolFactorGraph, v::Symbol) = copy(fadj(g, v))
4451

45-
outneighbors(g::SymbolFactorGraph, v::Symbol) = fadj(g, v)
52+
neighbors(g::SymbolFactorGraph, v::Symbol) = copy(fadj(g, v))
4653

4754
"""
4855
is_directed(g)

src/SymbolDFG/services/SymbolDFG.jl

Lines changed: 58 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import ...DistributedFactorGraphs: DFGVariable, DFGFactor
22

33
# Accessors
4-
getLabelDict(dfg::SymbolDFG) = dfg.g.labelDict
4+
getLabelDict(dfg::SymbolDFG) = dfg.labelDict
55
getDescription(dfg::SymbolDFG) = dfg.description
66
setDescription(dfg::SymbolDFG, description::String) = dfg.description = description
77
getInnerGraph(dfg::SymbolDFG) = dfg.g
@@ -38,6 +38,10 @@ exists(dfg::SymbolDFG, nId::Symbol) = haskey(dfg.g.fadjdict, nId)
3838
Add a DFGVariable to a DFG.
3939
"""
4040
function addVariable!(dfg::SymbolDFG, variable::DFGVariable)::Bool
41+
#TODO should this be an error
42+
if haskey(dfg.g.variables, variable.label)
43+
error("Variable '$(variable.label)' already exists in the factor graph")
44+
end
4145

4246
#NOTE Internal ID always set to zero as it is not needed?
4347
variable._internalId = 0
@@ -58,6 +62,10 @@ function addFactor!(dfg::SymbolDFG, variables::Vector{DFGVariable}, factor::DFGF
5862
# if haskey(dfg.g.metaindex[:label], factor.label)
5963
# error("Factor '$(factor.label)' already exists in the factor graph")
6064
# end
65+
#TODO should this be an error
66+
if haskey(dfg.g.factors, factor.label)
67+
error("Factor '$(factor.label)' already exists in the factor graph")
68+
end
6169
# for v in variables
6270
# if !(v.label in keys(dfg.g.metaindex[:label]))
6371
# error("Variable '$(v.label)' not found in graph when creating Factor '$(factor.label)'")
@@ -80,7 +88,10 @@ end
8088
Add a DFGFactor to a DFG.
8189
"""
8290
function addFactor!(dfg::SymbolDFG, variableLabels::Vector{Symbol}, factor::DFGFactor)::Bool
83-
91+
#TODO should this be an error
92+
if haskey(dfg.g.factors, factor.label)
93+
error("Factor '$(factor.label)' already exists in the factor graph")
94+
end
8495
factor._internalId = 0
8596

8697
factor._variableOrderSymbols = variableLabels
@@ -110,16 +121,15 @@ end
110121
getFactor(dfg::SymbolDFG, label::String) = getFactor(dfg, Symbol(label))
111122

112123

113-
#=
114124
"""
115125
$(SIGNATURES)
116126
Update a complete DFGVariable in the DFG.
117127
"""
118128
function updateVariable!(dfg::SymbolDFG, variable::DFGVariable)::DFGVariable
119-
if !haskey(dfg.g.metaindex[:label], variable.label)
129+
if !haskey(dfg.g.variables, variable.label)
120130
error("Variable label '$(variable.label)' does not exist in the factor graph")
121131
end
122-
set_prop!(dfg.g, dfg.g[variable.label,:label], :variable, variable)
132+
dfg.g.variables[variable.label] = variable
123133
return variable
124134
end
125135

@@ -128,10 +138,10 @@ end
128138
Update a complete DFGFactor in the DFG.
129139
"""
130140
function updateFactor!(dfg::SymbolDFG, factor::DFGFactor)::DFGFactor
131-
if !haskey(dfg.g.metaindex[:label], factor.label)
141+
if !haskey(dfg.g.factors, factor.label)
132142
error("Factor label '$(factor.label)' does not exist in the factor graph")
133143
end
134-
set_prop!(dfg.g, dfg.g[factor.label,:label], :factor, factor)
144+
dfg.g.factors[factor.label] = factor
135145
return factor
136146
end
137147

@@ -140,11 +150,11 @@ end
140150
Delete a DFGVariable from the DFG using its label.
141151
"""
142152
function deleteVariable!(dfg::SymbolDFG, label::Symbol)::DFGVariable
143-
if !haskey(dfg.g.metaindex[:label], label)
153+
if !haskey(dfg.g.variables, label)
144154
error("Variable label '$(label)' does not exist in the factor graph")
145155
end
146-
variable = get_prop(dfg.g, dfg.g[label,:label], :variable)
147-
rem_vertex!(dfg.g, dfg.g[label,:label])
156+
variable = dfg.g.variables[label]
157+
rem_vertex!(dfg.g, label)
148158

149159
return variable
150160
end
@@ -161,11 +171,11 @@ deleteVariable!(dfg::SymbolDFG, variable::DFGVariable)::DFGVariable = deleteVari
161171
Delete a DFGFactor from the DFG using its label.
162172
"""
163173
function deleteFactor!(dfg::SymbolDFG, label::Symbol)::DFGFactor
164-
if !haskey(dfg.g.metaindex[:label], label)
174+
if !haskey(dfg.g.factors, label)
165175
error("Factor label '$(label)' does not exist in the factor graph")
166176
end
167-
factor = get_prop(dfg.g, dfg.g[label,:label], :factor)
168-
MetaGraphs.rem_vertex!(dfg.g, dfg.g[label,:label])
177+
factor = dfg.g.factors[label]
178+
variable = rem_vertex!(dfg.g, label)
169179
return factor
170180
end
171181

@@ -184,8 +194,7 @@ Optionally specify a label regular expression to retrieves a subset of the varia
184194
function getVariables(dfg::SymbolDFG, regexFilter::Union{Nothing, Regex}=nothing; tags::Vector{Symbol}=Symbol[])::Vector{DFGVariable}
185195

186196
# variables = map(v -> v.dfgNode, filter(n -> n.dfgNode isa DFGVariable, vertices(dfg.g)))
187-
variableIds = collect(filter_vertices(dfg.g, :variable))
188-
variables = map(vId->getVariable(dfg, vId), variableIds)
197+
variables = collect(values(dfg.g.variables))
189198
if regexFilter != nothing
190199
variables = filter(v -> occursin(regexFilter, String(v.label)), variables)
191200
end
@@ -210,11 +219,7 @@ Related
210219
211220
ls
212221
"""
213-
function getVariableIds(dfg::SymbolDFG, regexFilter::Union{Nothing, Regex}=nothing; tags::Vector{Symbol}=Symbol[])::Vector{Symbol}
214-
vars = getVariables(dfg, regexFilter, tags=tags)
215-
# mask = map(v -> length(intersect(v.tags, tags)) > 0, vars )
216-
map(v -> v.label, vars)
217-
end
222+
getVariableIds(dfg::SymbolDFG, regexFilter::Union{Nothing, Regex}=nothing; tags::Vector{Symbol}=Symbol[])::Vector{Symbol} = map(v -> v.label, getVariables(dfg, regexFilter, tags=tags))
218223

219224
# Alias
220225
"""
@@ -231,8 +236,7 @@ Optionally specify a label regular expression to retrieves a subset of the facto
231236
"""
232237
function getFactors(dfg::SymbolDFG, regexFilter::Union{Nothing, Regex}=nothing)::Vector{DFGFactor}
233238
# factors = map(v -> v.dfgNode, filter(n -> n.dfgNode isa DFGFactor, vertices(dfg.g)))
234-
factorIds = collect(filter_vertices(dfg.g, :factor))
235-
factors = map(vId->getFactor(dfg, vId), factorIds)
239+
factors = collect(values(dfg.g.factors))
236240
if regexFilter != nothing
237241
factors = filter(f -> occursin(regexFilter, String(f.label)), factors)
238242
end
@@ -267,7 +271,7 @@ end
267271
Checks if the graph is fully connected, returns true if so.
268272
"""
269273
function isFullyConnected(dfg::SymbolDFG)::Bool
270-
return length(LightGraphs.connected_components(dfg.g)) == 1
274+
return length(connected_components(dfg.g)) == 1
271275
end
272276

273277
#Alias
@@ -277,70 +281,71 @@ Checks if the graph is not fully connected, returns true if it is not contiguous
277281
"""
278282
hasOrphans(dfg::SymbolDFG)::Bool = !isFullyConnected(dfg)
279283

280-
function _isready(dfg::SymbolDFG, idx::Int, ready::Int)::Bool
281-
p = props(dfg.g, idx)
282-
haskey(p, :variable) && (return p[:variable].ready == ready)
283-
haskey(p, :factor) && (return p[:factor].ready == ready)
284+
function _isready(dfg::SymbolDFG, label::Symbol, ready::Int)::Bool
285+
286+
haskey(dfg.g.variables, label) && (return dfg.g.variables[label].ready == ready)
287+
haskey(dfg.g.factors, label) && (return dfg.g.factors[label].ready == ready)
284288

285-
#TODO should this be an error?
286-
@warn "Node not a factor or variable"
289+
#TODO should this be a breaking error?
290+
@error "Node not in factor or variable"
287291
return false
288292
end
289293

290-
function _isbackendset(dfg::SymbolDFG, idx::Int, backendset::Int)::Bool
291-
p = props(dfg.g, idx)
292-
haskey(p, :variable) && (return p[:variable].ready == backendset)
293-
haskey(p, :factor) && (return p[:factor].ready == backendset)
294+
function _isbackendset(dfg::SymbolDFG, label::Symbol, backendset::Int)::Bool
295+
haskey(dfg.g.variables, label) && (return dfg.g.variables[label].backendset == backendset)
296+
haskey(dfg.g.factors, label) && (return dfg.g.factors[label].backendset == backendset)
294297

295-
#TODO should this be an error?
296-
@warn "Node not a factor or variable"
298+
#TODO should this be a breaking error?
299+
@error "Node not a factor or variable"
297300
return false
298301
end
302+
299303
"""
300304
$(SIGNATURES)
301305
Retrieve a list of labels of the immediate neighbors around a given variable or factor.
302306
"""
303-
function getNeighbors(dfg::SymbolDFG, node::T; ready::Union{Nothing, Int}=nothing, backendset::Union{Nothing, Int}=nothing)::Vector{Symbol} where T <: DFGNode
304-
if !haskey(dfg.g.metaindex[:label], node.label)
307+
function getNeighbors(dfg::SymbolDFG, node::DFGNode; ready::Union{Nothing, Int}=nothing, backendset::Union{Nothing, Int}=nothing)::Vector{Symbol}
308+
label = node.label
309+
if !haskey(dfg.g.fadjdict, label)
305310
error("Variable/factor with label '$(node.label)' does not exist in the factor graph")
306311
end
307312

308-
neighbors = map(idx->get_prop(dfg.g, idx, :label), LightGraphs.neighbors(dfg.g, dfg.g[node.label,:label]))
313+
neighbors_ll = outneighbors(dfg.g, label)
309314
# Additional filtering
310-
neighbors = ready != nothing ? filter(lbl -> _isready(dfg, dfg.g[lbl,:label], ready), neighbors) : neighbors
311-
neighbors = backendset != nothing ? filter(lbl -> _isbackendset(dfg, dfg.g[lbl,:label], backendset), neighbors) : neighbors
315+
ready != nothing && filter!(lbl -> _isready(dfg, lbl, ready), neighbors_ll)
316+
backendset != nothing && filter!(lbl -> _isbackendset(dfg, lbl, backendset), neighbors_ll)
312317

313318
# Variable sorting (order is important)
314319
if node isa DFGFactor
315-
order = intersect(node._variableOrderSymbols, neighbors)#map(v->v.dfgNode.label, neighbors))
320+
order = intersect(node._variableOrderSymbols, neighbors_ll)#map(v->v.dfgNode.label, neighbors))
316321
return order
317322
end
318323

319-
return neighbors
324+
return neighbors_ll
320325
end
326+
327+
321328
"""
322329
$(SIGNATURES)
323330
Retrieve a list of labels of the immediate neighbors around a given variable or factor specified by its label.
324331
"""
325332
function getNeighbors(dfg::SymbolDFG, label::Symbol; ready::Union{Nothing, Int}=nothing, backendset::Union{Nothing, Int}=nothing)::Vector{Symbol} where T <: DFGNode
326-
if !haskey(dfg.g.metaindex[:label], label)
333+
if !haskey(dfg.g.fadjdict, label)
327334
error("Variable/factor with label '$(label)' does not exist in the factor graph")
328335
end
329336

330-
# neighbors = in_neighbors(vert, dfg.g) #Don't use out_neighbors! It enforces directiveness even if we don't want it
331-
neighbors = map(idx->get_prop(dfg.g, idx, :label), LightGraphs.neighbors(dfg.g, dfg.g[label,:label]))
337+
neighbors_ll = outneighbors(dfg.g, label)
332338
# Additional filtering
333-
neighbors = ready != nothing ? filter(lbl -> _isready(dfg, dfg.g[lbl,:label], ready), neighbors) : neighbors
334-
neighbors = backendset != nothing ? filter(lbl -> _isbackendset(dfg, dfg.g[lbl,:label], backendset), neighbors) : neighbors
339+
ready != nothing && filter!(lbl -> _isready(dfg, lbl, ready), neighbors_ll)
340+
backendset != nothing && filter!(lbl -> _isbackendset(dfg, lbl, backendset), neighbors_ll)
335341

336-
# Variable sorting when using a factor (function order is important)
337-
if has_prop(dfg.g, dfg.g[label,:label], :factor)
338-
node = get_prop(dfg.g, dfg.g[label,:label], :factor)
339-
order = intersect(node._variableOrderSymbols, neighbors)
342+
# Variable sorting (order is important)
343+
if haskey(dfg.g.factors, label)
344+
order = intersect(dfg.g.factors[label]._variableOrderSymbols, neighbors_ll)#map(v->v.dfgNode.label, neighbors))
340345
return order
341346
end
342347

343-
return neighbors
348+
return neighbors_ll
344349

345350
end
346351

@@ -360,6 +365,7 @@ function ls(dfg::SymbolDFG, label::Symbol)::Vector{Symbol} where T <: DFGNode
360365
return getNeighbors(dfg, label)
361366
end
362367

368+
#=
363369
function _copyIntoGraph!(sourceDFG::SymbolDFG, destDFG::SymbolDFG, ns::Vector{Int}, includeOrphanFactors::Bool=false)::Nothing
364370
# Split into variables and factors
365371
subgraph = sourceDFG.g[ns]

test/interfaceTests.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ end
178178
end
179179

180180
@testset "Producing Dot Files" begin
181-
if testDFGAPI == LightGraphsDFG
181+
if testDFGAPI != GraphsDFG
182182
@warn "Skipping LightGraphsDFG toDot functions"
183183
@test_skip 1==0#toDot(dfg)
184184
@test_skip 1==0#toDotFile(dfg, "something.dot")

0 commit comments

Comments
 (0)