HybridGaussianConditional.cpp
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 
21 #include <gtsam/base/utilities.h>
29 
30 namespace gtsam {
33  auto func = [](const GaussianConditional::shared_ptr &conditional)
35  double value = 0.0;
36  // Check if conditional is pruned
37  if (conditional) {
38  // Assign log(\sqrt(|2πΣ|)) = -log(1 / sqrt(|2πΣ|))
39  value = conditional->negLogConstant();
40  }
41  return {std::dynamic_pointer_cast<GaussianFactor>(conditional), value};
42  };
44 }
45 
47  const KeyVector &continuousFrontals, const KeyVector &continuousParents,
48  const DiscreteKeys &discreteParents,
50  : BaseFactor(CollectKeys(continuousFrontals, continuousParents),
51  discreteParents, GetFactorValuePairs(conditionals)),
52  BaseConditional(continuousFrontals.size()),
53  conditionals_(conditionals) {
54  // Calculate negLogConstant_ as the minimum of the negative-log normalizers of
55  // the conditionals, by visiting the decision tree:
56  negLogConstant_ = std::numeric_limits<double>::infinity();
58  [this](const GaussianConditional::shared_ptr &conditional) {
59  if (conditional) {
60  this->negLogConstant_ =
61  std::min(this->negLogConstant_, conditional->negLogConstant());
62  }
63  });
64 }
65 
66 /* *******************************************************************************/
69  return conditionals_;
70 }
71 
72 /* *******************************************************************************/
74  const KeyVector &continuousFrontals, const KeyVector &continuousParents,
75  const DiscreteKey &discreteParent,
76  const std::vector<GaussianConditional::shared_ptr> &conditionals)
77  : HybridGaussianConditional(continuousFrontals, continuousParents,
78  DiscreteKeys{discreteParent},
79  Conditionals({discreteParent}, conditionals)) {}
80 
81 /* *******************************************************************************/
83  const {
84  auto wrap = [this](const GaussianConditional::shared_ptr &gc) {
85  // First check if conditional has not been pruned
86  if (gc) {
87  const double Cgm_Kgcm = gc->negLogConstant() - this->negLogConstant_;
88  // If there is a difference in the covariances, we need to account for
89  // that since the error is dependent on the mode.
90  if (Cgm_Kgcm > 0.0) {
91  // We add a constant factor which will be used when computing
92  // the probability of the discrete variables.
93  Vector c(1);
94  c << std::sqrt(2.0 * Cgm_Kgcm);
95  auto constantFactor = std::make_shared<JacobianFactor>(c);
96  return GaussianFactorGraph{gc, constantFactor};
97  }
98  }
99  return GaussianFactorGraph{gc};
100  };
101  return {conditionals_, wrap};
102 }
103 
104 /* *******************************************************************************/
106  size_t total = 0;
107  conditionals_.visit([&total](const GaussianFactor::shared_ptr &node) {
108  if (node) total += 1;
109  });
110  return total;
111 }
112 
113 /* *******************************************************************************/
115  const DiscreteValues &discreteValues) const {
116  auto &ptr = conditionals_(discreteValues);
117  if (!ptr) return nullptr;
118  auto conditional = std::dynamic_pointer_cast<GaussianConditional>(ptr);
119  if (conditional)
120  return conditional;
121  else
122  throw std::logic_error(
123  "A HybridGaussianConditional unexpectedly contained a non-conditional");
124 }
125 
126 /* *******************************************************************************/
128  double tol) const {
129  const This *e = dynamic_cast<const This *>(&lf);
130  if (e == nullptr) return false;
131 
132  // This will return false if either conditionals_ is empty or e->conditionals_
133  // is empty, but not if both are empty or both are not empty:
134  if (conditionals_.empty() ^ e->conditionals_.empty()) return false;
135 
136  // Check the base and the factors:
137  return BaseFactor::equals(*e, tol) &&
138  conditionals_.equals(e->conditionals_,
141  return f1->equals(*(f2), tol);
142  });
143 }
144 
145 /* *******************************************************************************/
146 void HybridGaussianConditional::print(const std::string &s,
147  const KeyFormatter &formatter) const {
148  std::cout << (s.empty() ? "" : s + "\n");
149  if (isContinuous()) std::cout << "Continuous ";
150  if (isDiscrete()) std::cout << "Discrete ";
151  if (isHybrid()) std::cout << "Hybrid ";
153  std::cout << " Discrete Keys = ";
154  for (auto &dk : discreteKeys()) {
155  std::cout << "(" << formatter(dk.first) << ", " << dk.second << "), ";
156  }
157  std::cout << std::endl
158  << " logNormalizationConstant: " << -negLogConstant() << std::endl
159  << std::endl;
161  "", [&](Key k) { return formatter(k); },
162  [&](const GaussianConditional::shared_ptr &gf) -> std::string {
163  RedirectCout rd;
164  if (gf && !gf->empty()) {
165  gf->print("", formatter);
166  return rd.str();
167  } else {
168  return "nullptr";
169  }
170  });
171 }
172 
173 /* ************************************************************************* */
175  // Get all parent keys:
176  const auto range = parents();
177  KeyVector continuousParentKeys(range.begin(), range.end());
178  // Loop over all discrete keys:
179  for (const auto &discreteKey : discreteKeys()) {
180  const Key key = discreteKey.first;
181  // remove that key from continuousParentKeys:
182  continuousParentKeys.erase(std::remove(continuousParentKeys.begin(),
183  continuousParentKeys.end(), key),
184  continuousParentKeys.end());
185  }
186  return continuousParentKeys;
187 }
188 
189 /* ************************************************************************* */
191  const VectorValues &given) const {
192  for (auto &&kv : given) {
193  if (given.find(kv.first) == given.end()) {
194  return false;
195  }
196  }
197  return true;
198 }
199 
200 /* ************************************************************************* */
201 std::shared_ptr<HybridGaussianFactor> HybridGaussianConditional::likelihood(
202  const VectorValues &given) const {
203  if (!allFrontalsGiven(given)) {
204  throw std::runtime_error(
205  "HybridGaussianConditional::likelihood: given values are missing some "
206  "frontals.");
207  }
208 
209  const DiscreteKeys discreteParentKeys = discreteKeys();
210  const KeyVector continuousParentKeys = continuousParents();
211  const HybridGaussianFactor::FactorValuePairs likelihoods(
213  [&](const GaussianConditional::shared_ptr &conditional)
215  const auto likelihood_m = conditional->likelihood(given);
216  const double Cgm_Kgcm = conditional->negLogConstant() - negLogConstant_;
217  if (Cgm_Kgcm == 0.0) {
218  return {likelihood_m, 0.0};
219  } else {
220  // Add a constant to the likelihood in case the noise models
221  // are not all equal.
222  return {likelihood_m, Cgm_Kgcm};
223  }
224  });
225  return std::make_shared<HybridGaussianFactor>(
226  continuousParentKeys, discreteParentKeys, likelihoods);
227 }
228 
229 /* ************************************************************************* */
230 std::set<DiscreteKey> DiscreteKeysAsSet(const DiscreteKeys &discreteKeys) {
231  std::set<DiscreteKey> s(discreteKeys.begin(), discreteKeys.end());
232  return s;
233 }
234 
235 /* ************************************************************************* */
243 std::function<GaussianConditional::shared_ptr(
244  const Assignment<Key> &, const GaussianConditional::shared_ptr &)>
246  // Get the discrete keys as sets for the decision tree
247  // and the hybrid gaussian conditional.
248  auto discreteProbsKeySet = DiscreteKeysAsSet(discreteProbs.discreteKeys());
249  auto hybridGaussianCondKeySet = DiscreteKeysAsSet(this->discreteKeys());
250 
251  auto pruner = [discreteProbs, discreteProbsKeySet, hybridGaussianCondKeySet](
252  const Assignment<Key> &choices,
253  const GaussianConditional::shared_ptr &conditional)
255  // typecast so we can use this to get probability value
256  const DiscreteValues values(choices);
257 
258  // Case where the hybrid gaussian conditional has the same
259  // discrete keys as the decision tree.
260  if (hybridGaussianCondKeySet == discreteProbsKeySet) {
261  if (discreteProbs(values) == 0.0) {
262  // empty aka null pointer
263  std::shared_ptr<GaussianConditional> null;
264  return null;
265  } else {
266  return conditional;
267  }
268  } else {
269  std::vector<DiscreteKey> set_diff;
270  std::set_difference(
271  discreteProbsKeySet.begin(), discreteProbsKeySet.end(),
272  hybridGaussianCondKeySet.begin(), hybridGaussianCondKeySet.end(),
273  std::back_inserter(set_diff));
274 
275  const std::vector<DiscreteValues> assignments =
277  for (const DiscreteValues &assignment : assignments) {
278  DiscreteValues augmented_values(values);
279  augmented_values.insert(assignment);
280 
281  // If any one of the sub-branches are non-zero,
282  // we need this conditional.
283  if (discreteProbs(augmented_values) > 0.0) {
284  return conditional;
285  }
286  }
287  // If we are here, it means that all the sub-branches are 0,
288  // so we prune.
289  return nullptr;
290  }
291  };
292  return pruner;
293 }
294 
295 /* *******************************************************************************/
297  // Functional which loops over all assignments and create a set of
298  // GaussianConditionals
299  auto pruner = prunerFunc(discreteProbs);
300 
301  auto pruned_conditionals = conditionals_.apply(pruner);
302  conditionals_.root_ = pruned_conditionals.root_;
303 }
304 
305 /* *******************************************************************************/
307  const VectorValues &continuousValues) const {
308  // functor to calculate (double) logProbability value from
309  // GaussianConditional.
310  auto probFunc =
311  [continuousValues](const GaussianConditional::shared_ptr &conditional) {
312  if (conditional) {
313  return conditional->logProbability(continuousValues);
314  } else {
315  // Return arbitrarily small logProbability if conditional is null
316  // Conditional is null if it is pruned out.
317  return -1e20;
318  }
319  };
320  return DecisionTree<Key, double>(conditionals_, probFunc);
321 }
322 
323 /* *******************************************************************************/
325  const HybridValues &values) const {
326  auto conditional = conditionals_(values.discrete());
327  return conditional->logProbability(values.continuous());
328 }
329 
330 /* *******************************************************************************/
332  auto conditional = conditionals_(values.discrete());
333  return conditional->evaluate(values.continuous());
334 }
335 
336 } // namespace gtsam
gtsam::Conditional::print
void print(const std::string &s="Conditional", const KeyFormatter &formatter=DefaultKeyFormatter) const
Definition: Conditional-inst.h:30
GaussianFactorGraph.h
Linear Factor Graph where all factors are Gaussians.
gtsam::DecisionTreeFactor
Definition: DecisionTreeFactor.h:44
gtsam::HybridValues
Definition: HybridValues.h:37
test_constructor::f1
auto f1
Definition: testHybridNonlinearFactor.cpp:56
HybridGaussianConditional.h
A hybrid conditional in the Conditional Linear Gaussian scheme.
s
RealScalar s
Definition: level1_cplx_impl.h:126
e
Array< double, 1, 3 > e(1./3., 0.5, 2.)
gtsam::HybridGaussianConditional::conditionals_
Conditionals conditionals_
Definition: HybridGaussianConditional.h:66
gtsam::DecisionTree::empty
bool empty() const
Check if tree is empty.
Definition: DecisionTree.h:269
c
Scalar Scalar * c
Definition: benchVecAdd.cpp:17
gtsam::DecisionTree::equals
bool equals(const DecisionTree &other, const CompareFunc &compare=&DefaultCompare) const
Definition: DecisionTree-inl.h:899
gtsam::HybridFactor::isDiscrete
bool isDiscrete() const
True if this is a factor of discrete variables only.
Definition: HybridFactor.h:122
gtsam::RedirectCout
Definition: base/utilities.h:16
gtsam::HybridFactor
Definition: HybridFactor.h:54
wrap
mxArray * wrap(const Class &value)
Definition: matlab.h:126
formatter
const KeyFormatter & formatter
Definition: treeTraversal-inst.h:204
f2
double f2(const Vector2 &x)
Definition: testNumericalDerivative.cpp:56
gtsam::DiscreteKeys
DiscreteKeys is a set of keys that can be assembled using the & operator.
Definition: DiscreteKey.h:41
gtsam::DecisionTree::print
void print(const std::string &s, const LabelFormatter &labelFormatter, const ValueFormatter &valueFormatter) const
GTSAM-style print.
Definition: DecisionTree-inl.h:905
GaussianBayesNet.h
Chordal Bayes Net, the result of eliminating a factor graph.
gtsam::HybridFactor::isHybrid
bool isHybrid() const
True is this is a Discrete-Continuous factor.
Definition: HybridFactor.h:128
gtsam::Vector
Eigen::VectorXd Vector
Definition: Vector.h:38
gtsam::KeyVector
FastVector< Key > KeyVector
Define collection type once and for all - also used in wrappers.
Definition: Key.h:92
HybridGaussianFactor.h
A set of GaussianFactors, indexed by a set of discrete keys.
utilities.h
equal_constants::conditionals
const std::vector< GaussianConditional::shared_ptr > conditionals
Definition: testHybridGaussianConditional.cpp:50
gtsam::AlgebraicDecisionTree< Key >
size
Scalar Scalar int size
Definition: benchVecAdd.cpp:17
gtsam::range
Double_ range(const Point2_ &p, const Point2_ &q)
Definition: slam/expressions.h:30
gtsam::GaussianFactorGraph
Definition: GaussianFactorGraph.h:73
gtsam::HybridGaussianConditional::logProbability
AlgebraicDecisionTree< Key > logProbability(const VectorValues &continuousValues) const
Compute logProbability of the HybridGaussianConditional as a tree.
Definition: HybridGaussianConditional.cpp:306
gtsam::HybridGaussianConditional::evaluate
double evaluate(const HybridValues &values) const override
Calculate probability density for given values.
Definition: HybridGaussianConditional.cpp:331
gtsam::DecisionTree::root_
NodePtr root_
A DecisionTree just contains the root. TODO(dellaert): make protected.
Definition: DecisionTree.h:150
gtsam::GaussianFactorValuePair
std::pair< GaussianFactor::shared_ptr, double > GaussianFactorValuePair
Alias for pair of GaussianFactor::shared_pointer and a double value.
Definition: HybridGaussianFactor.h:37
gtsam::VectorValues
Definition: VectorValues.h:74
gtsam::DiscreteValues::CartesianProduct
static std::vector< DiscreteValues > CartesianProduct(const DiscreteKeys &keys)
Return a vector of DiscreteValues, one for each possible combination of values.
Definition: DiscreteValues.h:85
gtsam::KeyFormatter
std::function< std::string(Key)> KeyFormatter
Typedef for a function to format a key, i.e. to convert it to a string.
Definition: Key.h:35
gtsam::HybridGaussianConditional::nrComponents
size_t nrComponents() const
Returns the total number of continuous components.
Definition: HybridGaussianConditional.cpp:105
gtsam::GaussianFactor::shared_ptr
std::shared_ptr< This > shared_ptr
shared_ptr to this class
Definition: GaussianFactor.h:42
gtsam::GetFactorValuePairs
HybridGaussianFactor::FactorValuePairs GetFactorValuePairs(const HybridGaussianConditional::Conditionals &conditionals)
Definition: HybridGaussianConditional.cpp:31
gtsam::HybridGaussianConditional
A conditional of gaussian conditionals indexed by discrete variables, as part of a Bayes Network....
Definition: HybridGaussianConditional.h:53
gtsam::DecisionTree::visit
void visit(Func f) const
Visit all leaves in depth-first fashion.
Definition: DecisionTree-inl.h:769
gtsam::CollectKeys
KeyVector CollectKeys(const KeyVector &continuousKeys, const DiscreteKeys &discreteKeys)
Definition: HybridFactor.cpp:23
gtsam::HybridGaussianConditional::prune
void prune(const DecisionTreeFactor &discreteProbs)
Prune the decision tree of Gaussian factors as per the discrete discreteProbs.
Definition: HybridGaussianConditional.cpp:296
gtsam::Assignment< Key >
gtsam::HybridGaussianConditional::continuousParents
KeyVector continuousParents() const
Returns the continuous keys among the parents.
Definition: HybridGaussianConditional.cpp:174
gtsam::HybridFactor::isContinuous
bool isContinuous() const
True if this is a factor of continuous variables only.
Definition: HybridFactor.h:125
gtsam::Conditional
Definition: Conditional.h:63
gtsam::DecisionTree::apply
DecisionTree apply(const Unary &op) const
Definition: DecisionTree-inl.h:922
gtsam::HybridGaussianConditional::likelihood
std::shared_ptr< HybridGaussianFactor > likelihood(const VectorValues &given) const
Definition: HybridGaussianConditional.cpp:201
gtsam::Conditional< HybridGaussianFactor, HybridGaussianConditional >::parents
Parents parents() const
Definition: Conditional.h:148
gtsam::HybridGaussianFactor::equals
bool equals(const HybridFactor &lf, double tol=1e-9) const override
equals
Definition: HybridGaussianFactor.cpp:86
gtsam::HybridGaussianConditional::prunerFunc
std::function< GaussianConditional::shared_ptr(const Assignment< Key > &, const GaussianConditional::shared_ptr &)> prunerFunc(const DecisionTreeFactor &discreteProbs)
Helper function to get the pruner functor.
Definition: HybridGaussianConditional.cpp:245
key
const gtsam::Symbol key('X', 0)
gtsam::HybridGaussianConditional::asGaussianFactorGraphTree
GaussianFactorGraphTree asGaussianFactorGraphTree() const
Convert a HybridGaussianConditional of conditionals into a DecisionTree of Gaussian factor graphs.
Definition: HybridGaussianConditional.cpp:82
gtsam::DecisionTree
a decision tree is a function from assignments to values.
Definition: DecisionTree.h:63
gtsam::DiscreteKeysAsSet
std::set< DiscreteKey > DiscreteKeysAsSet(const DiscreteKeys &discreteKeys)
Return the DiscreteKey vector as a set.
Definition: HybridGaussianConditional.cpp:230
gtsam
traits
Definition: chartTesting.h:28
DiscreteValues.h
gtsam::HybridGaussianFactor::FactorValuePairs
DecisionTree< Key, GaussianFactorValuePair > FactorValuePairs
typedef for Decision Tree of Gaussian factors and arbitrary value.
Definition: HybridGaussianFactor.h:68
gtsam::DiscreteValues
Definition: DiscreteValues.h:34
leaf::values
leaf::MyValues values
gtsam::HybridGaussianConditional::operator()
GaussianConditional::shared_ptr operator()(const DiscreteValues &discreteValues) const
Return the conditional Gaussian for the given discrete assignment.
Definition: HybridGaussianConditional.cpp:114
gtsam::DiscreteKey
std::pair< Key, size_t > DiscreteKey
Definition: DiscreteKey.h:38
gtsam::HybridGaussianConditional::allFrontalsGiven
bool allFrontalsGiven(const VectorValues &given) const
Check whether given has values for all frontal keys.
Definition: HybridGaussianConditional.cpp:190
gtsam::DiscreteValues::insert
std::pair< iterator, bool > insert(const value_type &value)
Definition: DiscreteValues.h:68
gtsam::HybridGaussianConditional::equals
bool equals(const HybridFactor &lf, double tol=1e-9) const override
Test equality with base HybridFactor.
Definition: HybridGaussianConditional.cpp:127
gtsam::HybridGaussianFactor
Implementation of a discrete-conditioned hybrid factor. Implements a joint discrete-continuous factor...
Definition: HybridGaussianFactor.h:59
gtsam::HybridGaussianConditional::conditionals
const Conditionals & conditionals() const
Getter for the underlying Conditionals DecisionTree.
Definition: HybridGaussianConditional.cpp:68
gtsam::GaussianConditional::shared_ptr
std::shared_ptr< This > shared_ptr
shared_ptr to this class
Definition: GaussianConditional.h:46
gtsam::HybridGaussianConditional::negLogConstant_
double negLogConstant_
Definition: HybridGaussianConditional.h:69
min
#define min(a, b)
Definition: datatypes.h:19
gtsam::HybridGaussianConditional::negLogConstant
double negLogConstant() const override
Return log normalization constant in negative log space.
Definition: HybridGaussianConditional.h:161
gtsam::tol
const G double tol
Definition: Group.h:79
gtsam::HybridGaussianConditional::HybridGaussianConditional
HybridGaussianConditional()=default
Default constructor, mainly for serialization.
gtsam::DiscreteFactor::discreteKeys
DiscreteKeys discreteKeys() const
Return all the discrete keys associated with this factor.
Definition: DiscreteFactor.cpp:32
func
Definition: benchGeometry.cpp:23
gtsam::Key
std::uint64_t Key
Integer nonlinear key type.
Definition: types.h:97
HybridValues.h
gtsam::HybridFactor::discreteKeys
const DiscreteKeys & discreteKeys() const
Return the discrete keys for this factor.
Definition: HybridFactor.h:134
test_callbacks.value
value
Definition: test_callbacks.py:160
gtsam::HybridGaussianConditional::print
void print(const std::string &s="HybridGaussianConditional\n", const KeyFormatter &formatter=DefaultKeyFormatter) const override
Print utility.
Definition: HybridGaussianConditional.cpp:146
ceres::sqrt
Jet< T, N > sqrt(const Jet< T, N > &f)
Definition: jet.h:418
gtsam::RedirectCout::str
std::string str() const
return the string
Definition: utilities.cpp:5
Conditional-inst.h


gtsam
Author(s):
autogenerated on Wed Sep 25 2024 03:02:32