testHybridGaussianFactorGraph.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 
12 /*
13  * @file testHybridGaussianFactorGraph.cpp
14  * @date Mar 11, 2022
15  * @author Fan Jiang
16  */
17 
18 #include <CppUnitLite/Test.h>
35 #include <gtsam/inference/Key.h>
37 #include <gtsam/inference/Symbol.h>
39 
40 #include <algorithm>
41 #include <cstddef>
42 #include <functional>
43 #include <iostream>
44 #include <iterator>
45 #include <numeric>
46 #include <vector>
47 
48 #include "Switching.h"
49 #include "TinyHybridExample.h"
50 
51 using namespace std;
52 using namespace gtsam;
53 
60 
61 // Set up sampling
62 std::mt19937_64 kRng(42);
63 
64 /* ************************************************************************* */
66  HybridConditional conditional;
67 
69 
70  hfg.emplace_shared<JacobianFactor>(X(0), I_3x3, Z_3x1);
71 
72  // Define a gaussian mixture conditional P(x0|x1, c0) and add it to the factor
73  // graph
74  GaussianMixture gm({X(0)}, {X(1)}, DiscreteKeys(DiscreteKey{M(0), 2}),
76  M(0),
77  std::make_shared<GaussianConditional>(
78  X(0), Z_3x1, I_3x3, X(1), I_3x3),
79  std::make_shared<GaussianConditional>(
80  X(0), Vector3::Ones(), I_3x3, X(1), I_3x3)));
81  hfg.add(gm);
82 
83  EXPECT_LONGS_EQUAL(2, hfg.size());
84 }
85 
86 /* ************************************************************************* */
87 TEST(HybridGaussianFactorGraph, EliminateSequential) {
88  // Test elimination of a single variable.
90 
91  hfg.emplace_shared<JacobianFactor>(0, I_3x3, Z_3x1);
92 
94 
95  EXPECT_LONGS_EQUAL(result.first->size(), 1);
96 }
97 
98 /* ************************************************************************* */
99 TEST(HybridGaussianFactorGraph, EliminateMultifrontal) {
100  // Test multifrontal elimination
102 
103  DiscreteKey m(M(1), 2);
104 
105  // Add priors on x0 and c1
106  hfg.add(JacobianFactor(X(0), I_3x3, Z_3x1));
107  hfg.add(DecisionTreeFactor(m, {2, 8}));
108 
110  ordering.push_back(X(0));
112 
113  EXPECT_LONGS_EQUAL(result.first->size(), 1);
114  EXPECT_LONGS_EQUAL(result.second->size(), 1);
115 }
116 
117 /* ************************************************************************* */
118 TEST(HybridGaussianFactorGraph, eliminateFullSequentialEqualChance) {
120 
121  // Add prior on x0
122  hfg.add(JacobianFactor(X(0), I_3x3, Z_3x1));
123 
124  // Add factor between x0 and x1
125  hfg.add(JacobianFactor(X(0), I_3x3, X(1), -I_3x3, Z_3x1));
126 
127  // Add a gaussian mixture factor ϕ(x1, c1)
128  DiscreteKey m1(M(1), 2);
130  M(1), std::make_shared<JacobianFactor>(X(1), I_3x3, Z_3x1),
131  std::make_shared<JacobianFactor>(X(1), I_3x3, Vector3::Ones()));
132  hfg.add(GaussianMixtureFactor({X(1)}, {m1}, dt));
133 
134  auto result = hfg.eliminateSequential();
135 
136  auto dc = result->at(2)->asDiscrete();
137  CHECK(dc);
138  DiscreteValues dv;
139  dv[M(1)] = 0;
140  // Regression test
141  EXPECT_DOUBLES_EQUAL(0.62245933120185448, dc->operator()(dv), 1e-3);
142 }
143 
144 /* ************************************************************************* */
145 TEST(HybridGaussianFactorGraph, eliminateFullSequentialSimple) {
147 
148  DiscreteKey m1(M(1), 2);
149 
150  // Add prior on x0
151  hfg.add(JacobianFactor(X(0), I_3x3, Z_3x1));
152  // Add factor between x0 and x1
153  hfg.add(JacobianFactor(X(0), I_3x3, X(1), -I_3x3, Z_3x1));
154 
155  std::vector<GaussianFactor::shared_ptr> factors = {
156  std::make_shared<JacobianFactor>(X(1), I_3x3, Z_3x1),
157  std::make_shared<JacobianFactor>(X(1), I_3x3, Vector3::Ones())};
158  hfg.add(GaussianMixtureFactor({X(1)}, {m1}, factors));
159 
160  // Discrete probability table for c1
161  hfg.add(DecisionTreeFactor(m1, {2, 8}));
162  // Joint discrete probability table for c1, c2
163  hfg.add(DecisionTreeFactor({{M(1), 2}, {M(2), 2}}, "1 2 3 4"));
164 
166 
167  // There are 4 variables (2 continuous + 2 discrete) in the bayes net.
169 }
170 
171 /* ************************************************************************* */
172 TEST(HybridGaussianFactorGraph, eliminateFullMultifrontalSimple) {
174 
175  DiscreteKey m1(M(1), 2);
176 
177  hfg.add(JacobianFactor(X(0), I_3x3, Z_3x1));
178  hfg.add(JacobianFactor(X(0), I_3x3, X(1), -I_3x3, Z_3x1));
179 
181  {X(1)}, {{M(1), 2}},
182  {std::make_shared<JacobianFactor>(X(1), I_3x3, Z_3x1),
183  std::make_shared<JacobianFactor>(X(1), I_3x3, Vector3::Ones())}));
184 
185  hfg.add(DecisionTreeFactor(m1, {2, 8}));
186  // TODO(Varun) Adding extra discrete variable not connected to continuous
187  // variable throws segfault
188  // hfg.add(DecisionTreeFactor({{M(1), 2}, {M(2), 2}}, "1 2 3 4"));
189 
191 
192  // The bayes tree should have 3 cliques
194  // GTSAM_PRINT(*result);
195  // GTSAM_PRINT(*result->marginalFactor(M(2)));
196 }
197 
198 /* ************************************************************************* */
199 TEST(HybridGaussianFactorGraph, eliminateFullMultifrontalCLG) {
201 
202  DiscreteKey m(M(1), 2);
203 
204  // Prior on x0
205  hfg.add(JacobianFactor(X(0), I_3x3, Z_3x1));
206  // Factor between x0-x1
207  hfg.add(JacobianFactor(X(0), I_3x3, X(1), -I_3x3, Z_3x1));
208 
209  // Decision tree with different modes on x1
211  M(1), std::make_shared<JacobianFactor>(X(1), I_3x3, Z_3x1),
212  std::make_shared<JacobianFactor>(X(1), I_3x3, Vector3::Ones()));
213 
214  // Hybrid factor P(x1|c1)
215  hfg.add(GaussianMixtureFactor({X(1)}, {m}, dt));
216  // Prior factor on c1
217  hfg.add(DecisionTreeFactor(m, {2, 8}));
218 
219  // Get a constrained ordering keeping c1 last
220  auto ordering_full = HybridOrdering(hfg);
221 
222  // Returns a Hybrid Bayes Tree with distribution P(x0|x1)P(x1|c1)P(c1)
223  HybridBayesTree::shared_ptr hbt = hfg.eliminateMultifrontal(ordering_full);
224 
225  EXPECT_LONGS_EQUAL(3, hbt->size());
226 }
227 
228 /* ************************************************************************* */
229 /*
230  * This test is about how to assemble the Bayes Tree roots after we do partial
231  * elimination
232  */
233 TEST(HybridGaussianFactorGraph, eliminateFullMultifrontalTwoClique) {
235 
236  hfg.add(JacobianFactor(X(0), I_3x3, X(1), -I_3x3, Z_3x1));
237  hfg.add(JacobianFactor(X(1), I_3x3, X(2), -I_3x3, Z_3x1));
238 
239  {
241  {X(0)}, {{M(0), 2}},
242  {std::make_shared<JacobianFactor>(X(0), I_3x3, Z_3x1),
243  std::make_shared<JacobianFactor>(X(0), I_3x3, Vector3::Ones())}));
244 
246  M(1), std::make_shared<JacobianFactor>(X(2), I_3x3, Z_3x1),
247  std::make_shared<JacobianFactor>(X(2), I_3x3, Vector3::Ones()));
248 
249  hfg.add(GaussianMixtureFactor({X(2)}, {{M(1), 2}}, dt1));
250  }
251 
252  hfg.add(DecisionTreeFactor({{M(1), 2}, {M(2), 2}}, "1 2 3 4"));
253 
254  hfg.add(JacobianFactor(X(3), I_3x3, X(4), -I_3x3, Z_3x1));
255  hfg.add(JacobianFactor(X(4), I_3x3, X(5), -I_3x3, Z_3x1));
256 
257  {
259  M(3), std::make_shared<JacobianFactor>(X(3), I_3x3, Z_3x1),
260  std::make_shared<JacobianFactor>(X(3), I_3x3, Vector3::Ones()));
261 
262  hfg.add(GaussianMixtureFactor({X(3)}, {{M(3), 2}}, dt));
263 
265  M(2), std::make_shared<JacobianFactor>(X(5), I_3x3, Z_3x1),
266  std::make_shared<JacobianFactor>(X(5), I_3x3, Vector3::Ones()));
267 
268  hfg.add(GaussianMixtureFactor({X(5)}, {{M(2), 2}}, dt1));
269  }
270 
271  auto ordering_full =
272  Ordering::ColamdConstrainedLast(hfg, {M(0), M(1), M(2), M(3)});
273 
274  const auto [hbt, remaining] = hfg.eliminatePartialMultifrontal(ordering_full);
275 
276  // 9 cliques in the bayes tree and 0 remaining variables to eliminate.
277  EXPECT_LONGS_EQUAL(9, hbt->size());
278  EXPECT_LONGS_EQUAL(0, remaining->size());
279 
280  /*
281  (Fan) Explanation: the Junction tree will need to reeliminate to get to the
282  marginal on X(1), which is not possible because it involves eliminating
283  discrete before continuous. The solution to this, however, is in Murphy02.
284  TLDR is that this is 1. expensive and 2. inexact. nevertheless it is doable.
285  And I believe that we should do this.
286  */
287 }
288 
290  const HybridBayesTree::shared_ptr &hbt,
291  const Ordering &ordering) {
292  DotWriter dw;
293  dw.positionHints['c'] = 2;
294  dw.positionHints['x'] = 1;
295  std::cout << hfg->dot(DefaultKeyFormatter, dw);
296  std::cout << "\n";
297  hbt->dot(std::cout);
298 
299  std::cout << "\n";
300  std::cout << hfg->eliminateSequential(ordering)->dot(DefaultKeyFormatter, dw);
301 }
302 
303 /* ************************************************************************* */
304 // TODO(fan): make a graph like Varun's paper one
306  auto N = 12;
307  auto hfg = makeSwitchingChain(N);
308 
309  // X(5) will be the center, X(1-4), X(6-9)
310  // X(3), X(7)
311  // X(2), X(8)
312  // X(1), X(4), X(6), X(9)
313  // M(5) will be the center, M(1-4), M(6-8)
314  // M(3), M(7)
315  // M(1), M(4), M(2), M(6), M(8)
316  // auto ordering_full =
317  // Ordering(KeyVector{X(1), X(4), X(2), X(6), X(9), X(8), X(3), X(7),
318  // X(5),
319  // M(1), M(4), M(2), M(6), M(8), M(3), M(7), M(5)});
321 
322  {
323  std::vector<int> naturalX(N);
324  std::iota(naturalX.begin(), naturalX.end(), 1);
325  std::vector<Key> ordX;
326  std::transform(naturalX.begin(), naturalX.end(), std::back_inserter(ordX),
327  [](int x) { return X(x); });
328 
329  auto [ndX, lvls] = makeBinaryOrdering(ordX);
330  std::copy(ndX.begin(), ndX.end(), std::back_inserter(ordering));
331  // TODO(dellaert): this has no effect!
332  for (auto &l : lvls) {
333  l = -l;
334  }
335  }
336  {
337  std::vector<int> naturalC(N - 1);
338  std::iota(naturalC.begin(), naturalC.end(), 1);
339  std::vector<Key> ordC;
340  std::transform(naturalC.begin(), naturalC.end(), std::back_inserter(ordC),
341  [](int x) { return M(x); });
342 
343  // std::copy(ordC.begin(), ordC.end(), std::back_inserter(ordering));
344  const auto [ndC, lvls] = makeBinaryOrdering(ordC);
345  std::copy(ndC.begin(), ndC.end(), std::back_inserter(ordering));
346  }
347  auto ordering_full = Ordering(ordering);
348 
349  // GTSAM_PRINT(*hfg);
350  // GTSAM_PRINT(ordering_full);
351 
352  const auto [hbt, remaining] =
353  hfg->eliminatePartialMultifrontal(ordering_full);
354 
355  // 12 cliques in the bayes tree and 0 remaining variables to eliminate.
356  EXPECT_LONGS_EQUAL(12, hbt->size());
357  EXPECT_LONGS_EQUAL(0, remaining->size());
358 }
359 
360 /* ************************************************************************* */
361 // TODO(fan): make a graph like Varun's paper one
363  auto N = 11;
364  auto hfg = makeSwitchingChain(N);
365 
366  // X(5) will be the center, X(1-4), X(6-9)
367  // X(3), X(7)
368  // X(2), X(8)
369  // X(1), X(4), X(6), X(9)
370  // M(5) will be the center, M(1-4), M(6-8)
371  // M(3), M(7)
372  // M(1), M(4), M(2), M(6), M(8)
373  // auto ordering_full =
374  // Ordering(KeyVector{X(1), X(4), X(2), X(6), X(9), X(8), X(3), X(7),
375  // X(5),
376  // M(1), M(4), M(2), M(6), M(8), M(3), M(7), M(5)});
378 
379  {
380  std::vector<int> naturalX(N);
381  std::iota(naturalX.begin(), naturalX.end(), 1);
382  std::vector<Key> ordX;
383  std::transform(naturalX.begin(), naturalX.end(), std::back_inserter(ordX),
384  [](int x) { return X(x); });
385 
386  auto [ndX, lvls] = makeBinaryOrdering(ordX);
387  std::copy(ndX.begin(), ndX.end(), std::back_inserter(ordering));
388  // TODO(dellaert): this has no effect!
389  for (auto &l : lvls) {
390  l = -l;
391  }
392  }
393  {
394  std::vector<int> naturalC(N - 1);
395  std::iota(naturalC.begin(), naturalC.end(), 1);
396  std::vector<Key> ordC;
397  std::transform(naturalC.begin(), naturalC.end(), std::back_inserter(ordC),
398  [](int x) { return M(x); });
399 
400  // std::copy(ordC.begin(), ordC.end(), std::back_inserter(ordering));
401  const auto [ndC, lvls] = makeBinaryOrdering(ordC);
402  std::copy(ndC.begin(), ndC.end(), std::back_inserter(ordering));
403  }
404  auto ordering_full = Ordering(ordering);
405 
406  const auto [hbt, remaining] =
407  hfg->eliminatePartialMultifrontal(ordering_full);
408 
409  auto new_fg = makeSwitchingChain(12);
410  auto isam = HybridGaussianISAM(*hbt);
411 
412  // Run an ISAM update.
413  HybridGaussianFactorGraph factorGraph;
414  factorGraph.push_back(new_fg->at(new_fg->size() - 2));
415  factorGraph.push_back(new_fg->at(new_fg->size() - 1));
416  isam.update(factorGraph);
417 
418  // ISAM should have 12 factors after the last update
419  EXPECT_LONGS_EQUAL(12, isam.size());
420 }
421 
422 /* ************************************************************************* */
423 TEST(HybridGaussianFactorGraph, SwitchingTwoVar) {
424  const int N = 7;
425  auto hfg = makeSwitchingChain(N, X);
426  hfg->push_back(*makeSwitchingChain(N, Y, D));
427 
428  for (int t = 1; t <= N; t++) {
429  hfg->add(JacobianFactor(X(t), I_3x3, Y(t), -I_3x3, Vector3(1.0, 0.0, 0.0)));
430  }
431 
433 
434  KeyVector naturalX(N);
435  std::iota(naturalX.begin(), naturalX.end(), 1);
436  KeyVector ordX;
437  for (size_t i = 1; i <= N; i++) {
438  ordX.emplace_back(X(i));
439  ordX.emplace_back(Y(i));
440  }
441 
442  for (size_t i = 1; i <= N - 1; i++) {
443  ordX.emplace_back(M(i));
444  }
445  for (size_t i = 1; i <= N - 1; i++) {
446  ordX.emplace_back(D(i));
447  }
448 
449  {
450  DotWriter dw;
451  dw.positionHints['x'] = 1;
452  dw.positionHints['c'] = 0;
453  dw.positionHints['d'] = 3;
454  dw.positionHints['y'] = 2;
455  // std::cout << hfg->dot(DefaultKeyFormatter, dw);
456  // std::cout << "\n";
457  }
458 
459  {
460  DotWriter dw;
461  dw.positionHints['y'] = 9;
462  // dw.positionHints['c'] = 0;
463  // dw.positionHints['d'] = 3;
464  dw.positionHints['x'] = 1;
465  // std::cout << "\n";
466  // std::cout << hfg->eliminateSequential(Ordering(ordX))
467  // ->dot(DefaultKeyFormatter, dw);
468  // hfg->eliminateMultifrontal(Ordering(ordX))->dot(std::cout);
469  }
470 
471  Ordering ordering_partial;
472  for (size_t i = 1; i <= N; i++) {
473  ordering_partial.emplace_back(X(i));
474  ordering_partial.emplace_back(Y(i));
475  }
476  const auto [hbn, remaining] =
477  hfg->eliminatePartialSequential(ordering_partial);
478 
479  EXPECT_LONGS_EQUAL(14, hbn->size());
480  EXPECT_LONGS_EQUAL(11, remaining->size());
481 
482  {
483  DotWriter dw;
484  dw.positionHints['x'] = 1;
485  dw.positionHints['c'] = 0;
486  dw.positionHints['d'] = 3;
487  dw.positionHints['y'] = 2;
488  // std::cout << remaining->dot(DefaultKeyFormatter, dw);
489  // std::cout << "\n";
490  }
491 }
492 
493 /* ************************************************************************* */
496 
497  DiscreteKey c1(C(1), 2);
498 
499  hfg.add(JacobianFactor(X(0), I_3x3, Z_3x1));
500  hfg.add(JacobianFactor(X(0), I_3x3, X(1), -I_3x3, Z_3x1));
501 
503  C(1), std::make_shared<JacobianFactor>(X(1), I_3x3, Z_3x1),
504  std::make_shared<JacobianFactor>(X(1), I_3x3, Vector3::Ones()));
505 
506  hfg.add(GaussianMixtureFactor({X(1)}, {c1}, dt));
507 
508  auto result = hfg.eliminateSequential();
509 
510  HybridValues hv = result->optimize();
511 
512  EXPECT(assert_equal(hv.atDiscrete(C(1)), int(0)));
513 }
514 
515 /* ************************************************************************* */
516 // Test adding of gaussian conditional and re-elimination.
518  Switching switching(4);
520 
521  hfg.push_back(switching.linearizedFactorGraph.at(0)); // P(X1)
523  ordering.push_back(X(0));
525 
526  hfg.push_back(switching.linearizedFactorGraph.at(1)); // P(X1, X2 | M1)
527  hfg.push_back(*bayes_net);
528  hfg.push_back(switching.linearizedFactorGraph.at(2)); // P(X2, X3 | M2)
529  hfg.push_back(switching.linearizedFactorGraph.at(5)); // P(M1)
530  ordering.push_back(X(1));
531  ordering.push_back(X(2));
532  ordering.push_back(M(0));
533  ordering.push_back(M(1));
534 
535  bayes_net = hfg.eliminateSequential(ordering);
536 
537  HybridValues result = bayes_net->optimize();
538 
539  Values expected_continuous;
540  expected_continuous.insert<double>(X(0), 0);
541  expected_continuous.insert<double>(X(1), 1);
542  expected_continuous.insert<double>(X(2), 2);
543  expected_continuous.insert<double>(X(3), 4);
544  Values result_continuous =
545  switching.linearizationPoint.retract(result.continuous());
546  EXPECT(assert_equal(expected_continuous, result_continuous));
547 
548  DiscreteValues expected_discrete;
549  expected_discrete[M(0)] = 1;
550  expected_discrete[M(1)] = 1;
551  EXPECT(assert_equal(expected_discrete, result.discrete()));
552 }
553 
554 /* ****************************************************************************/
555 // Test hybrid gaussian factor graph error and unnormalized probabilities
556 TEST(HybridGaussianFactorGraph, ErrorAndProbPrime) {
557  Switching s(3);
558 
559  HybridGaussianFactorGraph graph = s.linearizedFactorGraph;
560 
561  HybridBayesNet::shared_ptr hybridBayesNet = graph.eliminateSequential();
562 
563  const HybridValues delta = hybridBayesNet->optimize();
564  const double error = graph.error(delta);
565 
566  // regression
567  EXPECT(assert_equal(1.58886, error, 1e-5));
568 
569  // Real test:
571 }
572 
573 /* ****************************************************************************/
574 // Test hybrid gaussian factor graph error and unnormalized probabilities
575 TEST(HybridGaussianFactorGraph, ErrorAndProbPrimeTree) {
576  Switching s(3);
577 
578  HybridGaussianFactorGraph graph = s.linearizedFactorGraph;
579 
580  HybridBayesNet::shared_ptr hybridBayesNet = graph.eliminateSequential();
581 
582  HybridValues delta = hybridBayesNet->optimize();
583  auto error_tree = graph.errorTree(delta.continuous());
584 
585  std::vector<DiscreteKey> discrete_keys = {{M(0), 2}, {M(1), 2}};
586  std::vector<double> leaves = {0.9998558, 0.4902432, 0.5193694, 0.0097568};
587  AlgebraicDecisionTree<Key> expected_error(discrete_keys, leaves);
588 
589  // regression
590  EXPECT(assert_equal(expected_error, error_tree, 1e-7));
591 
592  auto probs = graph.probPrime(delta.continuous());
593  std::vector<double> prob_leaves = {0.36793249, 0.61247742, 0.59489556,
594  0.99029064};
595  AlgebraicDecisionTree<Key> expected_probs(discrete_keys, prob_leaves);
596 
597  // regression
598  EXPECT(assert_equal(expected_probs, probs, 1e-7));
599 }
600 
601 /* ****************************************************************************/
602 // Check that assembleGraphTree assembles Gaussian factor graphs for each
603 // assignment.
604 TEST(HybridGaussianFactorGraph, assembleGraphTree) {
605  const int num_measurements = 1;
607  num_measurements, VectorValues{{Z(0), Vector1(5.0)}});
608  EXPECT_LONGS_EQUAL(3, fg.size());
609 
610  // Assemble graph tree:
611  auto actual = fg.assembleGraphTree();
612 
613  // Create expected decision tree with two factor graphs:
614 
615  // Get mixture factor:
616  auto mixture = fg.at<GaussianMixtureFactor>(0);
617  CHECK(mixture);
618 
619  // Get prior factor:
620  const auto gf = fg.at<HybridConditional>(1);
621  CHECK(gf);
622  using GF = GaussianFactor::shared_ptr;
623  const GF prior = gf->asGaussian();
624  CHECK(prior);
625 
626  // Create DiscreteValues for both 0 and 1:
627  DiscreteValues d0{{M(0), 0}}, d1{{M(0), 1}};
628 
629  // Expected decision tree with two factor graphs:
630  // f(x0;mode=0)P(x0) and f(x0;mode=1)P(x0)
632  M(0), GaussianFactorGraph(std::vector<GF>{(*mixture)(d0), prior}),
633  GaussianFactorGraph(std::vector<GF>{(*mixture)(d1), prior})};
634 
635  EXPECT(assert_equal(expected(d0), actual(d0), 1e-5));
636  EXPECT(assert_equal(expected(d1), actual(d1), 1e-5));
637 }
638 
639 /* ****************************************************************************/
640 // Check that the factor graph unnormalized probability is proportional to the
641 // Bayes net probability for the given measurements.
642 bool ratioTest(const HybridBayesNet &bn, const VectorValues &measurements,
643  const HybridGaussianFactorGraph &fg, size_t num_samples = 100) {
644  auto compute_ratio = [&](HybridValues *sample) -> double {
645  sample->update(measurements); // update sample with given measurements:
646  return bn.evaluate(*sample) / fg.probPrime(*sample);
647  };
648 
649  HybridValues sample = bn.sample(&kRng);
650  double expected_ratio = compute_ratio(&sample);
651 
652  // Test ratios for a number of independent samples:
653  for (size_t i = 0; i < num_samples; i++) {
654  HybridValues sample = bn.sample(&kRng);
655  if (std::abs(expected_ratio - compute_ratio(&sample)) > 1e-6) return false;
656  }
657  return true;
658 }
659 
660 /* ****************************************************************************/
661 // Check that the bayes net unnormalized probability is proportional to the
662 // Bayes net probability for the given measurements.
663 bool ratioTest(const HybridBayesNet &bn, const VectorValues &measurements,
664  const HybridBayesNet &posterior, size_t num_samples = 100) {
665  auto compute_ratio = [&](HybridValues *sample) -> double {
666  sample->update(measurements); // update sample with given measurements:
667  return bn.evaluate(*sample) / posterior.evaluate(*sample);
668  };
669 
670  HybridValues sample = bn.sample(&kRng);
671  double expected_ratio = compute_ratio(&sample);
672 
673  // Test ratios for a number of independent samples:
674  for (size_t i = 0; i < num_samples; i++) {
675  HybridValues sample = bn.sample(&kRng);
676  // GTSAM_PRINT(sample);
677  // std::cout << "ratio: " << compute_ratio(&sample) << std::endl;
678  if (std::abs(expected_ratio - compute_ratio(&sample)) > 1e-6) return false;
679  }
680  return true;
681 }
682 
683 /* ****************************************************************************/
684 // Check that eliminating tiny net with 1 measurement yields correct result.
685 TEST(HybridGaussianFactorGraph, EliminateTiny1) {
686  const int num_measurements = 1;
687  const VectorValues measurements{{Z(0), Vector1(5.0)}};
688  auto bn = tiny::createHybridBayesNet(num_measurements);
689  auto fg = bn.toFactorGraph(measurements);
690  EXPECT_LONGS_EQUAL(3, fg.size());
691 
692  EXPECT(ratioTest(bn, measurements, fg));
693 
694  // Create expected Bayes Net:
695  HybridBayesNet expectedBayesNet;
696 
697  // Create Gaussian mixture on X(0).
698  using tiny::mode;
699  // regression, but mean checked to be 5.0 in both cases:
700  const auto conditional0 = std::make_shared<GaussianConditional>(
701  X(0), Vector1(14.1421), I_1x1 * 2.82843),
702  conditional1 = std::make_shared<GaussianConditional>(
703  X(0), Vector1(10.1379), I_1x1 * 2.02759);
704  expectedBayesNet.emplace_back(
705  new GaussianMixture({X(0)}, {}, {mode}, {conditional0, conditional1}));
706 
707  // Add prior on mode.
708  expectedBayesNet.emplace_back(new DiscreteConditional(mode, "74/26"));
709 
710  // Test elimination
711  const auto posterior = fg.eliminateSequential();
712  EXPECT(assert_equal(expectedBayesNet, *posterior, 0.01));
713 
714  EXPECT(ratioTest(bn, measurements, *posterior));
715 }
716 
717 /* ****************************************************************************/
718 // Check that eliminating tiny net with 1 measurement with mode order swapped
719 // yields correct result.
720 TEST(HybridGaussianFactorGraph, EliminateTiny1Swapped) {
721  const VectorValues measurements{{Z(0), Vector1(5.0)}};
722 
723  // Create mode key: 1 is low-noise, 0 is high-noise.
724  const DiscreteKey mode{M(0), 2};
725  HybridBayesNet bn;
726 
727  // Create Gaussian mixture z_0 = x0 + noise for each measurement.
729  {Z(0)}, {X(0)}, {mode},
730  {GaussianConditional::sharedMeanAndStddev(Z(0), I_1x1, X(0), Z_1x1, 3),
731  GaussianConditional::sharedMeanAndStddev(Z(0), I_1x1, X(0), Z_1x1,
732  0.5)}));
733 
734  // Create prior on X(0).
735  bn.push_back(
736  GaussianConditional::sharedMeanAndStddev(X(0), Vector1(5.0), 0.5));
737 
738  // Add prior on mode.
739  bn.emplace_back(new DiscreteConditional(mode, "1/1"));
740 
741  // bn.print();
742  auto fg = bn.toFactorGraph(measurements);
743  EXPECT_LONGS_EQUAL(3, fg.size());
744 
745  // fg.print();
746 
747  EXPECT(ratioTest(bn, measurements, fg));
748 
749  // Create expected Bayes Net:
750  HybridBayesNet expectedBayesNet;
751 
752  // Create Gaussian mixture on X(0).
753  // regression, but mean checked to be 5.0 in both cases:
754  const auto conditional0 = std::make_shared<GaussianConditional>(
755  X(0), Vector1(10.1379), I_1x1 * 2.02759),
756  conditional1 = std::make_shared<GaussianConditional>(
757  X(0), Vector1(14.1421), I_1x1 * 2.82843);
758  expectedBayesNet.emplace_back(
759  new GaussianMixture({X(0)}, {}, {mode}, {conditional0, conditional1}));
760 
761  // Add prior on mode.
762  expectedBayesNet.emplace_back(new DiscreteConditional(mode, "1/1"));
763 
764  // Test elimination
765  const auto posterior = fg.eliminateSequential();
766  // EXPECT(assert_equal(expectedBayesNet, *posterior, 0.01));
767 
768  EXPECT(ratioTest(bn, measurements, *posterior));
769 
770  // posterior->print();
771  // posterior->optimize().print();
772 }
773 
774 /* ****************************************************************************/
775 // Check that eliminating tiny net with 2 measurements yields correct result.
776 TEST(HybridGaussianFactorGraph, EliminateTiny2) {
777  // Create factor graph with 2 measurements such that posterior mean = 5.0.
778  const int num_measurements = 2;
779  const VectorValues measurements{{Z(0), Vector1(4.0)}, {Z(1), Vector1(6.0)}};
780  auto bn = tiny::createHybridBayesNet(num_measurements);
781  auto fg = bn.toFactorGraph(measurements);
782  EXPECT_LONGS_EQUAL(4, fg.size());
783 
784  // Create expected Bayes Net:
785  HybridBayesNet expectedBayesNet;
786 
787  // Create Gaussian mixture on X(0).
788  using tiny::mode;
789  // regression, but mean checked to be 5.0 in both cases:
790  const auto conditional0 = std::make_shared<GaussianConditional>(
791  X(0), Vector1(17.3205), I_1x1 * 3.4641),
792  conditional1 = std::make_shared<GaussianConditional>(
793  X(0), Vector1(10.274), I_1x1 * 2.0548);
794  expectedBayesNet.emplace_back(
795  new GaussianMixture({X(0)}, {}, {mode}, {conditional0, conditional1}));
796 
797  // Add prior on mode.
798  expectedBayesNet.emplace_back(new DiscreteConditional(mode, "23/77"));
799 
800  // Test elimination
801  const auto posterior = fg.eliminateSequential();
802  EXPECT(assert_equal(expectedBayesNet, *posterior, 0.01));
803 
804  EXPECT(ratioTest(bn, measurements, *posterior));
805 }
806 
807 /* ****************************************************************************/
808 // Test eliminating tiny net with 1 mode per measurement.
809 TEST(HybridGaussianFactorGraph, EliminateTiny22) {
810  // Create factor graph with 2 measurements such that posterior mean = 5.0.
811  const int num_measurements = 2;
812  const bool manyModes = true;
813 
814  // Create Bayes net and convert to factor graph.
815  auto bn = tiny::createHybridBayesNet(num_measurements, manyModes);
816  const VectorValues measurements{{Z(0), Vector1(4.0)}, {Z(1), Vector1(6.0)}};
817  auto fg = bn.toFactorGraph(measurements);
818  EXPECT_LONGS_EQUAL(5, fg.size());
819 
820  EXPECT(ratioTest(bn, measurements, fg));
821 
822  // Test elimination
823  const auto posterior = fg.eliminateSequential();
824 
825  EXPECT(ratioTest(bn, measurements, *posterior));
826 }
827 
828 /* ****************************************************************************/
829 // Test elimination of a switching network with one mode per measurement.
830 TEST(HybridGaussianFactorGraph, EliminateSwitchingNetwork) {
831  // Create a switching network with one mode per measurement.
832  HybridBayesNet bn;
833 
834  // NOTE: we add reverse topological so we can sample from the Bayes net.:
835 
836  // Add measurements:
837  for (size_t t : {0, 1, 2}) {
838  // Create Gaussian mixture on Z(t) conditioned on X(t) and mode N(t):
839  const auto noise_mode_t = DiscreteKey{N(t), 2};
840  bn.emplace_back(
841  new GaussianMixture({Z(t)}, {X(t)}, {noise_mode_t},
842  {GaussianConditional::sharedMeanAndStddev(
843  Z(t), I_1x1, X(t), Z_1x1, 0.5),
844  GaussianConditional::sharedMeanAndStddev(
845  Z(t), I_1x1, X(t), Z_1x1, 3.0)}));
846 
847  // Create prior on discrete mode N(t):
848  bn.emplace_back(new DiscreteConditional(noise_mode_t, "20/80"));
849  }
850 
851  // Add motion models:
852  for (size_t t : {2, 1}) {
853  // Create Gaussian mixture on X(t) conditioned on X(t-1) and mode M(t-1):
854  const auto motion_model_t = DiscreteKey{M(t), 2};
855  bn.emplace_back(
856  new GaussianMixture({X(t)}, {X(t - 1)}, {motion_model_t},
857  {GaussianConditional::sharedMeanAndStddev(
858  X(t), I_1x1, X(t - 1), Z_1x1, 0.2),
859  GaussianConditional::sharedMeanAndStddev(
860  X(t), I_1x1, X(t - 1), I_1x1, 0.2)}));
861 
862  // Create prior on motion model M(t):
863  bn.emplace_back(new DiscreteConditional(motion_model_t, "40/60"));
864  }
865 
866  // Create Gaussian prior on continuous X(0) using sharedMeanAndStddev:
867  bn.push_back(GaussianConditional::sharedMeanAndStddev(X(0), Z_1x1, 0.1));
868 
869  // Make sure we an sample from the Bayes net:
871 
872  // Create measurements consistent with moving right every time:
873  const VectorValues measurements{
874  {Z(0), Vector1(0.0)}, {Z(1), Vector1(1.0)}, {Z(2), Vector1(2.0)}};
875  const HybridGaussianFactorGraph fg = bn.toFactorGraph(measurements);
876 
877  // Factor graph is:
878  // D D
879  // | |
880  // m1 m2
881  // | |
882  // C-x0-HC-x1-HC-x2
883  // | | |
884  // HF HF HF
885  // | | |
886  // n0 n1 n2
887  // | | |
888  // D D D
889  EXPECT_LONGS_EQUAL(11, fg.size());
890  EXPECT(ratioTest(bn, measurements, fg));
891 
892  // Do elimination of X(2) only:
893  auto [bn1, fg1] = fg.eliminatePartialSequential(Ordering{X(2)});
894  fg1->push_back(*bn1);
895  EXPECT(ratioTest(bn, measurements, *fg1));
896 
897  // Create ordering that eliminates in time order, then discrete modes:
898  Ordering ordering{X(2), X(1), X(0), N(0), N(1), N(2), M(1), M(2)};
899 
900  // Do elimination:
902 
903  // Test resulting posterior Bayes net has correct size:
904  EXPECT_LONGS_EQUAL(8, posterior->size());
905 
906  // Ratio test
907  EXPECT(ratioTest(bn, measurements, *posterior));
908 }
909 
910 /* ************************************************************************* */
911 int main() {
912  TestResult tr;
913  return TestRegistry::runAllTests(tr);
914 }
915 /* ************************************************************************* */
gtsam::EliminateableFactorGraph::eliminatePartialMultifrontal
std::pair< std::shared_ptr< BayesTreeType >, std::shared_ptr< FactorGraphType > > eliminatePartialMultifrontal(const Ordering &ordering, const Eliminate &function=EliminationTraitsType::DefaultEliminate, OptionalVariableIndex variableIndex={}) const
Definition: EliminateableFactorGraph-inst.h:190
TestRegistry::runAllTests
static int runAllTests(TestResult &result)
Definition: TestRegistry.cpp:27
gtsam::GaussianMixtureFactor
Implementation of a discrete conditional mixture factor. Implements a joint discrete-continuous facto...
Definition: GaussianMixtureFactor.h:47
gtsam::HybridGaussianFactorGraph::shared_ptr
std::shared_ptr< This > shared_ptr
shared_ptr to This
Definition: HybridGaussianFactorGraph.h:118
DotWriter.h
Graphviz formatter.
gtsam::EliminateableFactorGraph::eliminateSequential
std::shared_ptr< BayesNetType > eliminateSequential(OptionalOrderingType orderingType={}, const Eliminate &function=EliminationTraitsType::DefaultEliminate, OptionalVariableIndex variableIndex={}) const
Definition: EliminateableFactorGraph-inst.h:29
gtsam::HybridGaussianISAM
Incremental Smoothing and Mapping (ISAM) algorithm for hybrid factor graphs.
Definition: HybridGaussianISAM.h:37
gtsam::DotWriter::positionHints
std::map< char, double > positionHints
Definition: DotWriter.h:55
gtsam::DecisionTreeFactor
Definition: DecisionTreeFactor.h:44
ratioTest
bool ratioTest(const HybridBayesNet &bn, const VectorValues &measurements, const HybridGaussianFactorGraph &fg, size_t num_samples=100)
Definition: testHybridGaussianFactorGraph.cpp:642
gtsam::HybridValues
Definition: HybridValues.h:38
Y
const char Y
Definition: test/EulerAngles.cpp:31
D
MatrixXcd D
Definition: EigenSolver_EigenSolver_MatrixType.cpp:14
gtsam::HybridGaussianFactorGraph::probPrime
AlgebraicDecisionTree< Key > probPrime(const VectorValues &continuousValues) const
Compute unnormalized probability for each discrete assignment, and return as a tree.
Definition: HybridGaussianFactorGraph.cpp:540
gtsam::HybridConditional
Definition: HybridConditional.h:59
gtsam::Values::size
size_t size() const
Definition: Values.h:178
s
RealScalar s
Definition: level1_cplx_impl.h:126
e
Array< double, 1, 3 > e(1./3., 0.5, 2.)
EXPECT_LONGS_EQUAL
#define EXPECT_LONGS_EQUAL(expected, actual)
Definition: Test.h:154
EXPECT
#define EXPECT(condition)
Definition: Test.h:150
optimize
int optimize(const SfmData &db, const NonlinearFactorGraph &graph, const Values &initial, bool separateCalibration=false)
Definition: timeSFMBAL.h:64
gtsam::Z_3x1
static const Eigen::MatrixBase< Vector3 >::ConstantReturnType Z_3x1
Definition: Vector.h:46
gtsam::symbol_shorthand::N
Key N(std::uint64_t j)
Definition: inference/Symbol.h:161
TestHarness.h
gtsam::HybridBayesNet
Definition: HybridBayesNet.h:35
gtsam::symbol_shorthand::M
Key M(std::uint64_t j)
Definition: inference/Symbol.h:160
kRng
std::mt19937_64 kRng(42)
gtsam::HybridBayesNet::evaluate
double evaluate(const HybridValues &values) const
Evaluate hybrid probability density for given HybridValues.
Definition: HybridBayesNet.cpp:354
gtsam::HybridValues::continuous
const VectorValues & continuous() const
Return the multi-dimensional vector values.
Definition: HybridValues.h:89
Switching.h
simple_graph::factors
const GaussianFactorGraph factors
Definition: testJacobianFactor.cpp:213
gtsam::GaussianMixture
A conditional of gaussian mixtures indexed by discrete variables, as part of a Bayes Network....
Definition: GaussianMixture.h:53
x
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy x
Definition: gnuplot_common_settings.hh:12
gtsam::JacobianFactor
Definition: JacobianFactor.h:91
dt
const double dt
Definition: testVelocityConstraint.cpp:15
m1
Matrix3d m1
Definition: IOFormat.cpp:2
gtsam::makeBinaryOrdering
std::pair< KeyVector, std::vector< int > > makeBinaryOrdering(std::vector< Key > &input)
Return the ordering as a binary tree such that all parent nodes are above their children.
Definition: Switching.h:85
HybridBayesNet.h
A Bayes net of Gaussian Conditionals indexed by discrete keys.
Ordering.h
Variable ordering for the elimination algorithm.
gtsam::HybridValues::atDiscrete
size_t & atDiscrete(Key j)
Definition: HybridValues.h:175
X
#define X
Definition: icosphere.cpp:20
gtsam::DiscreteKeys
DiscreteKeys is a set of keys that can be assembled using the & operator.
Definition: DiscreteKey.h:41
dotPrint
void dotPrint(const HybridGaussianFactorGraph::shared_ptr &hfg, const HybridBayesTree::shared_ptr &hbt, const Ordering &ordering)
Definition: testHybridGaussianFactorGraph.cpp:289
gtsam::Vector3
Eigen::Vector3d Vector3
Definition: Vector.h:43
exp
const EIGEN_DEVICE_FUNC ExpReturnType exp() const
Definition: ArrayCwiseUnaryOps.h:97
gtsam::KeyVector
FastVector< Key > KeyVector
Define collection type once and for all - also used in wrappers.
Definition: Key.h:92
gtsam::NonlinearFactorGraph::probPrime
double probPrime(const Values &values) const
Definition: NonlinearFactorGraph.cpp:49
result
Values result
Definition: OdometryOptimize.cpp:8
gtsam::NonlinearISAM::update
void update(const NonlinearFactorGraph &newFactors, const Values &initialValues)
Definition: NonlinearISAM.cpp:35
gtsam::EliminateableFactorGraph::eliminateMultifrontal
std::shared_ptr< BayesTreeType > eliminateMultifrontal(OptionalOrderingType orderingType={}, const Eliminate &function=EliminationTraitsType::DefaultEliminate, OptionalVariableIndex variableIndex={}) const
Definition: EliminateableFactorGraph-inst.h:89
TestableAssertions.h
Provides additional testing facilities for common data structures.
gtsam::DefaultKeyFormatter
KeyFormatter DefaultKeyFormatter
Assign default key formatter.
Definition: Key.cpp:30
gtsam::AlgebraicDecisionTree< Key >
c1
static double c1
Definition: airy.c:54
gtsam::Switching
Definition: Switching.h:120
gtsam::FactorGraph::at
const sharedFactor at(size_t i) const
Definition: FactorGraph.h:306
Key.h
gtsam::GaussianFactorGraph
Definition: GaussianFactorGraph.h:73
gtsam::symbol_shorthand::X
Key X(std::uint64_t j)
Definition: inference/Symbol.h:171
gtsam::NonlinearFactorGraph::error
double error(const Values &values) const
Definition: NonlinearFactorGraph.cpp:170
gtsam::Values::at
const ValueType at(Key j) const
Definition: Values-inl.h:261
Vector1
Eigen::Matrix< double, 1, 1 > Vector1
Definition: testEvent.cpp:33
gtsam::Values::retract
Values retract(const VectorValues &delta) const
Definition: Values.cpp:98
HybridFactor.h
gtsam.examples.PlanarManipulatorExample.delta
def delta(g0, g1)
Definition: PlanarManipulatorExample.py:45
gtsam::VectorValues
Definition: VectorValues.h:74
gtsam::EliminateableFactorGraph::eliminatePartialSequential
std::pair< std::shared_ptr< BayesNetType >, std::shared_ptr< FactorGraphType > > eliminatePartialSequential(const Ordering &ordering, const Eliminate &function=EliminationTraitsType::DefaultEliminate, OptionalVariableIndex variableIndex={}) const
Definition: EliminateableFactorGraph-inst.h:151
gtsam::symbol_shorthand::Z
Key Z(std::uint64_t j)
Definition: inference/Symbol.h:173
gtsam::symbol_shorthand::D
Key D(std::uint64_t j)
Definition: inference/Symbol.h:151
isam
NonlinearISAM isam(relinearizeInterval)
gtsam::GaussianFactor::shared_ptr
std::shared_ptr< This > shared_ptr
shared_ptr to this class
Definition: GaussianFactor.h:42
l
static const Line3 l(Rot3(), 1, 1)
TinyHybridExample.h
cholesky::expected
Matrix expected
Definition: testMatrix.cpp:971
HybridGaussianISAM.h
gtsam::HybridGaussianFactorGraph
Definition: HybridGaussianFactorGraph.h:104
GaussianMixture.h
A hybrid conditional in the Conditional Linear Gaussian scheme.
Symbol.h
equal_constants::mixture
const GaussianMixture mixture({Z(0)}, {X(0)}, {mode}, conditionals)
gtsam::symbol_shorthand::Y
Key Y(std::uint64_t j)
Definition: inference/Symbol.h:172
HybridBayesTree.h
Hybrid Bayes Tree, the result of eliminating a HybridJunctionTree.
m
Matrix3f m
Definition: AngleAxis_mimic_euler.cpp:1
transform
EIGEN_DONT_INLINE void transform(const Transformation &t, Data &data)
Definition: geometry.cpp:25
BayesNet.h
Bayes network.
EXPECT_DOUBLES_EQUAL
#define EXPECT_DOUBLES_EQUAL(expected, actual, threshold)
Definition: Test.h:161
ordering
static enum @1096 ordering
TestResult
Definition: TestResult.h:26
DiscreteKey.h
specialized key for discrete variables
TEST
TEST(HybridGaussianFactorGraph, Creation)
Definition: testHybridGaussianFactorGraph.cpp:65
JacobianFactor.h
gtsam::FactorGraph::size
size_t size() const
Definition: FactorGraph.h:297
gtsam::DecisionTree< Key, GaussianConditional::shared_ptr >
simulated2D::prior
Point2 prior(const Point2 &x)
Prior on a single pose.
Definition: simulated2D.h:88
gtsam::HybridBayesNet::push_back
void push_back(std::shared_ptr< HybridConditional > conditional)
Add a hybrid conditional using a shared_ptr.
Definition: HybridBayesNet.h:69
gtsam::DiscreteConditional
Definition: DiscreteConditional.h:37
Test.h
HybridGaussianFactorGraph.h
Linearized Hybrid factor graph that uses type erasure.
C
Matrix< Scalar, Dynamic, Dynamic > C
Definition: bench_gemm.cpp:50
gtsam
traits
Definition: chartTesting.h:28
DiscreteValues.h
error
static double error
Definition: testRot3.cpp:37
gtsam::DiscreteValues
Definition: DiscreteValues.h:34
gtsam::FactorGraph::push_back
IsDerived< DERIVEDFACTOR > push_back(std::shared_ptr< DERIVEDFACTOR > factor)
Add a factor directly using a shared_ptr.
Definition: FactorGraph.h:147
gtsam::Values
Definition: Values.h:65
CHECK
#define CHECK(condition)
Definition: Test.h:108
gtsam::HybridBayesNet::sample
HybridValues sample(const HybridValues &given, std::mt19937_64 *rng) const
Sample from an incomplete BayesNet, given missing variables.
Definition: HybridBayesNet.cpp:250
gtsam::DiscreteKey
std::pair< Key, size_t > DiscreteKey
Definition: DiscreteKey.h:38
std
Definition: BFloat16.h:88
gtsam::Switching::linearizationPoint
Values linearizationPoint
Definition: Switching.h:125
gtsam::HybridBayesNet::emplace_back
void emplace_back(Conditional *conditional)
Definition: HybridBayesNet.h:82
gtsam::Values::insert
void insert(Key j, const Value &val)
Definition: Values.cpp:155
gtsam::VectorValues::size
size_t size() const
Definition: VectorValues.h:130
gtsam::assert_equal
bool assert_equal(const Matrix &expected, const Matrix &actual, double tol)
Definition: Matrix.cpp:40
gtsam::HybridOrdering
const Ordering HybridOrdering(const HybridGaussianFactorGraph &graph)
Return a Colamd constrained ordering where the discrete keys are eliminated after the continuous keys...
Definition: HybridGaussianFactorGraph.cpp:70
gtsam::Switching::linearizedFactorGraph
HybridGaussianFactorGraph linearizedFactorGraph
Definition: Switching.h:124
mode
static const DiscreteKey mode(modeKey, 2)
gtsam::tiny::createHybridBayesNet
HybridBayesNet createHybridBayesNet(size_t num_measurements=1, bool manyModes=false)
Definition: TinyHybridExample.h:39
abs
#define abs(x)
Definition: datatypes.h:17
N
#define N
Definition: igam.h:9
gtsam::makeSwitchingChain
HybridGaussianFactorGraph::shared_ptr makeSwitchingChain(size_t n, std::function< Key(int)> keyFunc=X, std::function< Key(int)> dKeyFunc=M)
Create a switching system chain. A switching system is a continuous system which depends on a discret...
Definition: Switching.h:51
gtsam::HybridBayesNet::shared_ptr
std::shared_ptr< HybridBayesNet > shared_ptr
Definition: HybridBayesNet.h:40
gtsam::HybridBayesNet::toFactorGraph
HybridGaussianFactorGraph toFactorGraph(const VectorValues &measurements) const
Definition: HybridBayesNet.cpp:359
gtsam::FactorGraph::add
IsDerived< DERIVEDFACTOR > add(std::shared_ptr< DERIVEDFACTOR > factor)
add is a synonym for push_back.
Definition: FactorGraph.h:171
graph
NonlinearFactorGraph graph
Definition: doc/Code/OdometryExample.cpp:2
align_3::t
Point2 t(10, 10)
createHybridGaussianFactorGraph
static HybridGaussianFactorGraph::shared_ptr createHybridGaussianFactorGraph()
Definition: testHybridEstimation.cpp:449
Z
#define Z
Definition: icosphere.cpp:21
HybridValues.h
gtsam::Ordering
Definition: inference/Ordering.h:33
DecisionTreeFactor.h
i
int i
Definition: BiCGSTAB_step_by_step.cpp:9
gtsam::DotWriter
DotWriter is a helper class for writing graphviz .dot files.
Definition: DotWriter.h:36
GaussianMixtureFactor.h
A set of GaussianFactors, indexed by a set of discrete keys.
gtsam::HybridBayesTree::shared_ptr
std::shared_ptr< This > shared_ptr
Definition: HybridBayesTree.h:68
gtsam::FactorGraph::emplace_shared
IsDerived< DERIVEDFACTOR > emplace_shared(Args &&... args)
Emplace a shared pointer to factor of given type.
Definition: FactorGraph.h:153
main
int main()
Definition: testHybridGaussianFactorGraph.cpp:911
HybridConditional.h
M
Matrix< RealScalar, Dynamic, Dynamic > M
Definition: bench_gemm.cpp:51


gtsam
Author(s):
autogenerated on Tue Jun 25 2024 03:05:58