@@ -275,13 +275,34 @@ function getSparsityPattern(fg, varLabels, factLabels)
275275 return sparse (getindex .(iter,1 ), getindex .(iter,2 ), ones (Bool, length (iter)))
276276end
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
280300function 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, Σ
332369end
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, Σ
435480end
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
509553
510554function 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, Σ
535580end
536581
537582
0 commit comments