Merge branch 'slotMethod' into feature/LinearSolverCleanup

release/4.3a0
Frank Dellaert 2015-06-13 09:17:18 -07:00
commit 6f78e00812
5 changed files with 50 additions and 46 deletions

View File

@ -349,21 +349,12 @@ double HessianFactor::error(const VectorValues& c) const {
void HessianFactor::updateHessian(const Scatter& scatter, void HessianFactor::updateHessian(const Scatter& scatter,
SymmetricBlockMatrix* info) const { SymmetricBlockMatrix* info) const {
gttic(updateHessian_HessianFactor); gttic(updateHessian_HessianFactor);
// N is number of variables in information matrix, n in HessianFactor
DenseIndex N = info->nBlocks() - 1, n = size();
// First build an array of slots
FastVector<DenseIndex> slots(n + 1);
DenseIndex slot = 0;
BOOST_FOREACH (Key key, *this)
slots[slot++] = scatter.at(key).slot;
slots[n] = N;
// Apply updates to the upper triangle // Apply updates to the upper triangle
DenseIndex n = size(), N = info->nBlocks()-1;
for (DenseIndex j = 0; j <= n; ++j) { for (DenseIndex j = 0; j <= n; ++j) {
DenseIndex J = slots[j]; const DenseIndex J = j==n ? N : scatter.slot(keys_[j]);
for (DenseIndex i = 0; i <= j; ++i) { for (DenseIndex i = 0; i <= j; ++i) {
DenseIndex I = slots[i]; const DenseIndex I = i==n ? N : scatter.slot(keys_[i]);
(*info)(I, J) += info_(i, j); (*info)(I, J) += info_(i, j);
} }
} }

View File

@ -515,23 +515,15 @@ void JacobianFactor::updateHessian(const Scatter& scatter,
whitenedFactor.updateHessian(scatter, info); whitenedFactor.updateHessian(scatter, info);
} else { } else {
// Ab_ is the augmented Jacobian matrix A, and we perform I += A'*A below // Ab_ is the augmented Jacobian matrix A, and we perform I += A'*A below
// N is number of variables in information matrix, n in JacobianFactor DenseIndex n = Ab_.nBlocks() - 1, N = info->nBlocks() - 1;
DenseIndex N = info->nBlocks() - 1, n = Ab_.nBlocks() - 1;
// First build an array of slots
FastVector<DenseIndex> slots(n + 1);
DenseIndex slot = 0;
BOOST_FOREACH (Key key, *this)
slots[slot++] = scatter.at(key).slot;
slots[n] = N;
// Apply updates to the upper triangle // Apply updates to the upper triangle
// Loop over blocks of A, including RHS with j==n // Loop over blocks of A, including RHS with j==n
for (DenseIndex j = 0; j <= n; ++j) { for (DenseIndex j = 0; j <= n; ++j) {
DenseIndex J = slots[j]; const DenseIndex J = j==n ? N : scatter.slot(keys_[j]);
// Fill off-diagonal blocks with Ai'*Aj // Fill off-diagonal blocks with Ai'*Aj
for (DenseIndex i = 0; i < j; ++i) { for (DenseIndex i = 0; i < j; ++i) {
DenseIndex I = slots[i]; const DenseIndex I = scatter.slot(keys_[i]);
(*info)(I, J).knownOffDiagonal() += Ab_(i).transpose() * Ab_(j); (*info)(I, J).knownOffDiagonal() += Ab_(i).transpose() * Ab_(j);
} }
// Fill diagonal block with Aj'*Aj // Fill diagonal block with Aj'*Aj

View File

@ -36,14 +36,15 @@ string SlotEntry::toString() const {
Scatter::Scatter(const GaussianFactorGraph& gfg, Scatter::Scatter(const GaussianFactorGraph& gfg,
boost::optional<const Ordering&> ordering) { boost::optional<const Ordering&> ordering) {
gttic(Scatter_Constructor); gttic(Scatter_Constructor);
static const size_t none = std::numeric_limits<size_t>::max(); static const DenseIndex none = std::numeric_limits<size_t>::max();
// First do the set union. // First do the set union.
BOOST_FOREACH(const GaussianFactor::shared_ptr& factor, gfg) { BOOST_FOREACH (const GaussianFactor::shared_ptr& factor, gfg) {
if (factor) { if (factor) {
for (GaussianFactor::const_iterator variable = factor->begin(); for (GaussianFactor::const_iterator variable = factor->begin();
variable != factor->end(); ++variable) { variable != factor->end(); ++variable) {
// TODO: Fix this hack to cope with zero-row Jacobians that come from BayesTreeOrphanWrappers // TODO: Fix this hack to cope with zero-row Jacobians that come from
// BayesTreeOrphanWrappers
const JacobianFactor* asJacobian = const JacobianFactor* asJacobian =
dynamic_cast<const JacobianFactor*>(factor.get()); dynamic_cast<const JacobianFactor*>(factor.get());
if (!asJacobian || asJacobian->cols() > 1) if (!asJacobian || asJacobian->cols() > 1)
@ -56,22 +57,36 @@ Scatter::Scatter(const GaussianFactorGraph& gfg,
// If we have an ordering, pre-fill the ordered variables first // If we have an ordering, pre-fill the ordered variables first
size_t slot = 0; size_t slot = 0;
if (ordering) { if (ordering) {
BOOST_FOREACH(Key key, *ordering) { BOOST_FOREACH (Key key, *ordering) {
const_iterator entry = find(key); const_iterator entry = find(key);
if (entry == end()) if (entry == end())
throw std::invalid_argument( throw std::invalid_argument(
"The ordering provided to the HessianFactor Scatter constructor\n" "The ordering provided to the HessianFactor Scatter constructor\n"
"contained extra variables that did not appear in the factors to combine."); "contained extra variables that did not appear in the factors to "
"combine.");
at(key).slot = (slot++); at(key).slot = (slot++);
} }
} }
// Next fill in the slot indices (we can only get these after doing the set // Next fill in the slot indices (we can only get these after doing the set
// union. // union.
BOOST_FOREACH(value_type& var_slot, *this) { BOOST_FOREACH (value_type& var_slot, *this) {
if (var_slot.second.slot == none) if (var_slot.second.slot == none) var_slot.second.slot = (slot++);
var_slot.second.slot = (slot++);
} }
} }
/* ************************************************************************* */
FastVector<DenseIndex> Scatter::getSlotsForKeys(
const FastVector<Key>& keys) const {
gttic(getSlotsForKeys);
FastVector<DenseIndex> slots(keys.size() + 1);
DenseIndex slot = 0;
BOOST_FOREACH (Key key, keys)
slots[slot++] = at(key).slot;
slots.back() = size();
return slots;
}
/* ************************************************************************* */
} // gtsam } // gtsam

View File

@ -30,12 +30,11 @@ namespace gtsam {
class GaussianFactorGraph; class GaussianFactorGraph;
class Ordering; class Ordering;
/** /// One SlotEntry stores the slot index for a variable, as well its dimension.
* One SlotEntry stores the slot index for a variable, as well its dimension.
*/
struct GTSAM_EXPORT SlotEntry { struct GTSAM_EXPORT SlotEntry {
size_t slot, dimension; DenseIndex slot;
SlotEntry(size_t _slot, size_t _dimension) size_t dimension;
SlotEntry(DenseIndex _slot, size_t _dimension)
: slot(_slot), dimension(_dimension) {} : slot(_slot), dimension(_dimension) {}
std::string toString() const; std::string toString() const;
}; };
@ -43,14 +42,21 @@ struct GTSAM_EXPORT SlotEntry {
/** /**
* Scatter is an intermediate data structure used when building a HessianFactor * Scatter is an intermediate data structure used when building a HessianFactor
* incrementally, to get the keys in the right order. The "scatter" is a map * incrementally, to get the keys in the right order. The "scatter" is a map
* from * from global variable indices to slot indices in the union of involved
* global variable indices to slot indices in the union of involved variables. * variables. We also include the dimensionality of the variable.
* We also include the dimensionality of the variable.
*/ */
class Scatter : public FastMap<Key, SlotEntry> { class Scatter : public FastMap<Key, SlotEntry> {
public: public:
Scatter(const GaussianFactorGraph& gfg, Scatter(const GaussianFactorGraph& gfg,
boost::optional<const Ordering&> ordering = boost::none); boost::optional<const Ordering&> ordering = boost::none);
DenseIndex slot(Key key) const { return at(key).slot; }
/**
* For the subset of keys given, return the slots in the same order,
* terminated by the a RHS slot equal to N, the size of the Scatter
*/
FastVector<DenseIndex> getSlotsForKeys(const FastVector<Key>& keys) const;
}; };
} // \ namespace gtsam } // \ namespace gtsam

View File

@ -166,8 +166,8 @@ namespace gtsam {
DenseIndex N = info->nBlocks() - 1; DenseIndex N = info->nBlocks() - 1;
// First build an array of slots // First build an array of slots
DenseIndex slotC = scatter.at(this->keys().front()).slot; DenseIndex slotC = scatter.slot(keys_.front());
DenseIndex slotL = scatter.at(this->keys().back()).slot; DenseIndex slotL = scatter.slot(keys_.back());
DenseIndex slotB = N; DenseIndex slotB = N;
// We perform I += A'*A to the upper triangle // We perform I += A'*A to the upper triangle