gtsam  4.0.0
gtsam
NonlinearClusterTree.h
Go to the documentation of this file.
1 
7 #pragma once
8 
11 #include <gtsam/inference/ClusterTree.h>
12 
13 namespace gtsam {
14 class NonlinearClusterTree : public ClusterTree<NonlinearFactorGraph> {
15  public:
17 
18  struct NonlinearCluster : Cluster {
19  // Given graph, index, add factors with specified keys into
20  // Factors are erased in the graph
21  // TODO(frank): fairly hacky and inefficient. Think about iterating the graph once instead
22  NonlinearCluster(const VariableIndex& variableIndex, const KeyVector& keys,
23  NonlinearFactorGraph* graph) {
24  for (const Key key : keys) {
25  std::vector<NonlinearFactor::shared_ptr> factors;
26  for (auto i : variableIndex[key])
27  if (graph->at(i)) {
28  factors.push_back(graph->at(i));
29  graph->remove(i);
30  }
31  Cluster::addFactors(key, factors);
32  }
33  }
34 
35  GaussianFactorGraph::shared_ptr linearize(const Values& values) {
36  return factors.linearize(values);
37  }
38 
39  static NonlinearCluster* DownCast(const boost::shared_ptr<Cluster>& cluster) {
40  auto nonlinearCluster = boost::dynamic_pointer_cast<NonlinearCluster>(cluster);
41  if (!nonlinearCluster)
42  throw std::runtime_error("Expected NonlinearCluster");
43  return nonlinearCluster.get();
44  }
45 
46  // linearize local custer factors straight into hessianFactor, which is returned
47  // If no ordering given, uses colamd
48  HessianFactor::shared_ptr linearizeToHessianFactor(
49  const Values& values, boost::optional<Ordering> ordering = boost::none,
50  const NonlinearFactorGraph::Dampen& dampen = nullptr) const {
51  if (!ordering)
52  ordering.reset(Ordering::ColamdConstrainedFirst(factors, orderedFrontalKeys, true));
53  return factors.linearizeToHessianFactor(values, *ordering, dampen);
54  }
55 
56  // Recursively eliminate subtree rooted at this Cluster into a Bayes net and factor on parent
57  // TODO(frank): Use TBB to support deep trees and parallelism
58  std::pair<GaussianBayesNet, HessianFactor::shared_ptr> linearizeAndEliminate(
59  const Values& values, boost::optional<Ordering> ordering = boost::none,
60  const NonlinearFactorGraph::Dampen& dampen = nullptr) const {
61  // Linearize and create HessianFactor f(front,separator)
62  HessianFactor::shared_ptr localFactor = linearizeToHessianFactor(values, ordering, dampen);
63 
64  // Get contributions f(front) from children, as well as p(children|front)
65  GaussianBayesNet bayesNet;
66  for (const auto& child : children) {
67  auto message = DownCast(child)->linearizeAndEliminate(values, &bayesNet);
68  message->updateHessian(localFactor.get());
69  }
70  auto gaussianConditional = localFactor->eliminateCholesky(orderedFrontalKeys);
71  bayesNet.add(gaussianConditional);
72  return {bayesNet, localFactor};
73  }
74 
75  // Recursively eliminate subtree rooted at this Cluster
76  // Version that updates existing Bayes net and returns a new Hessian factor on parent clique
77  // It is possible to pass in a nullptr for the bayesNet if only interested in the new factor
78  HessianFactor::shared_ptr linearizeAndEliminate(
79  const Values& values, GaussianBayesNet* bayesNet,
80  boost::optional<Ordering> ordering = boost::none,
81  const NonlinearFactorGraph::Dampen& dampen = nullptr) const {
82  auto bayesNet_newFactor_pair = linearizeAndEliminate(values, ordering, dampen);
83  if (bayesNet) {
84  bayesNet->push_back(bayesNet_newFactor_pair.first);
85  }
86  return bayesNet_newFactor_pair.second;
87  }
88  };
89 
90  // Linearize and update linearization point with values
91  Values updateCholesky(const Values& values) {
92  GaussianBayesNet bayesNet;
93  for (const auto& root : roots_) {
94  auto result = NonlinearCluster::DownCast(root)->linearizeAndEliminate(values);
95  bayesNet.push_back(result.first);
96  }
97  VectorValues delta = bayesNet.optimize();
98  return values.retract(delta);
99  }
100 };
101 } // namespace gtsam
A non-templated config holding any types of Manifold-group elements.
Definition: Values.h:70
Gaussian Bayes Tree, the result of eliminating a GaussianJunctionTree.
Definition: NonlinearClusterTree.h:18
boost::shared_ptr< This > shared_ptr
shared_ptr to this class
Definition: GaussianFactorGraph.h:74
std::uint64_t Key
Integer nonlinear key type.
Definition: types.h:57
The VariableIndex class computes and stores the block column structure of a factor graph.
Definition: VariableIndex.h:43
A cluster-tree is associated with a factor graph and is defined as in Koller-Friedman: each node k re...
Definition: ClusterTree.h:25
boost::shared_ptr< This > shared_ptr
A shared_ptr to this class.
Definition: HessianFactor.h:110
Definition: NonlinearClusterTree.h:14
Factor Graph Constsiting of non-linear factors.
This class represents a collection of vector-valued variables associated each with a unique integer i...
Definition: VectorValues.h:73
A Bayes net made from linear-Gaussian densities.
Definition: GaussianBayesNet.h:30
FastVector< Key > KeyVector
Define collection type once and for all - also used in wrappers.
Definition: Key.h:56
static Ordering ColamdConstrainedFirst(const FACTOR_GRAPH &graph, const KeyVector &constrainFirst, bool forceOrder=false)
Compute a fill-reducing ordering using constrained COLAMD from a factor graph (see details for note o...
Definition: Ordering.h:128
std::function< void(const boost::shared_ptr< HessianFactor > &hessianFactor)> Dampen
typdef for dampen functions used below
Definition: NonlinearFactorGraph.h:146
VectorValues optimize() const
Solve the GaussianBayesNet, i.e. return , by back-substitution.
Definition: GaussianBayesNet.cpp:40
Values retract(const VectorValues &delta) const
Add a delta config to current config and returns a new config.
Definition: Values.cpp:102
A non-linear factor graph is a graph of non-Gaussian, i.e.
Definition: NonlinearFactorGraph.h:77
Global functions in a separate testing namespace.
Definition: chartTesting.h:28
std::enable_if< std::is_base_of< FactorType, DERIVEDFACTOR >::value >::type add(boost::shared_ptr< DERIVEDFACTOR > factor)
Add a factor directly using a shared_ptr.
Definition: FactorGraph.h:243
std::enable_if< std::is_base_of< FactorType, DERIVEDFACTOR >::value >::type push_back(boost::shared_ptr< DERIVEDFACTOR > factor)
Add a factor directly using a shared_ptr.
Definition: FactorGraph.h:159