Skip to content

Commit 07b4c23

Browse files
committed
Finishing touches
1 parent e59b3af commit 07b4c23

File tree

1 file changed

+46
-64
lines changed

1 file changed

+46
-64
lines changed

gtsam/hybrid/tests/testGaussianMixtureFactor.cpp

+46-64
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <gtsam/hybrid/HybridValues.h>
3030
#include <gtsam/inference/Symbol.h>
3131
#include <gtsam/linear/GaussianFactorGraph.h>
32+
#include <gtsam/linear/VectorValues.h>
3233
#include <gtsam/nonlinear/PriorFactor.h>
3334
#include <gtsam/slam/BetweenFactor.h>
3435

@@ -433,20 +434,20 @@ HybridBayesNet CreateBayesNet(
433434
return hbn;
434435
}
435436

436-
/// Create importance sampling network p(x1| x0, m1) p(x0) P(m1),
437-
/// using Q(x0) = N(z0, sigma_Q) to sample from p(x0)
437+
/// Create importance sampling network q(x0,x1,m) = p(x1|x0,m1) q(x0) P(m1),
438+
/// using q(x0) = N(z0, sigma_Q) to sample x0.
438439
HybridBayesNet CreateProposalNet(
439-
const GaussianMixture::shared_ptr& hybridMotionModel, double z0,
440+
const GaussianMixture::shared_ptr& hybridMotionModel, const Vector1& z0,
440441
double sigma_Q) {
441442
HybridBayesNet hbn;
442443

443444
// Add hybrid motion model
444445
hbn.push_back(hybridMotionModel);
445446

446-
// Add proposal Q(x0) for x0
447+
// Add proposal q(x0) for x0
447448
auto measurement_model = noiseModel::Isotropic::Sigma(1, sigma_Q);
448449
hbn.emplace_shared<GaussianConditional>(
449-
GaussianConditional::FromMeanAndStddev(X(0), Vector1(z0), sigma_Q));
450+
GaussianConditional::FromMeanAndStddev(X(0), z0, sigma_Q));
450451

451452
// Discrete uniform prior.
452453
hbn.emplace_shared<DiscreteConditional>(m1, "0.5/0.5");
@@ -466,7 +467,7 @@ void approximateDiscreteMarginal(const HybridBayesNet& hbn,
466467
HybridValues sample = proposalNet.sample(&rng);
467468
sample.insert(given);
468469
double weight = hbn.evaluate(sample) / proposalNet.evaluate(sample);
469-
(sample.atDiscrete(m1.first) == 0) ? w0 += weight : w1 += weight;
470+
(sample.atDiscrete(M(1)) == 0) ? w0 += weight : w1 += weight;
470471
}
471472
double sumWeights = w0 + w1;
472473
double pm1 = w1 / sumWeights;
@@ -478,15 +479,14 @@ void approximateDiscreteMarginal(const HybridBayesNet& hbn,
478479

479480
/* ************************************************************************* */
480481
/**
481-
* Test a model P(z0|x0)P(x1|x0,m1)P(z1|x1)P(m1).
482+
* Test a model p(z0|x0)p(z1|x1)p(x1|x0,m1)P(m1).
482483
*
483-
* P(f01|x1,x0,m1) has different means and same covariance.
484+
* p(x1|x0,m1) has mode-dependent mean but same covariance.
484485
*
485-
* Converting to a factor graph gives us
486-
* ϕ(x0)ϕ(x1,x0,m1)ϕ(x1)P(m1)
486+
* Converting to a factor graph gives us ϕ(x0;z0)ϕ(x1;z1)ϕ(x1,x0,m1)P(m1)
487487
*
488-
* If we only have a measurement on z0, then
489-
* the probability of m1 should be 0.5/0.5.
488+
* If we only have a measurement on x0, then
489+
* the posterior probability of m1 should be 0.5/0.5.
490490
* Getting a measurement on z1 gives use more information.
491491
*/
492492
TEST(GaussianMixtureFactor, TwoStateModel) {
@@ -497,10 +497,10 @@ TEST(GaussianMixtureFactor, TwoStateModel) {
497497
auto hybridMotionModel = CreateHybridMotionModel(mu0, mu1, sigma, sigma);
498498

499499
// Start with no measurement on x1, only on x0
500-
double z0 = 0.5;
500+
const Vector1 z0(0.5);
501501

502502
VectorValues given;
503-
given.insert(Z(0), Vector1(z0));
503+
given.insert(Z(0), z0);
504504

505505
// Create proposal network for importance sampling
506506
auto proposalNet = CreateProposalNet(hybridMotionModel, z0, 3.0);
@@ -522,10 +522,10 @@ TEST(GaussianMixtureFactor, TwoStateModel) {
522522
// Now we add a measurement z1 on x1
523523
HybridBayesNet hbn = CreateBayesNet(hybridMotionModel, true);
524524

525-
// If we see z1=4.5 (>> 2.5 which is the halfway point),
526-
// discrete mode should say m1=1
527-
const double z1 = 4.5;
528-
given.insert(Z(1), Vector1(z1));
525+
// If we set z1=4.5 (>> 2.5 which is the halfway point),
526+
// probability of discrete mode should be leaning to m1==1.
527+
const Vector1 z1(4.5);
528+
given.insert(Z(1), z1);
529529

530530
HybridGaussianFactorGraph gfg = hbn.toFactorGraph(given);
531531
HybridBayesNet::shared_ptr bn = gfg.eliminateSequential();
@@ -534,7 +534,7 @@ TEST(GaussianMixtureFactor, TwoStateModel) {
534534
// Values taken from an importance sampling run with 50k samples:
535535
// approximateDiscreteMarginal(hbn, proposalNet, given);
536536
DiscreteConditional expected(m1, "0.446629/0.553371");
537-
EXPECT(assert_equal(expected, *(bn->at(2)->asDiscrete()), 0.01));
537+
EXPECT(assert_equal(expected, *(bn->at(2)->asDiscrete()), 0.002));
538538
}
539539
}
540540

@@ -559,9 +559,9 @@ TEST(GaussianMixtureFactor, TwoStateModel2) {
559559
auto hybridMotionModel = CreateHybridMotionModel(mu0, mu1, sigma0, sigma1);
560560

561561
// Start with no measurement on x1, only on x0
562-
double z0 = 0.5;
562+
const Vector1 z0(0.5);
563563
VectorValues given;
564-
given.insert(Z(0), Vector1(z0));
564+
given.insert(Z(0), z0);
565565

566566
// Create proposal network for importance sampling
567567
// uncomment this and the approximateDiscreteMarginal calls to run
@@ -571,19 +571,13 @@ TEST(GaussianMixtureFactor, TwoStateModel2) {
571571
HybridBayesNet hbn = CreateBayesNet(hybridMotionModel);
572572
HybridGaussianFactorGraph gfg = hbn.toFactorGraph(given);
573573

574-
{
575-
VectorValues vv{
576-
{X(0), Vector1(0.0)}, {X(1), Vector1(1.0)}, {Z(0), Vector1(z0)}};
577-
HybridValues hv0(vv, DiscreteValues{{M(1), 0}}),
578-
hv1(vv, DiscreteValues{{M(1), 1}});
579-
EXPECT_DOUBLES_EQUAL(gfg.error(hv0) / hbn.error(hv0),
580-
gfg.error(hv1) / hbn.error(hv1), 1e-9);
581-
}
582-
{
583-
VectorValues vv{
584-
{X(0), Vector1(0.5)}, {X(1), Vector1(3.0)}, {Z(0), Vector1(z0)}};
585-
HybridValues hv0(vv, DiscreteValues{{M(1), 0}}),
586-
hv1(vv, DiscreteValues{{M(1), 1}});
574+
// Check that ratio of Bayes net and factor graph for different modes is
575+
// equal for several values of {x0,x1}.
576+
for (VectorValues vv :
577+
{VectorValues{{X(0), Vector1(0.0)}, {X(1), Vector1(1.0)}},
578+
VectorValues{{X(0), Vector1(0.5)}, {X(1), Vector1(3.0)}}}) {
579+
vv.insert(given); // add measurements for HBN
580+
HybridValues hv0(vv, {{M(1), 0}}), hv1(vv, {{M(1), 1}});
587581
EXPECT_DOUBLES_EQUAL(gfg.error(hv0) / hbn.error(hv0),
588582
gfg.error(hv1) / hbn.error(hv1), 1e-9);
589583
}
@@ -595,66 +589,54 @@ TEST(GaussianMixtureFactor, TwoStateModel2) {
595589

596590
// Since no measurement on x1, we a 50/50 probability
597591
auto p_m = bn->at(2)->asDiscrete();
598-
EXPECT_DOUBLES_EQUAL(0.5, p_m->operator()(DiscreteValues{{m1.first, 0}}),
599-
1e-9);
600-
EXPECT_DOUBLES_EQUAL(0.5, p_m->operator()(DiscreteValues{{m1.first, 1}}),
601-
1e-9);
592+
EXPECT_DOUBLES_EQUAL(0.5, p_m->operator()(DiscreteValues{{M(1), 0}}), 1e-9);
593+
EXPECT_DOUBLES_EQUAL(0.5, p_m->operator()(DiscreteValues{{M(1), 1}}), 1e-9);
602594
}
603595

604596
{
605597
// Now we add a measurement z1 on x1
606598
HybridBayesNet hbn = CreateBayesNet(hybridMotionModel, true);
607599

608-
double z1 = 4.0; // favors m==1
609-
given.insert(Z(1), Vector1(z1));
600+
const Vector1 z1(4.0); // favors m==1
601+
given.insert(Z(1), z1);
610602

611603
HybridGaussianFactorGraph gfg = hbn.toFactorGraph(given);
612604

613-
{
614-
VectorValues vv{{X(0), Vector1(0.0)},
615-
{X(1), Vector1(1.0)},
616-
{Z(0), Vector1(z0)},
617-
{Z(1), Vector1(z1)}};
618-
HybridValues hv0(vv, DiscreteValues{{M(1), 0}}),
619-
hv1(vv, DiscreteValues{{M(1), 1}});
620-
EXPECT_DOUBLES_EQUAL(gfg.error(hv0) / hbn.error(hv0),
621-
gfg.error(hv1) / hbn.error(hv1), 1e-9);
622-
}
623-
{
624-
VectorValues vv{{X(0), Vector1(0.5)},
625-
{X(1), Vector1(3.0)},
626-
{Z(0), Vector1(z0)},
627-
{Z(1), Vector1(z1)}};
628-
HybridValues hv0(vv, DiscreteValues{{M(1), 0}}),
629-
hv1(vv, DiscreteValues{{M(1), 1}});
605+
// Check that ratio of Bayes net and factor graph for different modes is
606+
// equal for several values of {x0,x1}.
607+
for (VectorValues vv :
608+
{VectorValues{{X(0), Vector1(0.0)}, {X(1), Vector1(1.0)}},
609+
VectorValues{{X(0), Vector1(0.5)}, {X(1), Vector1(3.0)}}}) {
610+
vv.insert(given); // add measurements for HBN
611+
HybridValues hv0(vv, {{M(1), 0}}), hv1(vv, {{M(1), 1}});
630612
EXPECT_DOUBLES_EQUAL(gfg.error(hv0) / hbn.error(hv0),
631613
gfg.error(hv1) / hbn.error(hv1), 1e-9);
632614
}
633615

634616
HybridBayesNet::shared_ptr bn = gfg.eliminateSequential();
635617

636-
// Since we have a measurement on z2, we get a definite result
618+
// Since we have a measurement z1 on x1, we get a definite result
637619
// Values taken from an importance sampling run with 50k samples:
638620
// approximateDiscreteMarginal(hbn, proposalNet, given);
639621
DiscreteConditional expected(m1, "0.481793/0.518207");
640-
EXPECT(assert_equal(expected, *(bn->at(2)->asDiscrete()), 0.01));
622+
EXPECT(assert_equal(expected, *(bn->at(2)->asDiscrete()), 0.001));
641623
}
642624

643625
{
644-
// Add a different measurement z1 on that favors m==0
626+
// Add a different measurement z1 on x1 that favors m==0
645627
HybridBayesNet hbn = CreateBayesNet(hybridMotionModel, true);
646628

647-
double z1 = 1.1;
648-
given.insert_or_assign(Z(1), Vector1(z1));
629+
const Vector1 z1(1.1);
630+
given.insert_or_assign(Z(1), z1);
649631

650632
HybridGaussianFactorGraph gfg = hbn.toFactorGraph(given);
651633
HybridBayesNet::shared_ptr bn = gfg.eliminateSequential();
652634

653-
// Since we have a measurement on z2, we get a definite result
635+
// Since we have a measurement z1 on x1, we get a definite result
654636
// Values taken from an importance sampling run with 50k samples:
655637
// approximateDiscreteMarginal(hbn, proposalNet, given);
656638
DiscreteConditional expected(m1, "0.554485/0.445515");
657-
EXPECT(assert_equal(expected, *(bn->at(2)->asDiscrete()), 0.01));
639+
EXPECT(assert_equal(expected, *(bn->at(2)->asDiscrete()), 0.001));
658640
}
659641
}
660642

0 commit comments

Comments
 (0)