2010-10-14 12:54:38 +08:00
|
|
|
/* ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
|
|
|
|
|
* Atlanta, Georgia 30332-0415
|
|
|
|
|
* All Rights Reserved
|
|
|
|
|
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
|
|
|
|
|
|
|
|
|
|
* See LICENSE for the license information
|
|
|
|
|
|
|
|
|
|
* -------------------------------------------------------------------------- */
|
|
|
|
|
|
2009-08-22 06:23:24 +08:00
|
|
|
/**
|
2009-11-13 00:41:18 +08:00
|
|
|
* @file GaussianConditional.cpp
|
2009-08-22 06:23:24 +08:00
|
|
|
* @brief Conditional Gaussian Base class
|
|
|
|
|
* @author Christian Potthast
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <string.h>
|
2010-10-09 06:04:47 +08:00
|
|
|
#include <boost/format.hpp>
|
2012-09-17 01:52:49 +08:00
|
|
|
#pragma GCC diagnostic push
|
|
|
|
|
#pragma GCC diagnostic ignored "-Wunused-variable"
|
2012-08-23 06:40:27 +08:00
|
|
|
#include <boost/lambda/lambda.hpp>
|
2012-09-17 01:52:49 +08:00
|
|
|
#pragma GCC diagnostic pop
|
2010-10-09 06:04:47 +08:00
|
|
|
#include <boost/lambda/bind.hpp>
|
|
|
|
|
|
2012-08-23 06:40:27 +08:00
|
|
|
#include <gtsam/linear/linearExceptions.h>
|
2010-08-20 01:23:19 +08:00
|
|
|
#include <gtsam/linear/GaussianConditional.h>
|
2011-01-21 06:22:00 +08:00
|
|
|
#include <gtsam/linear/GaussianFactor.h>
|
|
|
|
|
#include <gtsam/linear/JacobianFactor.h>
|
2009-08-22 06:23:24 +08:00
|
|
|
|
|
|
|
|
using namespace std;
|
2010-10-09 06:04:47 +08:00
|
|
|
|
|
|
|
|
namespace gtsam {
|
2009-08-22 06:23:24 +08:00
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
2010-10-09 06:04:47 +08:00
|
|
|
GaussianConditional::GaussianConditional() : rsd_(matrix_) {}
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
2010-10-20 05:31:13 +08:00
|
|
|
GaussianConditional::GaussianConditional(Index key) : IndexConditional(key), rsd_(matrix_) {}
|
2010-10-09 06:04:47 +08:00
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
2010-10-12 05:14:35 +08:00
|
|
|
GaussianConditional::GaussianConditional(Index key,const Vector& d, const Matrix& R, const Vector& sigmas) :
|
2010-10-20 05:31:13 +08:00
|
|
|
IndexConditional(key), rsd_(matrix_), sigmas_(sigmas) {
|
2011-05-20 21:52:08 +08:00
|
|
|
assert(R.rows() <= R.cols());
|
|
|
|
|
size_t dims[] = { R.cols(), 1 };
|
2010-10-09 06:04:47 +08:00
|
|
|
rsd_.copyStructureFrom(rsd_type(matrix_, dims, dims+2, d.size()));
|
2011-06-14 00:55:31 +08:00
|
|
|
rsd_(0) = R.triangularView<Eigen::Upper>();
|
2011-05-20 21:52:08 +08:00
|
|
|
get_d_() = d;
|
2009-08-22 06:23:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
2010-10-12 05:14:35 +08:00
|
|
|
GaussianConditional::GaussianConditional(Index key, const Vector& d, const Matrix& R,
|
|
|
|
|
Index name1, const Matrix& S, const Vector& sigmas) :
|
2010-10-20 05:31:13 +08:00
|
|
|
IndexConditional(key,name1), rsd_(matrix_), sigmas_(sigmas) {
|
2011-05-20 21:52:08 +08:00
|
|
|
assert(R.rows() <= R.cols());
|
|
|
|
|
size_t dims[] = { R.cols(), S.cols(), 1 };
|
2010-10-09 06:04:47 +08:00
|
|
|
rsd_.copyStructureFrom(rsd_type(matrix_, dims, dims+3, d.size()));
|
2011-05-20 21:52:08 +08:00
|
|
|
rsd_(0) = R.triangularView<Eigen::Upper>();
|
|
|
|
|
rsd_(1) = S;
|
|
|
|
|
get_d_() = d;
|
2009-08-22 06:23:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
2010-10-12 05:14:35 +08:00
|
|
|
GaussianConditional::GaussianConditional(Index key, const Vector& d, const Matrix& R,
|
|
|
|
|
Index name1, const Matrix& S, Index name2, const Matrix& T, const Vector& sigmas) :
|
2010-10-20 05:31:13 +08:00
|
|
|
IndexConditional(key,name1,name2), rsd_(matrix_), sigmas_(sigmas) {
|
2011-05-20 21:52:08 +08:00
|
|
|
assert(R.rows() <= R.cols());
|
|
|
|
|
size_t dims[] = { R.cols(), S.cols(), T.cols(), 1 };
|
2010-10-09 06:04:47 +08:00
|
|
|
rsd_.copyStructureFrom(rsd_type(matrix_, dims, dims+4, d.size()));
|
2011-05-20 21:52:08 +08:00
|
|
|
rsd_(0) = R.triangularView<Eigen::Upper>();
|
|
|
|
|
rsd_(1) = S;
|
|
|
|
|
rsd_(2) = T;
|
|
|
|
|
get_d_() = d;
|
2009-08-22 06:23:24 +08:00
|
|
|
}
|
|
|
|
|
|
2009-10-08 21:57:22 +08:00
|
|
|
/* ************************************************************************* */
|
2011-03-26 00:57:28 +08:00
|
|
|
GaussianConditional::GaussianConditional(Index key, const Vector& d,
|
|
|
|
|
const Matrix& R, const list<pair<Index, Matrix> >& parents, const Vector& sigmas) :
|
|
|
|
|
IndexConditional(key, GetKeys(parents.size(), parents.begin(), parents.end())), rsd_(matrix_), sigmas_(sigmas) {
|
2011-05-20 21:52:08 +08:00
|
|
|
assert(R.rows() <= R.cols());
|
2012-05-23 06:52:17 +08:00
|
|
|
size_t* dims = (size_t*)alloca(sizeof(size_t)*(1+parents.size()+1)); // FIXME: alloca is bad, just ask Google.
|
2011-05-20 21:52:08 +08:00
|
|
|
dims[0] = R.cols();
|
2010-10-09 06:04:47 +08:00
|
|
|
size_t j=1;
|
2011-03-26 00:57:28 +08:00
|
|
|
std::list<std::pair<Index, Matrix> >::const_iterator parent=parents.begin();
|
|
|
|
|
for(; parent!=parents.end(); ++parent,++j)
|
2011-05-20 21:52:08 +08:00
|
|
|
dims[j] = parent->second.cols();
|
2010-10-09 06:04:47 +08:00
|
|
|
dims[j] = 1;
|
|
|
|
|
rsd_.copyStructureFrom(rsd_type(matrix_, dims, dims+1+parents.size()+1, d.size()));
|
2011-05-20 21:52:08 +08:00
|
|
|
rsd_(0) = R.triangularView<Eigen::Upper>();
|
2010-10-09 06:04:47 +08:00
|
|
|
j = 1;
|
2010-10-12 05:14:35 +08:00
|
|
|
for(std::list<std::pair<Index, Matrix> >::const_iterator parent=parents.begin(); parent!=parents.end(); ++parent) {
|
2011-05-20 21:52:08 +08:00
|
|
|
rsd_(j).noalias() = parent->second;
|
2010-10-09 06:04:47 +08:00
|
|
|
++ j;
|
|
|
|
|
}
|
2011-09-23 10:50:46 +08:00
|
|
|
get_d_() = d;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
|
|
|
|
GaussianConditional::GaussianConditional(const std::list<std::pair<Index, Matrix> >& terms,
|
|
|
|
|
const size_t nrFrontals, const Vector& d, const Vector& sigmas) :
|
|
|
|
|
IndexConditional(GetKeys(terms.size(), terms.begin(), terms.end()), nrFrontals),
|
|
|
|
|
rsd_(matrix_), sigmas_(sigmas) {
|
2012-05-23 06:52:17 +08:00
|
|
|
size_t* dims = (size_t*)alloca(sizeof(size_t)*(terms.size()+1)); // FIXME: alloca is bad, just ask Google.
|
2011-09-23 10:50:46 +08:00
|
|
|
size_t j=0;
|
|
|
|
|
typedef pair<Index, Matrix> Index_Matrix;
|
|
|
|
|
BOOST_FOREACH(const Index_Matrix& term, terms) {
|
|
|
|
|
dims[j] = term.second.cols();
|
|
|
|
|
++ j;
|
|
|
|
|
}
|
|
|
|
|
dims[j] = 1;
|
|
|
|
|
rsd_.copyStructureFrom(rsd_type(matrix_, dims, dims+terms.size()+1, d.size()));
|
|
|
|
|
j=0;
|
|
|
|
|
BOOST_FOREACH(const Index_Matrix& term, terms) {
|
|
|
|
|
rsd_(j) = term.second;
|
|
|
|
|
++ j;
|
|
|
|
|
}
|
|
|
|
|
get_d_() = d;
|
2009-11-02 11:50:30 +08:00
|
|
|
}
|
2009-10-08 21:57:22 +08:00
|
|
|
|
2012-01-22 13:16:12 +08:00
|
|
|
/* ************************************************************************* */
|
|
|
|
|
GaussianConditional::GaussianConditional(const GaussianConditional& rhs) :
|
|
|
|
|
rsd_(matrix_) {
|
|
|
|
|
*this = rhs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
|
|
|
|
GaussianConditional& GaussianConditional::operator=(const GaussianConditional& rhs) {
|
|
|
|
|
if(this != &rhs) {
|
|
|
|
|
this->Base::operator=(rhs); // Copy keys
|
|
|
|
|
rsd_.assignNoalias(rhs.rsd_); // Copy matrix and block configuration
|
|
|
|
|
sigmas_ = rhs.sigmas_; // Copy sigmas
|
|
|
|
|
}
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-22 06:23:24 +08:00
|
|
|
/* ************************************************************************* */
|
2012-06-26 05:19:38 +08:00
|
|
|
void GaussianConditional::print(const string &s, const IndexFormatter& formatter) const
|
2009-08-22 06:23:24 +08:00
|
|
|
{
|
2011-06-14 00:55:31 +08:00
|
|
|
cout << s << ": density on ";
|
|
|
|
|
for(const_iterator it = beginFrontals(); it != endFrontals(); ++it) {
|
2012-06-26 05:19:38 +08:00
|
|
|
cout << (boost::format("[%1%]")%(formatter(*it))).str() << " ";
|
2011-06-14 00:55:31 +08:00
|
|
|
}
|
|
|
|
|
cout << endl;
|
2011-05-20 21:52:08 +08:00
|
|
|
gtsam::print(Matrix(get_R()),"R");
|
2011-06-14 00:55:31 +08:00
|
|
|
for(const_iterator it = beginParents() ; it != endParents() ; ++it ) {
|
2012-06-26 05:19:38 +08:00
|
|
|
gtsam::print(Matrix(get_S(it)), (boost::format("A[%1%]")%(formatter(*it))).str());
|
2009-08-22 06:23:24 +08:00
|
|
|
}
|
2011-05-20 21:52:08 +08:00
|
|
|
gtsam::print(Vector(get_d()),"d");
|
2009-11-05 14:59:59 +08:00
|
|
|
gtsam::print(sigmas_,"sigmas");
|
2009-08-22 06:23:24 +08:00
|
|
|
}
|
|
|
|
|
|
2009-10-25 07:14:14 +08:00
|
|
|
/* ************************************************************************* */
|
2010-10-09 06:04:47 +08:00
|
|
|
bool GaussianConditional::equals(const GaussianConditional &c, double tol) const {
|
2009-10-25 07:14:14 +08:00
|
|
|
// check if the size of the parents_ map is the same
|
2011-05-20 21:52:08 +08:00
|
|
|
if (parents().size() != c.parents().size())
|
|
|
|
|
return false;
|
2009-10-25 07:14:14 +08:00
|
|
|
|
2010-07-11 15:30:27 +08:00
|
|
|
// check if R_ and d_ are linear independent
|
2011-05-20 21:52:08 +08:00
|
|
|
for (size_t i=0; i<rsd_.rows(); i++) {
|
|
|
|
|
list<Vector> rows1; rows1.push_back(Vector(get_R().row(i)));
|
|
|
|
|
list<Vector> rows2; rows2.push_back(Vector(c.get_R().row(i)));
|
2009-11-05 04:59:16 +08:00
|
|
|
|
2010-07-05 07:50:21 +08:00
|
|
|
// check if the matrices are the same
|
|
|
|
|
// iterate over the parents_ map
|
2010-10-09 06:04:47 +08:00
|
|
|
for (const_iterator it = beginParents(); it != endParents(); ++it) {
|
|
|
|
|
const_iterator it2 = c.beginParents() + (it-beginParents());
|
|
|
|
|
if(*it != *(it2))
|
|
|
|
|
return false;
|
2011-05-20 21:52:08 +08:00
|
|
|
rows1.push_back(row(get_S(it), i));
|
|
|
|
|
rows2.push_back(row(c.get_S(it2), i));
|
2010-07-05 07:50:21 +08:00
|
|
|
}
|
|
|
|
|
|
2010-07-11 15:30:27 +08:00
|
|
|
Vector row1 = concatVectors(rows1);
|
|
|
|
|
Vector row2 = concatVectors(rows2);
|
2011-05-20 21:52:08 +08:00
|
|
|
if (!linear_dependent(row1, row2, tol))
|
|
|
|
|
return false;
|
2009-10-25 07:14:14 +08:00
|
|
|
}
|
2010-07-05 07:50:21 +08:00
|
|
|
|
|
|
|
|
// check if sigmas are equal
|
2010-10-09 06:04:47 +08:00
|
|
|
if (!(equal_with_abs_tol(sigmas_, c.sigmas_, tol))) return false;
|
2010-07-05 07:50:21 +08:00
|
|
|
|
2009-10-25 07:14:14 +08:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-21 06:22:00 +08:00
|
|
|
/* ************************************************************************* */
|
2011-03-04 08:18:17 +08:00
|
|
|
JacobianFactor::shared_ptr GaussianConditional::toFactor() const {
|
|
|
|
|
return JacobianFactor::shared_ptr(new JacobianFactor(*this));
|
2011-01-21 06:22:00 +08:00
|
|
|
}
|
2009-10-31 13:12:39 +08:00
|
|
|
|
2011-06-14 00:55:31 +08:00
|
|
|
/* ************************************************************************* */
|
|
|
|
|
void GaussianConditional::solveInPlace(VectorValues& x) const {
|
2012-06-30 09:45:21 +08:00
|
|
|
static const bool debug = false;
|
|
|
|
|
if(debug) this->print("Solving conditional in place");
|
|
|
|
|
Vector xS = internal::extractVectorValuesSlices(x, this->beginParents(), this->endParents());
|
|
|
|
|
xS = this->get_d() - this->get_S() * xS;
|
|
|
|
|
Vector soln = this->get_R().triangularView<Eigen::Upper>().solve(xS);
|
2012-08-23 06:40:27 +08:00
|
|
|
|
|
|
|
|
// Check for indeterminant solution
|
|
|
|
|
if(soln.unaryExpr(!boost::lambda::bind(ptr_fun(isfinite<double>), boost::lambda::_1)).any())
|
|
|
|
|
throw IndeterminantLinearSystemException(this->keys().front());
|
|
|
|
|
|
2012-06-30 09:45:21 +08:00
|
|
|
if(debug) {
|
|
|
|
|
gtsam::print(Matrix(this->get_R()), "Calling backSubstituteUpper on ");
|
|
|
|
|
gtsam::print(soln, "full back-substitution solution: ");
|
|
|
|
|
}
|
|
|
|
|
internal::writeVectorValuesSlices(soln, x, this->beginFrontals(), this->endFrontals());
|
2011-06-14 00:55:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
|
|
|
|
void GaussianConditional::solveTransposeInPlace(VectorValues& gy) const {
|
2012-03-19 22:32:37 +08:00
|
|
|
Vector frontalVec = internal::extractVectorValuesSlices(gy, beginFrontals(), endFrontals());
|
2012-05-15 23:49:14 +08:00
|
|
|
frontalVec = gtsam::backSubstituteUpper(frontalVec,Matrix(get_R()));
|
2012-08-23 06:40:27 +08:00
|
|
|
|
|
|
|
|
// Check for indeterminant solution
|
|
|
|
|
if(frontalVec.unaryExpr(!boost::lambda::bind(ptr_fun(isfinite<double>), boost::lambda::_1)).any())
|
|
|
|
|
throw IndeterminantLinearSystemException(this->keys().front());
|
|
|
|
|
|
2011-06-14 00:55:31 +08:00
|
|
|
GaussianConditional::const_iterator it;
|
|
|
|
|
for (it = beginParents(); it!= endParents(); it++) {
|
|
|
|
|
const Index i = *it;
|
|
|
|
|
transposeMultiplyAdd(-1.0,get_S(it),frontalVec,gy[i]);
|
|
|
|
|
}
|
2012-03-19 22:32:37 +08:00
|
|
|
internal::writeVectorValuesSlices(frontalVec, gy, beginFrontals(), endFrontals());
|
2009-08-22 06:23:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
2011-06-14 00:55:31 +08:00
|
|
|
void GaussianConditional::scaleFrontalsBySigma(VectorValues& gy) const {
|
2012-03-19 22:32:37 +08:00
|
|
|
Vector frontalVec = internal::extractVectorValuesSlices(gy, beginFrontals(), endFrontals());
|
2011-06-14 00:55:31 +08:00
|
|
|
frontalVec = emul(frontalVec, get_sigmas());
|
2012-03-19 22:32:37 +08:00
|
|
|
internal::writeVectorValuesSlices(frontalVec, gy, beginFrontals(), endFrontals());
|
2010-10-09 06:04:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|