1
1
using Manopt
2
2
using FiniteDiff
3
+ using SparseDiffTools
4
+ using BlockArrays
5
+ using SparseArrays
6
+
3
7
# using ForwardDiff
4
8
# using Zygote
5
9
@@ -18,9 +22,10 @@ struct CalcFactorManopt{
18
22
varOrderIdxs:: Vector{Int}
19
23
meas:: MEAS
20
24
iΣ:: SMatrix{D, D, Float64, L}
25
+ sqrt_iΣ:: SMatrix{D, D, Float64, L}
21
26
end
22
27
23
- function CalcFactorManopt (fg, fct:: DFGFactor , varIntLabel)
28
+ function CalcFactorManopt (fct:: DFGFactor , varIntLabel)
24
29
fac_func = getFactorType (fct)
25
30
varOrder = getVariableOrder (fct)
26
31
@@ -45,6 +50,7 @@ function CalcFactorManopt(fg, fct::DFGFactor, varIntLabel)
45
50
# make sure its an SMatrix
46
51
iΣ = convert (SMatrix{dims, dims}, _iΣ)
47
52
53
+ sqrt_iΣ = convert (SMatrix{dims, dims}, sqrt (iΣ))
48
54
# cache = preambleCache(fg, getVariable.(fg, varOrder), getFactorType(fct))
49
55
50
56
calcf = CalcFactor (
@@ -57,13 +63,14 @@ function CalcFactorManopt(fg, fct::DFGFactor, varIntLabel)
57
63
0 ,
58
64
getManifold (fac_func),
59
65
)
60
- return CalcFactorManopt (fct. label, calcf, varOrder, varOrderIdxs, meas, iΣ)
66
+ return CalcFactorManopt (fct. label, calcf, varOrder, varOrderIdxs, meas, iΣ, sqrt_iΣ )
61
67
end
62
68
63
69
function (cfm:: CalcFactorManopt )(p)
64
70
meas = cfm. meas
65
71
idx = cfm. varOrderIdxs
66
72
return cfm. calcfactor! (meas, p[idx]. .. )
73
+ # return cfm.sqrt_iΣ * cfm.calcfactor!(meas, p[idx]...)
67
74
end
68
75
69
76
# cost function f: M->ℝᵈ for Riemannian Levenberg-Marquardt
@@ -95,7 +102,7 @@ function JacF_RLM!(M, costF!; basis_domain::AbstractBasis = DefaultOrthogonalBas
95
102
96
103
p = costF!. points
97
104
98
- res = mapreduce (f -> f (p), vcat, costF!. costfuns)
105
+ res = Vector ( mapreduce (f -> f (p), vcat, costF!. costfuns) )
99
106
100
107
X0 = zeros (manifold_dimension (M))
101
108
@@ -125,25 +132,52 @@ function (jacF!::JacF_RLM!)(
125
132
126
133
fill! (X0, 0 )
127
134
128
- # J .= FiniteDiff.finite_difference_jacobian(
129
- # Xc -> jacF!.costF!(M, jacF!.res, exp!(M, q, p, get_vector!(M, X, p, Xc, basis_domain))),
130
- # X0,
131
- # )
135
+ # TODO maybe move to struct
136
+ colorvec = matrix_colors (J)
137
+
138
+ # ϵ = getPointIdentity(M)
139
+ # function jaccost(res, Xc)
140
+ # exp!(M, q, ϵ, get_vector!(M, X, p, Xc, basis_domain))
141
+ # compose!(M, q, p, q)
142
+ # jacF!.costF!(M, res, q)
143
+ # end
144
+
132
145
FiniteDiff. finite_difference_jacobian! (
133
146
J,
134
147
(res,Xc) -> jacF!. costF! (M, res, exp! (M, q, p, get_vector! (M, X, p, Xc, basis_domain))),
135
- X0,
148
+ X0;
149
+ colorvec
136
150
)
151
+ # @warn "1" Matrix(J)[1:3,1:3]
152
+ @warn " 2" Matrix (J)[4 : 6 ,1 : 6 ]
137
153
return J
138
154
end
139
155
156
+ function getSparsityPattern (fg)
157
+ biadj = getBiadjacencyMatrix (fg)
158
+
159
+ vdims = getDimension .(getVariable .(fg, biadj. varLabels))
160
+ fdims = getDimension .(getFactor .(fg, biadj. facLabels))
161
+
162
+ sm = map (eachindex (biadj. B)) do i
163
+ vdim = vdims[i[2 ]]
164
+ fdim = fdims[i[1 ]]
165
+ if biadj. B[i] > 0
166
+ trues (fdim,vdim)
167
+ else
168
+ falses (fdim,vdim)
169
+ end
170
+ end
171
+
172
+ return SparseMatrixCSC (mortar (sm))
173
+
174
+ end
140
175
141
176
function solve_RLM (
142
177
fg,
143
178
frontals:: Vector{Symbol} = ls (fg),
144
179
separators:: Vector{Symbol} = setdiff (ls (fg), frontals);
145
180
)
146
- @error " #FIXME, use covariances" maxlog= 1
147
181
148
182
# get the subgraph formed by all frontals, separators and fully connected factors
149
183
varlabels = union (frontals, separators)
@@ -162,7 +196,7 @@ function solve_RLM(
162
196
# varIntLabel_frontals = filter(p->first(p) in frontals, varIntLabel)
163
197
# varIntLabel_separators = filter(p->first(p) in separators, varIntLabel)
164
198
165
- calcfacs = CalcFactorManopt .(fg, facs, Ref (varIntLabel))
199
+ calcfacs = CalcFactorManopt .(facs, Ref (varIntLabel))
166
200
167
201
168
202
# get the manifold and variable types
@@ -194,7 +228,92 @@ function solve_RLM(
194
228
num_components = length (jacF!. res)
195
229
196
230
p0 = deepcopy (fro_p)
197
- lm_r = LevenbergMarquardt (MM, costF!, jacF!, p0, num_components; evaluation= InplaceEvaluation ())
231
+
232
+ initial_residual_values = zeros (num_components)
233
+ initial_jacF = zeros (num_components, manifold_dimension (MM))
234
+ #
235
+ # HEX solve
236
+ # sparse J 0.025235 seconds (133.65 k allocations: 9.964 MiB
237
+ # dense J 0.022079 seconds (283.54 k allocations: 18.146 MiB)
238
+
239
+ lm_r = LevenbergMarquardt (
240
+ MM,
241
+ costF!,
242
+ jacF!,
243
+ p0,
244
+ num_components;
245
+ evaluation= InplaceEvaluation (),
246
+ initial_residual_values,
247
+ initial_jacF,
248
+ )
249
+
250
+ return vartypeslist, lm_r
251
+ end
252
+
253
+ function solve_RLM_sparse (fg)
254
+
255
+ # get the subgraph formed by all frontals, separators and fully connected factors
256
+ varlabels = ls (fg)
257
+ faclabels = lsf (fg)
258
+
259
+ facs = getFactor .(fg, faclabels)
260
+
261
+ # so the subgraph consists of varlabels(frontals + separators) and faclabels
262
+
263
+ varIntLabel = OrderedDict (zip (varlabels, collect (1 : length (varlabels))))
264
+
265
+ calcfacs = CalcFactorManopt .(facs, Ref (varIntLabel))
266
+
267
+ # get the manifold and variable types
268
+ vars = getVariable .(fg, varlabels)
269
+ vartypes, vartypecount, vartypeslist = getVariableTypesCount (vars)
270
+
271
+ PMs = map (vartypes) do vartype
272
+ N = vartypecount[vartype]
273
+ G = getManifold (vartype)
274
+ return IIF. NPowerManifold (G, N)
275
+ end
276
+ M = ProductManifold (PMs... )
277
+
278
+ #
279
+ # FIXME
280
+ @assert length (M. manifolds) == 1 " #FIXME, this only works with 1 manifold type component"
281
+ MM = M. manifolds[1 ]
282
+
283
+ # inital values and separators from fg
284
+ fro_p = first .(getVal .(vars, solveKey = :parametric ))
285
+ sep_p = eltype (fro_p)[]
286
+
287
+ # cost and jacobian functions
288
+ # cost function f: M->ℝᵈ for Riemannian Levenberg-Marquardt
289
+ costF! = CostF_RLM! (calcfacs, fro_p, sep_p)
290
+ # jacobian of function for Riemannian Levenberg-Marquardt
291
+ jacF! = JacF_RLM! (MM, costF!)
292
+
293
+ num_components = length (jacF!. res)
294
+
295
+ p0 = deepcopy (fro_p)
296
+
297
+ initial_residual_values = zeros (num_components)
298
+ initial_jacF = Float64 .(getSparsityPattern (fg))
299
+
300
+ # HEX solve
301
+ # sparse J 0.025235 seconds (133.65 k allocations: 9.964 MiB
302
+ # dense J 0.022079 seconds (283.54 k allocations: 18.146 MiB)
303
+
304
+ # 9.125818 seconds (86.35 M allocations: 6.412 GiB, 14.34% gc time)
305
+ # 0.841720 seconds (7.96 M allocations: 751.825 MiB)
306
+
307
+ lm_r = LevenbergMarquardt (
308
+ MM,
309
+ costF!,
310
+ jacF!,
311
+ p0,
312
+ num_components;
313
+ evaluation= InplaceEvaluation (),
314
+ initial_residual_values,
315
+ initial_jacF,
316
+ )
198
317
199
318
return vartypeslist, lm_r
200
319
end
0 commit comments