326 lines
11 KiB
C++
326 lines
11 KiB
C++
/* ----------------------------------------------------------------------------
|
|
|
|
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
|
|
* Atlanta, Georgia 30332-0415
|
|
* All Rights Reserved
|
|
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
|
|
|
|
* See LICENSE for the license information
|
|
|
|
* -------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
* @file testSymbolicFactorGraph.cpp
|
|
* @brief Unit tests for symbolic factor graphs
|
|
* @author Christian Potthast
|
|
**/
|
|
|
|
#include <gtsam/symbolic/SymbolicFactorGraph.h>
|
|
|
|
#include <gtsam/base/TestableAssertions.h>
|
|
#include <gtsam/symbolic/SymbolicBayesNet.h>
|
|
#include <gtsam/symbolic/SymbolicBayesTree.h>
|
|
#include <gtsam/symbolic/SymbolicConditional.h>
|
|
#include <gtsam/symbolic/tests/symbolicExampleGraphs.h>
|
|
|
|
#include <CppUnitLite/TestHarness.h>
|
|
|
|
#include <boost/assign/list_of.hpp>
|
|
using namespace boost::assign;
|
|
|
|
using namespace std;
|
|
using namespace gtsam;
|
|
using namespace boost::assign;
|
|
|
|
/* ************************************************************************* */
|
|
TEST(SymbolicFactorGraph, keys1) {
|
|
KeySet expected {0, 1, 2, 3, 4};
|
|
KeySet actual = simpleTestGraph1.keys();
|
|
EXPECT(expected == actual);
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
TEST(SymbolicFactorGraph, keys2) {
|
|
KeySet expected {0, 1, 2, 3, 4, 5};
|
|
KeySet actual = simpleTestGraph2.keys();
|
|
EXPECT(expected == actual);
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
TEST(SymbolicFactorGraph, eliminateFullSequential) {
|
|
// Test with simpleTestGraph1
|
|
Ordering order{0, 1, 2, 3, 4};
|
|
SymbolicBayesNet actual1 = *simpleTestGraph1.eliminateSequential(order);
|
|
EXPECT(assert_equal(simpleTestGraph1BayesNet, actual1));
|
|
|
|
// Test with Asia graph
|
|
SymbolicBayesNet actual2 = *asiaGraph.eliminateSequential(asiaOrdering);
|
|
EXPECT(assert_equal(asiaBayesNet, actual2));
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
TEST(SymbolicFactorGraph, eliminatePartialSequential) {
|
|
// Eliminate 0 and 1
|
|
const Ordering order {0, 1};
|
|
|
|
const SymbolicBayesNet expectedBayesNet =
|
|
list_of(SymbolicConditional(0, 1, 2))(SymbolicConditional(1, 2, 3, 4));
|
|
|
|
const SymbolicFactorGraph expectedSfg = list_of(SymbolicFactor(2, 3))(
|
|
SymbolicFactor(4, 5))(SymbolicFactor(2, 3, 4));
|
|
|
|
SymbolicBayesNet::shared_ptr actualBayesNet;
|
|
SymbolicFactorGraph::shared_ptr actualSfg;
|
|
boost::tie(actualBayesNet, actualSfg) =
|
|
simpleTestGraph2.eliminatePartialSequential(Ordering{0, 1});
|
|
|
|
EXPECT(assert_equal(expectedSfg, *actualSfg));
|
|
EXPECT(assert_equal(expectedBayesNet, *actualBayesNet));
|
|
|
|
SymbolicBayesNet::shared_ptr actualBayesNet2;
|
|
SymbolicFactorGraph::shared_ptr actualSfg2;
|
|
boost::tie(actualBayesNet2, actualSfg2) =
|
|
simpleTestGraph2.eliminatePartialSequential(Ordering{0, 1});
|
|
|
|
EXPECT(assert_equal(expectedSfg, *actualSfg2));
|
|
EXPECT(assert_equal(expectedBayesNet, *actualBayesNet2));
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
TEST(SymbolicFactorGraph, eliminateFullMultifrontal) {
|
|
Ordering ordering;
|
|
ordering += 0, 1, 2, 3;
|
|
SymbolicBayesTree actual1 = *simpleChain.eliminateMultifrontal(ordering);
|
|
EXPECT(assert_equal(simpleChainBayesTree, actual1));
|
|
|
|
SymbolicBayesTree actual2 = *asiaGraph.eliminateMultifrontal(asiaOrdering);
|
|
EXPECT(assert_equal(asiaBayesTree, actual2));
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
TEST(SymbolicFactorGraph, eliminatePartialMultifrontal) {
|
|
SymbolicBayesTree expectedBayesTree;
|
|
SymbolicConditional::shared_ptr root =
|
|
boost::make_shared<SymbolicConditional>(
|
|
SymbolicConditional::FromKeys(KeyVector{4, 5, 1}, 2));
|
|
expectedBayesTree.insertRoot(
|
|
boost::make_shared<SymbolicBayesTreeClique>(root));
|
|
|
|
SymbolicFactorGraph expectedFactorGraph =
|
|
list_of(SymbolicFactor(0, 1))(SymbolicFactor(0, 2))(SymbolicFactor(1, 3))(
|
|
SymbolicFactor(2, 3))(SymbolicFactor(1));
|
|
|
|
SymbolicBayesTree::shared_ptr actualBayesTree;
|
|
SymbolicFactorGraph::shared_ptr actualFactorGraph;
|
|
boost::tie(actualBayesTree, actualFactorGraph) =
|
|
simpleTestGraph2.eliminatePartialMultifrontal(Ordering{4, 5});
|
|
|
|
EXPECT(assert_equal(expectedFactorGraph, *actualFactorGraph));
|
|
EXPECT(assert_equal(expectedBayesTree, *actualBayesTree));
|
|
|
|
SymbolicBayesTree expectedBayesTree2;
|
|
SymbolicBayesTreeClique::shared_ptr root2 =
|
|
boost::make_shared<SymbolicBayesTreeClique>(
|
|
boost::make_shared<SymbolicConditional>(4, 1));
|
|
root2->children.push_back(boost::make_shared<SymbolicBayesTreeClique>(
|
|
boost::make_shared<SymbolicConditional>(5, 4)));
|
|
expectedBayesTree2.insertRoot(root2);
|
|
|
|
SymbolicBayesTree::shared_ptr actualBayesTree2;
|
|
SymbolicFactorGraph::shared_ptr actualFactorGraph2;
|
|
boost::tie(actualBayesTree2, actualFactorGraph2) =
|
|
simpleTestGraph2.eliminatePartialMultifrontal(KeyVector{4, 5});
|
|
|
|
EXPECT(assert_equal(expectedFactorGraph, *actualFactorGraph2));
|
|
EXPECT(assert_equal(expectedBayesTree2, *actualBayesTree2));
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
TEST(SymbolicFactorGraph, marginalMultifrontalBayesNet) {
|
|
SymbolicBayesNet expectedBayesNet =
|
|
list_of(SymbolicConditional(0, 1, 2))(SymbolicConditional(1, 2, 3))(
|
|
SymbolicConditional(2, 3))(SymbolicConditional(3));
|
|
|
|
SymbolicBayesNet actual1 = *simpleTestGraph2.marginalMultifrontalBayesNet(
|
|
Ordering{0, 1, 2, 3});
|
|
EXPECT(assert_equal(expectedBayesNet, actual1));
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
TEST(SymbolicFactorGraph, eliminate_disconnected_graph) {
|
|
SymbolicFactorGraph fg;
|
|
fg.push_factor(0, 1);
|
|
fg.push_factor(0, 2);
|
|
fg.push_factor(1, 2);
|
|
fg.push_factor(3, 4);
|
|
|
|
// create expected Chordal bayes Net
|
|
SymbolicBayesNet expected;
|
|
expected.push_back(boost::make_shared<SymbolicConditional>(0, 1, 2));
|
|
expected.push_back(boost::make_shared<SymbolicConditional>(1, 2));
|
|
expected.push_back(boost::make_shared<SymbolicConditional>(2));
|
|
expected.push_back(boost::make_shared<SymbolicConditional>(3, 4));
|
|
expected.push_back(boost::make_shared<SymbolicConditional>(4));
|
|
|
|
Ordering order;
|
|
order += 0, 1, 2, 3, 4;
|
|
SymbolicBayesNet actual = *fg.eliminateSequential(order);
|
|
|
|
EXPECT(assert_equal(expected, actual));
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
TEST(SymbolicFactorGraph, marginals) {
|
|
// Create factor graph
|
|
SymbolicFactorGraph fg;
|
|
fg.push_factor(0, 1);
|
|
fg.push_factor(0, 2);
|
|
fg.push_factor(1, 4);
|
|
fg.push_factor(2, 4);
|
|
fg.push_factor(3, 4);
|
|
|
|
// eliminate
|
|
Ordering ord{3, 4, 2, 1, 0};
|
|
auto actual = fg.eliminateSequential(ord);
|
|
SymbolicBayesNet expected;
|
|
expected.emplace_shared<SymbolicConditional>(3, 4);
|
|
expected.emplace_shared<SymbolicConditional>(4, 1, 2);
|
|
expected.emplace_shared<SymbolicConditional>(2, 0, 1);
|
|
expected.emplace_shared<SymbolicConditional>(1, 0);
|
|
expected.emplace_shared<SymbolicConditional>(0);
|
|
EXPECT(assert_equal(expected, *actual));
|
|
|
|
{
|
|
// jointBayesNet
|
|
Ordering ord {0, 4, 3};
|
|
auto actual = fg.eliminatePartialSequential(ord);
|
|
SymbolicBayesNet expectedBN;
|
|
expectedBN.emplace_shared<SymbolicConditional>(0, 1, 2);
|
|
expectedBN.emplace_shared<SymbolicConditional>(4, 1, 2, 3);
|
|
expectedBN.emplace_shared<SymbolicConditional>(3, 1, 2);
|
|
EXPECT(assert_equal(expectedBN, *(actual.first)));
|
|
}
|
|
|
|
{
|
|
// jointBayesNet
|
|
Ordering ord {0, 2, 3};
|
|
auto actual = fg.eliminatePartialSequential(ord);
|
|
SymbolicBayesNet expectedBN;
|
|
expectedBN.emplace_shared<SymbolicConditional>(0, 1, 2);
|
|
expectedBN.emplace_shared<SymbolicConditional>(2, 1, 4);
|
|
expectedBN.emplace_shared<SymbolicConditional>(3, 4);
|
|
EXPECT(assert_equal(expectedBN, *(actual.first)));
|
|
}
|
|
|
|
{
|
|
// conditionalBayesNet
|
|
Ordering ord{0, 2};
|
|
auto actual = fg.eliminatePartialSequential(ord);
|
|
SymbolicBayesNet expectedBN;
|
|
expectedBN.emplace_shared<SymbolicConditional>(0, 1, 2);
|
|
expectedBN.emplace_shared<SymbolicConditional>(2, 1, 4);
|
|
EXPECT(assert_equal(expectedBN, *(actual.first)));
|
|
}
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
TEST(SymbolicFactorGraph, constructFromBayesNet) {
|
|
// create expected factor graph
|
|
SymbolicFactorGraph expected;
|
|
expected.push_factor(0, 1, 2);
|
|
expected.push_factor(1, 2);
|
|
expected.push_factor(1);
|
|
|
|
// create Bayes Net
|
|
SymbolicBayesNet bayesNet;
|
|
bayesNet += SymbolicConditional(0, 1, 2);
|
|
bayesNet += SymbolicConditional(1, 2);
|
|
bayesNet += SymbolicConditional(1);
|
|
|
|
// create actual factor graph from a Bayes Net
|
|
SymbolicFactorGraph actual(bayesNet);
|
|
|
|
CHECK(assert_equal(expected, actual));
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
TEST(SymbolicFactorGraph, constructFromBayesTree) {
|
|
// create expected factor graph
|
|
SymbolicFactorGraph expected;
|
|
expected.push_factor(_E_, _L_, _B_);
|
|
expected.push_factor(_S_, _B_, _L_);
|
|
expected.push_factor(_T_, _E_, _L_);
|
|
expected.push_factor(_X_, _E_);
|
|
|
|
// create actual factor graph
|
|
SymbolicFactorGraph actual(asiaBayesTree);
|
|
|
|
CHECK(assert_equal(expected, actual));
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
TEST(SymbolicFactorGraph, push_back) {
|
|
// Create two factor graphs and expected combined graph
|
|
SymbolicFactorGraph fg1, fg2, expected;
|
|
|
|
fg1.push_factor(1);
|
|
fg1.push_factor(0, 1);
|
|
|
|
fg2.push_factor(1, 2);
|
|
fg2.push_factor(0, 2);
|
|
|
|
expected.push_factor(1);
|
|
expected.push_factor(0, 1);
|
|
expected.push_factor(1, 2);
|
|
expected.push_factor(0, 2);
|
|
|
|
// combine
|
|
SymbolicFactorGraph actual;
|
|
actual.push_back(fg1);
|
|
actual.push_back(fg2);
|
|
CHECK(assert_equal(expected, actual));
|
|
|
|
// combine in second way
|
|
SymbolicFactorGraph actual2 = fg1;
|
|
actual2.push_back(fg2);
|
|
CHECK(assert_equal(expected, actual2));
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
TEST(SymbolicFactorGraph, add_factors) {
|
|
SymbolicFactorGraph fg1;
|
|
fg1.push_factor(10);
|
|
fg1 += SymbolicFactor::shared_ptr(); // empty slot!
|
|
fg1.push_factor(11);
|
|
|
|
SymbolicFactorGraph fg2;
|
|
fg2.push_factor(1);
|
|
fg2.push_factor(2);
|
|
|
|
SymbolicFactorGraph expected;
|
|
expected.push_factor(10);
|
|
expected.push_factor(1);
|
|
expected.push_factor(11);
|
|
expected.push_factor(2);
|
|
const FactorIndices expectedIndices {1, 3};
|
|
const FactorIndices actualIndices = fg1.add_factors(fg2, true);
|
|
|
|
EXPECT(assert_equal(expected, fg1));
|
|
EXPECT(assert_container_equality(expectedIndices, actualIndices));
|
|
|
|
expected.push_factor(1);
|
|
expected.push_factor(2);
|
|
const FactorIndices expectedIndices2 {4, 5};
|
|
const FactorIndices actualIndices2 = fg1.add_factors(fg2, false);
|
|
|
|
EXPECT(assert_equal(expected, fg1));
|
|
EXPECT(assert_container_equality(expectedIndices2, actualIndices2));
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
int main() {
|
|
TestResult tr;
|
|
return TestRegistry::runAllTests(tr);
|
|
}
|
|
/* ************************************************************************* */
|