Skip to content

Commit 28b2173

Browse files
authored
Merge pull request #67 from JuliaRobotics/feature/LightGraphs
LightGraphs integration
2 parents 28f545d + 3589149 commit 28b2173

File tree

10 files changed

+734
-14
lines changed

10 files changed

+734
-14
lines changed

.travis.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ matrix:
2828
# - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
2929
# - julia --check-bounds=yes -e 'using Pkg; Pkg.clone(pwd()); Pkg.build("DistributedFactorGraphs"); Pkg.test("DistributedFactorGraphs"; coverage=true)'
3030

31+
# can be used if master of package is required
32+
# script:
33+
# - julia --project --color=yes --check-bounds=yes -e 'using Pkg; Pkg.add(PackageSpec(name="MetaGraphs", rev="master")); Pkg.build(); Pkg.test(coverage=true)'
34+
3135
after_success:
3236
- julia -e 'using Pkg; cd(Pkg.dir("DistributedFactorGraphs")); Pkg.add("Coverage"); using Coverage; Codecov.submit(process_folder()); Coveralls.submit(process_folder())'
3337

Project.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
99
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
1010
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
1111
JSON2 = "2535ab7d-5cd8-5a07-80ac-9b1792aadce3"
12+
LightGraphs = "093fc24a-ae57-5d10-9952-331d41423f4d"
1213
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
14+
MetaGraphs = "626554b9-1ddb-594c-aa3c-2596fe9399a5"
1315
Neo4j = "d2adbeaf-5838-5367-8a2f-e46d570981db"
1416
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
1517
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
@@ -21,6 +23,7 @@ Graphs = "≥ 0.10.3"
2123
Reexport = "≥ 0.2"
2224
Requires = "≥ 0.5"
2325
julia = "0.7, 1"
26+
MetaGraphs = "≥ 0.6.4"
2427

2528
[extras]
2629
IncrementalInference = "904591bb-b899-562f-9e6f-b8df64c7d480"

src/DistributedFactorGraphs.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ include("GraphsDFG/GraphsDFG.jl")
4444
# Include the FilesDFG API.
4545
include("FileDFG/FileDFG.jl")
4646

47+
# Include the LightGraphs.jl (MetaGraphs.jl) API.
48+
include("LightGraphsDFG/LightGraphsDFG.jl")
49+
4750
export saveDFG, loadDFG
4851

4952
function __init__()
@@ -55,7 +58,7 @@ function __init__()
5558
Rows are all factors, columns are all variables, and each cell contains either nothing or the symbol of the relating factor.
5659
The first column is the factor headings.
5760
"""
58-
function getAdjacencyMatrixDataFrame(dfg::GraphsDFG)::Main.DataFrames.DataFrame
61+
function getAdjacencyMatrixDataFrame(dfg::Union{GraphsDFG, LightGraphsDFG})::Main.DataFrames.DataFrame
5962
varLabels = sort(map(v->v.label, getVariables(dfg)))
6063
factLabels = sort(map(f->f.label, getFactors(dfg)))
6164
adjDf = DataFrames.DataFrame(:Factor => Union{Missing, Symbol}[])

src/GraphsDFG/services/GraphsDFG.jl

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ end
195195
$(SIGNATURES)
196196
Delete a referenced DFGVariable from the DFG.
197197
"""
198-
deleteVariable!(dfg::GraphsDFG, variable::DFGVariable)::DFGVariable = deleteVariable(dfg, variable.label)
198+
deleteVariable!(dfg::GraphsDFG, variable::DFGVariable)::DFGVariable = deleteVariable!(dfg, variable.label)
199199

200200
"""
201201
$(SIGNATURES)
@@ -224,7 +224,7 @@ List the DFGVariables in the DFG.
224224
Optionally specify a label regular expression to retrieves a subset of the variables.
225225
"""
226226
function getVariables(dfg::GraphsDFG, regexFilter::Union{Nothing, Regex}=nothing; tags::Vector{Symbol}=Symbol[])::Vector{DFGVariable}
227-
variables = map(v -> v.dfgNode, filter(n -> n.dfgNode isa DFGVariable, vertices(dfg.g)))
227+
variables = map(v -> v.dfgNode, filter(n -> n.dfgNode isa DFGVariable, Graphs.vertices(dfg.g)))
228228
if regexFilter != nothing
229229
variables = filter(v -> occursin(regexFilter, String(v.label)), variables)
230230
end
@@ -269,7 +269,7 @@ List the DFGFactors in the DFG.
269269
Optionally specify a label regular expression to retrieves a subset of the factors.
270270
"""
271271
function getFactors(dfg::GraphsDFG, regexFilter::Union{Nothing, Regex}=nothing)::Vector{DFGFactor}
272-
factors = map(v -> v.dfgNode, filter(n -> n.dfgNode isa DFGFactor, vertices(dfg.g)))
272+
factors = map(v -> v.dfgNode, filter(n -> n.dfgNode isa DFGFactor, Graphs.vertices(dfg.g)))
273273
if regexFilter != nothing
274274
factors = filter(f -> occursin(regexFilter, String(f.label)), factors)
275275
end
@@ -304,7 +304,7 @@ end
304304
Checks if the graph is fully connected, returns true if so.
305305
"""
306306
function isFullyConnected(dfg::GraphsDFG)::Bool
307-
return length(connected_components(dfg.g)) == 1
307+
return length(Graphs.connected_components(dfg.g)) == 1
308308
end
309309

310310
#Alias
@@ -326,8 +326,8 @@ function getNeighbors(dfg::GraphsDFG, node::T; ready::Union{Nothing, Int}=nothin
326326
vert = dfg.g.vertices[dfg.labelDict[node.label]]
327327
neighbors = in_neighbors(vert, dfg.g) #Don't use out_neighbors! It enforces directiveness even if we don't want it
328328
# Additional filtering
329-
neighbors = ready != nothing ? filter(v -> v.ready == ready, neighbors) : neighbors
330-
neighbors = backendset != nothing ? filter(v -> v.backendset == backendset, neighbors) : neighbors
329+
neighbors = ready != nothing ? filter(v -> v.dfgNode.ready == ready, neighbors) : neighbors
330+
neighbors = backendset != nothing ? filter(v -> v.dfgNode.backendset == backendset, neighbors) : neighbors
331331
# Variable sorting (order is important)
332332
if node isa DFGFactor
333333
order = intersect(node._variableOrderSymbols, map(v->v.dfgNode.label, neighbors))
@@ -347,8 +347,8 @@ function getNeighbors(dfg::GraphsDFG, label::Symbol; ready::Union{Nothing, Int}=
347347
vert = dfg.g.vertices[dfg.labelDict[label]]
348348
neighbors = in_neighbors(vert, dfg.g) #Don't use out_neighbors! It enforces directiveness even if we don't want it
349349
# Additional filtering
350-
neighbors = ready != nothing ? filter(v -> v.ready == ready, neighbors) : neighbors
351-
neighbors = backendset != nothing ? filter(v -> v.backendset == backendset, neighbors) : neighbors
350+
neighbors = ready != nothing ? filter(v -> v.dfgNode.ready == ready, neighbors) : neighbors
351+
neighbors = backendset != nothing ? filter(v -> v.dfgNode.backendset == backendset, neighbors) : neighbors
352352
# Variable sorting when using a factor (function order is important)
353353
if vert.dfgNode isa DFGFactor
354354
vert.dfgNode._variableOrderSymbols
@@ -451,7 +451,7 @@ Get a deep subgraph copy from the DFG given a list of variables and factors.
451451
Optionally provide an existing subgraph addToDFG, the extracted nodes will be copied into this graph. By default a new subgraph will be created.
452452
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.
453453
"""
454-
function getSubgraph(dfg::GraphsDFG, variableFactorLabels::Vector{Symbol}, includeOrphanFactors::Bool=false, addToDFG::GraphsDFG=GraphsDFG())::GraphsDFG
454+
function getSubgraph(dfg::GraphsDFG, variableFactorLabels::Vector{Symbol}, includeOrphanFactors::Bool=false, addToDFG::GraphsDFG=GraphsDFG{AbstractParams}())::GraphsDFG
455455
for label in variableFactorLabels
456456
if !haskey(dfg.labelDict, label)
457457
error("Variable/factor with label '$(label)' does not exist in the factor graph")

src/LightGraphsDFG/LightGraphsDFG.jl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using LightGraphs
2+
using MetaGraphs
3+
4+
# Imports
5+
include("entities/LightGraphsDFG.jl")
6+
include("services/LightGraphsDFG.jl")
7+
8+
# Exports
9+
export LightGraphsDFG
10+
export exists
11+
export getLabelDict, getDescription, setDescription, getInnerGraph, getAddHistory, getSolverParams, setSolverParams
12+
#
13+
export getAddHistory, getDescription, getLabelDict
14+
export addVariable!, addFactor!
15+
export ls, lsf, getVariables, getFactors, getVariableIds, getFactorIds
16+
export getVariable, getFactor
17+
export updateVariable!, updateFactor!
18+
export deleteVariable!, deleteFactor!
19+
export getAdjacencyMatrix
20+
export getAdjacencyMatrixDataFrame
21+
export getNeighbors
22+
export getSubgraphAroundNode
23+
export getSubgraph
24+
export isFullyConnected, hasOrphans
25+
export toDot, toDotFile
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Starting of with Graph.jl implementation. There are a lot of overlap with metagraphs and some data can be moved there.
2+
"""
3+
$(TYPEDEF)
4+
Encapsulation structure for a DFGNode (Variable or Factor) in LightGraphs.jl graph.
5+
"""
6+
mutable struct LightGraphsNode
7+
index::Int
8+
dfgNode::DFGNode
9+
end
10+
11+
const LFGType = MetaGraph{Int64,Float64}
12+
13+
mutable struct LightGraphsDFG{T <: AbstractParams} <: AbstractDFG
14+
g::LFGType
15+
description::String
16+
userId::String
17+
robotId::String
18+
sessionId::String
19+
#NOTE Removed nodeCounter
20+
# nodeCounter::Int64
21+
#NOTE using matagraphs labels
22+
# labelDict::Dict{Symbol, Int64}
23+
addHistory::Vector{Symbol} #TODO: Discuss more - is this an audit trail?
24+
solverParams::T # Solver parameters
25+
end
26+
27+
#TODO? do we not want props such as userId, robotId, sessionId, etc...
28+
function LightGraphsDFG{T}(g::LFGType=MetaGraph();
29+
description::String="LightGraphs.jl implementation",
30+
userId::String="User ID",
31+
robotId::String="Robot ID",
32+
sessionId::String="Session ID",
33+
params::T=NoSolverParams()) where T <: AbstractParams
34+
set_prop!(g, :description, description)
35+
set_prop!(g, :userId, userId)
36+
set_prop!(g, :robotId, robotId)
37+
set_prop!(g, :sessionId, sessionId)
38+
set_indexing_prop!(g, :label)
39+
LightGraphsDFG{T}(g, description, userId, robotId, sessionId, Symbol[], params)
40+
end
41+
42+
Base.propertynames(x::LightGraphsDFG, private::Bool=false) =
43+
(:g, :description, :userId, :robotId, :sessionId, :nodeCounter, :labelDict, :addHistory, :solverParams)
44+
# (private ? fieldnames(typeof(x)) : ())...)
45+
46+
Base.getproperty(x::LightGraphsDFG,f::Symbol) = begin
47+
if f == :nodeCounter
48+
nv(x.g)
49+
elseif f == :labelDict
50+
@warn "Read only! using internal labelDict"
51+
x.g.metaindex[:label]
52+
else
53+
getfield(x,f)
54+
end
55+
end

0 commit comments

Comments
 (0)