Storing variable index in solver, saved between nonlinear iterations
parent
a124ce132f
commit
d6929d4409
|
|
@ -4,6 +4,7 @@
|
||||||
* @author Frank Dellaert
|
* @author Frank Dellaert
|
||||||
* @created Oct 13, 2010
|
* @created Oct 13, 2010
|
||||||
*/
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include <gtsam/base/timing.h>
|
#include <gtsam/base/timing.h>
|
||||||
#include <gtsam/inference/EliminationTree.h>
|
#include <gtsam/inference/EliminationTree.h>
|
||||||
|
|
|
||||||
|
|
@ -33,14 +33,31 @@ namespace gtsam {
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
template<class FACTOR, class JUNCTIONTREE>
|
template<class FACTOR, class JUNCTIONTREE>
|
||||||
GenericMultifrontalSolver<FACTOR, JUNCTIONTREE>::GenericMultifrontalSolver(const FactorGraph<FACTOR>& factorGraph) :
|
GenericMultifrontalSolver<FACTOR, JUNCTIONTREE>::GenericMultifrontalSolver(const FactorGraph<FACTOR>& factorGraph) :
|
||||||
junctionTree_(factorGraph) {}
|
structure_(new VariableIndex(factorGraph)), junctionTree_(new JUNCTIONTREE(factorGraph, *structure_)) {}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template<class FACTOR, class JUNCTIONTREE>
|
||||||
|
GenericMultifrontalSolver<FACTOR, JUNCTIONTREE>::GenericMultifrontalSolver(const typename FactorGraph<FACTOR>::shared_ptr& factorGraph) :
|
||||||
|
structure_(new VariableIndex(*factorGraph)), junctionTree_(new JUNCTIONTREE(*factorGraph, *structure_)) {}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template<class FACTOR, class JUNCTIONTREE>
|
||||||
|
GenericMultifrontalSolver<FACTOR, JUNCTIONTREE>::GenericMultifrontalSolver(
|
||||||
|
const typename FactorGraph<FACTOR>::shared_ptr& factorGraph, const VariableIndex::shared_ptr& variableIndex) :
|
||||||
|
structure_(variableIndex), junctionTree_(new JUNCTIONTREE(*factorGraph, *structure_)) {}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template<class FACTOR, class JUNCTIONTREE>
|
||||||
|
void GenericMultifrontalSolver<FACTOR, JUNCTIONTREE>::replaceFactors(const typename FactorGraph<FACTOR>::shared_ptr& factorGraph) {
|
||||||
|
junctionTree_.reset(new JUNCTIONTREE(*factorGraph, *structure_));
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
template<class FACTOR, class JUNCTIONTREE>
|
template<class FACTOR, class JUNCTIONTREE>
|
||||||
typename JUNCTIONTREE::BayesTree::shared_ptr
|
typename JUNCTIONTREE::BayesTree::shared_ptr
|
||||||
GenericMultifrontalSolver<FACTOR, JUNCTIONTREE>::eliminate() const {
|
GenericMultifrontalSolver<FACTOR, JUNCTIONTREE>::eliminate() const {
|
||||||
typename JUNCTIONTREE::BayesTree::shared_ptr bayesTree(new typename JUNCTIONTREE::BayesTree);
|
typename JUNCTIONTREE::BayesTree::shared_ptr bayesTree(new typename JUNCTIONTREE::BayesTree);
|
||||||
bayesTree->insert(junctionTree_.eliminate());
|
bayesTree->insert(junctionTree_->eliminate());
|
||||||
return bayesTree;
|
return bayesTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,17 +31,40 @@ class GenericMultifrontalSolver {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
// Column structure of the factor graph
|
||||||
|
VariableIndex::shared_ptr structure_;
|
||||||
|
|
||||||
// Junction tree that performs elimination.
|
// Junction tree that performs elimination.
|
||||||
JUNCTIONTREE junctionTree_;
|
typename JUNCTIONTREE::shared_ptr junctionTree_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct the solver for a factor graph. This builds the elimination
|
* Construct the solver for a factor graph. This builds the junction
|
||||||
* tree, which already does some of the symbolic work of elimination.
|
* tree, which already does some of the work of elimination.
|
||||||
*/
|
*/
|
||||||
GenericMultifrontalSolver(const FactorGraph<FACTOR>& factorGraph);
|
GenericMultifrontalSolver(const FactorGraph<FACTOR>& factorGraph);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct the solver for a factor graph. This builds the junction
|
||||||
|
* tree, which already does some of the work of elimination.
|
||||||
|
*/
|
||||||
|
GenericMultifrontalSolver(const typename FactorGraph<FACTOR>::shared_ptr& factorGraph);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct the solver with a shared pointer to a factor graph and to a
|
||||||
|
* VariableIndex. The solver will store these pointers, so this constructor
|
||||||
|
* is the fastest.
|
||||||
|
*/
|
||||||
|
GenericMultifrontalSolver(const typename FactorGraph<FACTOR>::shared_ptr& factorGraph, const VariableIndex::shared_ptr& variableIndex);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace the factor graph with a new one having the same structure. The
|
||||||
|
* This function can be used if the numerical part of the factors changes,
|
||||||
|
* such as during relinearization or adjusting of noise models.
|
||||||
|
*/
|
||||||
|
void replaceFactors(const typename FactorGraph<FACTOR>::shared_ptr& factorGraph);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Eliminate the factor graph sequentially. Uses a column elimination tree
|
* Eliminate the factor graph sequentially. Uses a column elimination tree
|
||||||
* to recursively eliminate.
|
* to recursively eliminate.
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,30 @@ namespace gtsam {
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
template<class FACTOR>
|
template<class FACTOR>
|
||||||
GenericSequentialSolver<FACTOR>::GenericSequentialSolver(const FactorGraph<FACTOR>& factorGraph) :
|
GenericSequentialSolver<FACTOR>::GenericSequentialSolver(const FactorGraph<FACTOR>& factorGraph) :
|
||||||
structure_(factorGraph),
|
factors_(new FactorGraph<FACTOR>(factorGraph)), structure_(new VariableIndex(factorGraph)),
|
||||||
eliminationTree_(EliminationTree<FACTOR>::Create(factorGraph, structure_)) {
|
eliminationTree_(EliminationTree<FACTOR>::Create(*factors_, *structure_)) {}
|
||||||
factors_.push_back(factorGraph);
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template<class FACTOR>
|
||||||
|
GenericSequentialSolver<FACTOR>::GenericSequentialSolver(const typename FactorGraph<FACTOR>::shared_ptr& factorGraph) :
|
||||||
|
factors_(factorGraph), structure_(new VariableIndex(*factorGraph)),
|
||||||
|
eliminationTree_(EliminationTree<FACTOR>::Create(*factors_, *structure_)) {}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template<class FACTOR>
|
||||||
|
GenericSequentialSolver<FACTOR>::GenericSequentialSolver(const typename FactorGraph<FACTOR>::shared_ptr& factorGraph,
|
||||||
|
const VariableIndex::shared_ptr& variableIndex) :
|
||||||
|
factors_(factorGraph), structure_(variableIndex),
|
||||||
|
eliminationTree_(EliminationTree<FACTOR>::Create(*factors_, *structure_)) {}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template<class FACTOR>
|
||||||
|
void GenericSequentialSolver<FACTOR>::replaceFactors(const typename FactorGraph<FACTOR>::shared_ptr& factorGraph) {
|
||||||
|
// Reset this shared pointer first to deallocate if possible - for big
|
||||||
|
// problems there may not be enough memory to store two copies.
|
||||||
|
eliminationTree_.reset();
|
||||||
|
factors_ = factorGraph;
|
||||||
|
eliminationTree_ = EliminationTree<FACTOR>::Create(*factors_, *structure_);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
@ -47,23 +68,23 @@ template<class FACTOR>
|
||||||
typename FactorGraph<FACTOR>::shared_ptr GenericSequentialSolver<FACTOR>::jointFactorGraph(const std::vector<Index>& js) const {
|
typename FactorGraph<FACTOR>::shared_ptr GenericSequentialSolver<FACTOR>::jointFactorGraph(const std::vector<Index>& js) const {
|
||||||
|
|
||||||
// Compute a COLAMD permutation with the marginal variable constrained to the end.
|
// Compute a COLAMD permutation with the marginal variable constrained to the end.
|
||||||
Permutation::shared_ptr permutation(Inference::PermutationCOLAMD(structure_, js));
|
Permutation::shared_ptr permutation(Inference::PermutationCOLAMD(*structure_, js));
|
||||||
Permutation::shared_ptr permutationInverse(permutation->inverse());
|
Permutation::shared_ptr permutationInverse(permutation->inverse());
|
||||||
|
|
||||||
// Permute the factors - NOTE that this permutes the original factors, not
|
// 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
|
// copies. Other parts of the code may hold shared_ptr's to these factors so
|
||||||
// we must undo the permutation before returning.
|
// we must undo the permutation before returning.
|
||||||
BOOST_FOREACH(const typename FACTOR::shared_ptr& factor, factors_) {
|
BOOST_FOREACH(const typename FACTOR::shared_ptr& factor, *factors_) {
|
||||||
if(factor)
|
if(factor)
|
||||||
factor->permuteWithInverse(*permutationInverse);
|
factor->permuteWithInverse(*permutationInverse);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Eliminate all variables
|
// Eliminate all variables
|
||||||
typename BayesNet<typename FACTOR::Conditional>::shared_ptr bayesNet(
|
typename BayesNet<typename FACTOR::Conditional>::shared_ptr bayesNet(
|
||||||
EliminationTree<FACTOR>::Create(factors_)->eliminate());
|
EliminationTree<FACTOR>::Create(*factors_)->eliminate());
|
||||||
|
|
||||||
// Undo the permuation on the original factors and on the structure.
|
// Undo the permuation on the original factors and on the structure.
|
||||||
BOOST_FOREACH(const typename FACTOR::shared_ptr& factor, factors_) {
|
BOOST_FOREACH(const typename FACTOR::shared_ptr& factor, *factors_) {
|
||||||
if(factor)
|
if(factor)
|
||||||
factor->permuteWithInverse(*permutation);
|
factor->permuteWithInverse(*permutation);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,10 @@ class GenericSequentialSolver {
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Store the original factors for computing marginals
|
// Store the original factors for computing marginals
|
||||||
FactorGraph<FACTOR> factors_;
|
typename FactorGraph<FACTOR>::shared_ptr factors_;
|
||||||
|
|
||||||
// Column structure of the factor graph
|
// Column structure of the factor graph
|
||||||
VariableIndex structure_;
|
VariableIndex::shared_ptr structure_;
|
||||||
|
|
||||||
// Elimination tree that performs elimination.
|
// Elimination tree that performs elimination.
|
||||||
typename EliminationTree<FACTOR>::shared_ptr eliminationTree_;
|
typename EliminationTree<FACTOR>::shared_ptr eliminationTree_;
|
||||||
|
|
@ -44,10 +44,30 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct the solver for a factor graph. This builds the elimination
|
* Construct the solver for a factor graph. This builds the elimination
|
||||||
* tree, which already does some of the symbolic work of elimination.
|
* tree, which already does some of the work of elimination.
|
||||||
*/
|
*/
|
||||||
GenericSequentialSolver(const FactorGraph<FACTOR>& factorGraph);
|
GenericSequentialSolver(const FactorGraph<FACTOR>& factorGraph);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct the solver for a factor graph. This builds the elimination
|
||||||
|
* tree, which already does some of the work of elimination.
|
||||||
|
*/
|
||||||
|
GenericSequentialSolver(const typename FactorGraph<FACTOR>::shared_ptr& factorGraph);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct the solver with a shared pointer to a factor graph and to a
|
||||||
|
* VariableIndex. The solver will store these pointers, so this constructor
|
||||||
|
* is the fastest.
|
||||||
|
*/
|
||||||
|
GenericSequentialSolver(const typename FactorGraph<FACTOR>::shared_ptr& factorGraph, const VariableIndex::shared_ptr& variableIndex);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace the factor graph with a new one having the same structure. The
|
||||||
|
* This function can be used if the numerical part of the factors changes,
|
||||||
|
* such as during relinearization or adjusting of noise models.
|
||||||
|
*/
|
||||||
|
void replaceFactors(const typename FactorGraph<FACTOR>::shared_ptr& factorGraph);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Eliminate the factor graph sequentially. Uses a column elimination tree
|
* Eliminate the factor graph sequentially. Uses a column elimination tree
|
||||||
* to recursively eliminate.
|
* to recursively eliminate.
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
#include <gtsam/inference/JunctionTree.h>
|
#include <gtsam/inference/JunctionTree.h>
|
||||||
#include <gtsam/inference/inference-inl.h>
|
#include <gtsam/inference/inference-inl.h>
|
||||||
#include <gtsam/inference/VariableSlots.h>
|
#include <gtsam/inference/VariableSlots.h>
|
||||||
#include <gtsam/inference/SymbolicSequentialSolver.h>
|
#include <gtsam/inference/EliminationTree-inl.h>
|
||||||
#include <gtsam/inference/ClusterTree-inl.h>
|
#include <gtsam/inference/ClusterTree-inl.h>
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
|
|
@ -35,129 +35,136 @@
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
/* ************************************************************************* */
|
|
||||||
template <class FG>
|
|
||||||
JunctionTree<FG>::JunctionTree(const FG& fg) {
|
|
||||||
tic("JT 1 constructor");
|
|
||||||
// Symbolic factorization: GaussianFactorGraph -> SymbolicFactorGraph
|
|
||||||
// -> SymbolicBayesNet -> SymbolicBayesTree
|
|
||||||
tic("JT 1.1 symbolic elimination");
|
|
||||||
SymbolicBayesNet::shared_ptr sbn = SymbolicSequentialSolver(fg).eliminate();
|
|
||||||
// SymbolicFactorGraph sfg(fg);
|
|
||||||
// SymbolicBayesNet::shared_ptr sbn_orig = Inference::Eliminate(sfg);
|
|
||||||
// assert(assert_equal(*sbn, *sbn_orig));
|
|
||||||
toc("JT 1.1 symbolic elimination");
|
|
||||||
tic("JT 1.2 symbolic BayesTree");
|
|
||||||
SymbolicBayesTree sbt(*sbn);
|
|
||||||
toc("JT 1.2 symbolic BayesTree");
|
|
||||||
|
|
||||||
// distribute factors
|
|
||||||
tic("JT 1.3 distributeFactors");
|
|
||||||
this->root_ = distributeFactors(fg, sbt.root());
|
|
||||||
toc("JT 1.3 distributeFactors");
|
|
||||||
toc("JT 1 constructor");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ************************************************************************* */
|
|
||||||
template<class FG>
|
|
||||||
typename JunctionTree<FG>::sharedClique JunctionTree<FG>::distributeFactors(
|
|
||||||
const FG& fg, const typename SymbolicBayesTree::sharedClique& bayesClique) {
|
|
||||||
|
|
||||||
// Build "target" index. This is an index for each variable of the factors
|
|
||||||
// that involve this variable as their *lowest-ordered* variable. For each
|
|
||||||
// factor, it is the lowest-ordered variable of that factor that pulls the
|
|
||||||
// factor into elimination, after which all of the information in the
|
|
||||||
// factor is contained in the eliminated factors that are passed up the
|
|
||||||
// tree as elimination continues.
|
|
||||||
|
|
||||||
// Two stages - first build an array of the lowest-ordered variable in each
|
|
||||||
// factor and find the last variable to be eliminated.
|
|
||||||
vector<Index> lowestOrdered(fg.size());
|
|
||||||
Index maxVar = 0;
|
|
||||||
for(size_t i=0; i<fg.size(); ++i)
|
|
||||||
if(fg[i]) {
|
|
||||||
typename FG::Factor::const_iterator min = std::min_element(fg[i]->begin(), fg[i]->end());
|
|
||||||
if(min == fg[i]->end())
|
|
||||||
lowestOrdered[i] = numeric_limits<Index>::max();
|
|
||||||
else {
|
|
||||||
lowestOrdered[i] = *min;
|
|
||||||
maxVar = std::max(maxVar, *min);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now add each factor to the list corresponding to its lowest-ordered
|
|
||||||
// variable.
|
|
||||||
vector<list<size_t, boost::fast_pool_allocator<size_t> > > targets(maxVar+1);
|
|
||||||
for(size_t i=0; i<lowestOrdered.size(); ++i)
|
|
||||||
if(lowestOrdered[i] != numeric_limits<Index>::max())
|
|
||||||
targets[lowestOrdered[i]].push_back(i);
|
|
||||||
|
|
||||||
// Now call the recursive distributeFactors
|
|
||||||
return distributeFactors(fg, targets, bayesClique);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
template<class FG>
|
template <class FG>
|
||||||
typename JunctionTree<FG>::sharedClique JunctionTree<FG>::distributeFactors(const FG& fg,
|
void JunctionTree<FG>::construct(const FG& fg, const VariableIndex& variableIndex) {
|
||||||
const std::vector<std::list<size_t,boost::fast_pool_allocator<size_t> > >& targets,
|
tic("JT 1 constructor");
|
||||||
|
tic("JT 1.1 symbolic elimination");
|
||||||
|
SymbolicBayesNet::shared_ptr sbn = EliminationTree<IndexFactor>::Create(fg, variableIndex)->eliminate();
|
||||||
|
toc("JT 1.1 symbolic elimination");
|
||||||
|
tic("JT 1.2 symbolic BayesTree");
|
||||||
|
SymbolicBayesTree sbt(*sbn);
|
||||||
|
toc("JT 1.2 symbolic BayesTree");
|
||||||
|
|
||||||
|
// distribute factors
|
||||||
|
tic("JT 1.3 distributeFactors");
|
||||||
|
this->root_ = distributeFactors(fg, sbt.root());
|
||||||
|
toc("JT 1.3 distributeFactors");
|
||||||
|
toc("JT 1 constructor");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template <class FG>
|
||||||
|
JunctionTree<FG>::JunctionTree(const FG& fg) {
|
||||||
|
construct(fg, VariableIndex(fg));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template <class FG>
|
||||||
|
JunctionTree<FG>::JunctionTree(const FG& fg, const VariableIndex& variableIndex) {
|
||||||
|
construct(fg, variableIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template<class FG>
|
||||||
|
typename JunctionTree<FG>::sharedClique JunctionTree<FG>::distributeFactors(
|
||||||
|
const FG& fg, const typename SymbolicBayesTree::sharedClique& bayesClique) {
|
||||||
|
|
||||||
|
// Build "target" index. This is an index for each variable of the factors
|
||||||
|
// that involve this variable as their *lowest-ordered* variable. For each
|
||||||
|
// factor, it is the lowest-ordered variable of that factor that pulls the
|
||||||
|
// factor into elimination, after which all of the information in the
|
||||||
|
// factor is contained in the eliminated factors that are passed up the
|
||||||
|
// tree as elimination continues.
|
||||||
|
|
||||||
|
// Two stages - first build an array of the lowest-ordered variable in each
|
||||||
|
// factor and find the last variable to be eliminated.
|
||||||
|
vector<Index> lowestOrdered(fg.size());
|
||||||
|
Index maxVar = 0;
|
||||||
|
for(size_t i=0; i<fg.size(); ++i)
|
||||||
|
if(fg[i]) {
|
||||||
|
typename FG::Factor::const_iterator min = std::min_element(fg[i]->begin(), fg[i]->end());
|
||||||
|
if(min == fg[i]->end())
|
||||||
|
lowestOrdered[i] = numeric_limits<Index>::max();
|
||||||
|
else {
|
||||||
|
lowestOrdered[i] = *min;
|
||||||
|
maxVar = std::max(maxVar, *min);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now add each factor to the list corresponding to its lowest-ordered
|
||||||
|
// variable.
|
||||||
|
vector<list<size_t, boost::fast_pool_allocator<size_t> > > targets(maxVar+1);
|
||||||
|
for(size_t i=0; i<lowestOrdered.size(); ++i)
|
||||||
|
if(lowestOrdered[i] != numeric_limits<Index>::max())
|
||||||
|
targets[lowestOrdered[i]].push_back(i);
|
||||||
|
|
||||||
|
// Now call the recursive distributeFactors
|
||||||
|
return distributeFactors(fg, targets, bayesClique);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template<class FG>
|
||||||
|
typename JunctionTree<FG>::sharedClique JunctionTree<FG>::distributeFactors(const FG& fg,
|
||||||
|
const std::vector<std::list<size_t,boost::fast_pool_allocator<size_t> > >& targets,
|
||||||
const SymbolicBayesTree::sharedClique& bayesClique) {
|
const SymbolicBayesTree::sharedClique& bayesClique) {
|
||||||
|
|
||||||
if(bayesClique) {
|
if(bayesClique) {
|
||||||
// create a new clique in the junction tree
|
// create a new clique in the junction tree
|
||||||
list<Index> frontals = bayesClique->ordering();
|
list<Index> frontals = bayesClique->ordering();
|
||||||
sharedClique clique(new Clique(frontals.begin(), frontals.end(), bayesClique->separator_.begin(), bayesClique->separator_.end()));
|
sharedClique clique(new Clique(frontals.begin(), frontals.end(), bayesClique->separator_.begin(), bayesClique->separator_.end()));
|
||||||
|
|
||||||
// count the factors for this cluster to pre-allocate space
|
// count the factors for this cluster to pre-allocate space
|
||||||
{
|
{
|
||||||
size_t nFactors = 0;
|
size_t nFactors = 0;
|
||||||
BOOST_FOREACH(const Index frontal, clique->frontal) {
|
BOOST_FOREACH(const Index frontal, clique->frontal) {
|
||||||
// There may be less variables in "targets" than there really are if
|
// There may be less variables in "targets" than there really are if
|
||||||
// some of the highest-numbered variables do not pull in any factors.
|
// some of the highest-numbered variables do not pull in any factors.
|
||||||
if(frontal < targets.size())
|
if(frontal < targets.size())
|
||||||
nFactors += targets[frontal].size(); }
|
nFactors += targets[frontal].size(); }
|
||||||
clique->reserve(nFactors);
|
clique->reserve(nFactors);
|
||||||
}
|
}
|
||||||
// add the factors to this cluster
|
// add the factors to this cluster
|
||||||
BOOST_FOREACH(const Index frontal, clique->frontal) {
|
BOOST_FOREACH(const Index frontal, clique->frontal) {
|
||||||
if(frontal < targets.size()) {
|
if(frontal < targets.size()) {
|
||||||
BOOST_FOREACH(const size_t factorI, targets[frontal]) {
|
BOOST_FOREACH(const size_t factorI, targets[frontal]) {
|
||||||
clique->push_back(fg[factorI]); } } }
|
clique->push_back(fg[factorI]); } } }
|
||||||
|
|
||||||
// recursively call the children
|
// recursively call the children
|
||||||
BOOST_FOREACH(const typename SymbolicBayesTree::sharedClique bayesChild, bayesClique->children()) {
|
BOOST_FOREACH(const typename SymbolicBayesTree::sharedClique bayesChild, bayesClique->children()) {
|
||||||
sharedClique child = distributeFactors(fg, targets, bayesChild);
|
sharedClique child = distributeFactors(fg, targets, bayesChild);
|
||||||
clique->addChild(child);
|
clique->addChild(child);
|
||||||
child->parent() = clique;
|
child->parent() = clique;
|
||||||
}
|
}
|
||||||
return clique;
|
return clique;
|
||||||
} else
|
} else
|
||||||
return sharedClique();
|
return sharedClique();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
template <class FG>
|
template <class FG>
|
||||||
pair<typename JunctionTree<FG>::BayesTree::sharedClique, typename FG::sharedFactor>
|
pair<typename JunctionTree<FG>::BayesTree::sharedClique, typename FG::sharedFactor>
|
||||||
JunctionTree<FG>::eliminateOneClique(const boost::shared_ptr<const Clique>& current) const {
|
JunctionTree<FG>::eliminateOneClique(const boost::shared_ptr<const Clique>& current) const {
|
||||||
|
|
||||||
FG fg; // factor graph will be assembled from local factors and marginalized children
|
FG fg; // factor graph will be assembled from local factors and marginalized children
|
||||||
fg.reserve(current->size() + current->children().size());
|
fg.reserve(current->size() + current->children().size());
|
||||||
fg.push_back(*current); // add the local factors
|
fg.push_back(*current); // add the local factors
|
||||||
|
|
||||||
// receive the factors from the child and its clique point
|
// receive the factors from the child and its clique point
|
||||||
list<typename BayesTree::sharedClique> children;
|
list<typename BayesTree::sharedClique> children;
|
||||||
BOOST_FOREACH(const boost::shared_ptr<const Clique>& child, current->children()) {
|
BOOST_FOREACH(const boost::shared_ptr<const Clique>& child, current->children()) {
|
||||||
pair<typename BayesTree::sharedClique, typename FG::sharedFactor> tree_factor(
|
pair<typename BayesTree::sharedClique, typename FG::sharedFactor> tree_factor(
|
||||||
eliminateOneClique(child));
|
eliminateOneClique(child));
|
||||||
children.push_back(tree_factor.first);
|
children.push_back(tree_factor.first);
|
||||||
fg.push_back(tree_factor.second);
|
fg.push_back(tree_factor.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eliminate the combined factors
|
// eliminate the combined factors
|
||||||
// warning: fg is being eliminated in-place and will contain marginal afterwards
|
// warning: fg is being eliminated in-place and will contain marginal afterwards
|
||||||
tic("JT 2.1 VariableSlots");
|
tic("JT 2.1 VariableSlots");
|
||||||
VariableSlots variableSlots(fg);
|
VariableSlots variableSlots(fg);
|
||||||
toc("JT 2.1 VariableSlots");
|
toc("JT 2.1 VariableSlots");
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// Debug check that the keys found in the factors match the frontal and
|
// Debug check that the keys found in the factors match the frontal and
|
||||||
|
|
@ -182,29 +189,29 @@ namespace gtsam {
|
||||||
assert(std::equal(jointFactor->begin(), jointFactor->end(), current->separator.begin()));
|
assert(std::equal(jointFactor->begin(), jointFactor->end(), current->separator.begin()));
|
||||||
|
|
||||||
tic("JT 2.4 Update tree");
|
tic("JT 2.4 Update tree");
|
||||||
// create a new clique corresponding the combined factors
|
// create a new clique corresponding the combined factors
|
||||||
typename BayesTree::sharedClique new_clique(new typename BayesTree::Clique(*fragment));
|
typename BayesTree::sharedClique new_clique(new typename BayesTree::Clique(*fragment));
|
||||||
new_clique->children_ = children;
|
new_clique->children_ = children;
|
||||||
|
|
||||||
BOOST_FOREACH(typename BayesTree::sharedClique& childRoot, children)
|
BOOST_FOREACH(typename BayesTree::sharedClique& childRoot, children)
|
||||||
childRoot->parent_ = new_clique;
|
childRoot->parent_ = new_clique;
|
||||||
|
|
||||||
toc("JT 2.4 Update tree");
|
toc("JT 2.4 Update tree");
|
||||||
return make_pair(new_clique, jointFactor);
|
return make_pair(new_clique, jointFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
template <class FG>
|
template <class FG>
|
||||||
typename JunctionTree<FG>::BayesTree::sharedClique JunctionTree<FG>::eliminate() const {
|
typename JunctionTree<FG>::BayesTree::sharedClique JunctionTree<FG>::eliminate() const {
|
||||||
if(this->root()) {
|
if(this->root()) {
|
||||||
tic("JT 2 eliminate");
|
tic("JT 2 eliminate");
|
||||||
pair<typename BayesTree::sharedClique, typename FG::sharedFactor> ret = this->eliminateOneClique(this->root());
|
pair<typename BayesTree::sharedClique, typename FG::sharedFactor> ret = this->eliminateOneClique(this->root());
|
||||||
if (ret.second->size() != 0)
|
if (ret.second->size() != 0)
|
||||||
throw runtime_error("JuntionTree::eliminate: elimination failed because of factors left over!");
|
throw runtime_error("JuntionTree::eliminate: elimination failed because of factors left over!");
|
||||||
toc("JT 2 eliminate");
|
toc("JT 2 eliminate");
|
||||||
return ret.first;
|
return ret.first;
|
||||||
} else
|
} else
|
||||||
return typename BayesTree::sharedClique();
|
return typename BayesTree::sharedClique();
|
||||||
}
|
}
|
||||||
|
|
||||||
} //namespace gtsam
|
} //namespace gtsam
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,8 @@ namespace gtsam {
|
||||||
|
|
||||||
typedef class BayesTree<typename FG::Factor::Conditional> BayesTree;
|
typedef class BayesTree<typename FG::Factor::Conditional> BayesTree;
|
||||||
|
|
||||||
|
typedef boost::shared_ptr<JunctionTree<FG> > shared_ptr;
|
||||||
|
|
||||||
// And we will frequently refer to a symbolic Bayes tree
|
// And we will frequently refer to a symbolic Bayes tree
|
||||||
typedef gtsam::BayesTree<IndexConditional> SymbolicBayesTree;
|
typedef gtsam::BayesTree<IndexConditional> SymbolicBayesTree;
|
||||||
|
|
||||||
|
|
@ -64,14 +66,19 @@ namespace gtsam {
|
||||||
std::pair<typename BayesTree::sharedClique, typename FG::sharedFactor>
|
std::pair<typename BayesTree::sharedClique, typename FG::sharedFactor>
|
||||||
eliminateOneClique(const boost::shared_ptr<const Clique>& clique) const;
|
eliminateOneClique(const boost::shared_ptr<const Clique>& clique) const;
|
||||||
|
|
||||||
public:
|
// internal constructor
|
||||||
// constructor
|
void construct(const FG& fg, const VariableIndex& variableIndex);
|
||||||
JunctionTree() {
|
|
||||||
}
|
|
||||||
|
|
||||||
// constructor given a factor graph and the elimination ordering
|
public:
|
||||||
|
/** Default constructor */
|
||||||
|
JunctionTree() {}
|
||||||
|
|
||||||
|
/** Construct from a factor graph. Computes a variable index. */
|
||||||
JunctionTree(const FG& fg);
|
JunctionTree(const FG& fg);
|
||||||
|
|
||||||
|
/** Construct from a factor graph and a pre-computed variable index. */
|
||||||
|
JunctionTree(const FG& fg, const VariableIndex& variableIndex);
|
||||||
|
|
||||||
// eliminate the factors in the subgraphs
|
// eliminate the factors in the subgraphs
|
||||||
typename BayesTree::sharedClique eliminate() const;
|
typename BayesTree::sharedClique eliminate() const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ using namespace boost::assign;
|
||||||
#include <gtsam/inference/ClusterTree-inl.h>
|
#include <gtsam/inference/ClusterTree-inl.h>
|
||||||
#include <gtsam/inference/JunctionTree-inl.h>
|
#include <gtsam/inference/JunctionTree-inl.h>
|
||||||
#include <gtsam/inference/IndexFactor.h>
|
#include <gtsam/inference/IndexFactor.h>
|
||||||
|
#include <gtsam/inference/SymbolicSequentialSolver.h>
|
||||||
|
|
||||||
using namespace gtsam;
|
using namespace gtsam;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -146,24 +146,6 @@ GaussianFactorGraph GaussianFactorGraph::combine2(const GaussianFactorGraph& lfg
|
||||||
return fg;
|
return fg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
|
||||||
GaussianFactorGraph GaussianFactorGraph::add_priors(double sigma, const vector<size_t>& dimensions) const {
|
|
||||||
|
|
||||||
// start with this factor graph
|
|
||||||
GaussianFactorGraph result = *this;
|
|
||||||
|
|
||||||
// for each of the variables, add a prior
|
|
||||||
for(Index j=0; j<dimensions.size(); ++j) {
|
|
||||||
size_t dim = dimensions[j];
|
|
||||||
Matrix A = eye(dim);
|
|
||||||
Vector b = zero(dim);
|
|
||||||
SharedDiagonal model = noiseModel::Isotropic::Sigma(dim,sigma);
|
|
||||||
sharedFactor prior(new GaussianFactor(j, A, b, model));
|
|
||||||
result.push_back(prior);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GaussianFactorGraph::split(const std::map<Index, Index> &M, GaussianFactorGraph &Ab1, GaussianFactorGraph &Ab2) const {
|
bool GaussianFactorGraph::split(const std::map<Index, Index> &M, GaussianFactorGraph &Ab1, GaussianFactorGraph &Ab2) const {
|
||||||
|
|
||||||
//typedef sharedFactor F ;
|
//typedef sharedFactor F ;
|
||||||
|
|
|
||||||
|
|
@ -151,13 +151,6 @@ namespace gtsam {
|
||||||
*/
|
*/
|
||||||
void combine(const GaussianFactorGraph &lfg);
|
void combine(const GaussianFactorGraph &lfg);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add zero-mean i.i.d. Gaussian prior terms to each variable
|
|
||||||
* @param sigma Standard deviation of Gaussian
|
|
||||||
*/
|
|
||||||
GaussianFactorGraph add_priors(double sigma, const std::vector<size_t>& dimensions) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Split a Gaussian factor graph into two, according to M
|
* Split a Gaussian factor graph into two, according to M
|
||||||
* M keeps the vertex indices of edges of A1. The others belong to A2.
|
* M keeps the vertex indices of edges of A1. The others belong to A2.
|
||||||
|
|
|
||||||
|
|
@ -43,11 +43,15 @@ namespace gtsam {
|
||||||
|
|
||||||
public :
|
public :
|
||||||
|
|
||||||
|
/** Default constructor */
|
||||||
GaussianJunctionTree() : Base() {}
|
GaussianJunctionTree() : Base() {}
|
||||||
|
|
||||||
// constructor
|
/** Constructor from a factor graph. Builds a VariableIndex. */
|
||||||
GaussianJunctionTree(const GaussianFactorGraph& fg) : Base(fg) {}
|
GaussianJunctionTree(const GaussianFactorGraph& fg) : Base(fg) {}
|
||||||
|
|
||||||
|
/** Construct from a factor graph and a pre-computed variable index. */
|
||||||
|
GaussianJunctionTree(const GaussianFactorGraph& fg, const VariableIndex& variableIndex) : Base(fg, variableIndex) {}
|
||||||
|
|
||||||
// optimize the linear graph
|
// optimize the linear graph
|
||||||
VectorValues optimize() const;
|
VectorValues optimize() const;
|
||||||
}; // GaussianJunctionTree
|
}; // GaussianJunctionTree
|
||||||
|
|
|
||||||
|
|
@ -31,17 +31,23 @@ GaussianMultifrontalSolver::GaussianMultifrontalSolver(const FactorGraph<Gaussia
|
||||||
Base(factorGraph) {}
|
Base(factorGraph) {}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
GaussianMultifrontalSolver::shared_ptr
|
GaussianMultifrontalSolver::GaussianMultifrontalSolver(const FactorGraph<GaussianFactor>::shared_ptr& factorGraph) :
|
||||||
GaussianMultifrontalSolver::Create(const FactorGraph<GaussianFactor>& factorGraph) {
|
Base(factorGraph) {}
|
||||||
return shared_ptr(new GaussianMultifrontalSolver(factorGraph));
|
|
||||||
}
|
/* ************************************************************************* */
|
||||||
|
GaussianMultifrontalSolver::GaussianMultifrontalSolver(const FactorGraph<GaussianFactor>::shared_ptr& factorGraph, const VariableIndex::shared_ptr& variableIndex) :
|
||||||
|
Base(factorGraph, variableIndex) {}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
GaussianMultifrontalSolver::shared_ptr
|
GaussianMultifrontalSolver::shared_ptr
|
||||||
GaussianMultifrontalSolver::update(const FactorGraph<GaussianFactor>& factorGraph) const {
|
GaussianMultifrontalSolver::Create(const FactorGraph<GaussianFactor>::shared_ptr& factorGraph,
|
||||||
// We do not yet have code written to update the junction tree, so we just
|
const VariableIndex::shared_ptr& variableIndex) {
|
||||||
// create a new solver.
|
return shared_ptr(new GaussianMultifrontalSolver(factorGraph, variableIndex));
|
||||||
return Create(factorGraph);
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
void GaussianMultifrontalSolver::replaceFactors(const FactorGraph<GaussianFactor>::shared_ptr& factorGraph) {
|
||||||
|
Base::replaceFactors(factorGraph);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
@ -51,7 +57,7 @@ BayesTree<GaussianConditional>::shared_ptr GaussianMultifrontalSolver::eliminate
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
VectorValues::shared_ptr GaussianMultifrontalSolver::optimize() const {
|
VectorValues::shared_ptr GaussianMultifrontalSolver::optimize() const {
|
||||||
return VectorValues::shared_ptr(new VectorValues(junctionTree_.optimize()));
|
return VectorValues::shared_ptr(new VectorValues(junctionTree_->optimize()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
|
||||||
|
|
@ -54,15 +54,28 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct the solver for a factor graph. This builds the elimination
|
* Construct the solver for a factor graph. This builds the elimination
|
||||||
* tree, which already does some of the symbolic work of elimination.
|
* tree, which already does some of the work of elimination.
|
||||||
*/
|
*/
|
||||||
GaussianMultifrontalSolver(const FactorGraph<GaussianFactor>& factorGraph);
|
GaussianMultifrontalSolver(const FactorGraph<GaussianFactor>& factorGraph);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Named constructor that returns a shared_ptr. This builds the junction
|
* Construct the solver for a factor graph. This builds the elimination
|
||||||
|
* tree, which already does some of the work of elimination.
|
||||||
|
*/
|
||||||
|
GaussianMultifrontalSolver(const FactorGraph<GaussianFactor>::shared_ptr& factorGraph);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct the solver with a shared pointer to a factor graph and to a
|
||||||
|
* VariableIndex. The solver will store these pointers, so this constructor
|
||||||
|
* is the fastest.
|
||||||
|
*/
|
||||||
|
GaussianMultifrontalSolver(const FactorGraph<GaussianFactor>::shared_ptr& factorGraph, const VariableIndex::shared_ptr& variableIndex);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Named constructor to return a shared_ptr. This builds the elimination
|
||||||
* tree, which already does some of the symbolic work of elimination.
|
* tree, which already does some of the symbolic work of elimination.
|
||||||
*/
|
*/
|
||||||
static shared_ptr Create(const FactorGraph<GaussianFactor>& factorGraph);
|
static shared_ptr Create(const FactorGraph<GaussianFactor>::shared_ptr& factorGraph, const VariableIndex::shared_ptr& variableIndex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a new solver that solves the given factor graph, which must have
|
* Return a new solver that solves the given factor graph, which must have
|
||||||
|
|
@ -71,7 +84,7 @@ public:
|
||||||
* used in cases where the numerical values of the linear problem change,
|
* used in cases where the numerical values of the linear problem change,
|
||||||
* e.g. during iterative nonlinear optimization.
|
* e.g. during iterative nonlinear optimization.
|
||||||
*/
|
*/
|
||||||
shared_ptr update(const FactorGraph<GaussianFactor>& factorGraph) const;
|
void replaceFactors(const FactorGraph<GaussianFactor>::shared_ptr& factorGraph);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Eliminate the factor graph sequentially. Uses a column elimination tree
|
* Eliminate the factor graph sequentially. Uses a column elimination tree
|
||||||
|
|
|
||||||
|
|
@ -31,15 +31,23 @@ GaussianSequentialSolver::GaussianSequentialSolver(const FactorGraph<GaussianFac
|
||||||
Base(factorGraph) {}
|
Base(factorGraph) {}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
GaussianSequentialSolver::shared_ptr GaussianSequentialSolver::Create(const FactorGraph<GaussianFactor>& factorGraph) {
|
GaussianSequentialSolver::GaussianSequentialSolver(const FactorGraph<GaussianFactor>::shared_ptr& factorGraph) :
|
||||||
return shared_ptr(new GaussianSequentialSolver(factorGraph));
|
Base(factorGraph) {}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
GaussianSequentialSolver::GaussianSequentialSolver(const FactorGraph<GaussianFactor>::shared_ptr& factorGraph,
|
||||||
|
const VariableIndex::shared_ptr& variableIndex) :
|
||||||
|
Base(factorGraph, variableIndex) {}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
GaussianSequentialSolver::shared_ptr GaussianSequentialSolver::Create(
|
||||||
|
const FactorGraph<GaussianFactor>::shared_ptr& factorGraph, const VariableIndex::shared_ptr& variableIndex) {
|
||||||
|
return shared_ptr(new GaussianSequentialSolver(factorGraph, variableIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
GaussianSequentialSolver::shared_ptr GaussianSequentialSolver::update(const FactorGraph<GaussianFactor>& factorGraph) const {
|
void GaussianSequentialSolver::replaceFactors(const FactorGraph<GaussianFactor>::shared_ptr& factorGraph) {
|
||||||
// We do not yet have code written to update the elimination tree, so we just
|
Base::replaceFactors(factorGraph);
|
||||||
// create a new solver.
|
|
||||||
return Create(factorGraph);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
@ -52,7 +60,7 @@ VectorValues::shared_ptr GaussianSequentialSolver::optimize() const {
|
||||||
|
|
||||||
static const bool debug = false;
|
static const bool debug = false;
|
||||||
|
|
||||||
if(debug) this->factors_.print("GaussianSequentialSolver, eliminating ");
|
if(debug) this->factors_->print("GaussianSequentialSolver, eliminating ");
|
||||||
if(debug) this->eliminationTree_->print("GaussianSequentialSolver, elimination tree ");
|
if(debug) this->eliminationTree_->print("GaussianSequentialSolver, elimination tree ");
|
||||||
|
|
||||||
// Eliminate using the elimination tree
|
// Eliminate using the elimination tree
|
||||||
|
|
|
||||||
|
|
@ -61,15 +61,28 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct the solver for a factor graph. This builds the elimination
|
* Construct the solver for a factor graph. This builds the elimination
|
||||||
* tree, which already does some of the symbolic work of elimination.
|
* tree, which already does some of the work of elimination.
|
||||||
*/
|
*/
|
||||||
GaussianSequentialSolver(const FactorGraph<GaussianFactor>& factorGraph);
|
GaussianSequentialSolver(const FactorGraph<GaussianFactor>& factorGraph);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct the solver for a factor graph. This builds the elimination
|
||||||
|
* tree, which already does some of the work of elimination.
|
||||||
|
*/
|
||||||
|
GaussianSequentialSolver(const FactorGraph<GaussianFactor>::shared_ptr& factorGraph);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct the solver with a shared pointer to a factor graph and to a
|
||||||
|
* VariableIndex. The solver will store these pointers, so this constructor
|
||||||
|
* is the fastest.
|
||||||
|
*/
|
||||||
|
GaussianSequentialSolver(const FactorGraph<GaussianFactor>::shared_ptr& factorGraph, const VariableIndex::shared_ptr& variableIndex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Named constructor to return a shared_ptr. This builds the elimination
|
* Named constructor to return a shared_ptr. This builds the elimination
|
||||||
* tree, which already does some of the symbolic work of elimination.
|
* tree, which already does some of the symbolic work of elimination.
|
||||||
*/
|
*/
|
||||||
static shared_ptr Create(const FactorGraph<GaussianFactor>& factorGraph);
|
static shared_ptr Create(const FactorGraph<GaussianFactor>::shared_ptr& factorGraph, const VariableIndex::shared_ptr& variableIndex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a new solver that solves the given factor graph, which must have
|
* Return a new solver that solves the given factor graph, which must have
|
||||||
|
|
@ -78,7 +91,7 @@ public:
|
||||||
* used in cases where the numerical values of the linear problem change,
|
* used in cases where the numerical values of the linear problem change,
|
||||||
* e.g. during iterative nonlinear optimization.
|
* e.g. during iterative nonlinear optimization.
|
||||||
*/
|
*/
|
||||||
shared_ptr update(const FactorGraph<GaussianFactor>& factorGraph) const;
|
void replaceFactors(const FactorGraph<GaussianFactor>::shared_ptr& factorGraph);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Eliminate the factor graph sequentially. Uses a column elimination tree
|
* Eliminate the factor graph sequentially. Uses a column elimination tree
|
||||||
|
|
|
||||||
|
|
@ -27,14 +27,13 @@ using namespace std;
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
template<class GRAPH, class LINEAR, class VALUES>
|
template<class GRAPH, class LINEAR, class VALUES>
|
||||||
typename SubgraphSolver<GRAPH,LINEAR,VALUES>::shared_ptr
|
void SubgraphSolver<GRAPH,LINEAR,VALUES>::replaceFactors(const typename LINEAR::shared_ptr &graph) {
|
||||||
SubgraphSolver<GRAPH,LINEAR,VALUES>::update(const LINEAR &graph) const {
|
|
||||||
|
|
||||||
shared_linear Ab1 = boost::make_shared<LINEAR>(),
|
shared_linear Ab1 = boost::make_shared<LINEAR>(),
|
||||||
Ab2 = boost::make_shared<LINEAR>();
|
Ab2 = boost::make_shared<LINEAR>();
|
||||||
|
|
||||||
if (parameters_->verbosity()) cout << "split the graph ...";
|
if (parameters_->verbosity()) cout << "split the graph ...";
|
||||||
graph.split(pairs_, *Ab1, *Ab2) ;
|
graph->split(pairs_, *Ab1, *Ab2) ;
|
||||||
if (parameters_->verbosity()) cout << ",with " << Ab1->size() << " and " << Ab2->size() << " factors" << endl;
|
if (parameters_->verbosity()) cout << ",with " << Ab1->size() << " and " << Ab2->size() << " factors" << endl;
|
||||||
|
|
||||||
// // Add a HardConstraint to the root, otherwise the root will be singular
|
// // Add a HardConstraint to the root, otherwise the root will be singular
|
||||||
|
|
@ -48,8 +47,7 @@ SubgraphSolver<GRAPH,LINEAR,VALUES>::update(const LINEAR &graph) const {
|
||||||
SubgraphPreconditioner::sharedBayesNet Rc1 = EliminationTree<GaussianFactor>::Create(sacrificialAb1)->eliminate();
|
SubgraphPreconditioner::sharedBayesNet Rc1 = EliminationTree<GaussianFactor>::Create(sacrificialAb1)->eliminate();
|
||||||
SubgraphPreconditioner::sharedValues xbar = gtsam::optimize_(*Rc1);
|
SubgraphPreconditioner::sharedValues xbar = gtsam::optimize_(*Rc1);
|
||||||
|
|
||||||
shared_preconditioner pc = boost::make_shared<SubgraphPreconditioner>(Ab1,Ab2,Rc1,xbar);
|
pc_ = boost::make_shared<SubgraphPreconditioner>(Ab1,Ab2,Rc1,xbar);
|
||||||
return boost::make_shared<SubgraphSolver>(ordering_, pairs_, pc, parameters_) ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class GRAPH, class LINEAR, class VALUES>
|
template<class GRAPH, class LINEAR, class VALUES>
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ namespace gtsam {
|
||||||
SubgraphSolver(const GRAPH& G, const VALUES& theta0, const Parameters ¶meters = Parameters()):
|
SubgraphSolver(const GRAPH& G, const VALUES& theta0, const Parameters ¶meters = Parameters()):
|
||||||
IterativeSolver(parameters){ initialize(G,theta0); }
|
IterativeSolver(parameters){ initialize(G,theta0); }
|
||||||
|
|
||||||
SubgraphSolver(const LINEAR &GFG) {
|
SubgraphSolver(const typename LINEAR::shared_ptr& GFG) {
|
||||||
std::cout << "[SubgraphSolver] Unexpected usage.." << std::endl;
|
std::cout << "[SubgraphSolver] Unexpected usage.." << std::endl;
|
||||||
throw std::runtime_error("SubgraphSolver: gaussian factor graph initialization not supported");
|
throw std::runtime_error("SubgraphSolver: gaussian factor graph initialization not supported");
|
||||||
}
|
}
|
||||||
|
|
@ -71,7 +71,7 @@ namespace gtsam {
|
||||||
sharedParameters parameters = boost::make_shared<Parameters>()) :
|
sharedParameters parameters = boost::make_shared<Parameters>()) :
|
||||||
IterativeSolver(parameters), ordering_(ordering), pairs_(pairs), pc_(pc) {}
|
IterativeSolver(parameters), ordering_(ordering), pairs_(pairs), pc_(pc) {}
|
||||||
|
|
||||||
shared_ptr update(const LINEAR &graph) const ;
|
void replaceFactors(const typename LINEAR::shared_ptr &graph);
|
||||||
VectorValues::shared_ptr optimize() const ;
|
VectorValues::shared_ptr optimize() const ;
|
||||||
shared_ordering ordering() const { return ordering_; }
|
shared_ordering ordering() const { return ordering_; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ namespace gtsam {
|
||||||
boost::shared_ptr<L> linearized = graph_->linearize(*values_, *ordering_);
|
boost::shared_ptr<L> linearized = graph_->linearize(*values_, *ordering_);
|
||||||
shared_solver newSolver = solver_;
|
shared_solver newSolver = solver_;
|
||||||
|
|
||||||
if(newSolver) newSolver = newSolver->update(*linearized);
|
if(newSolver) newSolver->replaceFactors(linearized);
|
||||||
else newSolver.reset(new S(*linearized));
|
else newSolver.reset(new S(*linearized));
|
||||||
|
|
||||||
VectorValues delta = *newSolver->optimize();
|
VectorValues delta = *newSolver->optimize();
|
||||||
|
|
@ -209,11 +209,24 @@ namespace gtsam {
|
||||||
if (verbosity >= Parameters::TRYLAMBDA) cout << "trying lambda = " << lambda << endl;
|
if (verbosity >= Parameters::TRYLAMBDA) cout << "trying lambda = " << lambda << endl;
|
||||||
|
|
||||||
// add prior-factors
|
// add prior-factors
|
||||||
L damped = linear.add_priors(1.0/sqrt(lambda), *dimensions_);
|
typename L::shared_ptr damped(new L(linear));
|
||||||
if (verbosity >= Parameters::DAMPED) damped.print("damped");
|
{
|
||||||
|
double sigma = 1.0 / sqrt(lambda);
|
||||||
|
damped->reserve(damped->size() + dimensions_->size());
|
||||||
|
// for each of the variables, add a prior
|
||||||
|
for(Index j=0; j<dimensions_->size(); ++j) {
|
||||||
|
size_t dim = (*dimensions_)[j];
|
||||||
|
Matrix A = eye(dim);
|
||||||
|
Vector b = zero(dim);
|
||||||
|
SharedDiagonal model = noiseModel::Isotropic::Sigma(dim,sigma);
|
||||||
|
GaussianFactor::shared_ptr prior(new GaussianFactor(j, A, b, model));
|
||||||
|
damped->push_back(prior);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (verbosity >= Parameters::DAMPED) damped->print("damped");
|
||||||
|
|
||||||
// solve
|
// solve
|
||||||
if(solver_) solver_ = solver_->update(damped);
|
if(solver_) solver_->replaceFactors(damped);
|
||||||
else solver_.reset(new S(damped));
|
else solver_.reset(new S(damped));
|
||||||
|
|
||||||
VectorValues delta = *solver_->optimize();
|
VectorValues delta = *solver_->optimize();
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ namespace gtsam {
|
||||||
typedef boost::shared_ptr<const T> shared_values;
|
typedef boost::shared_ptr<const T> shared_values;
|
||||||
typedef boost::shared_ptr<const G> shared_graph;
|
typedef boost::shared_ptr<const G> shared_graph;
|
||||||
typedef boost::shared_ptr<const Ordering> shared_ordering;
|
typedef boost::shared_ptr<const Ordering> shared_ordering;
|
||||||
typedef boost::shared_ptr<const GS> shared_solver;
|
typedef boost::shared_ptr<GS> shared_solver;
|
||||||
typedef NonlinearOptimizationParameters Parameters;
|
typedef NonlinearOptimizationParameters Parameters;
|
||||||
typedef boost::shared_ptr<const Parameters> shared_parameters ;
|
typedef boost::shared_ptr<const Parameters> shared_parameters ;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -339,21 +339,21 @@ TEST( GaussianFactorGraph, eliminateAll )
|
||||||
// CHECK(assert_equal(expected,actual,tol));
|
// CHECK(assert_equal(expected,actual,tol));
|
||||||
//}
|
//}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
///* ************************************************************************* */
|
||||||
TEST( GaussianFactorGraph, add_priors )
|
//TEST( GaussianFactorGraph, add_priors )
|
||||||
{
|
//{
|
||||||
Ordering ordering; ordering += "l1","x1","x2";
|
// Ordering ordering; ordering += "l1","x1","x2";
|
||||||
GaussianFactorGraph fg = createGaussianFactorGraph(ordering);
|
// GaussianFactorGraph fg = createGaussianFactorGraph(ordering);
|
||||||
GaussianFactorGraph actual = fg.add_priors(3, vector<size_t>(3,2));
|
// GaussianFactorGraph actual = fg.add_priors(3, vector<size_t>(3,2));
|
||||||
GaussianFactorGraph expected = createGaussianFactorGraph(ordering);
|
// GaussianFactorGraph expected = createGaussianFactorGraph(ordering);
|
||||||
Matrix A = eye(2);
|
// Matrix A = eye(2);
|
||||||
Vector b = zero(2);
|
// Vector b = zero(2);
|
||||||
SharedDiagonal sigma = sharedSigma(2,3.0);
|
// SharedDiagonal sigma = sharedSigma(2,3.0);
|
||||||
expected.push_back(GaussianFactor::shared_ptr(new GaussianFactor(ordering["l1"],A,b,sigma)));
|
// expected.push_back(GaussianFactor::shared_ptr(new GaussianFactor(ordering["l1"],A,b,sigma)));
|
||||||
expected.push_back(GaussianFactor::shared_ptr(new GaussianFactor(ordering["x1"],A,b,sigma)));
|
// expected.push_back(GaussianFactor::shared_ptr(new GaussianFactor(ordering["x1"],A,b,sigma)));
|
||||||
expected.push_back(GaussianFactor::shared_ptr(new GaussianFactor(ordering["x2"],A,b,sigma)));
|
// expected.push_back(GaussianFactor::shared_ptr(new GaussianFactor(ordering["x2"],A,b,sigma)));
|
||||||
CHECK(assert_equal(expected,actual));
|
// CHECK(assert_equal(expected,actual));
|
||||||
}
|
//}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
TEST( GaussianFactorGraph, copying )
|
TEST( GaussianFactorGraph, copying )
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue