Skip to content

Commit 5d62f24

Browse files
committed
Add Covariance estimate
1 parent c253495 commit 5d62f24

File tree

2 files changed

+60
-15
lines changed

2 files changed

+60
-15
lines changed

src/entities/CalcFactor.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,9 @@ struct CalcFactorResidual{
100100
cache::C
101101
varOrder::NTuple{N, Symbol}
102102
varOrderIdxs::NTuple{N, Int}
103-
points::P
103+
points::P #TODO remove or not?
104104
meas::MEAS
105-
::SMatrix{D, D, Float64, L}
105+
::SMatrix{D, D, Float64, L} #TODO remove or not?
106106
sqrt_iΣ::SMatrix{D, D, Float64, L}
107107
end
108108

src/parametric/services/ParametricManopt.jl

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -275,13 +275,34 @@ function getSparsityPattern(fg, varLabels, factLabels)
275275
return sparse(getindex.(iter,1), getindex.(iter,2), ones(Bool, length(iter)))
276276
end
277277

278+
# TODO only calculate marginal covariances
279+
280+
function covarianceFiniteDiff(M, jacF!::JacF_RLM!, p0)
281+
# Jcache
282+
X0 = fill!(deepcopy(jacF!.X0), 0)
283+
284+
function costf(Xc)
285+
let res = jacF!.res, X = jacF!.X, q = jacF!.q, p0=p0
286+
get_vector!(M, X, p0, Xc, DefaultOrthogonalBasis())
287+
exp!(M, q, p0, X)
288+
1/2*norm(jacF!.costF!(M, res, q))^2
289+
end
290+
end
291+
292+
@time H = FiniteDiff.finite_difference_hessian(costf, X0)
293+
294+
# inv(H)
295+
Σ = Matrix(H) \ Matrix{eltype(H)}(I, size(H)...)
296+
# sqrt.(diag(Σ))
297+
return Σ
298+
end
278299

279-
#TODO maybe split conditional solve as extra dispatch
280300
function solve_RLM(
281301
fg,
282302
varlabels = ls(fg),
283303
faclabels = lsf(fg);
284-
is_sparse=true,
304+
is_sparse = true,
305+
finiteDiffCovariance = false,
285306
kwargs...
286307
)
287308

@@ -328,7 +349,23 @@ function solve_RLM(
328349
kwargs...
329350
)
330351

331-
return varlabelsAP, lm_r
352+
if length(initial_residual_values) < 1000
353+
if finiteDiffCovariance
354+
# TODO this seems to be correct, but way to slow
355+
Σ = covarianceFiniteDiff(M, jacF!, lm_r)
356+
else
357+
# TODO make sure J initial_jacobian_f is updated, otherwise recalc jacF!(M, J, lm_r) # lm_r === p0
358+
J = initial_jacobian_f
359+
H = J'J
360+
Σ = H \ Matrix{eltype(H)}(I, size(H)...)
361+
# Σ = pinv(H)
362+
end
363+
else
364+
@warn "Not estimating a Dense Covariance $(size(initial_jacobian_f))"
365+
Σ = nothing
366+
end
367+
368+
return M, varlabelsAP, lm_r, Σ
332369
end
333370

334371
# nlso = NonlinearLeastSquaresObjective(
@@ -354,6 +391,7 @@ function solve_RLM_conditional(
354391
frontals::Vector{Symbol} = ls(fg),
355392
separators::Vector{Symbol} = setdiff(ls(fg), frontals);
356393
is_sparse=false,
394+
finiteDiffCovariance=true,
357395
kwargs...
358396
)
359397
is_sparse && error("Sparse solve_RLM_conditional not supported yet")
@@ -431,7 +469,14 @@ function solve_RLM_conditional(
431469
kwargs...
432470
)
433471

434-
return all_varlabelsAP, lm_r
472+
if finiteDiffCovariance
473+
Σ = covarianceFiniteDiff(M, jacF!, lm_r)
474+
else
475+
J = initial_jacobian_f
476+
Σ = pinv(J'J)
477+
end
478+
479+
return M, all_varlabelsAP, lm_r, Σ
435480
end
436481

437482
#HEX solve
@@ -478,16 +523,15 @@ function autoinitParametricManopt!(
478523
return isInitialized(dfg, vl, solveKey)
479524
end
480525

481-
vartypeslist, lm_r = solve_RLM_conditional(dfg, [initme], initfrom; kwargs...)
526+
M, vartypeslist, lm_r, Σ = solve_RLM_conditional(dfg, [initme], initfrom; kwargs...)
482527

483528
val = lm_r[1]
484529
vnd::VariableNodeData = getSolverData(xi, solveKey)
485530
vnd.val[1] = val
486-
487531

488-
# val = lm_r[1]
489-
# cov = ...
490-
# updateSolverDataParametric!(vnd, val, cov)
532+
!isnothing(Σ) && vnd.bw .= Σ
533+
534+
# updateSolverDataParametric!(vnd, val, Σ)
491535

492536
vnd.initialized = true
493537
#fill in ppe as mean
@@ -509,7 +553,8 @@ end
509553

510554
function DFG.solveGraphParametric!(
511555
::Val{:RLM},
512-
fg::AbstractDFG;
556+
fg::AbstractDFG,
557+
args...;
513558
init::Bool = false,
514559
solveKey::Symbol = :parametric, # FIXME, moot since only :parametric used for parametric solves
515560
initSolveKey::Symbol = :default,
@@ -527,11 +572,11 @@ function DFG.solveGraphParametric!(
527572
error("TODO: not implemented")
528573
end
529574

530-
v,r = solve_RLM(fg; is_sparse)
531-
575+
M, v, r, Σ = solve_RLM(fg, args...; is_sparse, kwargs...)
576+
#TODO update Σ in solver data
532577
updateParametricSolution!(fg, v, r)
533578

534-
return v,r
579+
return v,r, Σ
535580
end
536581

537582

0 commit comments

Comments
 (0)