testHybridGaussianConditional.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 
25 #include <gtsam/inference/Symbol.h>
27 
28 #include <vector>
29 
30 // Include for test suite
32 
33 using namespace gtsam;
37 
38 // Common constants
39 static const Key modeKey = M(0);
40 static const DiscreteKey mode(modeKey, 2);
41 static const VectorValues vv{{Z(0), Vector1(4.9)}, {X(0), Vector1(5.0)}};
42 static const DiscreteValues assignment0{{M(0), 0}}, assignment1{{M(0), 1}};
43 static const HybridValues hv0{vv, assignment0};
44 static const HybridValues hv1{vv, assignment1};
45 
46 /* ************************************************************************* */
47 namespace equal_constants {
48 // Create a simple HybridGaussianConditional
49 const double commonSigma = 2.0;
50 const std::vector<GaussianConditional::shared_ptr> conditionals{
52  commonSigma),
54  commonSigma)};
56 } // namespace equal_constants
57 
58 /* ************************************************************************* */
61  using namespace equal_constants;
62 
63  // Check that the conditional (negative log) normalization constant is the min
64  // of all constants which are all equal, in this case, hence:
65  const double K = hybrid_conditional.negLogConstant();
66  EXPECT_DOUBLES_EQUAL(K, conditionals[0]->negLogConstant(), 1e-8);
67  EXPECT_DOUBLES_EQUAL(K, conditionals[1]->negLogConstant(), 1e-8);
68 
71 }
72 
73 /* ************************************************************************* */
75 TEST(HybridGaussianConditional, LogProbability) {
76  using namespace equal_constants;
77  auto actual = hybrid_conditional.logProbability(vv);
78 
79  // Check result.
80  std::vector<DiscreteKey> discrete_keys = {mode};
81  std::vector<double> leaves = {conditionals[0]->logProbability(vv),
82  conditionals[1]->logProbability(vv)};
83  AlgebraicDecisionTree<Key> expected(discrete_keys, leaves);
84 
85  EXPECT(assert_equal(expected, actual, 1e-6));
86 
87  // Check for non-tree version.
88  for (size_t mode : {0, 1}) {
89  const HybridValues hv{vv, {{M(0), mode}}};
90  EXPECT_DOUBLES_EQUAL(conditionals[mode]->logProbability(vv),
92  }
93 }
94 
95 /* ************************************************************************* */
98  using namespace equal_constants;
99  auto actual = hybrid_conditional.errorTree(vv);
100 
101  // Check result.
102  DiscreteKeys discrete_keys{mode};
103  std::vector<double> leaves = {conditionals[0]->error(vv),
104  conditionals[1]->error(vv)};
105  AlgebraicDecisionTree<Key> expected(discrete_keys, leaves);
106 
107  EXPECT(assert_equal(expected, actual, 1e-6));
108 
109  // Check for non-tree version.
110  for (size_t mode : {0, 1}) {
111  const HybridValues hv{vv, {{M(0), mode}}};
113  hybrid_conditional.error(hv), 1e-8);
114  }
115 }
116 
117 /* ************************************************************************* */
121  using namespace equal_constants;
122 
123  // Compute likelihood
124  auto likelihood = hybrid_conditional.likelihood(vv);
125 
126  // Check that the hybrid conditional error and the likelihood error are the
127  // same.
128  EXPECT_DOUBLES_EQUAL(hybrid_conditional.error(hv0), likelihood->error(hv0),
129  1e-8);
130  EXPECT_DOUBLES_EQUAL(hybrid_conditional.error(hv1), likelihood->error(hv1),
131  1e-8);
132 
133  // Check that likelihood error is as expected, i.e., just the errors of the
134  // individual likelihoods, in the `equal_constants` case.
135  std::vector<DiscreteKey> discrete_keys = {mode};
136  std::vector<double> leaves = {conditionals[0]->likelihood(vv)->error(vv),
137  conditionals[1]->likelihood(vv)->error(vv)};
138  AlgebraicDecisionTree<Key> expected(discrete_keys, leaves);
139  EXPECT(assert_equal(expected, likelihood->errorTree(vv), 1e-6));
140 
141  // Check that the ratio of probPrime to evaluate is the same for all modes.
142  std::vector<double> ratio(2);
143  for (size_t mode : {0, 1}) {
144  const HybridValues hv{vv, {{M(0), mode}}};
145  ratio[mode] =
146  std::exp(-likelihood->error(hv)) / hybrid_conditional.evaluate(hv);
147  }
148  EXPECT_DOUBLES_EQUAL(ratio[0], ratio[1], 1e-8);
149 }
150 
151 /* ************************************************************************* */
153 // Create a HybridGaussianConditional with mode-dependent noise models.
154 // 0 is low-noise, 1 is high-noise.
155 const std::vector<GaussianConditional::shared_ptr> conditionals{
157  0.5),
159  3.0)};
161 } // namespace mode_dependent_constants
162 
163 /* ************************************************************************* */
164 // Create a test for continuousParents.
165 TEST(HybridGaussianConditional, ContinuousParents) {
166  using namespace mode_dependent_constants;
167  const KeyVector continuousParentKeys = hybrid_conditional.continuousParents();
168  // Check that the continuous parent keys are correct:
169  EXPECT(continuousParentKeys.size() == 1);
170  EXPECT(continuousParentKeys[0] == X(0));
171 
174 }
175 
176 /* ************************************************************************* */
179  using namespace mode_dependent_constants;
180  auto actual = hybrid_conditional.errorTree(vv);
181 
182  // Check result.
183  DiscreteKeys discrete_keys{mode};
184  double negLogConstant0 = conditionals[0]->negLogConstant();
185  double negLogConstant1 = conditionals[1]->negLogConstant();
186  double minErrorConstant = std::min(negLogConstant0, negLogConstant1);
187 
188  // Expected error is e(X) + log(sqrt(|2πΣ|)).
189  // We normalize log(sqrt(|2πΣ|)) with min(negLogConstant)
190  // so it is non-negative.
191  std::vector<double> leaves = {
192  conditionals[0]->error(vv) + negLogConstant0 - minErrorConstant,
193  conditionals[1]->error(vv) + negLogConstant1 - minErrorConstant};
194  AlgebraicDecisionTree<Key> expected(discrete_keys, leaves);
195 
196  EXPECT(assert_equal(expected, actual, 1e-6));
197 
198  // Check for non-tree version.
199  for (size_t mode : {0, 1}) {
200  const HybridValues hv{vv, {{M(0), mode}}};
202  conditionals[mode]->negLogConstant() -
203  minErrorConstant,
204  hybrid_conditional.error(hv), 1e-8);
205  }
206 }
207 
208 /* ************************************************************************* */
212  using namespace mode_dependent_constants;
213 
214  // Compute likelihood
215  auto likelihood = hybrid_conditional.likelihood(vv);
216 
217  // Check that the hybrid conditional error and the likelihood error are as
218  // expected, this invariant is the same as the equal noise case:
219  EXPECT_DOUBLES_EQUAL(hybrid_conditional.error(hv0), likelihood->error(hv0),
220  1e-8);
221  EXPECT_DOUBLES_EQUAL(hybrid_conditional.error(hv1), likelihood->error(hv1),
222  1e-8);
223 
224  // Check the detailed JacobianFactor calculation for mode==1.
225  {
226  // We have a JacobianFactor
227  const auto gf1 = (*likelihood)(assignment1);
228  const auto jf1 = std::dynamic_pointer_cast<JacobianFactor>(gf1);
229  CHECK(jf1);
230 
231  // It has 2 rows, not 1!
232  CHECK(jf1->rows() == 2);
233 
234  // Check that the constant C1 is properly encoded in the JacobianFactor.
235  const double C1 =
236  conditionals[1]->negLogConstant() - hybrid_conditional.negLogConstant();
237  const double c1 = std::sqrt(2.0 * C1);
238  Vector expected_unwhitened(2);
239  expected_unwhitened << 4.9 - 5.0, -c1;
240  Vector actual_unwhitened = jf1->unweighted_error(vv);
241  EXPECT(assert_equal(expected_unwhitened, actual_unwhitened));
242 
243  // Make sure the noise model does not touch it.
244  Vector expected_whitened(2);
245  expected_whitened << (4.9 - 5.0) / 3.0, -c1;
246  Vector actual_whitened = jf1->error_vector(vv);
247  EXPECT(assert_equal(expected_whitened, actual_whitened));
248 
249  // Check that the error is equal to the conditional error:
251  }
252 
253  // Check that the ratio of probPrime to evaluate is the same for all modes.
254  std::vector<double> ratio(2);
255  for (size_t mode : {0, 1}) {
256  const HybridValues hv{vv, {{M(0), mode}}};
257  ratio[mode] =
258  std::exp(-likelihood->error(hv)) / hybrid_conditional.evaluate(hv);
259  }
260  EXPECT_DOUBLES_EQUAL(ratio[0], ratio[1], 1e-8);
261 }
262 
263 /* ************************************************************************* */
264 int main() {
265  TestResult tr;
266  return TestRegistry::runAllTests(tr);
267 }
268 /* ************************************************************************* */
TestRegistry::runAllTests
static int runAllTests(TestResult &result)
Definition: TestRegistry.cpp:27
gtsam::Vector1
Eigen::Matrix< double, 1, 1 > Vector1
Definition: Vector.h:41
gtsam::HybridValues
Definition: HybridValues.h:37
GaussianConditional.h
Conditional Gaussian Base class.
equal_constants::commonSigma
const double commonSigma
Definition: testHybridGaussianConditional.cpp:49
HybridGaussianConditional.h
A hybrid conditional in the Conditional Linear Gaussian scheme.
e
Array< double, 1, 3 > e(1./3., 0.5, 2.)
gtsam::HybridGaussianFactor::errorTree
AlgebraicDecisionTree< Key > errorTree(const VectorValues &continuousValues) const override
Compute error of the HybridGaussianFactor as a tree.
Definition: HybridGaussianFactor.cpp:229
EXPECT
#define EXPECT(condition)
Definition: Test.h:150
TestHarness.h
gtsam::symbol_shorthand::M
Key M(std::uint64_t j)
Definition: inference/Symbol.h:160
mode_dependent_constants::hybrid_conditional
const HybridGaussianConditional hybrid_conditional(mode, conditionals)
assignment0
static const DiscreteValues assignment0
Definition: testHybridGaussianConditional.cpp:42
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
vv
static const VectorValues vv
Definition: testHybridGaussianConditional.cpp:41
exp
const EIGEN_DEVICE_FUNC ExpReturnType exp() const
Definition: ArrayCwiseUnaryOps.h:97
modeKey
static const Key modeKey
Definition: testHybridGaussianConditional.cpp:39
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.
assignment1
static const DiscreteValues assignment1
Definition: testHybridGaussianConditional.cpp:42
gtsam::AlgebraicDecisionTree< Key >
c1
static double c1
Definition: airy.c:54
gtsam::HybridGaussianConditional::logProbability
AlgebraicDecisionTree< Key > logProbability(const VectorValues &continuousValues) const
Compute logProbability of the HybridGaussianConditional as a tree.
Definition: HybridGaussianConditional.cpp:355
gtsam::symbol_shorthand::X
Key X(std::uint64_t j)
Definition: inference/Symbol.h:171
gtsam::HybridGaussianConditional::evaluate
double evaluate(const HybridValues &values) const override
Calculate probability density for given values.
Definition: HybridGaussianConditional.cpp:380
mode_dependent_constants
Definition: testHybridGaussianConditional.cpp:152
gtsam::VectorValues
Definition: VectorValues.h:74
gtsam::symbol_shorthand::Z
Key Z(std::uint64_t j)
Definition: inference/Symbol.h:173
mode
static const DiscreteKey mode(modeKey, 2)
C1
Definition: test_operator_overloading.cpp:97
gtsam::Conditional< HybridGaussianFactor, HybridGaussianConditional >::CheckInvariants
static bool CheckInvariants(const HybridGaussianConditional &conditional, const VALUES &x)
Definition: Conditional-inst.h:69
cholesky::expected
Matrix expected
Definition: testMatrix.cpp:971
gtsam::HybridGaussianConditional
A conditional of gaussian conditionals indexed by discrete variables, as part of a Bayes Network....
Definition: HybridGaussianConditional.h:53
Symbol.h
gtsam::HybridGaussianConditional::continuousParents
KeyVector continuousParents() const
Returns the continuous keys among the parents.
Definition: HybridGaussianConditional.cpp:230
gtsam::HybridGaussianConditional::likelihood
std::shared_ptr< HybridGaussianFactor > likelihood(const VectorValues &given) const
Definition: HybridGaussianConditional.cpp:257
EXPECT_DOUBLES_EQUAL
#define EXPECT_DOUBLES_EQUAL(expected, actual, threshold)
Definition: Test.h:161
TestResult
Definition: TestResult.h:26
gtsam
traits
Definition: chartTesting.h:28
gtsam::TEST
TEST(SmartFactorBase, Pinhole)
Definition: testSmartFactorBase.cpp:38
DiscreteValues.h
error
static double error
Definition: testRot3.cpp:37
K
#define K
Definition: igam.h:8
gtsam::DiscreteValues
Definition: DiscreteValues.h:34
CHECK
#define CHECK(condition)
Definition: Test.h:108
gtsam::DiscreteKey
std::pair< Key, size_t > DiscreteKey
Definition: DiscreteKey.h:38
main
int main()
Definition: testHybridGaussianConditional.cpp:264
equal_constants
Definition: testHybridGaussianConditional.cpp:47
ratio
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 y set format x g set format y g set format x2 g set format y2 g set format z g set angles radians set nogrid set key title set key left top Right noreverse box linetype linewidth samplen spacing width set nolabel set noarrow set nologscale set logscale x set set pointsize set encoding default set nopolar set noparametric set set set set surface set nocontour set clabel set mapping cartesian set nohidden3d set cntrparam order set cntrparam linear set cntrparam levels auto set cntrparam points set size ratio
Definition: gnuplot_common_settings.hh:44
mode_dependent_constants::conditionals
const std::vector< GaussianConditional::shared_ptr > conditionals
Definition: testHybridGaussianConditional.cpp:155
gtsam::assert_equal
bool assert_equal(const Matrix &expected, const Matrix &actual, double tol)
Definition: Matrix.cpp:40
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:185
hv0
static const HybridValues hv0
Definition: testHybridGaussianConditional.cpp:43
gtsam::HybridGaussianFactor::error
double error(const HybridValues &values) const override
Compute the log-likelihood, including the log-normalizing constant.
Definition: HybridGaussianFactor.cpp:240
gtsam::Key
std::uint64_t Key
Integer nonlinear key type.
Definition: types.h:97
hv1
static const HybridValues hv1
Definition: testHybridGaussianConditional.cpp:44
Z
#define Z
Definition: icosphere.cpp:21
HybridValues.h
ceres::sqrt
Jet< T, N > sqrt(const Jet< T, N > &f)
Definition: jet.h:418
gtsam::GaussianConditional::sharedMeanAndStddev
static shared_ptr sharedMeanAndStddev(Args &&... args)
Create shared pointer by forwarding arguments to fromMeanAndStddev.
Definition: GaussianConditional.h:105
M
Matrix< RealScalar, Dynamic, Dynamic > M
Definition: bench_gemm.cpp:51


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