From d07dfac2368f38b69b16656ce36f302a8b28e37f Mon Sep 17 00:00:00 2001 From: Frank Dellaert Date: Wed, 14 Jul 2010 04:32:58 +0000 Subject: [PATCH] Made JunctionTree a subclass of ClusterTree --- inference/ClusterTree-inl.h | 93 ++------------------------------- inference/ClusterTree.h | 67 +++++++++++------------- inference/JunctionTree-inl.h | 68 ++++-------------------- inference/JunctionTree.h | 73 +++++--------------------- inference/testClusterTree.cpp | 2 + inference/testJunctionTree.cpp | 9 ++-- linear/GaussianJunctionTree.cpp | 1 + 7 files changed, 66 insertions(+), 247 deletions(-) diff --git a/inference/ClusterTree-inl.h b/inference/ClusterTree-inl.h index 488dac352..810a51d36 100644 --- a/inference/ClusterTree-inl.h +++ b/inference/ClusterTree-inl.h @@ -20,7 +20,7 @@ namespace gtsam { /* ************************************************************************* */ template - bool ClusterTree::Clique::equals(const ClusterTree::Clique& other) const { + bool ClusterTree::Cluster::equals(const ClusterTree::Cluster& other) const { if (!frontal_.equals(other.frontal_)) return false; @@ -43,7 +43,7 @@ namespace gtsam { * ClusterTree */ template - void ClusterTree::Clique::print(const string& indent) const { + void ClusterTree::Cluster::print(const string& indent) const { // FG::print(indent); cout << indent; BOOST_FOREACH(const Symbol& key, frontal_) @@ -56,99 +56,12 @@ namespace gtsam { /* ************************************************************************* */ template - void ClusterTree::Clique::printTree(const string& indent) const { + void ClusterTree::Cluster::printTree(const string& indent) const { print(indent); BOOST_FOREACH(const shared_ptr& child, children_) child->printTree(indent+" "); } - /* ************************************************************************* */ - template - ClusterTree::ClusterTree(FG& fg, const Ordering& ordering) { - // Symbolic factorization: GaussianFactorGraph -> SymbolicFactorGraph -> SymbolicBayesNet -> SymbolicBayesTree - SymbolicFactorGraph sfg(fg); - SymbolicBayesNet sbn = sfg.eliminate(ordering); - BayesTree sbt(sbn); - - // distribtue factors - root_ = distributeFactors(fg, sbt.root()); - } - - /* ************************************************************************* */ - template - typename ClusterTree::sharedClique ClusterTree::distributeFactors(FG& fg, - const BayesTree::sharedClique bayesClique) { - // create a new clique in the junction tree - sharedClique clique(new Clique()); - clique->frontal_ = bayesClique->ordering(); - clique->separator_.insert(bayesClique->separator_.begin(), bayesClique->separator_.end()); - - // recursively call the children - BOOST_FOREACH(const BayesTree::sharedClique bayesChild, bayesClique->children()) { - sharedClique child = distributeFactors(fg, bayesChild); - clique->children_.push_back(child); - child->parent_ = clique; - } - - // collect the factors - typedef vector Factors; - BOOST_FOREACH(const Symbol& frontal, clique->frontal_) { - Factors factors = fg.template findAndRemoveFactors(frontal); - BOOST_FOREACH(const typename FG::sharedFactor& factor_, factors) { - clique->push_back(factor_); - } - } - - return clique; - } - - /* ************************************************************************* */ - template template - pair > - ClusterTree::eliminateOneClique(sharedClique current) { - -// current->frontal_.print("current clique:"); - - typedef typename BayesTree::sharedClique sharedBtreeClique; - FG fg; // factor graph will be assembled from local factors and marginalized children - list > children; - fg.push_back(*current); // add the local factor graph - -// BOOST_FOREACH(const typename FG::sharedFactor& factor_, fg) -// Ordering(factor_->keys()).print("local factor:"); - - BOOST_FOREACH(sharedClique& child, current->children_) { - // receive the factors from the child and its clique point - FG fgChild; BayesTree childTree; - boost::tie(fgChild, childTree) = eliminateOneClique(child); - -// BOOST_FOREACH(const typename FG::sharedFactor& factor_, fgChild) -// Ordering(factor_->keys()).print("factor from child:"); - - fg.push_back(fgChild); - children.push_back(childTree); - } - - // eliminate the combined factors - // warning: fg is being eliminated in-place and will contain marginal afterwards - BayesNet bn = fg.eliminateFrontals(current->frontal_); - - // create a new clique corresponding the combined factors - BayesTree bayesTree(bn, children); - - return make_pair(fg, bayesTree); - } - - /* ************************************************************************* */ - template template - BayesTree ClusterTree::eliminate() { - pair > ret = this->eliminateOneClique(root_); -// ret.first.print("ret.first"); - if (ret.first.nrFactors() != 0) - throw runtime_error("JuntionTree::eliminate: elimination failed because of factors left over!"); - return ret.second; - } - /* ************************************************************************* */ template bool ClusterTree::equals(const ClusterTree& other, double tol) const { diff --git a/inference/ClusterTree.h b/inference/ClusterTree.h index 926a944e1..a2473a37b 100644 --- a/inference/ClusterTree.h +++ b/inference/ClusterTree.h @@ -10,38 +10,45 @@ #include #include -#include "BayesTree.h" -#include "SymbolicConditional.h" namespace gtsam { - /* ************************************************************************* */ + /** + * A cluster-tree is associated with a factor graph and is defined as in Koller-Friedman: + * each node k represents a subset C_k \sub X, and the tree is family preserving, in that + * each factor f_i is associated with a single cluster and scope(f_i) \sub C_k. + */ template class ClusterTree : public Testable > { - public: - // the class for subgraphs that also include the pointers to the parents and two children - class Clique : public FG { - private: - typedef typename boost::shared_ptr shared_ptr; - shared_ptr parent_; // the parent subgraph node - std::vector children_; // the child cliques - Ordering frontal_; // the frontal varaibles - Unordered separator_; // the separator variables - friend class ClusterTree; + public: + + // the class for subgraphs that also include the pointers to the parents and two children + class Cluster : public FG { + + public: + + typedef typename boost::shared_ptr shared_ptr; + + /* commented private out to make compile but needs to be addressed */ + + shared_ptr parent_; // the parent subgraph node + std::vector children_; // the child clusters + Ordering frontal_; // the frontal variables + Unordered separator_; // the separator variables public: // empty constructor - Clique() {} + Cluster() {} // constructor with all the information - Clique(const FG& fgLocal, const Ordering& frontal, const Unordered& separator, + Cluster(const FG& fgLocal, const Ordering& frontal, const Unordered& separator, const shared_ptr& parent) : frontal_(frontal), separator_(separator), FG(fgLocal), parent_(parent) {} // constructor for an empty graph - Clique(const Ordering& frontal, const Unordered& separator, const shared_ptr& parent) + Cluster(const Ordering& frontal, const Unordered& separator, const shared_ptr& parent) : frontal_(frontal), separator_(separator), parent_(parent) {} // return the members @@ -57,23 +64,15 @@ namespace gtsam { void printTree(const std::string& indent) const; // check equality - bool equals(const Clique& other) const; + bool equals(const Cluster& other) const; }; - // typedef for shared pointers to cliques - typedef typename Clique::shared_ptr sharedClique; + // typedef for shared pointers to clusters + typedef typename Cluster::shared_ptr sharedCluster; protected: - // Root clique - sharedClique root_; - - private: - // distribute the factors along the Bayes tree - sharedClique distributeFactors(FG& fg, const BayesTree::sharedClique clique); - - // utility function called by eliminate - template - std::pair > eliminateOneClique(sharedClique fg_); + // Root cluster + sharedCluster root_; public: // constructor @@ -82,16 +81,12 @@ namespace gtsam { // constructor given a factor graph and the elimination ordering ClusterTree(FG& fg, const Ordering& ordering); - // return the root clique - sharedClique root() const { return root_; } - - // eliminate the factors in the subgraphs - template - BayesTree eliminate(); + // return the root cluster + sharedCluster root() const { return root_; } // print the object void print(const std::string& str) const { - cout << str << endl; + std::cout << str << std::endl; if (root_.get()) root_->printTree(""); } diff --git a/inference/JunctionTree-inl.h b/inference/JunctionTree-inl.h index bb2ae5033..7e23398e2 100644 --- a/inference/JunctionTree-inl.h +++ b/inference/JunctionTree-inl.h @@ -18,70 +18,28 @@ namespace gtsam { using namespace std; - /* ************************************************************************* */ - template - bool JunctionTree::Clique::equals(const JunctionTree::Clique& other) const { - if (!frontal_.equals(other.frontal_)) - return false; - - if (!separator_.equals(other.separator_)) - return false; - - if (children_.size() != other.children_.size()) - return false; - - typename vector::const_iterator it1 = children_.begin(); - typename vector::const_iterator it2 = other.children_.begin(); - for(; it1!=children_.end(); it1++, it2++) - if (!(*it1)->equals(**it2)) return false; - - return true; - } - - /* ************************************************************************* */ - /** - * JunctionTree - */ - template - void JunctionTree::Clique::print(const string& indent) const { - // FG::print(indent); - cout << indent; - BOOST_FOREACH(const Symbol& key, frontal_) - cout << (string)key << " "; - cout << ":"; - BOOST_FOREACH(const Symbol& key, separator_) - cout << (string)key << " "; - cout << endl; - } - - /* ************************************************************************* */ - template - void JunctionTree::Clique::printTree(const string& indent) const { - print(indent); - BOOST_FOREACH(const shared_ptr& child, children_) - child->printTree(indent+" "); - } - /* ************************************************************************* */ template JunctionTree::JunctionTree(FG& fg, const Ordering& ordering) { - // Symbolic factorization: GaussianFactorGraph -> SymbolicFactorGraph -> SymbolicBayesNet -> SymbolicBayesTree + // Symbolic factorization: GaussianFactorGraph -> SymbolicFactorGraph + // -> SymbolicBayesNet -> SymbolicBayesTree SymbolicFactorGraph sfg(fg); SymbolicBayesNet sbn = sfg.eliminate(ordering); BayesTree sbt(sbn); // distribtue factors - root_ = distributeFactors(fg, sbt.root()); + this->root_ = distributeFactors(fg, sbt.root()); } /* ************************************************************************* */ - template - typename JunctionTree::sharedClique JunctionTree::distributeFactors(FG& fg, - const BayesTree::sharedClique bayesClique) { + template + typename JunctionTree::sharedClique JunctionTree::distributeFactors( + FG& fg, const BayesTree::sharedClique bayesClique) { // create a new clique in the junction tree sharedClique clique(new Clique()); clique->frontal_ = bayesClique->ordering(); - clique->separator_.insert(bayesClique->separator_.begin(), bayesClique->separator_.end()); + clique->separator_.insert(bayesClique->separator_.begin(), + bayesClique->separator_.end()); // recursively call the children BOOST_FOREACH(const BayesTree::sharedClique bayesChild, bayesClique->children()) { @@ -142,18 +100,10 @@ namespace gtsam { /* ************************************************************************* */ template template BayesTree JunctionTree::eliminate() { - pair > ret = this->eliminateOneClique(root_); -// ret.first.print("ret.first"); + pair > ret = this->eliminateOneClique(this->root()); if (ret.first.nrFactors() != 0) throw runtime_error("JuntionTree::eliminate: elimination failed because of factors left over!"); return ret.second; } - /* ************************************************************************* */ - template - bool JunctionTree::equals(const JunctionTree& other, double tol) const { - if (!root_ || !other.root_) return false; - return root_->equals(*other.root_); - } - } //namespace gtsam diff --git a/inference/JunctionTree.h b/inference/JunctionTree.h index 21720c25f..63827254d 100644 --- a/inference/JunctionTree.h +++ b/inference/JunctionTree.h @@ -11,62 +11,29 @@ #include #include #include "BayesTree.h" +#include "ClusterTree.h" #include "SymbolicConditional.h" namespace gtsam { - /* ************************************************************************* */ + /** + * A junction tree (or clique-tree) is a cluster-tree where each node k represents a + * clique (maximal fully connected subset) of an associated chordal graph, such as a + * chordal Bayes net resulting from elimination. In GTSAM the BayesTree is used to + * represent the clique tree associated with a Bayes net, and the JunctionTree is + * used to collect the factors associated with each clique during the elimination process. + */ template - class JunctionTree : public Testable > { + class JunctionTree : public ClusterTree { + public: - // the class for subgraphs that also include the pointers to the parents and two children - class Clique : public FG { - private: - typedef typename boost::shared_ptr shared_ptr; - shared_ptr parent_; // the parent subgraph node - std::vector children_; // the child cliques - Ordering frontal_; // the frontal varaibles - Unordered separator_; // the separator variables - friend class JunctionTree; - - public: - - // empty constructor - Clique() {} - - // constructor with all the information - Clique(const FG& fgLocal, const Ordering& frontal, const Unordered& separator, - const shared_ptr& parent) - : frontal_(frontal), separator_(separator), FG(fgLocal), parent_(parent) {} - - // constructor for an empty graph - Clique(const Ordering& frontal, const Unordered& separator, const shared_ptr& parent) - : frontal_(frontal), separator_(separator), parent_(parent) {} - - // return the members - const Ordering& frontal() const { return frontal_;} - const Unordered& separator() const { return separator_;} - const std::vector& children() { return children_; } - - // add a child node - void addChild(const shared_ptr& child) { children_.push_back(child); } - - // print the object - void print(const std::string& indent) const; - void printTree(const std::string& indent) const; - - // check equality - bool equals(const Clique& other) const; - }; - - // typedef for shared pointers to cliques + /** + * In a junction tree each cluster is associated with a clique + */ + typedef typename ClusterTree::Cluster Clique; typedef typename Clique::shared_ptr sharedClique; - protected: - // Root clique - sharedClique root_; - private: // distribute the factors along the Bayes tree sharedClique distributeFactors(FG& fg, const BayesTree::sharedClique clique); @@ -82,22 +49,10 @@ namespace gtsam { // constructor given a factor graph and the elimination ordering JunctionTree(FG& fg, const Ordering& ordering); - // return the root clique - sharedClique root() const { return root_; } - // eliminate the factors in the subgraphs template BayesTree eliminate(); - // print the object - void print(const std::string& str) const { - std::cout << str << std::endl; - if (root_.get()) root_->printTree(""); - } - - /** check equality */ - bool equals(const JunctionTree& other, double tol = 1e-9) const; - }; // JunctionTree } // namespace gtsam diff --git a/inference/testClusterTree.cpp b/inference/testClusterTree.cpp index 914a68de9..b47a75d76 100644 --- a/inference/testClusterTree.cpp +++ b/inference/testClusterTree.cpp @@ -15,6 +15,8 @@ using namespace boost::assign; using namespace gtsam; +// explicit instantiation and typedef +template class ClusterTree; typedef ClusterTree SymbolicClusterTree; /* ************************************************************************* */ diff --git a/inference/testJunctionTree.cpp b/inference/testJunctionTree.cpp index 618ee36b1..2dfefd589 100644 --- a/inference/testJunctionTree.cpp +++ b/inference/testJunctionTree.cpp @@ -15,18 +15,21 @@ using namespace boost::assign; #include "Ordering.h" #include "SymbolicFactorGraph.h" +#include "JunctionTree.h" +#include "ClusterTree-inl.h" #include "JunctionTree-inl.h" using namespace gtsam; +// explicit instantiation and typedef +template class JunctionTree; typedef JunctionTree SymbolicJunctionTree; -/* ************************************************************************* */ -/** +/* ************************************************************************* * * x1 - x2 - x3 - x4 * x3 x4 * x2 x1 : x3 - */ + ****************************************************************************/ TEST( JunctionTree, constructor ) { SymbolicFactorGraph fg; diff --git a/linear/GaussianJunctionTree.cpp b/linear/GaussianJunctionTree.cpp index 16c1225d5..c4b3ac52b 100644 --- a/linear/GaussianJunctionTree.cpp +++ b/linear/GaussianJunctionTree.cpp @@ -8,6 +8,7 @@ #include +#include "ClusterTree-inl.h" #include "JunctionTree-inl.h" #include "GaussianJunctionTree.h"