Added fastBackSubstitute method
parent
5223713c18
commit
ba64402985
|
@ -207,6 +207,80 @@ bool ISAM2Clique::isDirty(const KeySet& replaced, const KeySet& changed) const {
|
||||||
return dirty;
|
return dirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
/**
|
||||||
|
* Back-substitute - special version stores solution pointers in cliques for
|
||||||
|
* fast access.
|
||||||
|
*/
|
||||||
|
void ISAM2Clique::fastBackSubstitute(VectorValues* delta) const {
|
||||||
|
// TODO(gareth): This code shares a lot of logic w/ linearAlgorithms-inst,
|
||||||
|
// potentially refactor
|
||||||
|
|
||||||
|
// Create solution part pointers if necessary and possible - necessary if
|
||||||
|
// solnPointers_ is empty, and possible if either we're a root, or we have
|
||||||
|
// a parent with valid solnPointers_.
|
||||||
|
ISAM2::sharedClique parent = parent_.lock();
|
||||||
|
if (solnPointers_.empty() && (isRoot() || !parent->solnPointers_.empty())) {
|
||||||
|
for (Key frontal : conditional_->frontals())
|
||||||
|
solnPointers_.emplace(frontal, delta->find(frontal));
|
||||||
|
for (Key parentKey : conditional_->parents()) {
|
||||||
|
assert(parent->solnPointers_.exists(parentKey));
|
||||||
|
solnPointers_.emplace(parentKey, parent->solnPointers_.at(parentKey));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if we can use solution part pointers - we can if they either
|
||||||
|
// already existed or were created above.
|
||||||
|
if (!solnPointers_.empty()) {
|
||||||
|
GaussianConditional& c = *conditional_;
|
||||||
|
// Solve matrix
|
||||||
|
Vector xS;
|
||||||
|
{
|
||||||
|
// Count dimensions of vector
|
||||||
|
DenseIndex dim = 0;
|
||||||
|
FastVector<VectorValues::const_iterator> parentPointers;
|
||||||
|
parentPointers.reserve(conditional_->nrParents());
|
||||||
|
for (Key parent : conditional_->parents()) {
|
||||||
|
parentPointers.push_back(solnPointers_.at(parent));
|
||||||
|
dim += parentPointers.back()->second.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill parent vector
|
||||||
|
xS.resize(dim);
|
||||||
|
DenseIndex vectorPos = 0;
|
||||||
|
for (const VectorValues::const_iterator& parentPointer : parentPointers) {
|
||||||
|
const Vector& parentVector = parentPointer->second;
|
||||||
|
xS.block(vectorPos, 0, parentVector.size(), 1) =
|
||||||
|
parentVector.block(0, 0, parentVector.size(), 1);
|
||||||
|
vectorPos += parentVector.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE(gareth): We can no longer write: xS = b - S * xS
|
||||||
|
// This is because Eigen (as of 3.3) no longer evaluates S * xS into
|
||||||
|
// a temporary, and the operation trashes valus in xS.
|
||||||
|
// See: http://eigen.tuxfamily.org/index.php?title=3.3
|
||||||
|
const Vector rhs = c.getb() - c.get_S() * xS;
|
||||||
|
const Vector solution = c.get_R().triangularView<Eigen::Upper>().solve(rhs);
|
||||||
|
|
||||||
|
// Check for indeterminant solution
|
||||||
|
if (solution.hasNaN())
|
||||||
|
throw IndeterminantLinearSystemException(c.keys().front());
|
||||||
|
|
||||||
|
// Insert solution into a VectorValues
|
||||||
|
DenseIndex vectorPosition = 0;
|
||||||
|
for (GaussianConditional::const_iterator frontal = c.beginFrontals();
|
||||||
|
frontal != c.endFrontals(); ++frontal) {
|
||||||
|
solnPointers_.at(*frontal)->second =
|
||||||
|
solution.segment(vectorPosition, c.getDim(frontal));
|
||||||
|
vectorPosition += c.getDim(frontal);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Just call plain solve because we couldn't use solution pointers.
|
||||||
|
delta->update(conditional_->solve(*delta));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
bool ISAM2Clique::valuesChanged(const KeySet& replaced,
|
bool ISAM2Clique::valuesChanged(const KeySet& replaced,
|
||||||
const Vector& originalValues,
|
const Vector& originalValues,
|
||||||
|
@ -273,76 +347,7 @@ bool ISAM2Clique::optimizeWildfireNode(const KeySet& replaced, double threshold,
|
||||||
// Temporary copy of the original values, to check how much they change
|
// Temporary copy of the original values, to check how much they change
|
||||||
auto originalValues = delta->vector(conditional_->frontals());
|
auto originalValues = delta->vector(conditional_->frontals());
|
||||||
|
|
||||||
// Back-substitute - special version stores solution pointers in cliques for
|
fastBackSubstitute(delta);
|
||||||
// fast access.
|
|
||||||
{
|
|
||||||
// Create solution part pointers if necessary and possible - necessary if
|
|
||||||
// solnPointers_ is empty, and possible if either we're a root, or we have
|
|
||||||
// a parent with valid solnPointers_.
|
|
||||||
ISAM2::sharedClique parent = parent_.lock();
|
|
||||||
if (solnPointers_.empty() &&
|
|
||||||
(isRoot() || !parent->solnPointers_.empty())) {
|
|
||||||
for (Key frontal : conditional_->frontals())
|
|
||||||
solnPointers_.emplace(frontal, delta->find(frontal));
|
|
||||||
for (Key parentKey : conditional_->parents()) {
|
|
||||||
assert(parent->solnPointers_.exists(parentKey));
|
|
||||||
solnPointers_.emplace(parentKey, parent->solnPointers_.at(parentKey));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// See if we can use solution part pointers - we can if they either
|
|
||||||
// already existed or were created above.
|
|
||||||
if (!solnPointers_.empty()) {
|
|
||||||
GaussianConditional& c = *conditional_;
|
|
||||||
// Solve matrix
|
|
||||||
Vector xS;
|
|
||||||
{
|
|
||||||
// Count dimensions of vector
|
|
||||||
DenseIndex dim = 0;
|
|
||||||
FastVector<VectorValues::const_iterator> parentPointers;
|
|
||||||
parentPointers.reserve(conditional_->nrParents());
|
|
||||||
for (Key parent : conditional_->parents()) {
|
|
||||||
parentPointers.push_back(solnPointers_.at(parent));
|
|
||||||
dim += parentPointers.back()->second.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill parent vector
|
|
||||||
xS.resize(dim);
|
|
||||||
DenseIndex vectorPos = 0;
|
|
||||||
for (const VectorValues::const_iterator& parentPointer :
|
|
||||||
parentPointers) {
|
|
||||||
const Vector& parentVector = parentPointer->second;
|
|
||||||
xS.block(vectorPos, 0, parentVector.size(), 1) =
|
|
||||||
parentVector.block(0, 0, parentVector.size(), 1);
|
|
||||||
vectorPos += parentVector.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE(gareth): We can no longer write: xS = b - S * xS
|
|
||||||
// This is because Eigen (as of 3.3) no longer evaluates S * xS into
|
|
||||||
// a temporary, and the operation trashes valus in xS.
|
|
||||||
// See: http://eigen.tuxfamily.org/index.php?title=3.3
|
|
||||||
const Vector rhs = c.getb() - c.get_S() * xS;
|
|
||||||
const Vector solution =
|
|
||||||
c.get_R().triangularView<Eigen::Upper>().solve(rhs);
|
|
||||||
|
|
||||||
// Check for indeterminant solution
|
|
||||||
if (solution.hasNaN())
|
|
||||||
throw IndeterminantLinearSystemException(c.keys().front());
|
|
||||||
|
|
||||||
// Insert solution into a VectorValues
|
|
||||||
DenseIndex vectorPosition = 0;
|
|
||||||
for (GaussianConditional::const_iterator frontal = c.beginFrontals();
|
|
||||||
frontal != c.endFrontals(); ++frontal) {
|
|
||||||
solnPointers_.at(*frontal)->second =
|
|
||||||
solution.segment(vectorPosition, c.getDim(frontal));
|
|
||||||
vectorPosition += c.getDim(frontal);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Just call plain solve because we couldn't use solution pointers.
|
|
||||||
delta->update(conditional_->solve(*delta));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
count += conditional_->nrFrontals();
|
count += conditional_->nrFrontals();
|
||||||
|
|
||||||
if (valuesChanged(replaced, originalValues, *delta, threshold)) {
|
if (valuesChanged(replaced, originalValues, *delta, threshold)) {
|
||||||
|
|
|
@ -568,6 +568,12 @@ class GTSAM_EXPORT ISAM2Clique
|
||||||
*/
|
*/
|
||||||
bool isDirty(const KeySet& replaced, const KeySet& changed) const;
|
bool isDirty(const KeySet& replaced, const KeySet& changed) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Back-substitute - special version stores solution pointers in cliques for
|
||||||
|
* fast access.
|
||||||
|
*/
|
||||||
|
void fastBackSubstitute(VectorValues* delta) const;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check whether the values changed above a threshold, or always true if the
|
* Check whether the values changed above a threshold, or always true if the
|
||||||
* clique was replaced.
|
* clique was replaced.
|
||||||
|
|
Loading…
Reference in New Issue