gtsam
Loading...
Searching...
No Matches
MultifrontalClique.h
Go to the documentation of this file.
1/* ----------------------------------------------------------------------------
2
3 * GTSAM Copyright 2010, Georgia Tech Research Corporation,
4 * Atlanta, Georgia 30332-0415
5 * All Rights Reserved
6 * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
7
8 * See LICENSE for the license information
9
10 * -------------------------------------------------------------------------- */
11
18
19#pragma once
20
23#include <gtsam/dllexport.h>
24#include <gtsam/inference/Key.h>
29#include <gtsam/linear/internal/BatchHessianMapping.h>
32
33#include <cstdint>
34#include <iosfwd>
35#include <map>
36#include <memory>
37#include <optional>
38#include <string>
39#include <unordered_map>
40#include <unordered_set>
41#include <vector>
42
43namespace gtsam {
44
47class HessianFactor;
48class JacobianFactor;
49
51using KeyDimMap = std::map<Key, size_t>;
52
53namespace internal {
54
56template <typename KeyRange>
57inline size_t sumDims(const KeyDimMap& dims, const KeyRange& keys) {
58 size_t dim = 0;
59 for (Key key : keys) {
60 auto it = dims.find(key);
61 if (it != dims.end()) dim += it->second;
62 }
63 return dim;
64}
65
66} // namespace internal
67
71class GTSAM_EXPORT MultifrontalClique {
72 public:
73 using shared_ptr = std::shared_ptr<MultifrontalClique>;
74 using Children = std::vector<shared_ptr>;
75 struct ChildInfo {
76 shared_ptr clique;
77 KeySet separatorKeys;
78 };
79
80 std::weak_ptr<MultifrontalClique> parent;
81 Children children;
82 size_t frontalDim = 0;
83 size_t separatorDim = 0;
84
96 explicit MultifrontalClique(std::vector<size_t> factorIndices,
97 const std::weak_ptr<MultifrontalClique>& parent,
98 const KeyVector& frontals,
99 const KeySet& separatorKeys,
100 const KeyDimMap& dims, size_t vbmRows,
101 VectorValues* solution,
102 const std::unordered_set<Key>* fixedKeys,
103 size_t numEliminatedFrontals);
104
107
113 void finalize(std::vector<ChildInfo> children,
114 const MultifrontalParameters& params);
115
123 void fillAb(const GaussianFactorGraph& graph);
124
128
130 void factorize();
131
136 void addIdentityDamping(double lambda);
137
144 void addDiagonalDamping(double lambda, double minDiagonal,
145 double maxDiagonal);
146
160 void addExactDiagonalDamping(double lambda,
161 const VectorValues& hessianDiagonal,
162 double minDiagonal, double maxDiagonal);
163
165
168
170 int problemSize() const {
171 return static_cast<int>(frontalDim + separatorDim);
172 }
173
175 size_t numFrontals() const { return frontalPtrs_.size(); }
176
178 bool fullyEliminated() const { return numFrontals() == totalFrontals_; }
179
181 const KeyVector& orderedKeys() const { return orderedKeys_; }
182
184 std::shared_ptr<GaussianConditional> conditional() const;
185
193 std::shared_ptr<HessianFactor> remainingFactor() const;
194
196 const VerticalBlockMatrix& Ab() const { return Ab_; }
197
199 const SymmetricBlockMatrix& info() const { return info_; }
200
202 bool useQR() const { return solveMode_ == SolveMode::QrLeaf; }
203
205 bool useCompactCholesky() const {
206 return solveMode_ == SolveMode::CompactCholeskyLeaf ||
207 solveMode_ == SolveMode::FusedStarCandidate ||
208 solveMode_ == SolveMode::FusedStarCholeskyLeaf;
209 }
210
216 void print(const std::string& s = "",
217 const KeyFormatter& keyFormatter = DefaultKeyFormatter) const;
218
220
223
231 void eliminateInPlace();
232
240 void eliminateInPlace(double lambda, const LMDampingParams& dampingParams,
241 const VectorValues& exactHessianDiagonal);
242
251 void updateSolution();
252
254 double lastOldError() const { return lastOldError_; }
255
257 double lastNewError() const { return lastNewError_; }
258
260 double constantTermError() const;
262
263 friend std::ostream& operator<<(std::ostream& os,
264 const MultifrontalClique& clique);
265
266 private:
267 enum class SolveMode {
268 Cholesky,
269 QrLeaf,
270 CompactCholeskyLeaf,
271 FusedStarCandidate,
272 FusedStarCholeskyLeaf
273 };
274
276 void cacheSolutionPointers(VectorValues* delta, const KeyVector& frontals,
277 const KeyVector& separatorKeys);
278
280 DenseIndex blockIndex(Key key) const;
281
282 enum class FactorLoadKind : uint8_t { Empty, Jacobian, Batch };
283
284 struct FactorLoadPlan {
285 FactorLoadKind kind = FactorLoadKind::Empty;
286 size_t factorIndex = 0;
287 SharedDiagonal model;
288 size_t rows = 0;
290 size_t abRowOffset = 0;
293 std::vector<DenseIndex> blockIndices;
295 internal::BatchHessianMapping localMapping;
297 internal::BatchHessianMapping parentMapping;
299 internal::BatchHessianMapping separatorMapping;
300 bool canDirectUpdate = false;
301
303 static FactorLoadPlan forNullFactor(size_t factorIndex);
304
306 static FactorLoadPlan forJacobian(size_t factorIndex,
307 const JacobianFactor& factor,
308 const MultifrontalClique& clique);
309
311 static FactorLoadPlan forBatch(size_t factorIndex,
312 const BatchJacobianFactorBase& factor,
313 const MultifrontalClique& clique);
314
316 bool isDirectBatch() const {
317 return kind == FactorLoadKind::Batch && canDirectUpdate;
318 }
319
321 bool needsMaterializedRows(const MultifrontalClique& clique) const;
322
324 void assignMaterializedRows(size_t* nextRow);
325
327 void assertInvariants(const GaussianFactor* factor,
328 const MultifrontalClique& clique) const;
329
331 bool supportsFusedStarLeaf() const;
332
334 void buildSolveMappings(const BatchJacobianFactorBase& factor,
335 const MultifrontalClique& clique);
336
337 private:
339 void mapKeys(const KeyVector& keys, const MultifrontalClique& clique);
340
342 void buildLocalBatchMapping(const BatchJacobianFactorBase& factor,
343 const MultifrontalClique& clique);
344
346 internal::BatchHessianMapping buildRetainedMapping(
347 const BatchJacobianFactorBase& factor, DenseIndex numFrontals,
348 const std::vector<DenseIndex>& targetIndices,
349 const std::vector<DenseIndex>& targetScalarOffsets) const;
350 };
351
353 void buildLoadPlans(const GaussianFactorGraph& graph);
354
356 void allocateSolveStorage();
357
359 void resolveLeafSolveMode();
360
362 void buildFusedStarMappings();
363
366 void updateParentInfo(SymmetricBlockMatrix& parentInfo) const;
367
369 void updateParentMaterializedColumn(SymmetricBlockMatrix& parentInfo,
370 DenseIndex sourceSeparatorBlock) const;
371
373 void updateParentQrColumnScratch(DenseIndex sourceSeparatorBlock,
374 Matrix* scratch) const;
375
377 double parentRhsDiagonal() const;
378
380 void updateSeparatorInfo(SymmetricBlockMatrix& separatorInfo) const;
381
383 void prepareCompactCholesky();
384
386 void factorizeCompactCholesky();
387
389 void factorizeFusedStarCholesky();
390
392 void updateFusedStarInfo(SymmetricBlockMatrix& targetInfo,
393 const std::vector<DenseIndex>& targetIndices,
394 const std::vector<DenseIndex>& targetScalarOffsets,
395 bool useParentMappedSlots) const;
396
398 void updateCholeskyInfo(SymmetricBlockMatrix& targetInfo,
399 const std::vector<DenseIndex>& targetIndices,
400 const std::vector<DenseIndex>& targetBlockOffsets,
401 bool useParentMappedSlots) const;
402
404 void updateDirectFactors(SymmetricBlockMatrix& targetInfo,
405 const std::vector<DenseIndex>& targetIndices,
406 bool useParentMappedSlots) const;
407
410 void gatherUpdatesSequential();
411
414 void gatherUpdatesParallel(size_t numThreads);
415
417 void gatherSameSeparatorUpdates();
418
420 std::vector<size_t> blockDims(const KeyDimMap& dims,
421 const KeyVector& frontals,
422 const KeySet& separatorKeys) const;
423
425 void applyDampingQR(double lambda, const LMDampingParams& dampingParams,
426 const VectorValues& exactHessianDiagonal);
427
429 void applyDampingCholesky(double lambda, const LMDampingParams& dampingParams,
430 const VectorValues& exactHessianDiagonal);
431
436 size_t addJacobianFactor(const JacobianFactor& factor, size_t rowOffset,
437 const FactorLoadPlan& plan);
438
443 size_t addBatchJacobianFactor(const BatchJacobianFactorBase& factor,
444 size_t rowOffset, const FactorLoadPlan& plan);
445
446 void setParentIndices(const std::vector<DenseIndex>& indices,
447 const std::vector<DenseIndex>& scalarOffsets) {
448 parentIndices_ = indices;
449 parentScalarOffsets_ = scalarOffsets;
450 }
451
452 // Construction-time metadata (set once in the constructor).
453 std::vector<size_t> factorIndices_;
454 KeyVector orderedKeys_;
455 size_t totalFrontals_ = 0;
456 const std::unordered_set<Key>* fixedKeys_ = nullptr;
457 std::unordered_map<Key, DenseIndex> blockIndexCache_;
458 std::vector<Vector*> frontalPtrs_;
459 std::vector<const Vector*> separatorPtrs_;
460 std::vector<size_t> blockDims_;
461 size_t factorRows_ = 0;
462 mutable const GaussianFactorGraph* activeLoadGraph_ = nullptr;
463 mutable bool allBatchFactors_ = false;
464 mutable bool hasDirectBatchFactors_ = false;
465 mutable std::vector<FactorLoadPlan> loadPlans_;
466 mutable bool loadPlansBuilt_ = false;
467 mutable size_t materializedRows_ = 0;
468 mutable size_t fillRows_ = 0;
469
470 // Finalize-time metadata (set once after children are known).
471 std::vector<DenseIndex>
472 parentIndices_;
473 std::vector<DenseIndex>
474 parentScalarOffsets_;
475 std::vector<DenseIndex> separatorIndices_;
476 std::vector<DenseIndex>
477 separatorScalarOffsets_;
478 SolveMode solveMode_ = SolveMode::Cholesky;
479 SolveMode starFallbackMode_ = SolveMode::Cholesky;
481 bool deferredSingleFactorAutoQr_ = false;
482 std::vector<DenseIndex> parentSchurScalarOffsets_;
483 std::vector<DenseIndex> separatorSchurScalarOffsets_;
484
485 std::vector<std::vector<size_t>> sameSeparatorChildGroups_;
486 std::vector<std::vector<DenseIndex>> sameSeparatorParentIndices_;
487 std::vector<std::vector<DenseIndex>> sameSeparatorParentScalarOffsets_;
488 std::vector<SymmetricBlockMatrix> sameSeparatorInfos_;
489 std::vector<uint8_t> childInSameSeparatorGroup_;
490
491 struct ParentGatherPlan;
492 // Built after deferred modes resolve and reused across numerical reloads.
493 std::shared_ptr<ParentGatherPlan> parentGatherPlan_;
494
495 // Lazily allocated after load-plan construction. Direct batch factors need
496 // no rows; QR additionally reserves frontal damping rows.
497 VerticalBlockMatrix Ab_;
498
499 // Cached factorization storage reused by parent updates and result exports.
500 mutable VerticalBlockMatrix RSd_;
501 mutable SymmetricBlockMatrix info_;
502
503 // Elimination-time state.
504 bool RSdReady_ = false;
505 bool infoReady_ = false;
506
507 // Solve-time scratch space.
508 Vector rhsScratch_;
509 Vector separatorScratch_;
510
511 // Solve-time cached error contributions.
512 double lastOldError_ = 0.0;
513 double lastNewError_ = 0.0;
514};
515
516std::ostream& operator<<(std::ostream& os, const MultifrontalClique& clique);
517
518} // namespace gtsam
A matrix with column blocks of pre-defined sizes.
Access to matrices via blocks of pre-defined sizes.
size_t sumDims(const KeyDimMap &dims, const KeyRange &keys)
Sum variable dimensions for a key range, skipping unknown keys.
Definition MultifrontalClique.h:57
Linear Factor Graph where all factors are Gaussians.
Parameters for the imperative multifrontal solver.
A factor with a quadratic error function - a Gaussian.
Factor Graph Values.
Parameters controlling LM-style damping for NonlinearMultifrontalSolver.
Global functions in a separate testing namespace.
Definition chartTesting.h:28
KeyFormatter DefaultKeyFormatter
Assign default key formatter.
Definition Key.cpp:30
FastVector< Key > KeyVector
Define collection type once and for all - also used in wrappers.
Definition Key.h:91
void print(const Matrix &A, const string &s, ostream &stream)
print without optional string, must specify cout yourself
Definition Matrix.cpp:143
std::function< std::string(Key)> KeyFormatter
Typedef for a function to format a key, i.e. to convert it to a string.
Definition Key.h:35
std::map< Key, size_t > KeyDimMap
Map from variable key to dimension.
Definition MultifrontalClique.h:51
std::uint64_t Key
Integer nonlinear key type.
Definition types.h:43
This class stores a dense matrix and allows it to be accessed as a collection of blocks.
Definition SymmetricBlockMatrix.h:80
This class stores a dense matrix and allows it to be accessed as a collection of vertical blocks.
Definition VerticalBlockMatrix.h:47
Common interface for compact batch Jacobian factors.
Definition BatchJacobianFactor.h:78
A GaussianConditional functions as the node in a Bayes network.
Definition GaussianConditional.h:43
A Linear Factor Graph is a factor graph where all factors are Gaussian, i.e.
Definition GaussianFactorGraph.h:77
A Gaussian factor using the canonical parameters (information form).
Definition HessianFactor.h:101
A Gaussian factor in the squared-error form.
Definition JacobianFactor.h:92
Imperative multifrontal clique structure used by MultifrontalSolver.
Definition MultifrontalClique.h:71
const SymmetricBlockMatrix & info() const
Get the information matrix (const).
Definition MultifrontalClique.h:199
void addExactDiagonalDamping(double lambda, const VectorValues &hessianDiagonal, double minDiagonal, double maxDiagonal)
Add diagonal damping to the frontal block using an externally provided Hessian diagonal diag(J^T J) k...
Definition MultifrontalClique.cpp:1064
int problemSize() const
Return the clique dimension used for traversal scheduling.
Definition MultifrontalClique.h:170
void addIdentityDamping(double lambda)
Add identity damping to the frontal block.
Definition MultifrontalClique.cpp:1027
Children children
Child cliques used for traversal.
Definition MultifrontalClique.h:81
const VerticalBlockMatrix & Ab() const
Get the vertical block matrix Ab.
Definition MultifrontalClique.h:196
const KeyVector & orderedKeys() const
Return keys ordered by block index (frontals followed by separators).
Definition MultifrontalClique.h:181
size_t separatorDim
Separator dimension.
Definition MultifrontalClique.h:83
void fillAb(const GaussianFactorGraph &graph)
Load factor values into a lazily allocated, reusable Ab matrix.
Definition MultifrontalClique.cpp:688
bool useCompactCholesky() const
Check if this leaf avoids materializing its separator Hessian.
Definition MultifrontalClique.h:205
size_t numFrontals() const
Return the number of frontal keys in this clique.
Definition MultifrontalClique.h:175
bool useQR() const
Check if this clique is using QR elimination.
Definition MultifrontalClique.h:202
bool fullyEliminated() const
Return whether every symbolic frontal in this clique is eliminated.
Definition MultifrontalClique.h:178
size_t frontalDim
Frontal dimension.
Definition MultifrontalClique.h:82
double lastOldError() const
Access the last old error computed during updateSolution().
Definition MultifrontalClique.h:254
void prepareForElimination()
Zero out the info matrix, re-add Hessians, accumulate Jacobians and children.
Definition MultifrontalClique.cpp:788
MultifrontalClique(std::vector< size_t > factorIndices, const std::weak_ptr< MultifrontalClique > &parent, const KeyVector &frontals, const KeySet &separatorKeys, const KeyDimMap &dims, size_t vbmRows, VectorValues *solution, const std::unordered_set< Key > *fixedKeys, size_t numEliminatedFrontals)
Construct a clique from factor indices and cache static structure.
Definition MultifrontalClique.cpp:164
void addDiagonalDamping(double lambda, double minDiagonal, double maxDiagonal)
Add diagonal damping to the frontal block.
Definition MultifrontalClique.cpp:1043
std::weak_ptr< MultifrontalClique > parent
Parent clique.
Definition MultifrontalClique.h:80
void finalize(std::vector< ChildInfo > children, const MultifrontalParameters &params)
Cache the children list, compute parent indices, and lock in QR usage.
Definition MultifrontalClique.cpp:236
double lastNewError() const
Access the last new error computed during updateSolution().
Definition MultifrontalClique.h:257
void factorize()
Perform Cholesky factorization on the frontal block.
Definition MultifrontalClique.cpp:902
Definition MultifrontalClique.h:75
Parameters for gtsam::MultifrontalSolver.
Definition MultifrontalParameters.h:37
VectorValues represents a collection of vector-valued variables associated each with a unique integer...
Definition VectorValues.h:73
Parameters controlling LM-style damping as applied by gtsam::NonlinearMultifrontalSolver.
Definition LMDampingParams.h:31
The Factor::error simply extracts the.