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  conditionals);
57 } // namespace equal_constants
58 
59 /* ************************************************************************* */
62  using namespace equal_constants;
63 
64  // Check that the conditional (negative log) normalization constant is the min
65  // of all constants which are all equal, in this case, hence:
66  const double K = hybrid_conditional.negLogConstant();
67  EXPECT_DOUBLES_EQUAL(K, conditionals[0]->negLogConstant(), 1e-8);
68  EXPECT_DOUBLES_EQUAL(K, conditionals[1]->negLogConstant(), 1e-8);
69 
72 }
73 
74 /* ************************************************************************* */
76 TEST(HybridGaussianConditional, LogProbability) {
77  using namespace equal_constants;
78  auto actual = hybrid_conditional.logProbability(vv);
79 
80  // Check result.
81  std::vector<DiscreteKey> discrete_keys = {mode};
82  std::vector<double> leaves = {conditionals[0]->logProbability(vv),
83  conditionals[1]->logProbability(vv)};
84  AlgebraicDecisionTree<Key> expected(discrete_keys, leaves);
85 
86  EXPECT(assert_equal(expected, actual, 1e-6));
87 
88  // Check for non-tree version.
89  for (size_t mode : {0, 1}) {
90  const HybridValues hv{vv, {{M(0), mode}}};
91  EXPECT_DOUBLES_EQUAL(conditionals[mode]->logProbability(vv),
93  }
94 }
95 
96 /* ************************************************************************* */
99  using namespace equal_constants;
100  auto actual = hybrid_conditional.errorTree(vv);
101 
102  // Check result.
103  DiscreteKeys discrete_keys{mode};
104  std::vector<double> leaves = {conditionals[0]->error(vv),
105  conditionals[1]->error(vv)};
106  AlgebraicDecisionTree<Key> expected(discrete_keys, leaves);
107 
108  EXPECT(assert_equal(expected, actual, 1e-6));
109 
110  // Check for non-tree version.
111  for (size_t mode : {0, 1}) {
112  const HybridValues hv{vv, {{M(0), mode}}};
114  hybrid_conditional.error(hv), 1e-8);
115  }
116 }
117 
118 /* ************************************************************************* */
122  using namespace equal_constants;
123 
124  // Compute likelihood
125  auto likelihood = hybrid_conditional.likelihood(vv);
126 
127  // Check that the hybrid conditional error and the likelihood error are the
128  // same.
129  EXPECT_DOUBLES_EQUAL(hybrid_conditional.error(hv0), likelihood->error(hv0),
130  1e-8);
131  EXPECT_DOUBLES_EQUAL(hybrid_conditional.error(hv1), likelihood->error(hv1),
132  1e-8);
133 
134  // Check that likelihood error is as expected, i.e., just the errors of the
135  // individual likelihoods, in the `equal_constants` case.
136  std::vector<DiscreteKey> discrete_keys = {mode};
137  std::vector<double> leaves = {conditionals[0]->likelihood(vv)->error(vv),
138  conditionals[1]->likelihood(vv)->error(vv)};
139  AlgebraicDecisionTree<Key> expected(discrete_keys, leaves);
140  EXPECT(assert_equal(expected, likelihood->errorTree(vv), 1e-6));
141 
142  // Check that the ratio of probPrime to evaluate is the same for all modes.
143  std::vector<double> ratio(2);
144  for (size_t mode : {0, 1}) {
145  const HybridValues hv{vv, {{M(0), mode}}};
146  ratio[mode] =
147  std::exp(-likelihood->error(hv)) / hybrid_conditional.evaluate(hv);
148  }
149  EXPECT_DOUBLES_EQUAL(ratio[0], ratio[1], 1e-8);
150 }
151 
152 /* ************************************************************************* */
154 // Create a HybridGaussianConditional with mode-dependent noise models.
155 // 0 is low-noise, 1 is high-noise.
156 const std::vector<GaussianConditional::shared_ptr> conditionals{
158  0.5),
160  3.0)};
162  conditionals);
163 } // namespace mode_dependent_constants
164 
165 /* ************************************************************************* */
166 // Create a test for continuousParents.
167 TEST(HybridGaussianConditional, ContinuousParents) {
168  using namespace mode_dependent_constants;
169  const KeyVector continuousParentKeys = hybrid_conditional.continuousParents();
170  // Check that the continuous parent keys are correct:
171  EXPECT(continuousParentKeys.size() == 1);
172  EXPECT(continuousParentKeys[0] == X(0));
173 }
174 
175 /* ************************************************************************* */
178  using namespace mode_dependent_constants;
179  auto actual = hybrid_conditional.errorTree(vv);
180 
181  // Check result.
182  DiscreteKeys discrete_keys{mode};
183  double negLogConstant0 = conditionals[0]->negLogConstant();
184  double negLogConstant1 = conditionals[1]->negLogConstant();
185  double minErrorConstant = std::min(negLogConstant0, negLogConstant1);
186 
187  // Expected error is e(X) + log(sqrt(|2πΣ|)).
188  // We normalize log(sqrt(|2πΣ|)) with min(negLogConstant)
189  // so it is non-negative.
190  std::vector<double> leaves = {
191  conditionals[0]->error(vv) + negLogConstant0 - minErrorConstant,
192  conditionals[1]->error(vv) + negLogConstant1 - minErrorConstant};
193  AlgebraicDecisionTree<Key> expected(discrete_keys, leaves);
194 
195  EXPECT(assert_equal(expected, actual, 1e-6));
196 
197  // Check for non-tree version.
198  for (size_t mode : {0, 1}) {
199  const HybridValues hv{vv, {{M(0), mode}}};
201  conditionals[mode]->negLogConstant() -
202  minErrorConstant,
203  hybrid_conditional.error(hv), 1e-8);
204  }
205 }
206 
207 /* ************************************************************************* */
211  using namespace mode_dependent_constants;
212 
213  // Compute likelihood
214  auto likelihood = hybrid_conditional.likelihood(vv);
215 
216  // Check that the hybrid conditional error and the likelihood error are as
217  // expected, this invariant is the same as the equal noise case:
218  EXPECT_DOUBLES_EQUAL(hybrid_conditional.error(hv0), likelihood->error(hv0),
219  1e-8);
220  EXPECT_DOUBLES_EQUAL(hybrid_conditional.error(hv1), likelihood->error(hv1),
221  1e-8);
222 
223  // Check the detailed JacobianFactor calculation for mode==1.
224  {
225  // We have a JacobianFactor
226  const auto gf1 = (*likelihood)(assignment1);
227  const auto jf1 = std::dynamic_pointer_cast<JacobianFactor>(gf1);
228  CHECK(jf1);
229 
230  // It has 2 rows, not 1!
231  CHECK(jf1->rows() == 2);
232 
233  // Check that the constant C1 is properly encoded in the JacobianFactor.
234  const double C1 =
235  conditionals[1]->negLogConstant() - hybrid_conditional.negLogConstant();
236  const double c1 = std::sqrt(2.0 * C1);
237  Vector expected_unwhitened(2);
238  expected_unwhitened << 4.9 - 5.0, -c1;
239  Vector actual_unwhitened = jf1->unweighted_error(vv);
240  EXPECT(assert_equal(expected_unwhitened, actual_unwhitened));
241 
242  // Make sure the noise model does not touch it.
243  Vector expected_whitened(2);
244  expected_whitened << (4.9 - 5.0) / 3.0, -c1;
245  Vector actual_whitened = jf1->error_vector(vv);
246  EXPECT(assert_equal(expected_whitened, actual_whitened));
247 
248  // Check that the error is equal to the conditional error:
250  }
251 
252  // Check that the ratio of probPrime to evaluate is the same for all modes.
253  std::vector<double> ratio(2);
254  for (size_t mode : {0, 1}) {
255  const HybridValues hv{vv, {{M(0), mode}}};
256  ratio[mode] =
257  std::exp(-likelihood->error(hv)) / hybrid_conditional.evaluate(hv);
258  }
259  EXPECT_DOUBLES_EQUAL(ratio[0], ratio[1], 1e-8);
260 }
261 
262 /* ************************************************************************* */
263 int main() {
264  TestResult tr;
265  return TestRegistry::runAllTests(tr);
266 }
267 /* ************************************************************************* */
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:169
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
assignment0
static const DiscreteValues assignment0
Definition: testHybridGaussianConditional.cpp:42
mode_dependent_constants::hybrid_conditional
const HybridGaussianConditional hybrid_conditional({Z(0)}, {X(0)}, mode, conditionals)
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:306
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:331
mode_dependent_constants
Definition: testHybridGaussianConditional.cpp:153
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:174
gtsam::HybridGaussianConditional::likelihood
std::shared_ptr< HybridGaussianFactor > likelihood(const VectorValues &given) const
Definition: HybridGaussianConditional.cpp:201
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:263
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:156
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:161
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:180
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 Wed Sep 25 2024 03:10:20