32 template class BayesTreeCliqueBase<ISAM2Clique, GaussianFactorGraph>;
35 void ISAM2Clique::setEliminationResult(
37 conditional_ = eliminationResult.first;
38 cachedFactor_ = eliminationResult.second;
40 gradientContribution_.resize(conditional_->cols() - 1);
43 gradientContribution_ << -conditional_->R().transpose() *
45 -conditional_->S().transpose() * conditional_->d();
50 return Base::equals(
other) &&
51 ((!cachedFactor_ && !
other.cachedFactor_) ||
52 (cachedFactor_ &&
other.cachedFactor_ &&
53 cachedFactor_->equals(*
other.cachedFactor_,
tol)));
60 cachedFactor_->print(
s +
"Cached: ",
formatter);
62 cout <<
s <<
"Cached empty" << endl;
63 if (gradientContribution_.rows() != 0)
64 gtsam::print(gradientContribution_,
"Gradient contribution: ");
68 bool ISAM2Clique::isDirty(
const KeySet& replaced,
const KeySet& changed)
const {
74 bool dirty = replaced.
exists(conditional_->frontals().front());
75 #if !defined(NDEBUG) && defined(GTSAM_EXTRA_CONSISTENCY_CHECKS)
76 for (
Key frontal : conditional_->frontals()) {
77 assert(dirty == replaced.
exists(frontal));
83 for (
Key parent : conditional_->parents()) {
84 if (changed.
exists(parent)) {
99 #ifdef USE_BROKEN_FAST_BACKSUBSTITUTE
107 if (solnPointers_.empty() && (isRoot() || !parent->solnPointers_.empty())) {
108 for (
Key frontal : conditional_->frontals())
109 solnPointers_.emplace(frontal,
delta->find(frontal));
110 for (
Key parentKey : conditional_->parents()) {
111 assert(parent->solnPointers_.exists(parentKey));
112 solnPointers_.emplace(parentKey, parent->solnPointers_.at(parentKey));
118 if (!solnPointers_.empty()) {
126 parentPointers.reserve(conditional_->nrParents());
127 for (
Key parent : conditional_->parents()) {
128 parentPointers.push_back(solnPointers_.at(parent));
129 dim += parentPointers.back()->second.size();
136 const Vector& parentVector = parentPointer->second;
137 xS.block(vectorPos, 0, parentVector.size(), 1) =
138 parentVector.block(0, 0, parentVector.size(), 1);
139 vectorPos += parentVector.size();
147 const Vector rhs =
c.getb() -
c.S() * xS;
151 if (solution.hasNaN())
157 frontal !=
c.endFrontals(); ++frontal) {
158 solnPointers_.at(*frontal)->second =
159 solution.segment(vectorPosition,
c.getDim(frontal));
160 vectorPosition +=
c.getDim(frontal);
172 bool ISAM2Clique::valuesChanged(
const KeySet& replaced,
173 const Vector& originalValues,
175 double threshold)
const {
176 auto frontals = conditional_->frontals();
177 if (replaced.
exists(frontals.front()))
return true;
178 Vector diff = originalValues -
delta.vector(frontals);
184 void ISAM2Clique::markFrontalsAsChanged(
KeySet* changed)
const {
185 for (
Key frontal : conditional_->frontals()) {
186 changed->insert(frontal);
191 void ISAM2Clique::restoreFromOriginals(
const Vector& originalValues,
194 for (
Key frontal : conditional_->frontals()) {
195 auto v =
delta->at(frontal);
196 v = originalValues.segment(
pos,
v.size());
205 size_t* count)
const {
206 if (isDirty(replaced, *changed)) {
208 auto originalValues =
delta->vector(conditional_->frontals());
211 fastBackSubstitute(
delta);
212 count += conditional_->nrFrontals();
214 if (valuesChanged(replaced, originalValues, *
delta, threshold)) {
215 markFrontalsAsChanged(changed);
217 restoreFromOriginals(originalValues,
delta);
221 for (
const auto& child : children) {
222 child->optimizeWildfire(replaced, threshold, changed,
delta, count);
232 if (root) root->optimizeWildfire(
keys, threshold, &changed,
delta, &count);
237 bool ISAM2Clique::optimizeWildfireNode(
const KeySet& replaced,
double threshold,
239 size_t* count)
const {
242 bool dirty = isDirty(replaced, *changed);
245 auto originalValues =
delta->vector(conditional_->frontals());
248 fastBackSubstitute(
delta);
249 *count += conditional_->nrFrontals();
251 if (valuesChanged(replaced, originalValues, *
delta, threshold)) {
252 markFrontalsAsChanged(changed);
254 restoreFromOriginals(originalValues,
delta);
268 std::stack<ISAM2Clique::shared_ptr> travStack;
269 travStack.push(root);
271 while (!travStack.empty()) {
272 currentNode = travStack.top();
274 bool dirty = currentNode->optimizeWildfireNode(
keys, threshold, &changed,
277 for (
const auto& child : currentNode->children) {
278 travStack.push(child);
288 void ISAM2Clique::nnz_internal(
size_t*
result)
const {
289 size_t dimR = conditional_->rows();
290 size_t dimSep = conditional_->S().cols();
291 *
result += ((dimR + 1) * dimR) / 2 + dimSep * dimR;
293 for (
const auto& child : children) {
294 child->nnz_internal(
result);
299 size_t ISAM2Clique::calculate_nnz()
const {
307 static const bool debug =
false;
310 for (
Key key : conditional_->parents()) {
318 keys->insert(conditional_->beginFrontals(), conditional_->endFrontals());
320 if (
debug) cout <<
"so marking key " << conditional_->front() << endl;
322 for (
const auto& child : children) {
323 child->findAll(markedMask,
keys);
331 for (
auto it = conditional_->begin(); it != conditional_->end(); ++it) {
332 const DenseIndex dim = conditional_->getDim(it);
333 const Vector contribution = gradientContribution_.segment(
position, dim);
334 auto [values_it, success] =
g->tryInsert(*it, contribution);
335 if (!success) values_it->second += contribution;
340 for (
const auto& child : children) {
341 child->addGradientAtZero(
g);