Skip to content

Commit beec4cd

Browse files
authored
Merge pull request #216 from JuliaRobotics/feature/cgdfg_update
Updated CGDFG, still slow, but working. Stoked to refactor soon
2 parents 15673f7 + f349e71 commit beec4cd

File tree

5 files changed

+53
-99
lines changed

5 files changed

+53
-99
lines changed

src/CloudGraphsDFG/services/CloudGraphsDFG.jl

Lines changed: 30 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -398,8 +398,8 @@ deleteFactor!(dfg::CloudGraphsDFG, factor::DFGFactor)::DFGFactor = deleteFactor!
398398
List the DFGVariables in the DFG.
399399
Optionally specify a label regular expression to retrieves a subset of the variables.
400400
"""
401-
function getVariables(dfg::CloudGraphsDFG, regexFilter::Union{Nothing, Regex}=nothing; tags::Vector{Symbol}=Symbol[])::Vector{DFGVariable}
402-
variableIds = getVariableIds(dfg, regexFilter)
401+
function getVariables(dfg::CloudGraphsDFG, regexFilter::Union{Nothing, Regex}=nothing; tags::Vector{Symbol}=Symbol[], solvable::Int=0)::Vector{DFGVariable}
402+
variableIds = getVariableIds(dfg, regexFilter, tags=tags, solvable=solvable)
403403
# TODO: Optimize to use tags in query here!
404404
variables = map(vId->getVariable(dfg, vId), variableIds)
405405
if length(tags) > 0
@@ -414,30 +414,23 @@ end
414414
Get a list of IDs of the DFGVariables in the DFG.
415415
Optionally specify a label regular expression to retrieves a subset of the variables.
416416
"""
417-
function getVariableIds(dfg::CloudGraphsDFG, regexFilter::Union{Nothing, Regex}=nothing)::Vector{Symbol}
417+
function getVariableIds(dfg::CloudGraphsDFG, regexFilter::Union{Nothing, Regex}=nothing; tags::Vector{Symbol}=Symbol[], solvable::Int=0)::Vector{Symbol}
418418
# Optimized for DB call
419+
tagsFilter = length(tags) > 0 ? " and "*join("node:".*String.(tags), " or ") : ""
419420
if regexFilter == nothing
420-
return _getLabelsFromCyphonQuery(dfg.neo4jInstance, "(node:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId):VARIABLE)")
421+
return _getLabelsFromCyphonQuery(dfg.neo4jInstance, "(node:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId):VARIABLE) where node.solvable >= $solvable $tagsFilter")
421422
else
422-
return _getLabelsFromCyphonQuery(dfg.neo4jInstance, "(node:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId):VARIABLE) where node.label =~ '$(regexFilter.pattern)'")
423+
return _getLabelsFromCyphonQuery(dfg.neo4jInstance, "(node:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId):VARIABLE) where node.label =~ '$(regexFilter.pattern)' and node.solvable >= $solvable $tagsFilter")
423424
end
424425
end
425426

426-
# Alias
427-
"""
428-
$(SIGNATURES)
429-
List the DFGVariables in the DFG.
430-
Optionally specify a label regular expression to retrieves a subset of the variables.
431-
"""
432-
ls(dfg::CloudGraphsDFG, regexFilter::Union{Nothing, Regex}=nothing)::Vector{Symbol} = getVariableIds(dfg, regexFilter)
433-
434427
"""
435428
$(SIGNATURES)
436429
List the DFGFactors in the DFG.
437430
Optionally specify a label regular expression to retrieves a subset of the factors.
438431
"""
439-
function getFactors(dfg::CloudGraphsDFG, regexFilter::Union{Nothing, Regex}=nothing)::Vector{DFGFactor}
440-
factorIds = getFactorIds(dfg, regexFilter)
432+
function getFactors(dfg::CloudGraphsDFG, regexFilter::Union{Nothing, Regex}=nothing; solvable::Int=0)::Vector{DFGFactor}
433+
factorIds = getFactorIds(dfg, regexFilter, solvable=solvable)
441434
return map(vId->getFactor(dfg, vId), factorIds)
442435
end
443436

@@ -446,32 +439,15 @@ end
446439
Get a list of the IDs of the DFGFactors in the DFG.
447440
Optionally specify a label regular expression to retrieves a subset of the factors.
448441
"""
449-
function getFactorIds(dfg::CloudGraphsDFG, regexFilter::Union{Nothing, Regex}=nothing)::Vector{Symbol}
442+
function getFactorIds(dfg::CloudGraphsDFG, regexFilter::Union{Nothing, Regex}=nothing; solvable::Int=0)::Vector{Symbol}
450443
# Optimized for DB call
451444
if regexFilter == nothing
452-
return _getLabelsFromCyphonQuery(dfg.neo4jInstance, "(node:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId):FACTOR)")
445+
return _getLabelsFromCyphonQuery(dfg.neo4jInstance, "(node:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId):FACTOR) where node.solvable >= $solvable")
453446
else
454-
return _getLabelsFromCyphonQuery(dfg.neo4jInstance, "(node:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId):FACTOR) where node.label =~ '$(regexFilter.pattern)'")
447+
return _getLabelsFromCyphonQuery(dfg.neo4jInstance, "(node:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId):FACTOR) where node.label =~ '$(regexFilter.pattern)' and node.solvable >= $solvable")
455448
end
456449
end
457450

458-
# Alias
459-
"""
460-
$(SIGNATURES)
461-
List the DFGFactors in the DFG.
462-
Optionally specify a label regular expression to retrieves a subset of the factors.
463-
"""
464-
lsf(dfg::CloudGraphsDFG, regexFilter::Union{Nothing, Regex}=nothing)::Vector{Symbol} = getFactorIds(dfg, regexFilter)
465-
466-
# Alias - getNeighbors
467-
"""
468-
$(SIGNATURES)
469-
Get neighbors around a given node. TODO: Refactor this
470-
"""
471-
function lsf(dfg::CloudGraphsDFG, label::Symbol)::Vector{Symbol}
472-
return getNeighbors(dfg, label)
473-
end
474-
475451
"""
476452
$(SIGNATURES)
477453
Checks if the graph is fully connected, returns true if so.
@@ -496,22 +472,12 @@ function isFullyConnected(dfg::CloudGraphsDFG)::Bool
496472
return result.results[1]["data"][1]["row"][1] == length(varIds) + length(factIds)
497473
end
498474

499-
#Alias
500-
"""
501-
$(SIGNATURES)
502-
Checks if the graph is not fully connected, returns true if it is not contiguous.
503-
"""
504-
hasOrphans(dfg::CloudGraphsDFG)::Bool = !isFullyConnected(dfg)
505-
506475
"""
507476
$(SIGNATURES)
508477
Retrieve a list of labels of the immediate neighbors around a given variable or factor.
509478
"""
510-
function getNeighbors(dfg::CloudGraphsDFG, node::T; ready::Union{Nothing, Int}=nothing)::Vector{Symbol} where T <: DFGNode
511-
query = "(n:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId):$(node.label))--(node) where (node:VARIABLE or node:FACTOR) "
512-
if ready != nothing
513-
query = query * " and node.ready >= $(ready)"
514-
end
479+
function getNeighbors(dfg::CloudGraphsDFG, node::T; solvable::Int=0)::Vector{Symbol} where T <: DFGNode
480+
query = "(n:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId):$(node.label))--(node) where (node:VARIABLE or node:FACTOR) and node.solvable >= $solvable"
515481
@debug "[Query] $query"
516482
neighbors = _getLabelsFromCyphonQuery(dfg.neo4jInstance, query)
517483
# If factor, need to do variable ordering
@@ -525,11 +491,8 @@ end
525491
$(SIGNATURES)
526492
Retrieve a list of labels of the immediate neighbors around a given variable or factor specified by its label.
527493
"""
528-
function getNeighbors(dfg::CloudGraphsDFG, label::Symbol; ready::Union{Nothing, Int}=nothing)::Vector{Symbol}
529-
query = "(n:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId):$(label))--(node) where (node:VARIABLE or node:FACTOR) "
530-
if ready != nothing
531-
query = query * " and node.ready >= $(ready)"
532-
end
494+
function getNeighbors(dfg::CloudGraphsDFG, label::Symbol; solvable::Int=0)::Vector{Symbol}
495+
query = "(n:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId):$(label))--(node) where (node:VARIABLE or node:FACTOR) and node.solvable >= $solvable"
533496
@debug "[Query] $query"
534497
neighbors = _getLabelsFromCyphonQuery(dfg.neo4jInstance, query)
535498
# If factor, need to do variable ordering
@@ -541,25 +504,6 @@ function getNeighbors(dfg::CloudGraphsDFG, label::Symbol; ready::Union{Nothing,
541504
return neighbors
542505
end
543506

544-
# Aliases
545-
"""
546-
$(SIGNATURES)
547-
Retrieve a list of labels of the immediate neighbors around a given variable or factor.
548-
"""
549-
function ls(dfg::CloudGraphsDFG, node::T)::Vector{Symbol} where T <: DFGNode
550-
return getNeighbors(dfg, node)
551-
end
552-
"""
553-
$(SIGNATURES)
554-
Retrieve a list of labels of the immediate neighbors around a given variable or factor specified by its label.
555-
"""
556-
function ls(dfg::CloudGraphsDFG, label::Symbol)::Vector{Symbol} where T <: DFGNode
557-
return getNeighbors(dfg, label)
558-
end
559-
560-
## This is moved to services/AbstractDFG.jl
561-
# function _copyIntoGraph!(sourceDFG::CloudGraphsDFG, destDFG::CloudGraphsDFG, variableFactorLabels::Vector{Symbol}, includeOrphanFactors::Bool=false)::Nothing
562-
563507
"""
564508
$(SIGNATURES)
565509
Retrieve a deep subgraph copy around a given variable or factor.
@@ -572,7 +516,12 @@ function getSubgraphAroundNode(dfg::CloudGraphsDFG, node::DFGNode, distance::Int
572516

573517
# Thank you Neo4j for 0..* awesomeness!!
574518
neighborList = _getLabelsFromCyphonQuery(dfg.neo4jInstance,
575-
"(n:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId):$(node.label))-[FACTORGRAPH*0..$distance]-(node:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId)) WHERE (n:VARIABLE OR n:FACTOR OR node:VARIABLE OR node:FACTOR) and not (node:SESSION) and (node.solvable >= $solvable)")
519+
"""
520+
(n:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId):$(node.label))-[FACTORGRAPH*0..$distance]-(node:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId))
521+
WHERE (n:VARIABLE OR n:FACTOR OR node:VARIABLE OR node:FACTOR)
522+
and not (node:SESSION)
523+
and (node.solvable >= $solvable or node:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId):$(node.label))""" # Always return the root node
524+
)
576525

577526
# Copy the section of graph we want
578527
_copyIntoGraph!(dfg, addToDFG, neighborList, includeOrphanFactors)
@@ -604,9 +553,9 @@ Rows are all factors, columns are all variables, and each cell contains either n
604553
The first row and first column are factor and variable headings respectively.
605554
This is optimized for database usage.
606555
"""
607-
function getAdjacencyMatrix(dfg::CloudGraphsDFG)::Matrix{Union{Nothing, Symbol}}
608-
varLabels = sort(getVariableIds(dfg))
609-
factLabels = sort(getFactorIds(dfg))
556+
function getAdjacencyMatrix(dfg::CloudGraphsDFG; solvable::Int=0)::Matrix{Union{Nothing, Symbol}}
557+
varLabels = sort(getVariableIds(dfg, solvable=solvable))
558+
factLabels = sort(getFactorIds(dfg, solvable=solvable))
610559
vDict = Dict(varLabels .=> [1:length(varLabels)...].+1)
611560
fDict = Dict(factLabels .=> [1:length(factLabels)...].+1)
612561

@@ -617,7 +566,7 @@ function getAdjacencyMatrix(dfg::CloudGraphsDFG)::Matrix{Union{Nothing, Symbol}}
617566

618567
# Now ask for all relationships for this session graph
619568
loadtx = transaction(dfg.neo4jInstance.connection)
620-
query = "START n=node(*) MATCH (n:VARIABLE:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId))-[r:FACTORGRAPH]-(m:FACTOR:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId)) RETURN n.label as variable, m.label as factor;"
569+
query = "START n=node(*) MATCH (n:VARIABLE:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId))-[r:FACTORGRAPH]-(m:FACTOR:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId)) where n.solvable >= $solvable and m.solvable >= $solvable RETURN n.label as variable, m.label as factor;"
621570
nodes = loadtx(query; submit=true)
622571
# Have to finish the transaction
623572
commit(loadtx)
@@ -634,17 +583,18 @@ function getAdjacencyMatrix(dfg::CloudGraphsDFG)::Matrix{Union{Nothing, Symbol}}
634583
return adjMat
635584
end
636585

637-
function getAdjacencyMatrixSparse(dfg::CloudGraphsDFG)::Tuple{SparseMatrixCSC, Vector{Symbol}, Vector{Symbol}}
638-
varLabels = getVariableIds(dfg)
639-
factLabels = getFactorIds(dfg)
586+
function getAdjacencyMatrixSparse(dfg::CloudGraphsDFG; solvable::Int=0)::Tuple{SparseMatrixCSC, Vector{Symbol}, Vector{Symbol}}
587+
varLabels = getVariableIds(dfg, solvable=solvable)
588+
factLabels = getFactorIds(dfg, solvable=solvable)
640589
vDict = Dict(varLabels .=> [1:length(varLabels)...])
641590
fDict = Dict(factLabels .=> [1:length(factLabels)...])
642591

643592
adjMat = spzeros(Int, length(factLabels), length(varLabels))
644593

645594
# Now ask for all relationships for this session graph
646595
loadtx = transaction(dfg.neo4jInstance.connection)
647-
query = "START n=node(*) MATCH (n:VARIABLE:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId))-[r:FACTORGRAPH]-(m:FACTOR:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId)) RETURN n.label as variable, m.label as factor;"
596+
query = "START n=node(*) MATCH (n:VARIABLE:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId))-[r:FACTORGRAPH]-(m:FACTOR:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId)) where n.solvable >= $solvable and m.solvable >= $solvable RETURN n.label as variable, m.label as factor;"
597+
@debug "[Query] $query"
648598
nodes = loadtx(query; submit=true)
649599
# Have to finish the transaction
650600
commit(loadtx)

src/CloudGraphsDFG/services/CommonFunctions.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ So can make orderProperty = label or id.
4242
"""
4343
function _getLabelsFromCyphonQuery(neo4jInstance::Neo4jInstance, matchCondition::String, orderProperty::String="")::Vector{Symbol}
4444
query = "match $matchCondition return distinct(node.label) $(orderProperty != "" ? "order by node.$orderProperty" : "")";
45+
@debug "[Query] $query"
4546
result = _queryNeo4j(neo4jInstance, query)
4647
nodeIds = map(node -> node["row"][1], result.results[1]["data"])
4748
return Symbol.(nodeIds)

src/services/AbstractDFG.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ end
208208
$(SIGNATURES)
209209
List the DFGVariables in the DFG.
210210
Optionally specify a label regular expression to retrieves a subset of the variables.
211+
Tags is a list of any tags that a node must have (at least one match).
211212
"""
212213
function getVariables(dfg::G, regexFilter::Union{Nothing, Regex}=nothing; tags::Vector{Symbol}=Symbol[], solvable::Int=0)::Vector{AbstractDFGVariable} where G <: AbstractDFG
213214
error("getVariables not implemented for $(typeof(dfg))")
@@ -217,6 +218,7 @@ end
217218
$(SIGNATURES)
218219
Get a list of IDs of the DFGVariables in the DFG.
219220
Optionally specify a label regular expression to retrieves a subset of the variables.
221+
Tags is a list of any tags that a node must have (at least one match).
220222
221223
Example
222224
```julia
@@ -237,6 +239,8 @@ end
237239
$(SIGNATURES)
238240
List the DFGVariables in the DFG.
239241
Optionally specify a label regular expression to retrieves a subset of the variables.
242+
Tags is a list of any tags that a node must have (at least one match).
243+
240244
"""
241245
function ls(dfg::G, regexFilter::Union{Nothing, Regex}=nothing; tags::Vector{Symbol}=Symbol[], solvable::Int=0)::Vector{Symbol} where G <: AbstractDFG
242246
return getVariableIds(dfg, regexFilter, tags=tags, solvable=solvable)

test/iifInterfaceTests.jl

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -176,17 +176,15 @@ end
176176

177177
# Session, robot, and user small data tests
178178
# NOTE: CloudGraphDFG isnt supporting this yet.
179-
if !(typeof(dfg) <: CloudGraphsDFG)
180-
smallUserData = Dict{Symbol, String}(:a => "42", :b => "Hello")
181-
smallRobotData = Dict{Symbol, String}(:a => "43", :b => "Hello")
182-
smallSessionData = Dict{Symbol, String}(:a => "44", :b => "Hello")
183-
setUserData(dfg, deepcopy(smallUserData))
184-
setRobotData(dfg, deepcopy(smallRobotData))
185-
setSessionData(dfg, deepcopy(smallSessionData))
186-
@test getUserData(dfg) == smallUserData
187-
@test getRobotData(dfg) == smallRobotData
188-
@test getSessionData(dfg) == smallSessionData
189-
end
179+
smallUserData = Dict{Symbol, String}(:a => "42", :b => "Hello")
180+
smallRobotData = Dict{Symbol, String}(:a => "43", :b => "Hello")
181+
smallSessionData = Dict{Symbol, String}(:a => "44", :b => "Hello")
182+
setUserData(dfg, deepcopy(smallUserData))
183+
setRobotData(dfg, deepcopy(smallRobotData))
184+
setSessionData(dfg, deepcopy(smallSessionData))
185+
@test getUserData(dfg) == smallUserData
186+
@test getRobotData(dfg) == smallRobotData
187+
@test getSessionData(dfg) == smallSessionData
190188
end
191189

192190
@testset "BigData" begin
@@ -318,7 +316,7 @@ end
318316
@test size(adjMat) == (1,2)
319317
@test symdiff(adjMat[1, :], [nothing, :b]) == Symbol[]
320318
# sparse
321-
@show adjMat, v_ll, f_ll = getAdjacencyMatrixSparse(dfg, solvable=1)
319+
adjMat, v_ll, f_ll = getAdjacencyMatrixSparse(dfg, solvable=1)
322320
@test size(adjMat) == (0,1)
323321
@test v_ll == [:b]
324322
@test f_ll == []

test/runtests.jl

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ using Pkg
1111
##
1212

1313
# If you want to enable debugging logging (very verbose!)
14+
# using Logging
1415
# logger = SimpleLogger(stdout, Logging.Debug)
1516
# global_logger(logger)
1617

@@ -64,13 +65,13 @@ if get(ENV, "IIF_TEST", "") == "true"
6465
GraphsDFG{NoSolverParams}(),
6566
LightDFG{NoSolverParams}(),
6667
DistributedFactorGraphs.SymbolDFG{NoSolverParams}(),
67-
# CloudGraphsDFG{SolverParams}("localhost", 7474, "neo4j", "test",
68-
# "testUser", "testRobot", "testSession",
69-
# nothing,
70-
# nothing,
71-
# IncrementalInference.decodePackedType,
72-
# IncrementalInference.rebuildFactorMetadata!,
73-
# solverParams=SolverParams())
68+
CloudGraphsDFG{SolverParams}("localhost", 7474, "neo4j", "test",
69+
"testUser", "testRobot", "testSession",
70+
nothing,
71+
nothing,
72+
IncrementalInference.decodePackedType,
73+
IncrementalInference.rebuildFactorMetadata!,
74+
solverParams=SolverParams())
7475
]
7576
for api in apis
7677
@testset "Testing Driver: $(typeof(api))" begin

0 commit comments

Comments
 (0)