@@ -275,13 +275,34 @@ function getSparsityPattern(fg, varLabels, factLabels)
275
275
return sparse (getindex .(iter,1 ), getindex .(iter,2 ), ones (Bool, length (iter)))
276
276
end
277
277
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
278
299
279
- # TODO maybe split conditional solve as extra dispatch
280
300
function solve_RLM (
281
301
fg,
282
302
varlabels = ls (fg),
283
303
faclabels = lsf (fg);
284
- is_sparse= true ,
304
+ is_sparse = true ,
305
+ finiteDiffCovariance = false ,
285
306
kwargs...
286
307
)
287
308
@@ -328,7 +349,23 @@ function solve_RLM(
328
349
kwargs...
329
350
)
330
351
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, Σ
332
369
end
333
370
334
371
# nlso = NonlinearLeastSquaresObjective(
@@ -354,6 +391,7 @@ function solve_RLM_conditional(
354
391
frontals:: Vector{Symbol} = ls (fg),
355
392
separators:: Vector{Symbol} = setdiff (ls (fg), frontals);
356
393
is_sparse= false ,
394
+ finiteDiffCovariance= true ,
357
395
kwargs...
358
396
)
359
397
is_sparse && error (" Sparse solve_RLM_conditional not supported yet" )
@@ -431,7 +469,14 @@ function solve_RLM_conditional(
431
469
kwargs...
432
470
)
433
471
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, Σ
435
480
end
436
481
437
482
# HEX solve
@@ -478,16 +523,15 @@ function autoinitParametricManopt!(
478
523
return isInitialized (dfg, vl, solveKey)
479
524
end
480
525
481
- vartypeslist, lm_r = solve_RLM_conditional (dfg, [initme], initfrom; kwargs... )
526
+ M, vartypeslist, lm_r, Σ = solve_RLM_conditional (dfg, [initme], initfrom; kwargs... )
482
527
483
528
val = lm_r[1 ]
484
529
vnd:: VariableNodeData = getSolverData (xi, solveKey)
485
530
vnd. val[1 ] = val
486
-
487
531
488
- # val = lm_r[1]
489
- # cov = ...
490
- # updateSolverDataParametric!(vnd, val, cov )
532
+ ! isnothing (Σ) && vnd . bw . = Σ
533
+
534
+ # updateSolverDataParametric!(vnd, val, Σ )
491
535
492
536
vnd. initialized = true
493
537
# fill in ppe as mean
509
553
510
554
function DFG. solveGraphParametric! (
511
555
:: Val{:RLM} ,
512
- fg:: AbstractDFG ;
556
+ fg:: AbstractDFG ,
557
+ args... ;
513
558
init:: Bool = false ,
514
559
solveKey:: Symbol = :parametric , # FIXME , moot since only :parametric used for parametric solves
515
560
initSolveKey:: Symbol = :default ,
@@ -527,11 +572,11 @@ function DFG.solveGraphParametric!(
527
572
error (" TODO: not implemented" )
528
573
end
529
574
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
532
577
updateParametricSolution! (fg, v, r)
533
578
534
- return v,r
579
+ return v,r, Σ
535
580
end
536
581
537
582
0 commit comments