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-09-13 12:13:03 +08:00
|
|
|
/**
|
|
|
|
|
* @file FactorGraph-inl.h
|
|
|
|
|
* This is a template definition file, include it where needed (only!)
|
|
|
|
|
* so that the appropriate code is generated and link errors avoided.
|
|
|
|
|
* @brief Factor Graph Base Class
|
|
|
|
|
* @author Carlos Nieto
|
|
|
|
|
* @author Frank Dellaert
|
|
|
|
|
* @author Alireza Fathi
|
2010-07-10 02:15:54 +08:00
|
|
|
* @author Michael Kaess
|
2009-09-13 12:13:03 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
2011-12-13 07:19:31 +08:00
|
|
|
#include <gtsam/inference/BayesTree.h>
|
2012-08-31 03:58:33 +08:00
|
|
|
#include <gtsam/inference/VariableIndex.h>
|
2009-11-20 22:18:26 +08:00
|
|
|
|
2009-09-13 12:13:03 +08:00
|
|
|
#include <boost/foreach.hpp>
|
|
|
|
|
#include <boost/tuple/tuple.hpp>
|
2009-12-18 08:13:38 +08:00
|
|
|
#include <boost/format.hpp>
|
2011-03-25 03:27:12 +08:00
|
|
|
#include <boost/iterator/transform_iterator.hpp>
|
2010-10-15 09:07:51 +08:00
|
|
|
|
2011-11-05 11:23:55 +08:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <list>
|
|
|
|
|
#include <sstream>
|
|
|
|
|
#include <stdexcept>
|
2009-09-13 12:13:03 +08:00
|
|
|
|
|
|
|
|
namespace gtsam {
|
|
|
|
|
|
2012-06-10 05:33:10 +08:00
|
|
|
/* ************************************************************************* */
|
|
|
|
|
template<class FACTOR>
|
|
|
|
|
template<class CONDITIONAL>
|
|
|
|
|
FactorGraph<FACTOR>::FactorGraph(const BayesNet<CONDITIONAL>& bayesNet) {
|
|
|
|
|
factors_.reserve(bayesNet.size());
|
|
|
|
|
BOOST_FOREACH(const typename CONDITIONAL::shared_ptr& cond, bayesNet) {
|
|
|
|
|
this->push_back(cond->toFactor());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-14 21:55:32 +08:00
|
|
|
/* ************************************************************************* */
|
2010-10-18 01:10:10 +08:00
|
|
|
template<class FACTOR>
|
2012-06-28 03:16:18 +08:00
|
|
|
void FactorGraph<FACTOR>::print(const std::string& s,
|
2012-06-28 09:52:48 +08:00
|
|
|
const IndexFormatter& formatter) const {
|
2012-06-08 22:33:36 +08:00
|
|
|
std::cout << s << std::endl;
|
|
|
|
|
std::cout << "size: " << size() << std::endl;
|
2010-07-14 21:55:32 +08:00
|
|
|
for (size_t i = 0; i < factors_.size(); i++) {
|
2012-06-08 22:33:36 +08:00
|
|
|
std::stringstream ss;
|
2011-11-05 11:23:55 +08:00
|
|
|
ss << "factor " << i << ": ";
|
2012-06-28 03:16:18 +08:00
|
|
|
if (factors_[i] != NULL) factors_[i]->print(ss.str(), formatter);
|
2010-07-14 21:55:32 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
2010-10-18 01:10:10 +08:00
|
|
|
template<class FACTOR>
|
2012-06-10 05:33:10 +08:00
|
|
|
bool FactorGraph<FACTOR>::equals(const This& fg, double tol) const {
|
2010-07-14 21:55:32 +08:00
|
|
|
/** check whether the two factor graphs have the same number of factors_ */
|
|
|
|
|
if (factors_.size() != fg.size()) return false;
|
|
|
|
|
|
|
|
|
|
/** check whether the factors_ are the same */
|
|
|
|
|
for (size_t i = 0; i < factors_.size(); i++) {
|
|
|
|
|
// TODO: Doesn't this force order of factor insertion?
|
|
|
|
|
sharedFactor f1 = factors_[i], f2 = fg.factors_[i];
|
|
|
|
|
if (f1 == NULL && f2 == NULL) continue;
|
|
|
|
|
if (f1 == NULL || f2 == NULL) return false;
|
|
|
|
|
if (!f1->equals(*f2, tol)) return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
2009-10-26 06:27:18 +08:00
|
|
|
}
|
2010-07-14 21:55:32 +08:00
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
2010-10-18 01:10:10 +08:00
|
|
|
template<class FACTOR>
|
|
|
|
|
size_t FactorGraph<FACTOR>::nrFactors() const {
|
2010-07-14 21:55:32 +08:00
|
|
|
size_t size_ = 0;
|
|
|
|
|
for (const_iterator factor = factors_.begin(); factor != factors_.end(); factor++)
|
|
|
|
|
if (*factor != NULL) size_++;
|
|
|
|
|
return size_;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-31 03:58:33 +08:00
|
|
|
/* ************************************************************************* */
|
|
|
|
|
template<class FACTOR>
|
|
|
|
|
std::pair<typename FactorGraph<FACTOR>::sharedConditional, FactorGraph<FACTOR> >
|
|
|
|
|
FactorGraph<FACTOR>::eliminateFrontals(size_t nFrontals, const Eliminate& eliminate) const
|
|
|
|
|
{
|
|
|
|
|
// Build variable index
|
|
|
|
|
VariableIndex variableIndex(*this);
|
|
|
|
|
|
|
|
|
|
// Find first variable
|
|
|
|
|
Index firstIndex = 0;
|
|
|
|
|
while(firstIndex < variableIndex.size() && variableIndex[firstIndex].empty())
|
|
|
|
|
++ firstIndex;
|
|
|
|
|
|
|
|
|
|
// Check that number of variables is in bounds
|
|
|
|
|
if(firstIndex + nFrontals >= variableIndex.size())
|
|
|
|
|
throw std::invalid_argument("Requested to eliminate more frontal variables than exist in the factor graph.");
|
|
|
|
|
|
|
|
|
|
// Get set of involved factors
|
|
|
|
|
FastSet<size_t> involvedFactorIs;
|
|
|
|
|
for(Index j = firstIndex; j < firstIndex + nFrontals; ++j) {
|
|
|
|
|
BOOST_FOREACH(size_t i, variableIndex[j]) {
|
|
|
|
|
involvedFactorIs.insert(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Separate factors into involved and remaining
|
|
|
|
|
FactorGraph<FactorType> involvedFactors;
|
|
|
|
|
FactorGraph<FactorType> remainingFactors;
|
|
|
|
|
FastSet<size_t>::const_iterator involvedFactorIsIt = involvedFactorIs.begin();
|
|
|
|
|
for(size_t i = 0; i < this->size(); ++i) {
|
|
|
|
|
if(*involvedFactorIsIt == i) {
|
|
|
|
|
// If the current factor is involved, add it to involved and increment involved iterator
|
|
|
|
|
involvedFactors.push_back((*this)[i]);
|
|
|
|
|
++ involvedFactorIsIt;
|
|
|
|
|
} else {
|
|
|
|
|
// If not involved, add to remaining
|
|
|
|
|
remainingFactors.push_back((*this)[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Do dense elimination on the involved factors
|
|
|
|
|
typename FactorGraph<FactorType>::EliminationResult eliminationResult =
|
|
|
|
|
eliminate(involvedFactors, nFrontals);
|
|
|
|
|
|
|
|
|
|
// Add the remaining factor back into the factor graph
|
|
|
|
|
remainingFactors.push_back(eliminationResult.second);
|
|
|
|
|
|
|
|
|
|
// Return the eliminated factor and remaining factor graph
|
|
|
|
|
return std::make_pair(eliminationResult.first, remainingFactors);
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-14 21:55:32 +08:00
|
|
|
/* ************************************************************************* */
|
2010-10-18 01:10:10 +08:00
|
|
|
template<class FACTOR>
|
|
|
|
|
void FactorGraph<FACTOR>::replace(size_t index, sharedFactor factor) {
|
2012-06-08 22:33:36 +08:00
|
|
|
if (index >= factors_.size()) throw std::invalid_argument(boost::str(
|
2010-07-14 21:55:32 +08:00
|
|
|
boost::format("Factor graph does not contain a factor with index %d.")
|
|
|
|
|
% index));
|
|
|
|
|
// Replace the factor
|
|
|
|
|
factors_[index] = factor;
|
2010-01-06 19:15:37 +08:00
|
|
|
}
|
|
|
|
|
|
2010-07-14 21:55:32 +08:00
|
|
|
/* ************************************************************************* */
|
2010-10-20 09:10:27 +08:00
|
|
|
template<class FACTORGRAPH>
|
|
|
|
|
FACTORGRAPH combine(const FACTORGRAPH& fg1, const FACTORGRAPH& fg2) {
|
2010-07-14 21:55:32 +08:00
|
|
|
// create new linear factor graph equal to the first one
|
2010-10-20 09:10:27 +08:00
|
|
|
FACTORGRAPH fg = fg1;
|
2010-07-14 21:55:32 +08:00
|
|
|
|
|
|
|
|
// add the second factors_ in the graph
|
|
|
|
|
fg.push_back(fg2);
|
|
|
|
|
|
|
|
|
|
return fg;
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-25 03:27:12 +08:00
|
|
|
/* ************************************************************************* */
|
2012-07-02 10:14:44 +08:00
|
|
|
template<class DERIVEDFACTOR, class KEY>
|
|
|
|
|
typename DERIVEDFACTOR::shared_ptr Combine(const FactorGraph<DERIVEDFACTOR>& factors,
|
2012-06-08 00:12:55 +08:00
|
|
|
const FastMap<KEY, std::vector<KEY> >& variableSlots) {
|
|
|
|
|
|
2012-06-08 22:34:03 +08:00
|
|
|
typedef const std::pair<const KEY, std::vector<KEY> > KeySlotPair;
|
2012-06-08 00:12:55 +08:00
|
|
|
// Local functional for getting keys out of key-value pairs
|
|
|
|
|
struct Local { static KEY FirstOf(const KeySlotPair& pr) { return pr.first; } };
|
|
|
|
|
|
2012-07-02 10:14:44 +08:00
|
|
|
return typename DERIVEDFACTOR::shared_ptr(new DERIVEDFACTOR(
|
2012-06-08 00:12:55 +08:00
|
|
|
boost::make_transform_iterator(variableSlots.begin(), &Local::FirstOf),
|
|
|
|
|
boost::make_transform_iterator(variableSlots.end(), &Local::FirstOf)));
|
2011-03-25 03:27:12 +08:00
|
|
|
}
|
|
|
|
|
|
2011-11-06 05:29:02 +08:00
|
|
|
/* ************************************************************************* */
|
2012-06-10 05:33:10 +08:00
|
|
|
// Recursive function to add factors in cliques to vector of factors_io
|
2011-11-13 05:19:46 +08:00
|
|
|
template<class FACTOR, class CONDITIONAL, class CLIQUE>
|
2011-11-06 05:29:02 +08:00
|
|
|
void _FactorGraph_BayesTree_adder(
|
2012-06-10 05:33:10 +08:00
|
|
|
std::vector<typename boost::shared_ptr<FACTOR> >& factors_io,
|
2011-11-13 05:19:46 +08:00
|
|
|
const typename BayesTree<CONDITIONAL,CLIQUE>::sharedClique& clique) {
|
2011-11-06 05:29:02 +08:00
|
|
|
|
|
|
|
|
if(clique) {
|
|
|
|
|
// Add factor from this clique
|
2012-06-10 05:33:10 +08:00
|
|
|
factors_io.push_back((*clique)->toFactor());
|
2011-11-06 05:29:02 +08:00
|
|
|
|
|
|
|
|
// Traverse children
|
2011-11-13 05:19:46 +08:00
|
|
|
typedef typename BayesTree<CONDITIONAL,CLIQUE>::sharedClique sharedClique;
|
2012-06-10 05:33:10 +08:00
|
|
|
BOOST_FOREACH(const sharedClique& child, clique->children())
|
|
|
|
|
_FactorGraph_BayesTree_adder<FACTOR,CONDITIONAL,CLIQUE>(factors_io, child);
|
2011-11-06 05:29:02 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
|
|
|
|
template<class FACTOR>
|
2011-11-13 05:19:46 +08:00
|
|
|
template<class CONDITIONAL, class CLIQUE>
|
|
|
|
|
FactorGraph<FACTOR>::FactorGraph(const BayesTree<CONDITIONAL,CLIQUE>& bayesTree) {
|
2011-11-06 05:29:02 +08:00
|
|
|
factors_.reserve(bayesTree.size());
|
2011-11-13 05:19:46 +08:00
|
|
|
_FactorGraph_BayesTree_adder<FACTOR,CONDITIONAL,CLIQUE>(factors_, bayesTree.root());
|
2011-11-06 05:29:02 +08:00
|
|
|
}
|
|
|
|
|
|
2010-07-14 21:55:32 +08:00
|
|
|
/* ************************************************************************* */
|
2010-03-30 15:27:10 +08:00
|
|
|
} // namespace gtsam
|