gtsam  3.2.1
gtsam
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
EliminateableFactorGraph-inst.h
1 /* ----------------------------------------------------------------------------
2 
3  * GTSAM Copyright 2010, Georgia Tech Research Corporation,
4  * Atlanta, Georgia 30332-0415
5  * All Rights Reserved
6  * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
7 
8  * See LICENSE for the license information
9 
10  * -------------------------------------------------------------------------- */
11 
19 #pragma once
20 
23 #include <boost/tuple/tuple.hpp>
24 
25 namespace gtsam {
26 
27  /* ************************************************************************* */
28  template<class FACTORGRAPH>
29  boost::shared_ptr<typename EliminateableFactorGraph<FACTORGRAPH>::BayesNetType>
31  OptionalOrdering ordering, const Eliminate& function, OptionalVariableIndex variableIndex) const
32  {
33  if(ordering && variableIndex) {
34  gttic(eliminateSequential);
35  // Do elimination
36  EliminationTreeType etree(asDerived(), *variableIndex, *ordering);
37  boost::shared_ptr<BayesNetType> bayesNet;
38  boost::shared_ptr<FactorGraphType> factorGraph;
39  boost::tie(bayesNet,factorGraph) = etree.eliminate(function);
40  // If any factors are remaining, the ordering was incomplete
41  if(!factorGraph->empty())
43  // Return the Bayes net
44  return bayesNet;
45  }
46  else if(!variableIndex) {
47  // If no VariableIndex provided, compute one and call this function again IMPORTANT: we check
48  // for no variable index first so that it's always computed if we need to call COLAMD because
49  // no Ordering is provided.
50  return eliminateSequential(ordering, function, VariableIndex(asDerived()));
51  }
52  else /*if(!ordering)*/ {
53  // If no Ordering provided, compute one and call this function again. We are guaranteed to
54  // have a VariableIndex already here because we computed one if needed in the previous 'else'
55  // block.
56  return eliminateSequential(Ordering::COLAMD(*variableIndex), function);
57  }
58  }
59 
60  /* ************************************************************************* */
61  template<class FACTORGRAPH>
62  boost::shared_ptr<typename EliminateableFactorGraph<FACTORGRAPH>::BayesTreeType>
64  OptionalOrdering ordering, const Eliminate& function, OptionalVariableIndex variableIndex) const
65  {
66  if(ordering && variableIndex) {
67  gttic(eliminateMultifrontal);
68  // Do elimination with given ordering
69  EliminationTreeType etree(asDerived(), *variableIndex, *ordering);
70  JunctionTreeType junctionTree(etree);
71  boost::shared_ptr<BayesTreeType> bayesTree;
72  boost::shared_ptr<FactorGraphType> factorGraph;
73  boost::tie(bayesTree,factorGraph) = junctionTree.eliminate(function);
74  // If any factors are remaining, the ordering was incomplete
75  if(!factorGraph->empty())
77  // Return the Bayes tree
78  return bayesTree;
79  }
80  else if(!variableIndex) {
81  // If no VariableIndex provided, compute one and call this function again IMPORTANT: we check
82  // for no variable index first so that it's always computed if we need to call COLAMD because
83  // no Ordering is provided.
84  return eliminateMultifrontal(ordering, function, VariableIndex(asDerived()));
85  }
86  else /*if(!ordering)*/ {
87  // If no Ordering provided, compute one and call this function again. We are guaranteed to
88  // have a VariableIndex already here because we computed one if needed in the previous 'else'
89  // block.
90  return eliminateMultifrontal(Ordering::COLAMD(*variableIndex), function);
91  }
92  }
93 
94  /* ************************************************************************* */
95  template<class FACTORGRAPH>
96  std::pair<boost::shared_ptr<typename EliminateableFactorGraph<FACTORGRAPH>::BayesNetType>, boost::shared_ptr<FACTORGRAPH> >
98  const Ordering& ordering, const Eliminate& function, OptionalVariableIndex variableIndex) const
99  {
100  if(variableIndex) {
101  gttic(eliminatePartialSequential);
102  // Do elimination
103  EliminationTreeType etree(asDerived(), *variableIndex, ordering);
104  return etree.eliminate(function);
105  } else {
106  // If no variable index is provided, compute one and call this function again
107  return eliminatePartialSequential(ordering, function, VariableIndex(asDerived()));
108  }
109  }
110 
111  /* ************************************************************************* */
112  template<class FACTORGRAPH>
113  std::pair<boost::shared_ptr<typename EliminateableFactorGraph<FACTORGRAPH>::BayesNetType>, boost::shared_ptr<FACTORGRAPH> >
115  const std::vector<Key>& variables, const Eliminate& function, OptionalVariableIndex variableIndex) const
116  {
117  if(variableIndex) {
118  gttic(eliminatePartialSequential);
119  // Compute full ordering
120  Ordering fullOrdering = Ordering::COLAMDConstrainedFirst(*variableIndex, variables);
121 
122  // Split off the part of the ordering for the variables being eliminated
123  Ordering ordering(fullOrdering.begin(), fullOrdering.begin() + variables.size());
124  return eliminatePartialSequential(ordering, function, variableIndex);
125  } else {
126  // If no variable index is provided, compute one and call this function again
127  return eliminatePartialSequential(variables, function, VariableIndex(asDerived()));
128  }
129  }
130 
131  /* ************************************************************************* */
132  template<class FACTORGRAPH>
133  std::pair<boost::shared_ptr<typename EliminateableFactorGraph<FACTORGRAPH>::BayesTreeType>, boost::shared_ptr<FACTORGRAPH> >
135  const Ordering& ordering, const Eliminate& function, OptionalVariableIndex variableIndex) const
136  {
137  if(variableIndex) {
138  gttic(eliminatePartialMultifrontal);
139  // Do elimination
140  EliminationTreeType etree(asDerived(), *variableIndex, ordering);
141  JunctionTreeType junctionTree(etree);
142  return junctionTree.eliminate(function);
143  } else {
144  // If no variable index is provided, compute one and call this function again
145  return eliminatePartialMultifrontal(ordering, function, VariableIndex(asDerived()));
146  }
147  }
148 
149  /* ************************************************************************* */
150  template<class FACTORGRAPH>
151  std::pair<boost::shared_ptr<typename EliminateableFactorGraph<FACTORGRAPH>::BayesTreeType>, boost::shared_ptr<FACTORGRAPH> >
153  const std::vector<Key>& variables, const Eliminate& function, OptionalVariableIndex variableIndex) const
154  {
155  if(variableIndex) {
156  gttic(eliminatePartialMultifrontal);
157  // Compute full ordering
158  Ordering fullOrdering = Ordering::COLAMDConstrainedFirst(*variableIndex, variables);
159 
160  // Split off the part of the ordering for the variables being eliminated
161  Ordering ordering(fullOrdering.begin(), fullOrdering.begin() + variables.size());
162  return eliminatePartialMultifrontal(ordering, function, variableIndex);
163  } else {
164  // If no variable index is provided, compute one and call this function again
165  return eliminatePartialMultifrontal(variables, function, VariableIndex(asDerived()));
166  }
167  }
168 
169  /* ************************************************************************* */
170  template<class FACTORGRAPH>
171  boost::shared_ptr<typename EliminateableFactorGraph<FACTORGRAPH>::BayesNetType>
173  boost::variant<const Ordering&, const std::vector<Key>&> variables,
174  OptionalOrdering marginalizedVariableOrdering,
175  const Eliminate& function, OptionalVariableIndex variableIndex) const
176  {
177  if(variableIndex)
178  {
179  if(marginalizedVariableOrdering)
180  {
181  gttic(marginalMultifrontalBayesNet);
182  // An ordering was provided for the marginalized variables, so we can first eliminate them
183  // in the order requested.
184  boost::shared_ptr<BayesTreeType> bayesTree;
185  boost::shared_ptr<FactorGraphType> factorGraph;
186  boost::tie(bayesTree,factorGraph) =
187  eliminatePartialMultifrontal(*marginalizedVariableOrdering, function, *variableIndex);
188 
189  if(const Ordering* varsAsOrdering = boost::get<const Ordering&>(&variables))
190  {
191  // An ordering was also provided for the unmarginalized variables, so we can also
192  // eliminate them in the order requested.
193  return factorGraph->eliminateSequential(*varsAsOrdering, function);
194  }
195  else
196  {
197  // No ordering was provided for the unmarginalized variables, so order them with COLAMD.
198  return factorGraph->eliminateSequential(boost::none, function);
199  }
200  }
201  else
202  {
203  // No ordering was provided for the marginalized variables, so order them using constrained
204  // COLAMD.
205  bool unmarginalizedAreOrdered = (boost::get<const Ordering&>(&variables) != 0);
206  const std::vector<Key>* variablesOrOrdering =
207  unmarginalizedAreOrdered ?
208  boost::get<const Ordering&>(&variables) : boost::get<const std::vector<Key>&>(&variables);
209 
210  Ordering totalOrdering =
211  Ordering::COLAMDConstrainedLast(*variableIndex, *variablesOrOrdering, unmarginalizedAreOrdered);
212 
213  // Split up ordering
214  const size_t nVars = variablesOrOrdering->size();
215  Ordering marginalizationOrdering(totalOrdering.begin(), totalOrdering.end() - nVars);
216  Ordering marginalVarsOrdering(totalOrdering.end() - nVars, totalOrdering.end());
217 
218  // Call this function again with the computed orderings
219  return marginalMultifrontalBayesNet(marginalVarsOrdering, marginalizationOrdering, function, *variableIndex);
220  }
221  } else {
222  // If no variable index is provided, compute one and call this function again
223  VariableIndex index(asDerived());
224  return marginalMultifrontalBayesNet(variables, marginalizedVariableOrdering, function, index);
225  }
226  }
227 
228  /* ************************************************************************* */
229  template<class FACTORGRAPH>
230  boost::shared_ptr<typename EliminateableFactorGraph<FACTORGRAPH>::BayesTreeType>
232  boost::variant<const Ordering&, const std::vector<Key>&> variables,
233  OptionalOrdering marginalizedVariableOrdering,
234  const Eliminate& function, OptionalVariableIndex variableIndex) const
235  {
236  if(variableIndex)
237  {
238  if(marginalizedVariableOrdering)
239  {
240  gttic(marginalMultifrontalBayesTree);
241  // An ordering was provided for the marginalized variables, so we can first eliminate them
242  // in the order requested.
243  boost::shared_ptr<BayesTreeType> bayesTree;
244  boost::shared_ptr<FactorGraphType> factorGraph;
245  boost::tie(bayesTree,factorGraph) =
246  eliminatePartialMultifrontal(*marginalizedVariableOrdering, function, *variableIndex);
247 
248  if(const Ordering* varsAsOrdering = boost::get<const Ordering&>(&variables))
249  {
250  // An ordering was also provided for the unmarginalized variables, so we can also
251  // eliminate them in the order requested.
252  return factorGraph->eliminateMultifrontal(*varsAsOrdering, function);
253  }
254  else
255  {
256  // No ordering was provided for the unmarginalized variables, so order them with COLAMD.
257  return factorGraph->eliminateMultifrontal(boost::none, function);
258  }
259  }
260  else
261  {
262  // No ordering was provided for the marginalized variables, so order them using constrained
263  // COLAMD.
264  bool unmarginalizedAreOrdered = (boost::get<const Ordering&>(&variables) != 0);
265  const std::vector<Key>* variablesOrOrdering =
266  unmarginalizedAreOrdered ?
267  boost::get<const Ordering&>(&variables) : boost::get<const std::vector<Key>&>(&variables);
268 
269  Ordering totalOrdering =
270  Ordering::COLAMDConstrainedLast(*variableIndex, *variablesOrOrdering, unmarginalizedAreOrdered);
271 
272  // Split up ordering
273  const size_t nVars = variablesOrOrdering->size();
274  Ordering marginalizationOrdering(totalOrdering.begin(), totalOrdering.end() - nVars);
275  Ordering marginalVarsOrdering(totalOrdering.end() - nVars, totalOrdering.end());
276 
277  // Call this function again with the computed orderings
278  return marginalMultifrontalBayesTree(marginalVarsOrdering, marginalizationOrdering, function, *variableIndex);
279  }
280  } else {
281  // If no variable index is provided, compute one and call this function again
282  return marginalMultifrontalBayesTree(variables, marginalizedVariableOrdering, function, VariableIndex(asDerived()));
283  }
284  }
285 
286  /* ************************************************************************* */
287  template<class FACTORGRAPH>
288  boost::shared_ptr<FACTORGRAPH>
290  const std::vector<Key>& variables,
291  const Eliminate& function, OptionalVariableIndex variableIndex) const
292  {
293  if(variableIndex)
294  {
295  // Compute a total ordering for all variables
296  Ordering totalOrdering = Ordering::COLAMDConstrainedLast(*variableIndex, variables);
297 
298  // Split out the part for the marginalized variables
299  Ordering marginalizationOrdering(totalOrdering.begin(), totalOrdering.end() - variables.size());
300 
301  // Eliminate and return the remaining factor graph
302  return eliminatePartialMultifrontal(marginalizationOrdering, function, *variableIndex).second;
303  }
304  else
305  {
306  // If no variable index is provided, compute one and call this function again
307  return marginal(variables, function, VariableIndex(asDerived()));
308  }
309  }
310 
311 
312 }
An inference algorithm was called with inconsistent arguments.
Definition: inferenceExceptions.h:29
std::pair< boost::shared_ptr< BayesTreeType >, boost::shared_ptr< FactorGraphType > > eliminatePartialMultifrontal(const Ordering &ordering, const Eliminate &function=EliminationTraitsType::DefaultEliminate, OptionalVariableIndex variableIndex=boost::none) const
Do multifrontal elimination of some variables, in ordering provided, to produce a Bayes tree and a re...
Definition: EliminateableFactorGraph-inst.h:134
Variable elimination algorithms for factor graphs.
boost::shared_ptr< BayesNetType > marginalMultifrontalBayesNet(boost::variant< const Ordering &, const std::vector< Key > & > variables, OptionalOrdering marginalizedVariableOrdering=boost::none, const Eliminate &function=EliminationTraitsType::DefaultEliminate, OptionalVariableIndex variableIndex=boost::none) const
Compute the marginal of the requested variables and return the result as a Bayes net.
Definition: EliminateableFactorGraph-inst.h:172
boost::optional< const VariableIndex & > OptionalVariableIndex
Typedef for an optional variable index as an argument to elimination functions.
Definition: EliminateableFactorGraph.h:95
static Ordering COLAMD(const FactorGraph< FACTOR > &graph)
Compute a fill-reducing ordering using COLAMD from a factor graph (see details for note on performanc...
Definition: Ordering.h:65
boost::shared_ptr< BayesTreeType > marginalMultifrontalBayesTree(boost::variant< const Ordering &, const std::vector< Key > & > variables, OptionalOrdering marginalizedVariableOrdering=boost::none, const Eliminate &function=EliminationTraitsType::DefaultEliminate, OptionalVariableIndex variableIndex=boost::none) const
Compute the marginal of the requested variables and return the result as a Bayes tree.
Definition: EliminateableFactorGraph-inst.h:231
boost::optional< const Ordering & > OptionalOrdering
Typedef for an optional ordering as an argument to elimination functions.
Definition: EliminateableFactorGraph.h:92
static Ordering COLAMDConstrainedLast(const FactorGraph< FACTOR > &graph, const std::vector< Key > &constrainLast, bool forceOrder=false)
Compute a fill-reducing ordering using constrained COLAMD from a factor graph (see details for note o...
Definition: Ordering.h:80
static Ordering COLAMDConstrainedFirst(const FactorGraph< FACTOR > &graph, const std::vector< Key > &constrainFirst, bool forceOrder=false)
Compute a fill-reducing ordering using constrained COLAMD from a factor graph (see details for note o...
Definition: Ordering.h:102
EliminationTraitsType::JunctionTreeType JunctionTreeType
Junction tree type that can do multifrontal elimination of this graph.
Definition: EliminateableFactorGraph.h:82
boost::function< EliminationResult(const FactorGraphType &, const Ordering &)> Eliminate
The function type that does a single dense elimination step on a subgraph.
Definition: EliminateableFactorGraph.h:89
The VariableIndex class computes and stores the block column structure of a factor graph...
Definition: VariableIndex.h:42
boost::shared_ptr< FactorGraphType > marginal(const std::vector< Key > &variables, const Eliminate &function=EliminationTraitsType::DefaultEliminate, OptionalVariableIndex variableIndex=boost::none) const
Compute the marginal factor graph of the requested variables.
Definition: EliminateableFactorGraph-inst.h:289
Exceptions that may be thrown by inference algorithms.
boost::shared_ptr< BayesTreeType > eliminateMultifrontal(OptionalOrdering ordering=boost::none, const Eliminate &function=EliminationTraitsType::DefaultEliminate, OptionalVariableIndex variableIndex=boost::none) const
Do multifrontal elimination of all variables to produce a Bayes tree.
Definition: EliminateableFactorGraph-inst.h:63
Definition: Ordering.h:30
EliminationTraitsType::EliminationTreeType EliminationTreeType
Elimination tree type that can do sequential elimination of this graph.
Definition: EliminateableFactorGraph.h:76
boost::shared_ptr< BayesNetType > eliminateSequential(OptionalOrdering ordering=boost::none, const Eliminate &function=EliminationTraitsType::DefaultEliminate, OptionalVariableIndex variableIndex=boost::none) const
Do sequential elimination of all variables to produce a Bayes net.
Definition: EliminateableFactorGraph-inst.h:30
std::pair< boost::shared_ptr< BayesNetType >, boost::shared_ptr< FactorGraphType > > eliminatePartialSequential(const Ordering &ordering, const Eliminate &function=EliminationTraitsType::DefaultEliminate, OptionalVariableIndex variableIndex=boost::none) const
Do sequential elimination of some variables, in ordering provided, to produce a Bayes net and a remai...
Definition: EliminateableFactorGraph-inst.h:97