/** * @file inference-inl.h * @brief inference template definitions * @author Frank Dellaert */ #pragma once #include "inference.h" #include "FactorGraph-inl.h" #include "BayesNet-inl.h" #include "Key.h" using namespace std; namespace gtsam { /* ************************************************************************* */ /* eliminate one node from the factor graph */ /* ************************************************************************* */ template boost::shared_ptr eliminateOne(FactorGraph& graph, const Symbol& key) { // combine the factors of all nodes connected to the variable to be eliminated // if no factors are connected to key, returns an empty factor boost::shared_ptr joint_factor = removeAndCombineFactors(graph,key); // eliminate that joint factor boost::shared_ptr factor; boost::shared_ptr conditional; boost::tie(conditional, factor) = joint_factor->eliminate(key); // add new factor on separator back into the graph if (!factor->empty()) graph.push_back(factor); // return the conditional Gaussian return conditional; } /* ************************************************************************* */ // This doubly templated function is generic. There is a GaussianFactorGraph // version that returns a more specific GaussianBayesNet. // Note, you will need to include this file to instantiate the function. /* ************************************************************************* */ template BayesNet eliminate(FactorGraph& factorGraph, const Ordering& ordering) { BayesNet bayesNet; // empty BOOST_FOREACH(Symbol key, ordering) { boost::shared_ptr cg = eliminateOne(factorGraph,key); bayesNet.push_back(cg); } return bayesNet; } /* ************************************************************************* */ template pair< BayesNet, FactorGraph > factor(const BayesNet& bn, const Ordering& keys) { // Convert to factor graph FactorGraph factorGraph(bn); // Get the keys of all variables and remove all keys we want the marginal for Ordering ord = bn.ordering(); BOOST_FOREACH(const Symbol& key, keys) ord.remove(key); // TODO: O(n*k), faster possible? // eliminate partially, BayesNet conditional = eliminate(factorGraph,ord); // at this moment, the factor graph only encodes P(keys) return make_pair(conditional,factorGraph); } /* ************************************************************************* */ template FactorGraph marginalize(const BayesNet& bn, const Ordering& keys) { // factor P(X,Y) as P(X|Y)P(Y), where Y corresponds to keys pair< BayesNet, FactorGraph > factors = gtsam::factor(bn,keys); // throw away conditional, return marginal P(Y) return factors.second; } /* ************************************************************************* */ // pair marginalGaussian(const GaussianFactorGraph& fg, const Symbol& key) { // // // todo: this does not use colamd! // // list ord; // BOOST_FOREACH(const Symbol& k, fg.keys()) { // if(k != key) // ord.push_back(k); // } // Ordering ordering(ord); // // // Now make another factor graph where we eliminate all the other variables // GaussianFactorGraph marginal(fg); // marginal.eliminate(ordering); // // GaussianFactor::shared_ptr factor; // for(size_t i=0; ikeys().size() != 1 || factor->keys().front() != key) // throw runtime_error("Didn't get the right marginal!"); // // VectorConfig mean_cfg(marginal.optimize(Ordering(key))); // Matrix A(factor->get_A(key)); // // return make_pair(mean_cfg[key], inverse(prod(trans(A), A))); // } /* ************************************************************************* */ } // namespace gtsam