Multifrontal QR using new solver interface
parent
31a080e4bf
commit
7c40fe32cf
|
@ -35,7 +35,7 @@ namespace lam = boost::lambda;
|
|||
#include <gtsam/base/FastSet.h>
|
||||
#include <gtsam/inference/BayesTree.h>
|
||||
#include <gtsam/inference/inference-inl.h>
|
||||
#include <gtsam/inference/GenericSequentialSolver.h>
|
||||
#include <gtsam/inference/GenericSequentialSolver-inl.h>
|
||||
|
||||
namespace gtsam {
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ namespace gtsam {
|
|||
|
||||
public:
|
||||
|
||||
typedef boost::shared_ptr<BayesTree<CONDITIONAL> > shared_ptr;
|
||||
typedef boost::shared_ptr<CONDITIONAL> sharedConditional;
|
||||
typedef boost::shared_ptr<BayesNet<CONDITIONAL> > sharedBayesNet;
|
||||
|
||||
|
|
|
@ -19,66 +19,19 @@ namespace gtsam {
|
|||
|
||||
/* ************************************************************************* */
|
||||
template<class FACTOR>
|
||||
GenericSequentialSolver<FACTOR>::GenericSequentialSolver(const FactorGraph<FACTOR>& factorGraph) :
|
||||
structure_(factorGraph),
|
||||
eliminationTree_(EliminationTree<FACTOR>::Create(factorGraph, structure_)) {
|
||||
factors_.push_back(factorGraph);
|
||||
GenericMultifrontalSolver<FACTOR>::GenericMultifrontalSolver(const FactorGraph<FACTOR>& factorGraph) :
|
||||
junctionTree_(new JunctionTree<FactorGraph<FACTOR> >(factorGraph)) {}
|
||||
|
||||
/* ************************************************************************* */
|
||||
template<class FACTOR>
|
||||
typename BayesTree<typename FACTOR::Conditional>::shared_ptr GenericMultifrontalSolver<FACTOR>::eliminate() const {
|
||||
return junctionTree_->eliminate();
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
template<class FACTOR>
|
||||
typename BayesNet<typename FACTOR::Conditional>::shared_ptr GenericSequentialSolver<FACTOR>::eliminate() const {
|
||||
return eliminationTree_->eliminate();
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
template<class FACTOR>
|
||||
typename FactorGraph<FACTOR>::shared_ptr GenericSequentialSolver<FACTOR>::joint(const std::vector<Index>& js) const {
|
||||
|
||||
// Compute a COLAMD permutation with the marginal variable constrained to the end.
|
||||
Permutation::shared_ptr permutation(Inference::PermutationCOLAMD(structure_, js));
|
||||
Permutation::shared_ptr permutationInverse(permutation->inverse());
|
||||
|
||||
// Permute the factors - NOTE that this permutes the original factors, not
|
||||
// copies. Other parts of the code may hold shared_ptr's to these factors so
|
||||
// we must undo the permutation before returning.
|
||||
BOOST_FOREACH(const typename FACTOR::shared_ptr& factor, factors_) {
|
||||
if(factor)
|
||||
factor->permuteWithInverse(*permutationInverse);
|
||||
}
|
||||
|
||||
// Eliminate all variables
|
||||
typename BayesNet<typename FACTOR::Conditional>::shared_ptr bayesNet(
|
||||
EliminationTree<FACTOR>::Create(factors_)->eliminate());
|
||||
|
||||
// Undo the permuation on the original factors and on the structure.
|
||||
BOOST_FOREACH(const typename FACTOR::shared_ptr& factor, factors_) {
|
||||
if(factor)
|
||||
factor->permuteWithInverse(*permutation);
|
||||
}
|
||||
|
||||
// Take the joint marginal from the Bayes net.
|
||||
typename FactorGraph<FACTOR>::shared_ptr joint(new FactorGraph<FACTOR>);
|
||||
joint->reserve(js.size());
|
||||
typename BayesNet<typename FACTOR::Conditional>::const_reverse_iterator conditional = bayesNet->rbegin();
|
||||
for(size_t i = 0; i < js.size(); ++i) {
|
||||
joint->push_back(typename FACTOR::shared_ptr(new FACTOR(**(conditional++)))); }
|
||||
|
||||
// Undo the permutation on the eliminated joint marginal factors
|
||||
BOOST_FOREACH(const typename FACTOR::shared_ptr& factor, *joint) {
|
||||
factor->permuteWithInverse(*permutation); }
|
||||
|
||||
return joint;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
template<class FACTOR>
|
||||
typename FACTOR::shared_ptr GenericSequentialSolver<FACTOR>::marginal(Index j) const {
|
||||
// Create a container for the one variable index
|
||||
vector<Index> js(1); js[0] = j;
|
||||
|
||||
// Call joint and return the only factor in the factor graph it returns
|
||||
return (*this->joint(js))[0];
|
||||
typename FACTOR::shared_ptr GenericMultifrontalSolver<FACTOR>::marginal(Index j) const {
|
||||
return eliminate()->marginal(j);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,14 +20,8 @@ class GenericMultifrontalSolver {
|
|||
|
||||
protected:
|
||||
|
||||
// Store the original factors for computing marginals
|
||||
FactorGraph<FACTOR> factors_;
|
||||
|
||||
// Column structure of the factor graph
|
||||
VariableIndex<> structure_;
|
||||
|
||||
// Elimination tree that performs elimination.
|
||||
typename JunctionTree<FactorGraph<FACTOR> >::shared_ptr eliminationTree_;
|
||||
typename JunctionTree<FactorGraph<FACTOR> >::shared_ptr junctionTree_;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -41,7 +35,7 @@ public:
|
|||
* Eliminate the factor graph sequentially. Uses a column elimination tree
|
||||
* to recursively eliminate.
|
||||
*/
|
||||
typename BayesNet<typename FACTOR::Conditional>::shared_ptr eliminate() const;
|
||||
typename BayesTree<typename FACTOR::Conditional>::shared_ptr eliminate() const;
|
||||
|
||||
/**
|
||||
* Compute the marginal Gaussian density over a variable, by integrating out
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include <gtsam/linear/GaussianConditional.h>
|
||||
#include <gtsam/linear/GaussianFactorGraph.h>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace gtsam {
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
@ -31,6 +33,7 @@ namespace gtsam {
|
|||
*/
|
||||
class GaussianJunctionTree: public JunctionTree<GaussianFactorGraph> {
|
||||
public:
|
||||
typedef boost::shared_ptr<GaussianJunctionTree> shared_ptr;
|
||||
typedef JunctionTree<GaussianFactorGraph> Base;
|
||||
typedef Base::sharedClique sharedClique;
|
||||
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* @file GaussianMultifrontalSolver.cpp
|
||||
* @brief
|
||||
* @author Richard Roberts
|
||||
* @created Oct 21, 2010
|
||||
*/
|
||||
|
||||
#include <gtsam/linear/GaussianMultifrontalSolver.h>
|
||||
|
||||
#include <gtsam/inference/GenericMultifrontalSolver-inl.h>
|
||||
|
||||
namespace gtsam {
|
||||
|
||||
/* ************************************************************************* */
|
||||
GaussianMultifrontalSolver::GaussianMultifrontalSolver(const FactorGraph<GaussianFactor>& factorGraph) :
|
||||
junctionTree_(new GaussianJunctionTree(factorGraph)) {}
|
||||
|
||||
/* ************************************************************************* */
|
||||
typename BayesTree<GaussianConditional>::sharedClique GaussianMultifrontalSolver::eliminate() const {
|
||||
return junctionTree_->eliminate();
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
VectorValues::shared_ptr GaussianMultifrontalSolver::optimize() const {
|
||||
return VectorValues::shared_ptr(new VectorValues(junctionTree_->optimize()));
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
GaussianFactor::shared_ptr GaussianMultifrontalSolver::marginal(Index j) const {
|
||||
BayesTree<GaussianConditional> bayesTree;
|
||||
bayesTree.insert(junctionTree_->eliminate());
|
||||
return bayesTree.marginal(j);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/**
|
||||
* @file GaussianMultifrontalSolver.h
|
||||
* @brief
|
||||
* @author Richard Roberts
|
||||
* @created Oct 21, 2010
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtsam/linear/GaussianJunctionTree.h>
|
||||
#include <gtsam/linear/GaussianBayesNet.h>
|
||||
#include <gtsam/linear/GaussianFactorGraph.h>
|
||||
#include <gtsam/linear/VectorValues.h>
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace gtsam {
|
||||
|
||||
/** This solver uses sequential variable elimination to solve a
|
||||
* GaussianFactorGraph, i.e. a sparse linear system. Underlying this is a
|
||||
* column elimination tree (inference/EliminationTree), see Gilbert 2001 BIT.
|
||||
*
|
||||
* The elimination ordering is "baked in" to the variable indices at this
|
||||
* stage, i.e. elimination proceeds in order from '0'. A fill-reducing
|
||||
* ordering is computed symbolically from the NonlinearFactorGraph, on the
|
||||
* nonlinear side of gtsam. (To be precise, it is possible to permute an
|
||||
* existing GaussianFactorGraph into a COLAMD ordering instead, this is done
|
||||
* when computing marginals).
|
||||
*
|
||||
* This is not the most efficient algorithm we provide, most efficient is the
|
||||
* MultifrontalSolver, which performs Multi-frontal QR factorization. However,
|
||||
* sequential variable elimination is easier to understand so this is a good
|
||||
* starting point to learn about these algorithms and our implementation.
|
||||
* Additionally, the first step of MFQR is symbolic sequential elimination.
|
||||
*
|
||||
* The EliminationTree recursively produces a BayesNet<GaussianFactor>,
|
||||
* typedef'ed in linear/GaussianBayesNet, on which this class calls
|
||||
* optimize(...) to perform back-substitution.
|
||||
*/
|
||||
class GaussianMultifrontalSolver {
|
||||
|
||||
protected:
|
||||
|
||||
GaussianJunctionTree::shared_ptr junctionTree_;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Construct the solver for a factor graph. This builds the elimination
|
||||
* tree, which already does some of the symbolic work of elimination.
|
||||
*/
|
||||
GaussianMultifrontalSolver(const FactorGraph<GaussianFactor>& factorGraph);
|
||||
|
||||
/**
|
||||
* Eliminate the factor graph sequentially. Uses a column elimination tree
|
||||
* to recursively eliminate.
|
||||
*/
|
||||
typename BayesTree<GaussianConditional>::sharedClique eliminate() const;
|
||||
|
||||
/**
|
||||
* Compute the least-squares solution of the GaussianFactorGraph. This
|
||||
* eliminates to create a BayesNet and then back-substitutes this BayesNet to
|
||||
* obtain the solution.
|
||||
*/
|
||||
VectorValues::shared_ptr optimize() const;
|
||||
|
||||
/**
|
||||
* Compute the marginal Gaussian density over a variable, by integrating out
|
||||
* all of the other variables. This function returns the result as an upper-
|
||||
* triangular R factor and right-hand-side, i.e. a GaussianConditional with
|
||||
* R*x = d. To get a mean and covariance matrix, use marginalStandard(...)
|
||||
*/
|
||||
GaussianFactor::shared_ptr marginal(Index j) const;
|
||||
|
||||
/**
|
||||
* Compute the marginal Gaussian density over a variable, by integrating out
|
||||
* all of the other variables. This function returns the result as a mean
|
||||
* vector and covariance matrix. Compared to marginalCanonical, which
|
||||
* returns a GaussianConditional, this function back-substitutes the R factor
|
||||
* to obtain the mean, then computes \Sigma = (R^T * R)^-1.
|
||||
*/
|
||||
// std::pair<Vector, Matrix> marginalStandard(Index j) const;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -8,8 +8,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <gtsam/inference/GenericSequentialSolver.h>
|
||||
#include <gtsam/inference/VariableIndex.h>
|
||||
#include <gtsam/inference/EliminationTree.h>
|
||||
#include <gtsam/linear/GaussianBayesNet.h>
|
||||
#include <gtsam/linear/GaussianFactorGraph.h>
|
||||
#include <gtsam/linear/VectorValues.h>
|
||||
|
@ -19,11 +17,6 @@
|
|||
|
||||
namespace gtsam {
|
||||
|
||||
|
||||
/** A GaussianEliminationTree is just a typedef of the template EliminationTree */
|
||||
typedef EliminationTree<GaussianFactor> GaussianEliminationTree;
|
||||
|
||||
|
||||
/** This solver uses sequential variable elimination to solve a
|
||||
* GaussianFactorGraph, i.e. a sparse linear system. Underlying this is a
|
||||
* column elimination tree (inference/EliminationTree), see Gilbert 2001 BIT.
|
||||
|
|
|
@ -22,7 +22,7 @@ check_PROGRAMS += tests/testVectorValues
|
|||
#check_PROGRAMS += tests/testVectorMap tests/testVectorBTree
|
||||
|
||||
# Solvers
|
||||
sources += GaussianSequentialSolver.cpp
|
||||
sources += GaussianSequentialSolver.cpp GaussianMultifrontalSolver.cpp
|
||||
|
||||
# Gaussian Factor Graphs
|
||||
headers += GaussianFactorSet.h Factorization.h
|
||||
|
|
Loading…
Reference in New Issue