BayesTreeMarginalizationHelper.h
Go to the documentation of this file.
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 
20 // \callgraph
21 #pragma once
22 
23 #include <unordered_map>
24 #include <unordered_set>
25 #include <deque>
28 #include <gtsam/base/debug.h>
29 #include "gtsam_unstable/dllexport.h"
30 
31 namespace gtsam {
32 
36 template <typename BayesTree>
37 class GTSAM_UNSTABLE_EXPORT BayesTreeMarginalizationHelper {
38 
39 public:
40  using Clique = typename BayesTree::Clique;
42 
66  static std::unordered_set<Key>
68  const BayesTree& bayesTree,
69  const KeyVector& marginalizableKeys) {
70  const bool debug = ISDEBUG("BayesTreeMarginalizationHelper");
71 
72  std::unordered_set<const Clique*> additionalCliques =
73  gatherAdditionalCliquesToReEliminate(bayesTree, marginalizableKeys);
74 
75  std::unordered_set<Key> additionalKeys;
76  for (const Clique* clique : additionalCliques) {
77  addCliqueToKeySet(clique, &additionalKeys);
78  }
79 
80  if (debug) {
81  std::cout << "BayesTreeMarginalizationHelper: Additional keys to re-eliminate: ";
82  for (const Key& key : additionalKeys) {
83  std::cout << DefaultKeyFormatter(key) << " ";
84  }
85  std::cout << std::endl;
86  }
87 
88  return additionalKeys;
89  }
90 
91  protected:
97  static std::unordered_set<const Clique*>
99  const BayesTree& bayesTree,
100  const KeyVector& marginalizableKeys) {
101  std::unordered_set<const Clique*> additionalCliques;
102  std::unordered_set<Key> marginalizableKeySet(
103  marginalizableKeys.begin(), marginalizableKeys.end());
104  CachedSearch cachedSearch;
105 
106  // Check each clique that contains a marginalizable key
107  for (const Clique* clique :
108  getCliquesContainingKeys(bayesTree, marginalizableKeySet)) {
109  if (additionalCliques.count(clique)) {
110  // The clique has already been visited. This can happen when an
111  // ancestor of the current clique also contain some marginalizable
112  // varaibles and it's processed beore the current.
113  continue;
114  }
115 
116  if (needsReelimination(clique, marginalizableKeySet, &cachedSearch)) {
117  // Add the current clique
118  additionalCliques.insert(clique);
119 
120  // Then add the dependent cliques
121  gatherDependentCliques(clique, marginalizableKeySet, &additionalCliques,
122  &cachedSearch);
123  }
124  }
125  return additionalCliques;
126  }
127 
135  static std::unordered_set<const Clique*> getCliquesContainingKeys(
136  const BayesTree& bayesTree,
137  const std::unordered_set<Key>& keysOfInterest) {
138  std::unordered_set<const Clique*> cliques;
139  for (const Key& key : keysOfInterest) {
140  cliques.insert(bayesTree[key].get());
141  }
142  return cliques;
143  }
144 
148  struct CachedSearch {
149  std::unordered_map<const Clique*, bool> wholeMarginalizableCliques;
150  std::unordered_map<const Clique*, bool> wholeMarginalizableSubtrees;
151  };
152 
159  const Clique* clique,
160  const std::unordered_set<Key>& marginalizableKeys,
161  CachedSearch* cache) {
162  auto it = cache->wholeMarginalizableCliques.find(clique);
163  if (it != cache->wholeMarginalizableCliques.end()) {
164  return it->second;
165  } else {
166  bool ret = true;
167  for (Key key : clique->conditional()->frontals()) {
168  if (!marginalizableKeys.count(key)) {
169  ret = false;
170  break;
171  }
172  }
173  cache->wholeMarginalizableCliques.insert({clique, ret});
174  return ret;
175  }
176  }
177 
184  const Clique* subtree,
185  const std::unordered_set<Key>& marginalizableKeys,
186  CachedSearch* cache) {
187  auto it = cache->wholeMarginalizableSubtrees.find(subtree);
188  if (it != cache->wholeMarginalizableSubtrees.end()) {
189  return it->second;
190  } else {
191  bool ret = true;
192  if (isWholeCliqueMarginalizable(subtree, marginalizableKeys, cache)) {
193  for (const sharedClique& child : subtree->children) {
194  if (!isWholeSubtreeMarginalizable(child.get(), marginalizableKeys, cache)) {
195  ret = false;
196  break;
197  }
198  }
199  } else {
200  ret = false;
201  }
202  cache->wholeMarginalizableSubtrees.insert({subtree, ret});
203  return ret;
204  }
205  }
206 
215  static bool needsReelimination(
216  const Clique* clique,
217  const std::unordered_set<Key>& marginalizableKeys,
218  CachedSearch* cache) {
219  bool hasNonMarginalizableAhead = false;
220 
221  // Check each frontal variable in order
222  for (Key key : clique->conditional()->frontals()) {
223  if (marginalizableKeys.count(key)) {
224  // If we've seen non-marginalizable variables before this one,
225  // we need to reeliminate
226  if (hasNonMarginalizableAhead) {
227  return true;
228  }
229 
230  // Check if any child depends on this marginalizable key and the
231  // subtree rooted at that child contains non-marginalizables.
232  for (const sharedClique& child : clique->children) {
233  if (hasDependency(child.get(), key) &&
234  !isWholeSubtreeMarginalizable(child.get(), marginalizableKeys, cache)) {
235  return true;
236  }
237  }
238  } else {
239  hasNonMarginalizableAhead = true;
240  }
241  }
242  return false;
243  }
244 
253  const Clique* rootClique,
254  const std::unordered_set<Key>& marginalizableKeys,
255  std::unordered_set<const Clique*>* additionalCliques,
256  CachedSearch* cache) {
257  std::vector<const Clique*> dependentChildren;
258  dependentChildren.reserve(rootClique->children.size());
259  for (const sharedClique& child : rootClique->children) {
260  if (additionalCliques->count(child.get())) {
261  // This child has already been visited. This can happen if the
262  // child itself contains a marginalizable variable and it's
263  // processed before the current rootClique.
264  continue;
265  }
266  if (hasDependency(child.get(), marginalizableKeys)) {
267  dependentChildren.push_back(child.get());
268  }
269  }
270  gatherDependentCliquesFromChildren(
271  dependentChildren, marginalizableKeys, additionalCliques, cache);
272  }
273 
278  const std::vector<const Clique*>& dependentChildren,
279  const std::unordered_set<Key>& marginalizableKeys,
280  std::unordered_set<const Clique*>* additionalCliques,
281  CachedSearch* cache) {
282  std::deque<const Clique*> descendants(
283  dependentChildren.begin(), dependentChildren.end());
284  while (!descendants.empty()) {
285  const Clique* descendant = descendants.front();
286  descendants.pop_front();
287 
288  // If the subtree rooted at this descendant contains non-marginalizables,
289  // it must lie on a path from the root clique to a clique containing
290  // non-marginalizables at the leaf side.
291  if (!isWholeSubtreeMarginalizable(descendant, marginalizableKeys, cache)) {
292  additionalCliques->insert(descendant);
293 
294  // Add children of the current descendant to the set descendants.
295  for (const sharedClique& child : descendant->children) {
296  if (additionalCliques->count(child.get())) {
297  // This child has already been visited.
298  continue;
299  } else {
300  descendants.push_back(child.get());
301  }
302  }
303  }
304  }
305  }
306 
313  static void addCliqueToKeySet(
314  const Clique* clique,
315  std::unordered_set<Key>* additionalKeys) {
316  for (Key key : clique->conditional()->frontals()) {
317  additionalKeys->insert(key);
318  }
319  }
320 
328  static bool hasDependency(
329  const Clique* clique, Key key) {
330  auto& conditional = clique->conditional();
331  if (std::find(conditional->beginParents(),
332  conditional->endParents(), key)
333  != conditional->endParents()) {
334  return true;
335  } else {
336  return false;
337  }
338  }
339 
343  static bool hasDependency(
344  const Clique* clique, const std::unordered_set<Key>& keys) {
345  auto& conditional = clique->conditional();
346  for (auto it = conditional->beginParents();
347  it != conditional->endParents(); ++it) {
348  if (keys.count(*it)) {
349  return true;
350  }
351  }
352 
353  return false;
354  }
355 };
356 // BayesTreeMarginalizationHelper
357 
358 }
keys
const KeyVector keys
Definition: testRegularImplicitSchurFactor.cpp:40
BayesTree.h
Bayes Tree is a tree of cliques of a Bayes Chain.
gtsam::BayesTreeMarginalizationHelper::isWholeSubtreeMarginalizable
static bool isWholeSubtreeMarginalizable(const Clique *subtree, const std::unordered_set< Key > &marginalizableKeys, CachedSearch *cache)
Definition: BayesTreeMarginalizationHelper.h:183
ret
DenseIndex ret
Definition: level1_cplx_impl.h:44
BayesTreeCliqueBase.h
Base class for cliques of a BayesTree.
gtsam::BayesTreeMarginalizationHelper::getCliquesContainingKeys
static std::unordered_set< const Clique * > getCliquesContainingKeys(const BayesTree &bayesTree, const std::unordered_set< Key > &keysOfInterest)
Definition: BayesTreeMarginalizationHelper.h:135
gtsam::KeyVector
FastVector< Key > KeyVector
Define collection type once and for all - also used in wrappers.
Definition: Key.h:92
gtsam::BayesTreeMarginalizationHelper::gatherAdditionalKeysToReEliminate
static std::unordered_set< Key > gatherAdditionalKeysToReEliminate(const BayesTree &bayesTree, const KeyVector &marginalizableKeys)
Definition: BayesTreeMarginalizationHelper.h:67
gtsam::BayesTreeMarginalizationHelper
Definition: BayesTreeMarginalizationHelper.h:37
gtsam::DefaultKeyFormatter
KeyFormatter DefaultKeyFormatter
Assign default key formatter.
Definition: Key.cpp:30
ISDEBUG
#define ISDEBUG(S)
Definition: debug.h:60
gtsam::BayesTreeMarginalizationHelper::needsReelimination
static bool needsReelimination(const Clique *clique, const std::unordered_set< Key > &marginalizableKeys, CachedSearch *cache)
Definition: BayesTreeMarginalizationHelper.h:215
gtsam::BayesTreeMarginalizationHelper::CachedSearch
Definition: BayesTreeMarginalizationHelper.h:148
gtsam::BayesTreeMarginalizationHelper::isWholeCliqueMarginalizable
static bool isWholeCliqueMarginalizable(const Clique *clique, const std::unordered_set< Key > &marginalizableKeys, CachedSearch *cache)
Definition: BayesTreeMarginalizationHelper.h:158
gtsam::BayesTreeMarginalizationHelper::CachedSearch::wholeMarginalizableCliques
std::unordered_map< const Clique *, bool > wholeMarginalizableCliques
Definition: BayesTreeMarginalizationHelper.h:149
gtsam::BayesTreeMarginalizationHelper::gatherDependentCliques
static void gatherDependentCliques(const Clique *rootClique, const std::unordered_set< Key > &marginalizableKeys, std::unordered_set< const Clique * > *additionalCliques, CachedSearch *cache)
Definition: BayesTreeMarginalizationHelper.h:252
debug
static constexpr bool debug
Definition: testDiscreteBayesTree.cpp:31
gtsam::BayesTreeMarginalizationHelper::sharedClique
typename BayesTree::sharedClique sharedClique
Definition: BayesTreeMarginalizationHelper.h:41
gtsam::BayesTreeMarginalizationHelper::CachedSearch::wholeMarginalizableSubtrees
std::unordered_map< const Clique *, bool > wholeMarginalizableSubtrees
Definition: BayesTreeMarginalizationHelper.h:150
gtsam::BayesTreeMarginalizationHelper::hasDependency
static bool hasDependency(const Clique *clique, Key key)
Definition: BayesTreeMarginalizationHelper.h:328
gtsam::BayesTreeMarginalizationHelper::gatherDependentCliquesFromChildren
static void gatherDependentCliquesFromChildren(const std::vector< const Clique * > &dependentChildren, const std::unordered_set< Key > &marginalizableKeys, std::unordered_set< const Clique * > *additionalCliques, CachedSearch *cache)
Definition: BayesTreeMarginalizationHelper.h:277
key
const gtsam::Symbol key('X', 0)
gtsam
traits
Definition: SFMdata.h:40
gtsam::BayesTree
Definition: BayesTree.h:66
gtsam::BayesTree::sharedClique
std::shared_ptr< Clique > sharedClique
Shared pointer to a clique.
Definition: BayesTree.h:74
gtsam::Key
std::uint64_t Key
Integer nonlinear key type.
Definition: types.h:97
gtsam::BayesTreeMarginalizationHelper::hasDependency
static bool hasDependency(const Clique *clique, const std::unordered_set< Key > &keys)
Definition: BayesTreeMarginalizationHelper.h:343
gtsam::BayesTreeMarginalizationHelper::Clique
typename BayesTree::Clique Clique
Definition: BayesTreeMarginalizationHelper.h:40
gtsam::BayesTreeMarginalizationHelper::addCliqueToKeySet
static void addCliqueToKeySet(const Clique *clique, std::unordered_set< Key > *additionalKeys)
Definition: BayesTreeMarginalizationHelper.h:313
get
Container::iterator get(Container &c, Position position)
Definition: stdlist_overload.cpp:29
gtsam::BayesTree::Clique
CLIQUE Clique
The clique type, normally BayesTreeClique.
Definition: BayesTree.h:73
gtsam::BayesTreeMarginalizationHelper::gatherAdditionalCliquesToReEliminate
static std::unordered_set< const Clique * > gatherAdditionalCliquesToReEliminate(const BayesTree &bayesTree, const KeyVector &marginalizableKeys)
Definition: BayesTreeMarginalizationHelper.h:98
debug.h
Global debugging flags.


gtsam
Author(s):
autogenerated on Sun Dec 22 2024 04:11:11