gtsam  3.2.1
gtsam
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ClusterTree-inst.h
Go to the documentation of this file.
1 
10 #include <gtsam/base/timing.h>
15 
16 #include <boost/foreach.hpp>
17 #include <boost/bind.hpp>
18 
19 namespace gtsam
20 {
21  namespace
22  {
23  /* ************************************************************************* */
24  // Elimination traversal data - stores a pointer to the parent data and collects the factors
25  // resulting from elimination of the children. Also sets up BayesTree cliques with parent and
26  // child pointers.
27  template<class CLUSTERTREE>
28  struct EliminationData {
29  EliminationData* const parentData;
30  size_t myIndexInParent;
31  FastVector<typename CLUSTERTREE::sharedFactor> childFactors;
32  boost::shared_ptr<typename CLUSTERTREE::BayesTreeType::Node> bayesTreeNode;
33  EliminationData(EliminationData* _parentData, size_t nChildren) :
34  parentData(_parentData),
35  bayesTreeNode(boost::make_shared<typename CLUSTERTREE::BayesTreeType::Node>())
36  {
37  if(parentData) {
38  myIndexInParent = parentData->childFactors.size();
39  parentData->childFactors.push_back(typename CLUSTERTREE::sharedFactor());
40  } else {
41  myIndexInParent = 0;
42  }
43  // Set up BayesTree parent and child pointers
44  if(parentData) {
45  if(parentData->parentData) // If our parent is not the dummy node
46  bayesTreeNode->parent_ = parentData->bayesTreeNode;
47  parentData->bayesTreeNode->children.push_back(bayesTreeNode);
48  }
49  }
50  };
51 
52  /* ************************************************************************* */
53  // Elimination pre-order visitor - just creates the EliminationData structure for the visited
54  // node.
55  template<class CLUSTERTREE>
56  EliminationData<CLUSTERTREE> eliminationPreOrderVisitor(
57  const typename CLUSTERTREE::sharedNode& node, EliminationData<CLUSTERTREE>& parentData)
58  {
59  EliminationData<CLUSTERTREE> myData(&parentData, node->children.size());
60  myData.bayesTreeNode->problemSize_ = node->problemSize();
61  return myData;
62  }
63 
64  /* ************************************************************************* */
65  // Elimination post-order visitor - combine the child factors with our own factors, add the
66  // resulting conditional to the BayesTree, and add the remaining factor to the parent.
67  template<class CLUSTERTREE>
68  struct EliminationPostOrderVisitor
69  {
70  const typename CLUSTERTREE::Eliminate& eliminationFunction;
71  typename CLUSTERTREE::BayesTreeType::Nodes& nodesIndex;
72  EliminationPostOrderVisitor(const typename CLUSTERTREE::Eliminate& eliminationFunction,
73  typename CLUSTERTREE::BayesTreeType::Nodes& nodesIndex) :
74  eliminationFunction(eliminationFunction), nodesIndex(nodesIndex) {}
75  void operator()(const typename CLUSTERTREE::sharedNode& node, EliminationData<CLUSTERTREE>& myData)
76  {
77  // Typedefs
78  typedef typename CLUSTERTREE::sharedFactor sharedFactor;
79  typedef typename CLUSTERTREE::FactorType FactorType;
80  typedef typename CLUSTERTREE::FactorGraphType FactorGraphType;
81  typedef typename CLUSTERTREE::ConditionalType ConditionalType;
82  typedef typename CLUSTERTREE::BayesTreeType::Node BTNode;
83 
84  // Gather factors
85  FactorGraphType gatheredFactors;
86  gatheredFactors.reserve(node->factors.size() + node->children.size());
87  gatheredFactors += node->factors;
88  gatheredFactors += myData.childFactors;
89 
90  // Check for Bayes tree orphan subtrees, and add them to our children
91  BOOST_FOREACH(const sharedFactor& f, node->factors)
92  {
93  if(const BayesTreeOrphanWrapper<BTNode>* asSubtree = dynamic_cast<const BayesTreeOrphanWrapper<BTNode>*>(f.get()))
94  {
95  myData.bayesTreeNode->children.push_back(asSubtree->clique);
96  asSubtree->clique->parent_ = myData.bayesTreeNode;
97  }
98  }
99 
100  // Do dense elimination step
101  std::pair<boost::shared_ptr<ConditionalType>, boost::shared_ptr<FactorType> > eliminationResult =
102  eliminationFunction(gatheredFactors, Ordering(node->keys));
103 
104  // Store conditional in BayesTree clique, and in the case of ISAM2Clique also store the remaining factor
105  myData.bayesTreeNode->setEliminationResult(eliminationResult);
106 
107  // Fill nodes index - we do this here instead of calling insertRoot at the end to avoid
108  // putting orphan subtrees in the index - they'll already be in the index of the ISAM2
109  // object they're added to.
110  BOOST_FOREACH(const Key& j, myData.bayesTreeNode->conditional()->frontals())
111  nodesIndex.insert(std::make_pair(j, myData.bayesTreeNode));
112 
113  // Store remaining factor in parent's gathered factors
114  if(!eliminationResult.second->empty())
115  myData.parentData->childFactors[myData.myIndexInParent] = eliminationResult.second;
116  }
117  };
118  }
119 
120  /* ************************************************************************* */
121  template<class BAYESTREE, class GRAPH>
123  const std::string& s, const KeyFormatter& keyFormatter) const
124  {
125  std::cout << s;
126  BOOST_FOREACH(Key j, keys)
127  std::cout << j << " ";
128  std::cout << "problemSize = " << problemSize_ << std::endl;
129  }
130 
131  /* ************************************************************************* */
132  template<class BAYESTREE, class GRAPH>
134  const std::string& s, const KeyFormatter& keyFormatter) const
135  {
136  treeTraversal::PrintForest(*this, s, keyFormatter);
137  }
138 
139  /* ************************************************************************* */
140  template<class BAYESTREE, class GRAPH>
142  {
143  // Start by duplicating the tree.
144  roots_ = treeTraversal::CloneForest(other);
145 
146  // Assign the remaining factors - these are pointers to factors in the original factor graph and
147  // we do not clone them.
148  remainingFactors_ = other.remainingFactors_;
149 
150  return *this;
151  }
152 
153  /* ************************************************************************* */
154  template<class BAYESTREE, class GRAPH>
155  std::pair<boost::shared_ptr<BAYESTREE>, boost::shared_ptr<GRAPH> >
157  {
158  gttic(ClusterTree_eliminate);
159  // Do elimination (depth-first traversal). The rootsContainer stores a 'dummy' BayesTree node
160  // that contains all of the roots as its children. rootsContainer also stores the remaining
161  // uneliminated factors passed up from the roots.
162  boost::shared_ptr<BayesTreeType> result = boost::make_shared<BayesTreeType>();
163  EliminationData<This> rootsContainer(0, roots_.size());
164  EliminationPostOrderVisitor<This> visitorPost(function, result->nodes_);
165  {
166  TbbOpenMPMixedScope threadLimiter; // Limits OpenMP threads since we're mixing TBB and OpenMP
167  treeTraversal::DepthFirstForestParallel(*this, rootsContainer,
168  eliminationPreOrderVisitor<This>, visitorPost, 10);
169  }
170 
171  // Create BayesTree from roots stored in the dummy BayesTree node.
172  result->roots_.insert(result->roots_.end(), rootsContainer.bayesTreeNode->children.begin(), rootsContainer.bayesTreeNode->children.end());
173 
174  // Add remaining factors that were not involved with eliminated variables
175  boost::shared_ptr<FactorGraphType> allRemainingFactors = boost::make_shared<FactorGraphType>();
176  allRemainingFactors->reserve(remainingFactors_.size() + rootsContainer.childFactors.size());
177  allRemainingFactors->push_back(remainingFactors_.begin(), remainingFactors_.end());
178  BOOST_FOREACH(const sharedFactor& factor, rootsContainer.childFactors)
179  if(factor)
180  allRemainingFactors->push_back(factor);
181 
182  // Return result
183  return std::make_pair(result, allRemainingFactors);
184  }
185 
186 }
Bayes Tree is a tree of cliques of a Bayes Chain.
FastVector< boost::shared_ptr< typename FOREST::Node > > CloneForest(const FOREST &forest)
Clone a tree, copy-constructing new nodes (calling boost::make_shared) and setting up child pointers ...
Definition: treeTraversal-inst.h:189
std::pair< boost::shared_ptr< BayesTreeType >, boost::shared_ptr< FactorGraphType > > eliminate(const Eliminate &function) const
Eliminate the factors to a Bayes tree and remaining factor graph.
Definition: ClusterTree-inst.h:156
Timing utilities.
FactorGraphType::Eliminate Eliminate
Typedef for an eliminate subroutine.
Definition: ClusterTree.h:37
void DepthFirstForestParallel(FOREST &forest, DATA &rootData, VISITOR_PRE &visitorPre, VISITOR_POST &visitorPost, int problemSizeThreshold=10)
Traverse a forest depth-first with pre-order and post-order visits.
Definition: treeTraversal-inst.h:152
size_t Key
Integer nonlinear key type.
Definition: types.h:59
Keys keys
Frontal keys of this node.
Definition: ClusterTree.h:44
This & operator=(const This &other)
Assignment operator - makes a deep copy of the tree structure, but only pointers to factors are copie...
Definition: ClusterTree-inst.h:141
void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const
Print the cluster tree.
Definition: ClusterTree-inst.h:133
void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const
print this node
Definition: ClusterTree-inst.h:122
void PrintForest(const FOREST &forest, std::string str, const KeyFormatter &keyFormatter)
Print a tree, prefixing each line with str, and formatting keys using keyFormatter.
Definition: treeTraversal-inst.h:218
Collects factorgraph fragments defined on variable clusters, arranged in a tree.
boost::function< std::string(Key)> KeyFormatter
Typedef for a function to format a key, i.e. to convert it to a string.
Definition: types.h:62
An object whose scope defines a block where TBB and OpenMP parallelism are mixed. ...
Definition: types.h:258
A cluster-tree is associated with a factor graph and is defined as in Koller-Friedman: each node k re...
Definition: BayesTree.h:33