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>
21 #include <gtsam/base/Vector.h>
36 #include <gtsam/inference/Key.h>
38 #include <gtsam/inference/Symbol.h>
40 
41 #include <algorithm>
42 #include <cstddef>
43 #include <functional>
44 #include <iostream>
45 #include <iterator>
46 #include <memory>
47 #include <numeric>
48 #include <vector>
49 
50 #include "Switching.h"
51 #include "TinyHybridExample.h"
52 
53 using namespace std;
54 using namespace gtsam;
55 
62 
63 // Set up sampling
64 std::mt19937_64 kRng(42);
65 
66 static const DiscreteKey m1(M(1), 2);
67 
68 /* ************************************************************************* */
70  HybridConditional conditional;
71 
73 
74  hfg.emplace_shared<JacobianFactor>(X(0), I_3x3, Z_3x1);
75 
76  // Define a hybrid gaussian conditional P(x0|x1, c0)
77  // and add it to the factor graph.
79  {M(0), 2},
80  {std::make_shared<GaussianConditional>(X(0), Z_3x1, I_3x3, X(1), I_3x3),
81  std::make_shared<GaussianConditional>(X(0), Vector3::Ones(), I_3x3, X(1),
82  I_3x3)});
83  hfg.add(gm);
84 
85  EXPECT_LONGS_EQUAL(2, hfg.size());
86 }
87 
88 /* ************************************************************************* */
89 TEST(HybridGaussianFactorGraph, EliminateSequential) {
90  // Test elimination of a single variable.
92 
93  hfg.emplace_shared<JacobianFactor>(0, I_3x3, Z_3x1);
94 
96 
97  EXPECT_LONGS_EQUAL(result.first->size(), 1);
98 }
99 
100 /* ************************************************************************* */
101 TEST(HybridGaussianFactorGraph, EliminateMultifrontal) {
102  // Test multifrontal elimination
104 
105  // Add priors on x0 and c1
106  hfg.add(JacobianFactor(X(0), I_3x3, Z_3x1));
107  hfg.add(DecisionTreeFactor(m1, {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 namespace two {
119 std::vector<GaussianFactor::shared_ptr> components(Key key) {
120  return {std::make_shared<JacobianFactor>(key, I_3x3, Z_3x1),
121  std::make_shared<JacobianFactor>(key, I_3x3, Vector3::Ones())};
122 }
123 } // namespace two
124 
125 /* ************************************************************************* */
126 TEST(HybridGaussianFactorGraph, hybridEliminationOneFactor) {
129 
130  auto result = hfg.eliminate({X(1)});
131 
132  // Check that we have a valid Gaussian conditional.
133  auto hgc = result.first->asHybrid();
134  CHECK(hgc);
135  const HybridValues values{{{X(1), Z_3x1}}, {{M(1), 1}}};
136  EXPECT(HybridConditional::CheckInvariants(*result.first, values));
137 
138  // Check that factor is discrete and correct
139  auto factor = std::dynamic_pointer_cast<DecisionTreeFactor>(result.second);
140  CHECK(factor);
141  EXPECT(assert_equal(DecisionTreeFactor{m1, "1 1"}, *factor));
142 }
143 
144 /* ************************************************************************* */
145 TEST(HybridGaussianFactorGraph, eliminateFullSequentialEqualChance) {
147 
148  // Add prior on x0
149  hfg.add(JacobianFactor(X(0), I_3x3, Z_3x1));
150 
151  // Add factor between x0 and x1
152  hfg.add(JacobianFactor(X(0), I_3x3, X(1), -I_3x3, Z_3x1));
153 
154  // Add a hybrid gaussian factor ϕ(x1, c1)
156 
157  auto result = hfg.eliminateSequential();
158 
159  auto dc = result->at(2)->asDiscrete();
160  CHECK(dc);
161  DiscreteValues dv;
162  dv[M(1)] = 0;
163  // Regression test
164  EXPECT_DOUBLES_EQUAL(0.62245933120185448, dc->operator()(dv), 1e-3);
165 }
166 
167 /* ************************************************************************* */
168 TEST(HybridGaussianFactorGraph, eliminateFullSequentialSimple) {
170 
171  // Add prior on x0
172  hfg.add(JacobianFactor(X(0), I_3x3, Z_3x1));
173  // Add factor between x0 and x1
174  hfg.add(JacobianFactor(X(0), I_3x3, X(1), -I_3x3, Z_3x1));
175 
177 
178  // Discrete probability table for c1
179  hfg.add(DecisionTreeFactor(m1, {2, 8}));
180  // Joint discrete probability table for c1, c2
181  hfg.add(DecisionTreeFactor({{M(1), 2}, {M(2), 2}}, "1 2 3 4"));
182 
184 
185  // There are 4 variables (2 continuous + 2 discrete) in the bayes net.
187 }
188 
189 /* ************************************************************************* */
190 TEST(HybridGaussianFactorGraph, eliminateFullMultifrontalSimple) {
192 
193  hfg.add(JacobianFactor(X(0), I_3x3, Z_3x1));
194  hfg.add(JacobianFactor(X(0), I_3x3, X(1), -I_3x3, Z_3x1));
195 
196  hfg.add(HybridGaussianFactor({M(1), 2}, two::components(X(1))));
197 
198  hfg.add(DecisionTreeFactor(m1, {2, 8}));
199  // TODO(Varun) Adding extra discrete variable not connected to continuous
200  // variable throws segfault
201  // hfg.add(DecisionTreeFactor({{M(1), 2}, {M(2), 2}}, "1 2 3 4"));
202 
204 
205  // The bayes tree should have 3 cliques
207  // GTSAM_PRINT(*result);
208  // GTSAM_PRINT(*result->marginalFactor(M(2)));
209 }
210 
211 /* ************************************************************************* */
212 TEST(HybridGaussianFactorGraph, eliminateFullMultifrontalCLG) {
214 
215  // Prior on x0
216  hfg.add(JacobianFactor(X(0), I_3x3, Z_3x1));
217  // Factor between x0-x1
218  hfg.add(JacobianFactor(X(0), I_3x3, X(1), -I_3x3, Z_3x1));
219 
220  // Hybrid factor P(x1|c1)
222  // Prior factor on c1
223  hfg.add(DecisionTreeFactor(m1, {2, 8}));
224 
225  // Get a constrained ordering keeping c1 last
226  auto ordering_full = HybridOrdering(hfg);
227 
228  // Returns a Hybrid Bayes Tree with distribution P(x0|x1)P(x1|c1)P(c1)
229  HybridBayesTree::shared_ptr hbt = hfg.eliminateMultifrontal(ordering_full);
230 
231  EXPECT_LONGS_EQUAL(3, hbt->size());
232 }
233 
234 /* ************************************************************************* */
235 /*
236  * This test is about how to assemble the Bayes Tree roots after we do partial
237  * elimination
238  */
239 TEST(HybridGaussianFactorGraph, eliminateFullMultifrontalTwoClique) {
241 
242  hfg.add(JacobianFactor(X(0), I_3x3, X(1), -I_3x3, Z_3x1));
243  hfg.add(JacobianFactor(X(1), I_3x3, X(2), -I_3x3, Z_3x1));
244 
245  hfg.add(HybridGaussianFactor({M(0), 2}, two::components(X(0))));
246  hfg.add(HybridGaussianFactor({M(1), 2}, two::components(X(2))));
247 
248  hfg.add(DecisionTreeFactor({{M(1), 2}, {M(2), 2}}, "1 2 3 4"));
249 
250  hfg.add(JacobianFactor(X(3), I_3x3, X(4), -I_3x3, Z_3x1));
251  hfg.add(JacobianFactor(X(4), I_3x3, X(5), -I_3x3, Z_3x1));
252 
253  hfg.add(HybridGaussianFactor({M(3), 2}, two::components(X(3))));
254  hfg.add(HybridGaussianFactor({M(2), 2}, two::components(X(5))));
255 
256  auto ordering_full =
257  Ordering::ColamdConstrainedLast(hfg, {M(0), M(1), M(2), M(3)});
258 
259  const auto [hbt, remaining] = hfg.eliminatePartialMultifrontal(ordering_full);
260 
261  // 9 cliques in the bayes tree and 0 remaining variables to eliminate.
262  EXPECT_LONGS_EQUAL(9, hbt->size());
263  EXPECT_LONGS_EQUAL(0, remaining->size());
264 
265  /*
266  (Fan) Explanation: the Junction tree will need to re-eliminate to get to the
267  marginal on X(1), which is not possible because it involves eliminating
268  discrete before continuous. The solution to this, however, is in Murphy02.
269  TLDR is that this is 1. expensive and 2. inexact. nevertheless it is doable.
270  And I believe that we should do this.
271  */
272 }
273 
275  const HybridBayesTree::shared_ptr &hbt,
276  const Ordering &ordering) {
277  DotWriter dw;
278  dw.positionHints['c'] = 2;
279  dw.positionHints['x'] = 1;
280  std::cout << hfg->dot(DefaultKeyFormatter, dw);
281  std::cout << "\n";
282  hbt->dot(std::cout);
283 
284  std::cout << "\n";
285  std::cout << hfg->eliminateSequential(ordering)->dot(DefaultKeyFormatter, dw);
286 }
287 
288 /* ************************************************************************* */
289 // TODO(fan): make a graph like Varun's paper one
291  auto N = 12;
292  auto hfg = makeSwitchingChain(N);
293 
294  // X(5) will be the center, X(1-4), X(6-9)
295  // X(3), X(7)
296  // X(2), X(8)
297  // X(1), X(4), X(6), X(9)
298  // M(5) will be the center, M(1-4), M(6-8)
299  // M(3), M(7)
300  // M(1), M(4), M(2), M(6), M(8)
301  // auto ordering_full =
302  // Ordering(KeyVector{X(1), X(4), X(2), X(6), X(9), X(8), X(3), X(7),
303  // X(5),
304  // M(1), M(4), M(2), M(6), M(8), M(3), M(7), M(5)});
306 
307  {
308  std::vector<int> naturalX(N);
309  std::iota(naturalX.begin(), naturalX.end(), 1);
310  std::vector<Key> ordX;
311  std::transform(naturalX.begin(), naturalX.end(), std::back_inserter(ordX),
312  [](int x) { return X(x); });
313 
314  auto [ndX, lvls] = makeBinaryOrdering(ordX);
315  std::copy(ndX.begin(), ndX.end(), std::back_inserter(ordering));
316  // TODO(dellaert): this has no effect!
317  for (auto &l : lvls) {
318  l = -l;
319  }
320  }
321  {
322  std::vector<int> naturalC(N - 1);
323  std::iota(naturalC.begin(), naturalC.end(), 1);
324  std::vector<Key> ordC;
325  std::transform(naturalC.begin(), naturalC.end(), std::back_inserter(ordC),
326  [](int x) { return M(x); });
327 
328  // std::copy(ordC.begin(), ordC.end(), std::back_inserter(ordering));
329  const auto [ndC, lvls] = makeBinaryOrdering(ordC);
330  std::copy(ndC.begin(), ndC.end(), std::back_inserter(ordering));
331  }
332  auto ordering_full = Ordering(ordering);
333 
334  // GTSAM_PRINT(*hfg);
335  // GTSAM_PRINT(ordering_full);
336 
337  const auto [hbt, remaining] =
338  hfg->eliminatePartialMultifrontal(ordering_full);
339 
340  // 12 cliques in the bayes tree and 0 remaining variables to eliminate.
341  EXPECT_LONGS_EQUAL(12, hbt->size());
342  EXPECT_LONGS_EQUAL(0, remaining->size());
343 }
344 
345 /* ************************************************************************* */
346 // TODO(fan): make a graph like Varun's paper one
348  auto N = 11;
349  auto hfg = makeSwitchingChain(N);
350 
351  // X(5) will be the center, X(1-4), X(6-9)
352  // X(3), X(7)
353  // X(2), X(8)
354  // X(1), X(4), X(6), X(9)
355  // M(5) will be the center, M(1-4), M(6-8)
356  // M(3), M(7)
357  // M(1), M(4), M(2), M(6), M(8)
358  // auto ordering_full =
359  // Ordering(KeyVector{X(1), X(4), X(2), X(6), X(9), X(8), X(3), X(7),
360  // X(5),
361  // M(1), M(4), M(2), M(6), M(8), M(3), M(7), M(5)});
363 
364  {
365  std::vector<int> naturalX(N);
366  std::iota(naturalX.begin(), naturalX.end(), 1);
367  std::vector<Key> ordX;
368  std::transform(naturalX.begin(), naturalX.end(), std::back_inserter(ordX),
369  [](int x) { return X(x); });
370 
371  auto [ndX, lvls] = makeBinaryOrdering(ordX);
372  std::copy(ndX.begin(), ndX.end(), std::back_inserter(ordering));
373  // TODO(dellaert): this has no effect!
374  for (auto &l : lvls) {
375  l = -l;
376  }
377  }
378  {
379  std::vector<int> naturalC(N - 1);
380  std::iota(naturalC.begin(), naturalC.end(), 1);
381  std::vector<Key> ordC;
382  std::transform(naturalC.begin(), naturalC.end(), std::back_inserter(ordC),
383  [](int x) { return M(x); });
384 
385  // std::copy(ordC.begin(), ordC.end(), std::back_inserter(ordering));
386  const auto [ndC, lvls] = makeBinaryOrdering(ordC);
387  std::copy(ndC.begin(), ndC.end(), std::back_inserter(ordering));
388  }
389  auto ordering_full = Ordering(ordering);
390 
391  const auto [hbt, remaining] =
392  hfg->eliminatePartialMultifrontal(ordering_full);
393 
394  auto new_fg = makeSwitchingChain(12);
395  auto isam = HybridGaussianISAM(*hbt);
396 
397  // Run an ISAM update.
398  HybridGaussianFactorGraph factorGraph;
399  factorGraph.push_back(new_fg->at(new_fg->size() - 2));
400  factorGraph.push_back(new_fg->at(new_fg->size() - 1));
401  isam.update(factorGraph);
402 
403  // ISAM should have 12 factors after the last update
404  EXPECT_LONGS_EQUAL(12, isam.size());
405 }
406 
407 /* ************************************************************************* */
408 TEST(HybridGaussianFactorGraph, SwitchingTwoVar) {
409  const int N = 7;
410  auto hfg = makeSwitchingChain(N, X);
411  hfg->push_back(*makeSwitchingChain(N, Y, D));
412 
413  for (int t = 1; t <= N; t++) {
414  hfg->add(JacobianFactor(X(t), I_3x3, Y(t), -I_3x3, Vector3(1.0, 0.0, 0.0)));
415  }
416 
418 
419  KeyVector naturalX(N);
420  std::iota(naturalX.begin(), naturalX.end(), 1);
421  KeyVector ordX;
422  for (size_t i = 1; i <= N; i++) {
423  ordX.emplace_back(X(i));
424  ordX.emplace_back(Y(i));
425  }
426 
427  for (size_t i = 1; i <= N - 1; i++) {
428  ordX.emplace_back(M(i));
429  }
430  for (size_t i = 1; i <= N - 1; i++) {
431  ordX.emplace_back(D(i));
432  }
433 
434  {
435  DotWriter dw;
436  dw.positionHints['x'] = 1;
437  dw.positionHints['c'] = 0;
438  dw.positionHints['d'] = 3;
439  dw.positionHints['y'] = 2;
440  // std::cout << hfg->dot(DefaultKeyFormatter, dw);
441  // std::cout << "\n";
442  }
443 
444  {
445  DotWriter dw;
446  dw.positionHints['y'] = 9;
447  // dw.positionHints['c'] = 0;
448  // dw.positionHints['d'] = 3;
449  dw.positionHints['x'] = 1;
450  // std::cout << "\n";
451  // std::cout << hfg->eliminateSequential(Ordering(ordX))
452  // ->dot(DefaultKeyFormatter, dw);
453  // hfg->eliminateMultifrontal(Ordering(ordX))->dot(std::cout);
454  }
455 
456  Ordering ordering_partial;
457  for (size_t i = 1; i <= N; i++) {
458  ordering_partial.emplace_back(X(i));
459  ordering_partial.emplace_back(Y(i));
460  }
461  const auto [hbn, remaining] =
462  hfg->eliminatePartialSequential(ordering_partial);
463 
464  EXPECT_LONGS_EQUAL(14, hbn->size());
465  EXPECT_LONGS_EQUAL(11, remaining->size());
466 
467  {
468  DotWriter dw;
469  dw.positionHints['x'] = 1;
470  dw.positionHints['c'] = 0;
471  dw.positionHints['d'] = 3;
472  dw.positionHints['y'] = 2;
473  // std::cout << remaining->dot(DefaultKeyFormatter, dw);
474  // std::cout << "\n";
475  }
476 }
477 
478 /* ****************************************************************************/
479 // Select a particular continuous factor graph given a discrete assignment
480 TEST(HybridGaussianFactorGraph, DiscreteSelection) {
481  Switching s(3);
482 
483  HybridGaussianFactorGraph graph = s.linearizedFactorGraph;
484 
485  DiscreteValues dv00{{M(0), 0}, {M(1), 0}};
486  GaussianFactorGraph continuous_00 = graph(dv00);
487  GaussianFactorGraph expected_00;
488  expected_00.push_back(JacobianFactor(X(0), I_1x1 * 10, Vector1(-10)));
489  expected_00.push_back(JacobianFactor(X(0), -I_1x1, X(1), I_1x1, Vector1(-1)));
490  expected_00.push_back(JacobianFactor(X(1), -I_1x1, X(2), I_1x1, Vector1(-1)));
491  expected_00.push_back(JacobianFactor(X(1), I_1x1 * 10, Vector1(-10)));
492  expected_00.push_back(JacobianFactor(X(2), I_1x1 * 10, Vector1(-10)));
493 
494  EXPECT(assert_equal(expected_00, continuous_00));
495 
496  DiscreteValues dv01{{M(0), 0}, {M(1), 1}};
497  GaussianFactorGraph continuous_01 = graph(dv01);
498  GaussianFactorGraph expected_01;
499  expected_01.push_back(JacobianFactor(X(0), I_1x1 * 10, Vector1(-10)));
500  expected_01.push_back(JacobianFactor(X(0), -I_1x1, X(1), I_1x1, Vector1(-1)));
501  expected_01.push_back(JacobianFactor(X(1), -I_1x1, X(2), I_1x1, Vector1(-0)));
502  expected_01.push_back(JacobianFactor(X(1), I_1x1 * 10, Vector1(-10)));
503  expected_01.push_back(JacobianFactor(X(2), I_1x1 * 10, Vector1(-10)));
504 
505  EXPECT(assert_equal(expected_01, continuous_01));
506 
507  DiscreteValues dv10{{M(0), 1}, {M(1), 0}};
508  GaussianFactorGraph continuous_10 = graph(dv10);
509  GaussianFactorGraph expected_10;
510  expected_10.push_back(JacobianFactor(X(0), I_1x1 * 10, Vector1(-10)));
511  expected_10.push_back(JacobianFactor(X(0), -I_1x1, X(1), I_1x1, Vector1(-0)));
512  expected_10.push_back(JacobianFactor(X(1), -I_1x1, X(2), I_1x1, Vector1(-1)));
513  expected_10.push_back(JacobianFactor(X(1), I_1x1 * 10, Vector1(-10)));
514  expected_10.push_back(JacobianFactor(X(2), I_1x1 * 10, Vector1(-10)));
515 
516  EXPECT(assert_equal(expected_10, continuous_10));
517 
518  DiscreteValues dv11{{M(0), 1}, {M(1), 1}};
519  GaussianFactorGraph continuous_11 = graph(dv11);
520  GaussianFactorGraph expected_11;
521  expected_11.push_back(JacobianFactor(X(0), I_1x1 * 10, Vector1(-10)));
522  expected_11.push_back(JacobianFactor(X(0), -I_1x1, X(1), I_1x1, Vector1(-0)));
523  expected_11.push_back(JacobianFactor(X(1), -I_1x1, X(2), I_1x1, Vector1(-0)));
524  expected_11.push_back(JacobianFactor(X(1), I_1x1 * 10, Vector1(-10)));
525  expected_11.push_back(JacobianFactor(X(2), I_1x1 * 10, Vector1(-10)));
526 
527  EXPECT(assert_equal(expected_11, continuous_11));
528 }
529 
530 /* ************************************************************************* */
533 
534  hfg.add(JacobianFactor(X(0), I_3x3, Z_3x1));
535  hfg.add(JacobianFactor(X(0), I_3x3, X(1), -I_3x3, Z_3x1));
537 
538  auto result = hfg.eliminateSequential();
539 
540  HybridValues hv = result->optimize();
541 
542  EXPECT(assert_equal(hv.atDiscrete(M(1)), int(0)));
543 }
544 
545 /* ************************************************************************* */
546 // Test adding of gaussian conditional and re-elimination.
548  Switching switching(4);
550 
551  hfg.push_back(switching.linearizedFactorGraph.at(0)); // P(X1)
553  ordering.push_back(X(0));
555 
556  hfg.push_back(switching.linearizedFactorGraph.at(1)); // P(X1, X2 | M1)
557  hfg.push_back(*bayes_net);
558  hfg.push_back(switching.linearizedFactorGraph.at(2)); // P(X2, X3 | M2)
559  hfg.push_back(switching.linearizedFactorGraph.at(5)); // P(M1)
560  ordering.push_back(X(1));
561  ordering.push_back(X(2));
562  ordering.push_back(M(0));
563  ordering.push_back(M(1));
564 
565  bayes_net = hfg.eliminateSequential(ordering);
566 
567  HybridValues result = bayes_net->optimize();
568 
569  Values expected_continuous;
570  expected_continuous.insert<double>(X(0), 0);
571  expected_continuous.insert<double>(X(1), 1);
572  expected_continuous.insert<double>(X(2), 2);
573  expected_continuous.insert<double>(X(3), 4);
574  Values result_continuous =
575  switching.linearizationPoint.retract(result.continuous());
576  EXPECT(assert_equal(expected_continuous, result_continuous));
577 
578  DiscreteValues expected_discrete;
579  expected_discrete[M(0)] = 1;
580  expected_discrete[M(1)] = 1;
581  EXPECT(assert_equal(expected_discrete, result.discrete()));
582 }
583 
584 /* ****************************************************************************/
585 // Test hybrid gaussian factor graph error and unnormalized probabilities
586 TEST(HybridGaussianFactorGraph, ErrorAndProbPrime) {
587  Switching s(3);
588 
589  HybridGaussianFactorGraph graph = s.linearizedFactorGraph;
590 
591  HybridBayesNet::shared_ptr hybridBayesNet = graph.eliminateSequential();
592 
593  const HybridValues delta = hybridBayesNet->optimize();
594  const double error = graph.error(delta);
595 
596  // regression
597  EXPECT(assert_equal(1.58886, error, 1e-5));
598 
599  // Real test:
601 }
602 
603 /* ****************************************************************************/
604 // Test hybrid gaussian factor graph error and unnormalized probabilities
605 TEST(HybridGaussianFactorGraph, ErrorAndProbPrimeTree) {
606  Switching s(3);
607 
608  HybridGaussianFactorGraph graph = s.linearizedFactorGraph;
609 
610  HybridBayesNet::shared_ptr hybridBayesNet = graph.eliminateSequential();
611 
612  HybridValues delta = hybridBayesNet->optimize();
613  auto error_tree = graph.errorTree(delta.continuous());
614 
615  std::vector<DiscreteKey> discrete_keys = {{M(0), 2}, {M(1), 2}};
616  std::vector<double> leaves = {0.9998558, 0.4902432, 0.5193694, 0.0097568};
617  AlgebraicDecisionTree<Key> expected_error(discrete_keys, leaves);
618 
619  // regression
620  EXPECT(assert_equal(expected_error, error_tree, 1e-7));
621 
622  auto probabilities = graph.probPrime(delta.continuous());
623  std::vector<double> prob_leaves = {0.36793249, 0.61247742, 0.59489556,
624  0.99029064};
625  AlgebraicDecisionTree<Key> expected_probabilities(discrete_keys, prob_leaves);
626 
627  // regression
628  EXPECT(assert_equal(expected_probabilities, probabilities, 1e-7));
629 }
630 
631 /* ****************************************************************************/
632 // Test hybrid gaussian factor graph errorTree during
633 // incremental operation
634 TEST(HybridGaussianFactorGraph, IncrementalErrorTree) {
635  Switching s(4);
636 
638  graph.push_back(s.linearizedFactorGraph.at(0)); // f(X0)
639  graph.push_back(s.linearizedFactorGraph.at(1)); // f(X0, X1, M0)
640  graph.push_back(s.linearizedFactorGraph.at(2)); // f(X1, X2, M1)
641  graph.push_back(s.linearizedFactorGraph.at(4)); // f(X1)
642  graph.push_back(s.linearizedFactorGraph.at(5)); // f(X2)
643  graph.push_back(s.linearizedFactorGraph.at(7)); // f(M0)
644  graph.push_back(s.linearizedFactorGraph.at(8)); // f(M0, M1)
645 
646  HybridBayesNet::shared_ptr hybridBayesNet = graph.eliminateSequential();
647  EXPECT_LONGS_EQUAL(5, hybridBayesNet->size());
648 
649  HybridValues delta = hybridBayesNet->optimize();
650  auto error_tree = graph.errorTree(delta.continuous());
651 
652  std::vector<DiscreteKey> discrete_keys = {{M(0), 2}, {M(1), 2}};
653  std::vector<double> leaves = {0.99985581, 0.4902432, 0.51936941,
654  0.0097568009};
655  AlgebraicDecisionTree<Key> expected_error(discrete_keys, leaves);
656 
657  // regression
658  EXPECT(assert_equal(expected_error, error_tree, 1e-7));
659 
661  graph.push_back(*hybridBayesNet);
662  graph.push_back(s.linearizedFactorGraph.at(3)); // f(X2, X3, M2)
663  graph.push_back(s.linearizedFactorGraph.at(6)); // f(X3)
664 
665  hybridBayesNet = graph.eliminateSequential();
666  EXPECT_LONGS_EQUAL(7, hybridBayesNet->size());
667 
668  delta = hybridBayesNet->optimize();
669  auto error_tree2 = graph.errorTree(delta.continuous());
670 
671  discrete_keys = {{M(0), 2}, {M(1), 2}, {M(2), 2}};
672  leaves = {0.50985198, 0.0097577296, 0.50009425, 0,
673  0.52922138, 0.029127133, 0.50985105, 0.0097567964};
674  AlgebraicDecisionTree<Key> expected_error2(discrete_keys, leaves);
675 
676  // regression
677  EXPECT(assert_equal(expected_error, error_tree, 1e-7));
678 }
679 
680 /* ****************************************************************************/
681 // Check that assembleGraphTree assembles Gaussian factor graphs for each
682 // assignment.
683 TEST(HybridGaussianFactorGraph, assembleGraphTree) {
684  const int num_measurements = 1;
686  num_measurements, VectorValues{{Z(0), Vector1(5.0)}});
687  EXPECT_LONGS_EQUAL(3, fg.size());
688 
689  // Assemble graph tree:
690  auto actual = fg.assembleGraphTree();
691 
692  // Create expected decision tree with two factor graphs:
693 
694  // Get hybrid factor:
695  auto hybrid = fg.at<HybridGaussianFactor>(0);
696  CHECK(hybrid);
697 
698  // Get prior factor:
699  const auto gf = fg.at<HybridConditional>(1);
700  CHECK(gf);
701  using GF = GaussianFactor::shared_ptr;
702  const GF prior = gf->asGaussian();
703  CHECK(prior);
704 
705  // Create DiscreteValues for both 0 and 1:
706  DiscreteValues d0{{M(0), 0}}, d1{{M(0), 1}};
707 
708  // Expected decision tree with two factor graphs:
709  // f(x0;mode=0)P(x0) and f(x0;mode=1)P(x0)
711  M(0), GaussianFactorGraph(std::vector<GF>{(*hybrid)(d0), prior}),
712  GaussianFactorGraph(std::vector<GF>{(*hybrid)(d1), prior})};
713 
714  EXPECT(assert_equal(expected(d0), actual(d0), 1e-5));
715  EXPECT(assert_equal(expected(d1), actual(d1), 1e-5));
716 }
717 
718 /* ****************************************************************************/
719 // Check that the factor graph unnormalized probability is proportional to the
720 // Bayes net probability for the given measurements.
721 bool ratioTest(const HybridBayesNet &bn, const VectorValues &measurements,
722  const HybridGaussianFactorGraph &fg, size_t num_samples = 100) {
723  auto compute_ratio = [&](HybridValues *sample) -> double {
724  sample->update(measurements); // update sample with given measurements:
725  return bn.evaluate(*sample) / fg.probPrime(*sample);
726  };
727 
728  HybridValues sample = bn.sample(&kRng);
729  double expected_ratio = compute_ratio(&sample);
730 
731  // Test ratios for a number of independent samples:
732  for (size_t i = 0; i < num_samples; i++) {
733  HybridValues sample = bn.sample(&kRng);
734  if (std::abs(expected_ratio - compute_ratio(&sample)) > 1e-6) return false;
735  }
736  return true;
737 }
738 
739 /* ****************************************************************************/
740 // Check that the bayes net unnormalized probability is proportional to the
741 // Bayes net probability for the given measurements.
742 bool ratioTest(const HybridBayesNet &bn, const VectorValues &measurements,
743  const HybridBayesNet &posterior, size_t num_samples = 100) {
744  auto compute_ratio = [&](HybridValues *sample) -> double {
745  sample->update(measurements); // update sample with given measurements:
746  return bn.evaluate(*sample) / posterior.evaluate(*sample);
747  };
748 
749  HybridValues sample = bn.sample(&kRng);
750  double expected_ratio = compute_ratio(&sample);
751 
752  // Test ratios for a number of independent samples:
753  for (size_t i = 0; i < num_samples; i++) {
754  HybridValues sample = bn.sample(&kRng);
755  // GTSAM_PRINT(sample);
756  // std::cout << "ratio: " << compute_ratio(&sample) << std::endl;
757  if (std::abs(expected_ratio - compute_ratio(&sample)) > 1e-6) return false;
758  }
759  return true;
760 }
761 
762 /* ****************************************************************************/
763 // Check that eliminating tiny net with 1 measurement yields correct result.
764 TEST(HybridGaussianFactorGraph, EliminateTiny1) {
765  const int num_measurements = 1;
766  const VectorValues measurements{{Z(0), Vector1(5.0)}};
767  auto bn = tiny::createHybridBayesNet(num_measurements);
768  auto fg = bn.toFactorGraph(measurements);
769  EXPECT_LONGS_EQUAL(3, fg.size());
770 
771  EXPECT(ratioTest(bn, measurements, fg));
772 
773  // Create expected Bayes Net:
774  HybridBayesNet expectedBayesNet;
775 
776  // Create hybrid Gaussian factor on X(0).
777  using tiny::mode;
778  // regression, but mean checked to be 5.0 in both cases:
779  const auto conditional0 = std::make_shared<GaussianConditional>(
780  X(0), Vector1(14.1421), I_1x1 * 2.82843),
781  conditional1 = std::make_shared<GaussianConditional>(
782  X(0), Vector1(10.1379), I_1x1 * 2.02759);
783  expectedBayesNet.emplace_shared<HybridGaussianConditional>(
784  mode, std::vector{conditional0, conditional1});
785 
786  // Add prior on mode.
787  expectedBayesNet.emplace_shared<DiscreteConditional>(mode, "74/26");
788 
789  // Test elimination
790  const auto posterior = fg.eliminateSequential();
791  EXPECT(assert_equal(expectedBayesNet, *posterior, 0.01));
792 
793  EXPECT(ratioTest(bn, measurements, *posterior));
794 }
795 
796 /* ****************************************************************************/
797 // Check that eliminating tiny net with 1 measurement with mode order swapped
798 // yields correct result.
799 TEST(HybridGaussianFactorGraph, EliminateTiny1Swapped) {
800  const VectorValues measurements{{Z(0), Vector1(5.0)}};
801 
802  HybridBayesNet bn;
803 
804  // mode-dependent: 1 is low-noise, 0 is high-noise.
805  // Create hybrid Gaussian factor z_0 = x0 + noise for each measurement.
806  std::vector<std::pair<Vector, double>> parms{{Z_1x1, 3}, {Z_1x1, 0.5}};
807  bn.emplace_shared<HybridGaussianConditional>(m1, Z(0), I_1x1, X(0), parms);
808 
809  // Create prior on X(0).
810  bn.push_back(
811  GaussianConditional::sharedMeanAndStddev(X(0), Vector1(5.0), 0.5));
812 
813  // Add prior on m1.
815 
816  // bn.print();
817  auto fg = bn.toFactorGraph(measurements);
818  EXPECT_LONGS_EQUAL(3, fg.size());
819 
820  // fg.print();
821 
822  EXPECT(ratioTest(bn, measurements, fg));
823 
824  // Create expected Bayes Net:
825  HybridBayesNet expectedBayesNet;
826 
827  // Create hybrid Gaussian factor on X(0).
828  // regression, but mean checked to be 5.0 in both cases:
829  const auto conditional0 = std::make_shared<GaussianConditional>(
830  X(0), Vector1(10.1379), I_1x1 * 2.02759),
831  conditional1 = std::make_shared<GaussianConditional>(
832  X(0), Vector1(14.1421), I_1x1 * 2.82843);
833  expectedBayesNet.emplace_shared<HybridGaussianConditional>(
834  m1, std::vector{conditional0, conditional1});
835 
836  // Add prior on m1.
837  expectedBayesNet.emplace_shared<DiscreteConditional>(m1, "1/1");
838 
839  // Test elimination
840  const auto posterior = fg.eliminateSequential();
841  // EXPECT(assert_equal(expectedBayesNet, *posterior, 0.01));
842 
843  EXPECT(ratioTest(bn, measurements, *posterior));
844 
845  // posterior->print();
846  // posterior->optimize().print();
847 }
848 
849 /* ****************************************************************************/
850 // Check that eliminating tiny net with 2 measurements yields correct result.
851 TEST(HybridGaussianFactorGraph, EliminateTiny2) {
852  // Create factor graph with 2 measurements such that posterior mean = 5.0.
853  const int num_measurements = 2;
854  const VectorValues measurements{{Z(0), Vector1(4.0)}, {Z(1), Vector1(6.0)}};
855  auto bn = tiny::createHybridBayesNet(num_measurements);
856  auto fg = bn.toFactorGraph(measurements);
857  EXPECT_LONGS_EQUAL(4, fg.size());
858 
859  // Create expected Bayes Net:
860  HybridBayesNet expectedBayesNet;
861 
862  // Create hybrid Gaussian factor on X(0).
863  using tiny::mode;
864  // regression, but mean checked to be 5.0 in both cases:
865  const auto conditional0 = std::make_shared<GaussianConditional>(
866  X(0), Vector1(17.3205), I_1x1 * 3.4641),
867  conditional1 = std::make_shared<GaussianConditional>(
868  X(0), Vector1(10.274), I_1x1 * 2.0548);
869  expectedBayesNet.emplace_shared<HybridGaussianConditional>(
870  mode, std::vector{conditional0, conditional1});
871 
872  // Add prior on mode.
873  expectedBayesNet.emplace_shared<DiscreteConditional>(mode, "23/77");
874 
875  // Test elimination
876  const auto posterior = fg.eliminateSequential();
877  EXPECT(assert_equal(expectedBayesNet, *posterior, 0.01));
878 
879  EXPECT(ratioTest(bn, measurements, *posterior));
880 }
881 
882 /* ****************************************************************************/
883 // Test eliminating tiny net with 1 mode per measurement.
884 TEST(HybridGaussianFactorGraph, EliminateTiny22) {
885  // Create factor graph with 2 measurements such that posterior mean = 5.0.
886  const int num_measurements = 2;
887  const bool manyModes = true;
888 
889  // Create Bayes net and convert to factor graph.
890  auto bn = tiny::createHybridBayesNet(num_measurements, manyModes);
891  const VectorValues measurements{{Z(0), Vector1(4.0)}, {Z(1), Vector1(6.0)}};
892  auto fg = bn.toFactorGraph(measurements);
893  EXPECT_LONGS_EQUAL(5, fg.size());
894 
895  EXPECT(ratioTest(bn, measurements, fg));
896 
897  // Test elimination
898  const auto posterior = fg.eliminateSequential();
899 
900  EXPECT(ratioTest(bn, measurements, *posterior));
901 }
902 
903 /* ****************************************************************************/
904 // Test elimination of a switching network with one mode per measurement.
905 TEST(HybridGaussianFactorGraph, EliminateSwitchingNetwork) {
906  // Create a switching network with one mode per measurement.
907  HybridBayesNet bn;
908 
909  // NOTE: we add reverse topological so we can sample from the Bayes net.:
910 
911  // Add measurements:
912  std::vector<std::pair<Vector, double>> measurementModels{{Z_1x1, 3},
913  {Z_1x1, 0.5}};
914  for (size_t t : {0, 1, 2}) {
915  // Create hybrid Gaussian factor on Z(t) conditioned on X(t) and mode N(t):
916  const auto noise_mode_t = DiscreteKey{N(t), 2};
917  bn.emplace_shared<HybridGaussianConditional>(noise_mode_t, Z(t), I_1x1,
918  X(t), measurementModels);
919 
920  // Create prior on discrete mode N(t):
921  bn.emplace_shared<DiscreteConditional>(noise_mode_t, "20/80");
922  }
923 
924  // Add motion models. TODO(frank): why are they exactly the same?
925  std::vector<std::pair<Vector, double>> motionModels{{Z_1x1, 0.2},
926  {Z_1x1, 0.2}};
927  for (size_t t : {2, 1}) {
928  // Create hybrid Gaussian factor on X(t) conditioned on X(t-1)
929  // and mode M(t-1):
930  const auto motion_model_t = DiscreteKey{M(t), 2};
931  bn.emplace_shared<HybridGaussianConditional>(motion_model_t, X(t), I_1x1,
932  X(t - 1), motionModels);
933 
934  // Create prior on motion model M(t):
935  bn.emplace_shared<DiscreteConditional>(motion_model_t, "40/60");
936  }
937 
938  // Create Gaussian prior on continuous X(0) using sharedMeanAndStddev:
939  bn.push_back(GaussianConditional::sharedMeanAndStddev(X(0), Z_1x1, 0.1));
940 
941  // Make sure we an sample from the Bayes net:
943 
944  // Create measurements consistent with moving right every time:
945  const VectorValues measurements{
946  {Z(0), Vector1(0.0)}, {Z(1), Vector1(1.0)}, {Z(2), Vector1(2.0)}};
947  const HybridGaussianFactorGraph fg = bn.toFactorGraph(measurements);
948 
949  // Factor graph is:
950  // D D
951  // | |
952  // m1 m2
953  // | |
954  // C-x0-HC-x1-HC-x2
955  // | | |
956  // HF HF HF
957  // | | |
958  // n0 n1 n2
959  // | | |
960  // D D D
961  EXPECT_LONGS_EQUAL(11, fg.size());
962  EXPECT(ratioTest(bn, measurements, fg));
963 
964  // Do elimination of X(2) only:
965  auto [bn1, fg1] = fg.eliminatePartialSequential(Ordering{X(2)});
966  fg1->push_back(*bn1);
967  EXPECT(ratioTest(bn, measurements, *fg1));
968 
969  // Create ordering that eliminates in time order, then discrete modes:
970  Ordering ordering{X(2), X(1), X(0), N(0), N(1), N(2), M(1), M(2)};
971 
972  // Do elimination:
974 
975  // Test resulting posterior Bayes net has correct size:
976  EXPECT_LONGS_EQUAL(8, posterior->size());
977 
978  // Ratio test
979  EXPECT(ratioTest(bn, measurements, *posterior));
980 }
981 
982 /* ************************************************************************* */
983 int main() {
984  TestResult tr;
985  return TestRegistry::runAllTests(tr);
986 }
987 /* ************************************************************************* */
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
different_sigmas::parms
const std::vector< std::pair< Vector, double > > parms
Definition: testHybridBayesNet.cpp:184
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:721
gtsam::HybridValues
Definition: HybridValues.h:37
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:528
Vector.h
typedef and functions to augment Eigen's VectorXd
gtsam::HybridConditional
Definition: HybridConditional.h:59
gtsam::Values::size
size_t size() const
Definition: Values.h:178
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.)
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:36
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:357
Switching.h
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
m1
static const DiscreteKey m1(M(1), 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:87
HybridBayesNet.h
A Bayes net of Gaussian Conditionals indexed by discrete keys.
different_sigmas::values
HybridValues values
Definition: testHybridBayesNet.cpp:195
Ordering.h
Variable ordering for the elimination algorithm.
X
#define X
Definition: icosphere.cpp:20
dotPrint
void dotPrint(const HybridGaussianFactorGraph::shared_ptr &hfg, const HybridBayesTree::shared_ptr &hbt, const Ordering &ordering)
Definition: testHybridGaussianFactorGraph.cpp:274
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
HybridGaussianFactor.h
A set of GaussianFactors, indexed by a set of discrete keys.
gtsam::HybridValues::continuous
const VectorValues & continuous() const
Return the multi-dimensional vector values.
Definition: HybridValues.cpp:54
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 >
gtsam::Switching
ϕ(X(0)) .. ϕ(X(k),X(k+1)) .. ϕ(X(k);z_k) .. ϕ(M(0)) .. ϕ(M(k),M(k+1))
Definition: Switching.h:122
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
mode
static const DiscreteKey mode(modeKey, 2)
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::HybridGaussianConditional
A conditional of gaussian conditionals indexed by discrete variables, as part of a Bayes Network....
Definition: HybridGaussianConditional.h:53
gtsam::HybridGaussianFactorGraph::eliminate
std::pair< std::shared_ptr< HybridConditional >, std::shared_ptr< Factor > > eliminate(const Ordering &keys) const
Eliminate the given continuous keys.
Definition: HybridGaussianFactorGraph.cpp:347
gtsam::HybridGaussianFactorGraph
Definition: HybridGaussianFactorGraph.h:104
gtsam::makeSwitchingChain
HybridGaussianFactorGraph::shared_ptr makeSwitchingChain(size_t n, std::function< Key(int)> x=X, std::function< Key(int)> m=M)
Create a switching system chain. A switching system is a continuous system which depends on a discret...
Definition: Switching.h:54
Symbol.h
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.
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:69
key
const gtsam::Symbol key('X', 0)
JacobianFactor.h
gtsam::FactorGraph::size
size_t size() const
Definition: FactorGraph.h:297
gtsam::DecisionTree
a decision tree is a function from assignments to values.
Definition: DecisionTree.h:63
gtsam::HybridBayesNet::push_back
void push_back(std::shared_ptr< HybridConditional > conditional)
Add a hybrid conditional using a shared_ptr.
Definition: HybridBayesNet.h:75
gtsam::DiscreteConditional
Definition: DiscreteConditional.h:37
Test.h
HybridGaussianFactorGraph.h
Linearized Hybrid factor graph that uses type erasure.
gtsam
traits
Definition: chartTesting.h:28
gtsam::HybridValues::atDiscrete
size_t & atDiscrete(Key j)
Definition: HybridValues.cpp:132
DiscreteValues.h
error
static double error
Definition: testRot3.cpp:37
two::components
std::vector< GaussianFactor::shared_ptr > components(Key key)
Definition: testHybridGaussianFactorGraph.cpp:119
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:253
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:127
gtsam::HybridGaussianFactor
Implementation of a discrete-conditioned hybrid factor. Implements a joint discrete-continuous factor...
Definition: HybridGaussianFactor.h:59
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:126
different_sigmas::prior
const auto prior
Definition: testHybridBayesNet.cpp:188
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
different_sigmas::hgc
const auto hgc
Definition: testHybridBayesNet.cpp:186
gtsam::HybridBayesNet::shared_ptr
std::shared_ptr< HybridBayesNet > shared_ptr
Definition: HybridBayesNet.h:41
gtsam::HybridBayesNet::toFactorGraph
HybridGaussianFactorGraph toFactorGraph(const VectorValues &measurements) const
Definition: HybridBayesNet.cpp:362
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
gtsam::Factor::size
size_t size() const
Definition: Factor.h:160
gtsam::Key
std::uint64_t Key
Integer nonlinear key type.
Definition: types.h:97
Z
#define Z
Definition: icosphere.cpp:21
two
Definition: testHybridGaussianFactorGraph.cpp:118
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
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:983
gtsam::HybridBayesNet::emplace_shared
void emplace_shared(Args &&...args)
Definition: HybridBayesNet.h:120
HybridConditional.h
M
Matrix< RealScalar, Dynamic, Dynamic > M
Definition: bench_gemm.cpp:51


gtsam
Author(s):
autogenerated on Fri Oct 4 2024 03:08:41