Merge branch 'slotMethod' into feature/LinearSolverCleanup
commit
6f78e00812
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
@ -61,7 +62,8 @@ Scatter::Scatter(const GaussianFactorGraph& gfg,
|
||||||
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++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,9 +71,22 @@ Scatter::Scatter(const GaussianFactorGraph& gfg,
|
||||||
// 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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue