133 lines
4.7 KiB
C++
133 lines
4.7 KiB
C++
/**
|
|
* @file bayesTreeOperations.cpp
|
|
*
|
|
* @date Jun 22, 2012
|
|
* @author Alex Cunningham
|
|
*/
|
|
|
|
#include <gtsam_unstable/linear/bayesTreeOperations.h>
|
|
|
|
#include <boost/foreach.hpp>
|
|
|
|
using namespace std;
|
|
|
|
namespace gtsam {
|
|
|
|
/* ************************************************************************* */
|
|
std::set<Index> keysToIndices(const KeySet& keys, const OrderingOrdered& ordering) {
|
|
std::set<Index> result;
|
|
BOOST_FOREACH(const Key& key, keys)
|
|
result.insert(ordering[key]);
|
|
return result;
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
GaussianFactorGraphOrdered splitFactors(const GaussianFactorGraphOrdered& fullgraph) {
|
|
GaussianFactorGraphOrdered result;
|
|
BOOST_FOREACH(const GaussianFactorOrdered::shared_ptr& factor, fullgraph) {
|
|
GaussianFactorGraphOrdered split = splitFactor(factor);
|
|
result.push_back(split);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
GaussianFactorGraphOrdered splitFactor(const GaussianFactorOrdered::shared_ptr& factor) {
|
|
GaussianFactorGraphOrdered result;
|
|
if (!factor) return result;
|
|
|
|
// Needs to be a jacobian factor - just pass along hessians
|
|
JacobianFactorOrdered::shared_ptr jf = boost::dynamic_pointer_cast<JacobianFactorOrdered>(factor);
|
|
if (!jf) {
|
|
result.push_back(factor);
|
|
return result;
|
|
}
|
|
|
|
// Loop over variables and strip off factors using split conditionals
|
|
// Assumes upper triangular structure
|
|
JacobianFactorOrdered::const_iterator rowIt, colIt;
|
|
const size_t totalRows = jf->rows();
|
|
size_t rowsRemaining = totalRows;
|
|
for (rowIt = jf->begin(); rowIt != jf->end() && rowsRemaining > 0; ++rowIt) {
|
|
// get dim of current variable
|
|
size_t varDim = jf->getDim(rowIt);
|
|
size_t startRow = totalRows - rowsRemaining;
|
|
size_t nrRows = std::min(rowsRemaining, varDim);
|
|
|
|
// Extract submatrices
|
|
std::vector<std::pair<Index, Matrix> > matrices;
|
|
for (colIt = rowIt; colIt != jf->end(); ++colIt) {
|
|
Index idx = *colIt;
|
|
const Matrix subA = jf->getA(colIt).middleRows(startRow, nrRows);
|
|
matrices.push_back(make_pair(idx, subA));
|
|
}
|
|
|
|
Vector subB = jf->getb().segment(startRow, nrRows);
|
|
Vector sigmas = jf->get_model()->sigmas().segment(startRow, nrRows);
|
|
SharedDiagonal model;
|
|
if (jf->get_model()->isConstrained())
|
|
model = noiseModel::Constrained::MixedSigmas(sigmas);
|
|
else
|
|
model = noiseModel::Diagonal::Sigmas(sigmas);
|
|
|
|
// extract matrices from each
|
|
// assemble into new JacobianFactor
|
|
result.add(matrices, subB, model);
|
|
|
|
rowsRemaining -= nrRows;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
GaussianFactorGraphOrdered removePriors(const GaussianFactorGraphOrdered& fullgraph) {
|
|
GaussianFactorGraphOrdered result;
|
|
BOOST_FOREACH(const GaussianFactorOrdered::shared_ptr& factor, fullgraph) {
|
|
JacobianFactorOrdered::shared_ptr jf = boost::dynamic_pointer_cast<JacobianFactorOrdered>(factor);
|
|
if (factor && (!jf || jf->size() > 1))
|
|
result.push_back(factor);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
void findCliques(const GaussianBayesTreeOrdered::sharedClique& current_clique,
|
|
std::set<GaussianConditionalOrdered::shared_ptr>& result) {
|
|
// Add the current clique
|
|
result.insert(current_clique->conditional());
|
|
|
|
// Add the parent if not root
|
|
if (!current_clique->isRoot())
|
|
findCliques(current_clique->parent(), result);
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
std::set<GaussianConditionalOrdered::shared_ptr> findAffectedCliqueConditionals(
|
|
const GaussianBayesTreeOrdered& bayesTree, const std::set<Index>& savedIndices) {
|
|
std::set<GaussianConditionalOrdered::shared_ptr> affected_cliques;
|
|
// FIXME: track previously found keys more efficiently
|
|
BOOST_FOREACH(const Index& index, savedIndices) {
|
|
GaussianBayesTreeOrdered::sharedClique clique = bayesTree.nodes()[index];
|
|
|
|
// add path back to root to affected set
|
|
findCliques(clique, affected_cliques);
|
|
}
|
|
return affected_cliques;
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
std::deque<GaussianBayesTreeOrdered::sharedClique>
|
|
findPathCliques(const GaussianBayesTreeOrdered::sharedClique& initial) {
|
|
std::deque<GaussianBayesTreeOrdered::sharedClique> result, parents;
|
|
if (initial->isRoot())
|
|
return result;
|
|
result.push_back(initial->parent());
|
|
parents = findPathCliques(initial->parent());
|
|
result.insert(result.end(), parents.begin(), parents.end());
|
|
return result;
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
} // \namespace gtsam
|
|
|