Merge pull request #1375 from borglab/feature/Ordering_initializers

release/4.3a0
Frank Dellaert 2023-01-10 15:19:04 -08:00 committed by GitHub
commit f7c6f2b3f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
129 changed files with 1425 additions and 1777 deletions

View File

@ -18,9 +18,6 @@
#include <gtsam/geometry/CalibratedCamera.h> #include <gtsam/geometry/CalibratedCamera.h>
#include <gtsam/slam/dataset.h> #include <gtsam/slam/dataset.h>
#include <boost/assign/std/vector.hpp>
using namespace boost::assign;
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;

View File

@ -18,13 +18,11 @@
#include <gtsam/global_includes.h> #include <gtsam/global_includes.h>
#include <gtsam/base/Matrix.h> #include <gtsam/base/Matrix.h>
#include <boost/assign/list_of.hpp>
#include <map> #include <map>
#include <iostream> #include <iostream>
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;
using boost::assign::list_of;
#ifdef GTSAM_USE_TBB #ifdef GTSAM_USE_TBB

View File

@ -56,6 +56,9 @@ public:
/** Copy constructor from the base list class */ /** Copy constructor from the base list class */
FastList(const Base& x) : Base(x) {} FastList(const Base& x) : Base(x) {}
/// Construct from c++11 initializer list:
FastList(std::initializer_list<VALUE> l) : Base(l) {}
#ifdef GTSAM_ALLOCATOR_BOOSTPOOL #ifdef GTSAM_ALLOCATOR_BOOSTPOOL
/** Copy constructor from a standard STL container */ /** Copy constructor from a standard STL container */
FastList(const std::list<VALUE>& x) { FastList(const std::list<VALUE>& x) {

View File

@ -56,15 +56,9 @@ public:
typedef std::set<VALUE, std::less<VALUE>, typedef std::set<VALUE, std::less<VALUE>,
typename internal::FastDefaultAllocator<VALUE>::type> Base; typename internal::FastDefaultAllocator<VALUE>::type> Base;
/** Default constructor */ using Base::Base; // Inherit the set constructors
FastSet() {
}
/** Constructor from a range, passes through to base class */ FastSet() = default; ///< Default constructor
template<typename INPUTITERATOR>
explicit FastSet(INPUTITERATOR first, INPUTITERATOR last) :
Base(first, last) {
}
/** Constructor from a iterable container, passes through to base class */ /** Constructor from a iterable container, passes through to base class */
template<typename INPUTCONTAINER> template<typename INPUTCONTAINER>

View File

@ -16,17 +16,14 @@
* @brief unit tests for DSFMap * @brief unit tests for DSFMap
*/ */
#include <CppUnitLite/TestHarness.h>
#include <gtsam/base/DSFMap.h> #include <gtsam/base/DSFMap.h>
#include <boost/assign/std/list.hpp>
#include <boost/assign/std/set.hpp>
using namespace boost::assign;
#include <CppUnitLite/TestHarness.h>
#include <iostream> #include <iostream>
#include <list>
#include <map>
#include <set>
using namespace std;
using namespace gtsam; using namespace gtsam;
/* ************************************************************************* */ /* ************************************************************************* */
@ -65,9 +62,8 @@ TEST(DSFMap, merge3) {
TEST(DSFMap, mergePairwiseMatches) { TEST(DSFMap, mergePairwiseMatches) {
// Create some "matches" // Create some "matches"
typedef pair<size_t,size_t> Match; typedef std::pair<size_t, size_t> Match;
list<Match> matches; const std::list<Match> matches{{1, 2}, {2, 3}, {4, 5}, {4, 6}};
matches += Match(1,2), Match(2,3), Match(4,5), Match(4,6);
// Merge matches // Merge matches
DSFMap<size_t> dsf; DSFMap<size_t> dsf;
@ -86,18 +82,17 @@ TEST(DSFMap, mergePairwiseMatches) {
TEST(DSFMap, mergePairwiseMatches2) { TEST(DSFMap, mergePairwiseMatches2) {
// Create some measurements with image index and feature index // Create some measurements with image index and feature index
typedef pair<size_t,size_t> Measurement; typedef std::pair<size_t,size_t> Measurement;
Measurement m11(1,1),m12(1,2),m14(1,4); // in image 1 Measurement m11(1,1),m12(1,2),m14(1,4); // in image 1
Measurement m22(2,2),m23(2,3),m25(2,5),m26(2,6); // in image 2 Measurement m22(2,2),m23(2,3),m25(2,5),m26(2,6); // in image 2
// Add them all // Add them all
list<Measurement> measurements; const std::list<Measurement> measurements{m11, m12, m14, m22, m23, m25, m26};
measurements += m11,m12,m14, m22,m23,m25,m26;
// Create some "matches" // Create some "matches"
typedef pair<Measurement,Measurement> Match; typedef std::pair<Measurement, Measurement> Match;
list<Match> matches; const std::list<Match> matches{
matches += Match(m11,m22), Match(m12,m23), Match(m14,m25), Match(m14,m26); {m11, m22}, {m12, m23}, {m14, m25}, {m14, m26}};
// Merge matches // Merge matches
DSFMap<Measurement> dsf; DSFMap<Measurement> dsf;
@ -114,26 +109,16 @@ TEST(DSFMap, mergePairwiseMatches2) {
/* ************************************************************************* */ /* ************************************************************************* */
TEST(DSFMap, sets){ TEST(DSFMap, sets){
// Create some "matches" // Create some "matches"
typedef pair<size_t,size_t> Match; using Match = std::pair<size_t,size_t>;
list<Match> matches; const std::list<Match> matches{{1, 2}, {2, 3}, {4, 5}, {4, 6}};
matches += Match(1,2), Match(2,3), Match(4,5), Match(4,6);
// Merge matches // Merge matches
DSFMap<size_t> dsf; DSFMap<size_t> dsf;
for(const Match& m: matches) for(const Match& m: matches)
dsf.merge(m.first,m.second); dsf.merge(m.first,m.second);
map<size_t, set<size_t> > sets = dsf.sets(); std::map<size_t, std::set<size_t> > sets = dsf.sets();
set<size_t> s1, s2; const std::set<size_t> s1{1, 2, 3}, s2{4, 5, 6};
s1 += 1,2,3;
s2 += 4,5,6;
/*for(key_pair st: sets){
cout << "Set " << st.first << " :{";
for(const size_t s: st.second)
cout << s << ", ";
cout << "}" << endl;
}*/
EXPECT(s1 == sets[1]); EXPECT(s1 == sets[1]);
EXPECT(s2 == sets[4]); EXPECT(s2 == sets[4]);

View File

@ -21,14 +21,15 @@
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
#include <boost/assign/std/list.hpp>
#include <boost/assign/std/set.hpp>
#include <boost/assign/std/vector.hpp>
using namespace boost::assign;
#include <iostream> #include <iostream>
#include <set>
#include <list>
#include <utility>
using namespace std; using std::pair;
using std::map;
using std::vector;
using namespace gtsam; using namespace gtsam;
/* ************************************************************************* */ /* ************************************************************************* */
@ -64,8 +65,8 @@ TEST(DSFBase, mergePairwiseMatches) {
// Create some "matches" // Create some "matches"
typedef pair<size_t,size_t> Match; typedef pair<size_t,size_t> Match;
vector<Match> matches; const vector<Match> matches{Match(1, 2), Match(2, 3), Match(4, 5),
matches += Match(1,2), Match(2,3), Match(4,5), Match(4,6); Match(4, 6)};
// Merge matches // Merge matches
DSFBase dsf(7); // We allow for keys 0..6 DSFBase dsf(7); // We allow for keys 0..6
@ -85,7 +86,7 @@ TEST(DSFBase, mergePairwiseMatches) {
/* ************************************************************************* */ /* ************************************************************************* */
TEST(DSFVector, merge2) { TEST(DSFVector, merge2) {
boost::shared_ptr<DSFBase::V> v = boost::make_shared<DSFBase::V>(5); boost::shared_ptr<DSFBase::V> v = boost::make_shared<DSFBase::V>(5);
std::vector<size_t> keys; keys += 1, 3; const std::vector<size_t> keys {1, 3};
DSFVector dsf(v, keys); DSFVector dsf(v, keys);
dsf.merge(1,3); dsf.merge(1,3);
EXPECT(dsf.find(1) == dsf.find(3)); EXPECT(dsf.find(1) == dsf.find(3));
@ -95,10 +96,10 @@ TEST(DSFVector, merge2) {
TEST(DSFVector, sets) { TEST(DSFVector, sets) {
DSFVector dsf(2); DSFVector dsf(2);
dsf.merge(0,1); dsf.merge(0,1);
map<size_t, set<size_t> > sets = dsf.sets(); map<size_t, std::set<size_t> > sets = dsf.sets();
LONGS_EQUAL(1, sets.size()); LONGS_EQUAL(1, sets.size());
set<size_t> expected; expected += 0, 1; const std::set<size_t> expected{0, 1};
EXPECT(expected == sets[dsf.find(0)]); EXPECT(expected == sets[dsf.find(0)]);
} }
@ -109,7 +110,7 @@ TEST(DSFVector, arrays) {
map<size_t, vector<size_t> > arrays = dsf.arrays(); map<size_t, vector<size_t> > arrays = dsf.arrays();
LONGS_EQUAL(1, arrays.size()); LONGS_EQUAL(1, arrays.size());
vector<size_t> expected; expected += 0, 1; const vector<size_t> expected{0, 1};
EXPECT(expected == arrays[dsf.find(0)]); EXPECT(expected == arrays[dsf.find(0)]);
} }
@ -118,10 +119,10 @@ TEST(DSFVector, sets2) {
DSFVector dsf(3); DSFVector dsf(3);
dsf.merge(0,1); dsf.merge(0,1);
dsf.merge(1,2); dsf.merge(1,2);
map<size_t, set<size_t> > sets = dsf.sets(); map<size_t, std::set<size_t> > sets = dsf.sets();
LONGS_EQUAL(1, sets.size()); LONGS_EQUAL(1, sets.size());
set<size_t> expected; expected += 0, 1, 2; const std::set<size_t> expected{0, 1, 2};
EXPECT(expected == sets[dsf.find(0)]); EXPECT(expected == sets[dsf.find(0)]);
} }
@ -133,7 +134,7 @@ TEST(DSFVector, arrays2) {
map<size_t, vector<size_t> > arrays = dsf.arrays(); map<size_t, vector<size_t> > arrays = dsf.arrays();
LONGS_EQUAL(1, arrays.size()); LONGS_EQUAL(1, arrays.size());
vector<size_t> expected; expected += 0, 1, 2; const vector<size_t> expected{0, 1, 2};
EXPECT(expected == arrays[dsf.find(0)]); EXPECT(expected == arrays[dsf.find(0)]);
} }
@ -141,10 +142,10 @@ TEST(DSFVector, arrays2) {
TEST(DSFVector, sets3) { TEST(DSFVector, sets3) {
DSFVector dsf(3); DSFVector dsf(3);
dsf.merge(0,1); dsf.merge(0,1);
map<size_t, set<size_t> > sets = dsf.sets(); map<size_t, std::set<size_t> > sets = dsf.sets();
LONGS_EQUAL(2, sets.size()); LONGS_EQUAL(2, sets.size());
set<size_t> expected; expected += 0, 1; const std::set<size_t> expected{0, 1};
EXPECT(expected == sets[dsf.find(0)]); EXPECT(expected == sets[dsf.find(0)]);
} }
@ -155,7 +156,7 @@ TEST(DSFVector, arrays3) {
map<size_t, vector<size_t> > arrays = dsf.arrays(); map<size_t, vector<size_t> > arrays = dsf.arrays();
LONGS_EQUAL(2, arrays.size()); LONGS_EQUAL(2, arrays.size());
vector<size_t> expected; expected += 0, 1; const vector<size_t> expected{0, 1};
EXPECT(expected == arrays[dsf.find(0)]); EXPECT(expected == arrays[dsf.find(0)]);
} }
@ -163,10 +164,10 @@ TEST(DSFVector, arrays3) {
TEST(DSFVector, set) { TEST(DSFVector, set) {
DSFVector dsf(3); DSFVector dsf(3);
dsf.merge(0,1); dsf.merge(0,1);
set<size_t> set = dsf.set(0); std::set<size_t> set = dsf.set(0);
LONGS_EQUAL(2, set.size()); LONGS_EQUAL(2, set.size());
std::set<size_t> expected; expected += 0, 1; const std::set<size_t> expected{0, 1};
EXPECT(expected == set); EXPECT(expected == set);
} }
@ -175,10 +176,10 @@ TEST(DSFVector, set2) {
DSFVector dsf(3); DSFVector dsf(3);
dsf.merge(0,1); dsf.merge(0,1);
dsf.merge(1,2); dsf.merge(1,2);
set<size_t> set = dsf.set(0); std::set<size_t> set = dsf.set(0);
LONGS_EQUAL(3, set.size()); LONGS_EQUAL(3, set.size());
std::set<size_t> expected; expected += 0, 1, 2; const std::set<size_t> expected{0, 1, 2};
EXPECT(expected == set); EXPECT(expected == set);
} }
@ -195,13 +196,12 @@ TEST(DSFVector, isSingleton) {
TEST(DSFVector, mergePairwiseMatches) { TEST(DSFVector, mergePairwiseMatches) {
// Create some measurements // Create some measurements
vector<size_t> keys; const vector<size_t> keys{1, 2, 3, 4, 5, 6};
keys += 1,2,3,4,5,6;
// Create some "matches" // Create some "matches"
typedef pair<size_t,size_t> Match; typedef pair<size_t,size_t> Match;
vector<Match> matches; const vector<Match> matches{Match(1, 2), Match(2, 3), Match(4, 5),
matches += Match(1,2), Match(2,3), Match(4,5), Match(4,6); Match(4, 6)};
// Merge matches // Merge matches
DSFVector dsf(keys); DSFVector dsf(keys);
@ -209,13 +209,13 @@ TEST(DSFVector, mergePairwiseMatches) {
dsf.merge(m.first,m.second); dsf.merge(m.first,m.second);
// Check that we have two connected components, 1,2,3 and 4,5,6 // Check that we have two connected components, 1,2,3 and 4,5,6
map<size_t, set<size_t> > sets = dsf.sets(); map<size_t, std::set<size_t> > sets = dsf.sets();
LONGS_EQUAL(2, sets.size()); LONGS_EQUAL(2, sets.size());
set<size_t> expected1; expected1 += 1,2,3; const std::set<size_t> expected1{1, 2, 3};
set<size_t> actual1 = sets[dsf.find(2)]; std::set<size_t> actual1 = sets[dsf.find(2)];
EXPECT(expected1 == actual1); EXPECT(expected1 == actual1);
set<size_t> expected2; expected2 += 4,5,6; const std::set<size_t> expected2{4, 5, 6};
set<size_t> actual2 = sets[dsf.find(5)]; std::set<size_t> actual2 = sets[dsf.find(5)];
EXPECT(expected2 == actual2); EXPECT(expected2 == actual2);
} }

View File

@ -11,12 +11,8 @@
#include <gtsam/base/FastSet.h> #include <gtsam/base/FastSet.h>
#include <gtsam/base/FastVector.h> #include <gtsam/base/FastVector.h>
#include <boost/assign/std/vector.hpp>
#include <boost/assign/std/set.hpp>
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
using namespace boost::assign;
using namespace gtsam; using namespace gtsam;
/* ************************************************************************* */ /* ************************************************************************* */
@ -25,7 +21,7 @@ TEST( testFastContainers, KeySet ) {
KeyVector init_vector {2, 3, 4, 5}; KeyVector init_vector {2, 3, 4, 5};
KeySet actSet(init_vector); KeySet actSet(init_vector);
KeySet expSet; expSet += 2, 3, 4, 5; KeySet expSet{2, 3, 4, 5};
EXPECT(actSet == expSet); EXPECT(actSet == expSet);
} }

View File

@ -17,14 +17,12 @@
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <gtsam/base/SymmetricBlockMatrix.h> #include <gtsam/base/SymmetricBlockMatrix.h>
#include <boost/assign/list_of.hpp>
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;
using boost::assign::list_of;
static SymmetricBlockMatrix testBlockMatrix( static SymmetricBlockMatrix testBlockMatrix(
list_of(3)(2)(1), std::vector<size_t>{3, 2, 1},
(Matrix(6, 6) << (Matrix(6, 6) <<
1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6,
2, 8, 9, 10, 11, 12, 2, 8, 9, 10, 11, 12,
@ -101,7 +99,8 @@ TEST(SymmetricBlockMatrix, Ranges)
/* ************************************************************************* */ /* ************************************************************************* */
TEST(SymmetricBlockMatrix, expressions) TEST(SymmetricBlockMatrix, expressions)
{ {
SymmetricBlockMatrix expected1(list_of(2)(3)(1), (Matrix(6, 6) << const std::vector<size_t> dimensions{2, 3, 1};
SymmetricBlockMatrix expected1(dimensions, (Matrix(6, 6) <<
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 4, 6, 8, 0, 0, 0, 4, 6, 8, 0,
@ -109,7 +108,7 @@ TEST(SymmetricBlockMatrix, expressions)
0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 16, 0,
0, 0, 0, 0, 0, 0).finished()); 0, 0, 0, 0, 0, 0).finished());
SymmetricBlockMatrix expected2(list_of(2)(3)(1), (Matrix(6, 6) << SymmetricBlockMatrix expected2(dimensions, (Matrix(6, 6) <<
0, 0, 10, 15, 20, 0, 0, 0, 10, 15, 20, 0,
0, 0, 12, 18, 24, 0, 0, 0, 12, 18, 24, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -120,32 +119,32 @@ TEST(SymmetricBlockMatrix, expressions)
Matrix a = (Matrix(1, 3) << 2, 3, 4).finished(); Matrix a = (Matrix(1, 3) << 2, 3, 4).finished();
Matrix b = (Matrix(1, 2) << 5, 6).finished(); Matrix b = (Matrix(1, 2) << 5, 6).finished();
SymmetricBlockMatrix bm1(list_of(2)(3)(1)); SymmetricBlockMatrix bm1(dimensions);
bm1.setZero(); bm1.setZero();
bm1.diagonalBlock(1).rankUpdate(a.transpose()); bm1.diagonalBlock(1).rankUpdate(a.transpose());
EXPECT(assert_equal(Matrix(expected1.selfadjointView()), bm1.selfadjointView())); EXPECT(assert_equal(Matrix(expected1.selfadjointView()), bm1.selfadjointView()));
SymmetricBlockMatrix bm2(list_of(2)(3)(1)); SymmetricBlockMatrix bm2(dimensions);
bm2.setZero(); bm2.setZero();
bm2.updateOffDiagonalBlock(0, 1, b.transpose() * a); bm2.updateOffDiagonalBlock(0, 1, b.transpose() * a);
EXPECT(assert_equal(Matrix(expected2.selfadjointView()), bm2.selfadjointView())); EXPECT(assert_equal(Matrix(expected2.selfadjointView()), bm2.selfadjointView()));
SymmetricBlockMatrix bm3(list_of(2)(3)(1)); SymmetricBlockMatrix bm3(dimensions);
bm3.setZero(); bm3.setZero();
bm3.updateOffDiagonalBlock(1, 0, a.transpose() * b); bm3.updateOffDiagonalBlock(1, 0, a.transpose() * b);
EXPECT(assert_equal(Matrix(expected2.selfadjointView()), bm3.selfadjointView())); EXPECT(assert_equal(Matrix(expected2.selfadjointView()), bm3.selfadjointView()));
SymmetricBlockMatrix bm4(list_of(2)(3)(1)); SymmetricBlockMatrix bm4(dimensions);
bm4.setZero(); bm4.setZero();
bm4.updateDiagonalBlock(1, expected1.diagonalBlock(1)); bm4.updateDiagonalBlock(1, expected1.diagonalBlock(1));
EXPECT(assert_equal(Matrix(expected1.selfadjointView()), bm4.selfadjointView())); EXPECT(assert_equal(Matrix(expected1.selfadjointView()), bm4.selfadjointView()));
SymmetricBlockMatrix bm5(list_of(2)(3)(1)); SymmetricBlockMatrix bm5(dimensions);
bm5.setZero(); bm5.setZero();
bm5.updateOffDiagonalBlock(0, 1, expected2.aboveDiagonalBlock(0, 1)); bm5.updateOffDiagonalBlock(0, 1, expected2.aboveDiagonalBlock(0, 1));
EXPECT(assert_equal(Matrix(expected2.selfadjointView()), bm5.selfadjointView())); EXPECT(assert_equal(Matrix(expected2.selfadjointView()), bm5.selfadjointView()));
SymmetricBlockMatrix bm6(list_of(2)(3)(1)); SymmetricBlockMatrix bm6(dimensions);
bm6.setZero(); bm6.setZero();
bm6.updateOffDiagonalBlock(1, 0, expected2.aboveDiagonalBlock(0, 1).transpose()); bm6.updateOffDiagonalBlock(1, 0, expected2.aboveDiagonalBlock(0, 1).transpose());
EXPECT(assert_equal(Matrix(expected2.selfadjointView()), bm6.selfadjointView())); EXPECT(assert_equal(Matrix(expected2.selfadjointView()), bm6.selfadjointView()));
@ -162,7 +161,8 @@ TEST(SymmetricBlockMatrix, inverseInPlace) {
inputMatrix += c * c.transpose(); inputMatrix += c * c.transpose();
const Matrix expectedInverse = inputMatrix.inverse(); const Matrix expectedInverse = inputMatrix.inverse();
SymmetricBlockMatrix symmMatrix(list_of(2)(1), inputMatrix); const std::vector<size_t> dimensions{2, 1};
SymmetricBlockMatrix symmMatrix(dimensions, inputMatrix);
// invert in place // invert in place
symmMatrix.invertInPlace(); symmMatrix.invertInPlace();
EXPECT(assert_equal(expectedInverse, symmMatrix.selfadjointView())); EXPECT(assert_equal(expectedInverse, symmMatrix.selfadjointView()));

View File

@ -23,16 +23,13 @@
#include <list> #include <list>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
#include <boost/assign/std/list.hpp>
using boost::assign::operator+=;
using namespace std;
using namespace gtsam; using namespace gtsam;
struct TestNode { struct TestNode {
typedef boost::shared_ptr<TestNode> shared_ptr; typedef boost::shared_ptr<TestNode> shared_ptr;
int data; int data;
vector<shared_ptr> children; std::vector<shared_ptr> children;
TestNode() : data(-1) {} TestNode() : data(-1) {}
TestNode(int data) : data(data) {} TestNode(int data) : data(data) {}
}; };
@ -110,10 +107,8 @@ TEST(treeTraversal, DepthFirst)
TestForest testForest = makeTestForest(); TestForest testForest = makeTestForest();
// Expected visit order // Expected visit order
std::list<int> preOrderExpected; const std::list<int> preOrderExpected{0, 2, 3, 4, 1};
preOrderExpected += 0, 2, 3, 4, 1; const std::list<int> postOrderExpected{2, 4, 3, 0, 1};
std::list<int> postOrderExpected;
postOrderExpected += 2, 4, 3, 0, 1;
// Actual visit order // Actual visit order
PreOrderVisitor preVisitor; PreOrderVisitor preVisitor;
@ -135,8 +130,7 @@ TEST(treeTraversal, CloneForest)
testForest2.roots_ = treeTraversal::CloneForest(testForest1); testForest2.roots_ = treeTraversal::CloneForest(testForest1);
// Check that the original and clone both are expected // Check that the original and clone both are expected
std::list<int> preOrder1Expected; const std::list<int> preOrder1Expected{0, 2, 3, 4, 1};
preOrder1Expected += 0, 2, 3, 4, 1;
std::list<int> preOrder1Actual = getPreorder(testForest1); std::list<int> preOrder1Actual = getPreorder(testForest1);
std::list<int> preOrder2Actual = getPreorder(testForest2); std::list<int> preOrder2Actual = getPreorder(testForest2);
EXPECT(assert_container_equality(preOrder1Expected, preOrder1Actual)); EXPECT(assert_container_equality(preOrder1Expected, preOrder1Actual));
@ -144,8 +138,7 @@ TEST(treeTraversal, CloneForest)
// Modify clone - should not modify original // Modify clone - should not modify original
testForest2.roots_[0]->children[1]->data = 10; testForest2.roots_[0]->children[1]->data = 10;
std::list<int> preOrderModifiedExpected; const std::list<int> preOrderModifiedExpected{0, 2, 10, 4, 1};
preOrderModifiedExpected += 0, 2, 10, 4, 1;
// Check that original is the same and only the clone is modified // Check that original is the same and only the clone is modified
std::list<int> preOrder1ModActual = getPreorder(testForest1); std::list<int> preOrder1ModActual = getPreorder(testForest1);

View File

@ -18,14 +18,13 @@
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <gtsam/base/VerticalBlockMatrix.h> #include <gtsam/base/VerticalBlockMatrix.h>
#include <boost/assign/list_of.hpp>
using namespace std; #include<list>
#include<vector>
using namespace gtsam; using namespace gtsam;
using boost::assign::list_of;
list<size_t> L = list_of(3)(2)(1); const std::vector<size_t> dimensions{3, 2, 1};
vector<size_t> dimensions(L.begin(),L.end());
//***************************************************************************** //*****************************************************************************
TEST(VerticalBlockMatrix, Constructor1) { TEST(VerticalBlockMatrix, Constructor1) {

View File

@ -22,14 +22,10 @@
#include <gtsam/discrete/DecisionTree.h> #include <gtsam/discrete/DecisionTree.h>
#include <algorithm> #include <algorithm>
#include <boost/assign/std/vector.hpp>
#include <boost/format.hpp> #include <boost/format.hpp>
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
#include <boost/noncopyable.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/type_traits/has_dereference.hpp>
#include <boost/unordered_set.hpp>
#include <cmath> #include <cmath>
#include <fstream> #include <fstream>
#include <list> #include <list>
@ -41,8 +37,6 @@
namespace gtsam { namespace gtsam {
using boost::assign::operator+=;
/****************************************************************************/ /****************************************************************************/
// Node // Node
/****************************************************************************/ /****************************************************************************/
@ -535,8 +529,7 @@ namespace gtsam {
template<typename L, typename Y> template<typename L, typename Y>
DecisionTree<L, Y>::DecisionTree(const L& label, DecisionTree<L, Y>::DecisionTree(const L& label,
const DecisionTree& f0, const DecisionTree& f1) { const DecisionTree& f0, const DecisionTree& f1) {
std::vector<DecisionTree> functions; const std::vector<DecisionTree> functions{f0, f1};
functions += f0, f1;
root_ = compose(functions.begin(), functions.end(), label); root_ = compose(functions.begin(), functions.end(), label);
} }

View File

@ -399,13 +399,9 @@ TEST(ADT, factor_graph) {
/* ************************************************************************* */ /* ************************************************************************* */
// test equality // test equality
TEST(ADT, equality_noparser) { TEST(ADT, equality_noparser) {
DiscreteKey A(0, 2), B(1, 2); const DiscreteKey A(0, 2), B(1, 2);
Signature::Table tableA, tableB; const Signature::Row rA{80, 20}, rB{60, 40};
Signature::Row rA, rB; const Signature::Table tableA{rA}, tableB{rB};
rA += 80, 20;
rB += 60, 40;
tableA += rA;
tableB += rB;
// Check straight equality // Check straight equality
ADT pA1 = create(A % tableA); ADT pA1 = create(A % tableA);
@ -520,9 +516,9 @@ TEST(ADT, elimination) {
// normalize // normalize
ADT actual = f1 / actualSum; ADT actual = f1 / actualSum;
vector<double> cpt; const vector<double> cpt{
cpt += 1.0 / 3, 2.0 / 3, 3.0 / 7, 4.0 / 7, 5.0 / 11, 6.0 / 11, // 1.0 / 3, 2.0 / 3, 3.0 / 7, 4.0 / 7, 5.0 / 11, 6.0 / 11, //
1.0 / 9, 8.0 / 9, 3.0 / 6, 3.0 / 6, 5.0 / 10, 5.0 / 10; 1.0 / 9, 8.0 / 9, 3.0 / 6, 3.0 / 6, 5.0 / 10, 5.0 / 10};
ADT expected(A & B & C, cpt); ADT expected(A & B & C, cpt);
CHECK(assert_equal(expected, actual)); CHECK(assert_equal(expected, actual));
} }
@ -535,9 +531,9 @@ TEST(ADT, elimination) {
// normalize // normalize
ADT actual = f1 / actualSum; ADT actual = f1 / actualSum;
vector<double> cpt; const vector<double> cpt{
cpt += 1.0 / 21, 2.0 / 21, 3.0 / 21, 4.0 / 21, 5.0 / 21, 6.0 / 21, // 1.0 / 21, 2.0 / 21, 3.0 / 21, 4.0 / 21, 5.0 / 21, 6.0 / 21, //
1.0 / 25, 8.0 / 25, 3.0 / 25, 3.0 / 25, 5.0 / 25, 5.0 / 25; 1.0 / 25, 8.0 / 25, 3.0 / 25, 3.0 / 25, 5.0 / 25, 5.0 / 25};
ADT expected(A & B & C, cpt); ADT expected(A & B & C, cpt);
CHECK(assert_equal(expected, actual)); CHECK(assert_equal(expected, actual));
} }

View File

@ -26,7 +26,9 @@
#include <gtsam/discrete/DecisionTree-inl.h> #include <gtsam/discrete/DecisionTree-inl.h>
#include <gtsam/discrete/Signature.h> #include <gtsam/discrete/Signature.h>
using namespace std; using std::vector;
using std::string;
using std::map;
using namespace gtsam; using namespace gtsam;
template <typename T> template <typename T>
@ -280,8 +282,7 @@ TEST(DecisionTree, Compose) {
DT f1(B, DT(A, 0, 1), DT(A, 2, 3)); DT f1(B, DT(A, 0, 1), DT(A, 2, 3));
// Create from string // Create from string
vector<DT::LabelC> keys; vector<DT::LabelC> keys{DT::LabelC(A, 2), DT::LabelC(B, 2)};
keys += DT::LabelC(A, 2), DT::LabelC(B, 2);
DT f2(keys, "0 2 1 3"); DT f2(keys, "0 2 1 3");
EXPECT(assert_equal(f2, f1, 1e-9)); EXPECT(assert_equal(f2, f1, 1e-9));
@ -291,7 +292,7 @@ TEST(DecisionTree, Compose) {
DOT(f4); DOT(f4);
// a bigger tree // a bigger tree
keys += DT::LabelC(C, 2); keys.push_back(DT::LabelC(C, 2));
DT f5(keys, "0 4 2 6 1 5 3 7"); DT f5(keys, "0 4 2 6 1 5 3 7");
EXPECT(assert_equal(f5, f4, 1e-9)); EXPECT(assert_equal(f5, f4, 1e-9));
DOT(f5); DOT(f5);
@ -322,7 +323,7 @@ TEST(DecisionTree, Containers) {
/* ************************************************************************** */ /* ************************************************************************** */
// Test nrAssignments. // Test nrAssignments.
TEST(DecisionTree, NrAssignments) { TEST(DecisionTree, NrAssignments) {
pair<string, size_t> A("A", 2), B("B", 2), C("C", 2); const std::pair<string, size_t> A("A", 2), B("B", 2), C("C", 2);
DT tree({A, B, C}, "1 1 1 1 1 1 1 1"); DT tree({A, B, C}, "1 1 1 1 1 1 1 1");
EXPECT(tree.root_->isLeaf()); EXPECT(tree.root_->isLeaf());
auto leaf = boost::dynamic_pointer_cast<const DT::Leaf>(tree.root_); auto leaf = boost::dynamic_pointer_cast<const DT::Leaf>(tree.root_);
@ -472,8 +473,8 @@ TEST(DecisionTree, unzip) {
// Test thresholding. // Test thresholding.
TEST(DecisionTree, threshold) { TEST(DecisionTree, threshold) {
// Create three level tree // Create three level tree
vector<DT::LabelC> keys; const vector<DT::LabelC> keys{DT::LabelC("C", 2), DT::LabelC("B", 2),
keys += DT::LabelC("C", 2), DT::LabelC("B", 2), DT::LabelC("A", 2); DT::LabelC("A", 2)};
DT tree(keys, "0 1 2 3 4 5 6 7"); DT tree(keys, "0 1 2 3 4 5 6 7");
// Check number of leaves equal to zero // Check number of leaves equal to zero
@ -495,8 +496,8 @@ TEST(DecisionTree, threshold) {
// Test apply with assignment. // Test apply with assignment.
TEST(DecisionTree, ApplyWithAssignment) { TEST(DecisionTree, ApplyWithAssignment) {
// Create three level tree // Create three level tree
vector<DT::LabelC> keys; const vector<DT::LabelC> keys{DT::LabelC("C", 2), DT::LabelC("B", 2),
keys += DT::LabelC("C", 2), DT::LabelC("B", 2), DT::LabelC("A", 2); DT::LabelC("A", 2)};
DT tree(keys, "1 2 3 4 5 6 7 8"); DT tree(keys, "1 2 3 4 5 6 7 8");
DecisionTree<string, double> probTree( DecisionTree<string, double> probTree(

View File

@ -53,12 +53,8 @@ TEST(DiscreteConditional, constructors) {
TEST(DiscreteConditional, constructors_alt_interface) { TEST(DiscreteConditional, constructors_alt_interface) {
DiscreteKey X(0, 2), Y(2, 3), Z(1, 2); // watch ordering ! DiscreteKey X(0, 2), Y(2, 3), Z(1, 2); // watch ordering !
Signature::Table table; const Signature::Row r1{1, 1}, r2{2, 3}, r3{1, 4};
Signature::Row r1, r2, r3; const Signature::Table table{r1, r2, r3};
r1 += 1.0, 1.0;
r2 += 2.0, 3.0;
r3 += 1.0, 4.0;
table += r1, r2, r3;
DiscreteConditional actual1(X, {Y}, table); DiscreteConditional actual1(X, {Y}, table);
DecisionTreeFactor f1(X & Y, "0.5 0.4 0.2 0.5 0.6 0.8"); DecisionTreeFactor f1(X & Y, "0.5 0.4 0.2 0.5 0.6 0.8");

View File

@ -183,8 +183,7 @@ TEST_UNSAFE(DiscreteMarginals, truss2) {
F[j] /= sum; F[j] /= sum;
// Marginals // Marginals
vector<double> table; const vector<double> table{F[j], T[j]};
table += F[j], T[j];
DecisionTreeFactor expectedM(key[j], table); DecisionTreeFactor expectedM(key[j], table);
DiscreteFactor::shared_ptr actualM = marginals(j); DiscreteFactor::shared_ptr actualM = marginals(j);
EXPECT(assert_equal( EXPECT(assert_equal(

View File

@ -18,12 +18,13 @@
#pragma once #pragma once
#include <gtsam/geometry/Point3.h>
#include <gtsam/geometry/CalibratedCamera.h> // for Cheirality exception
#include <gtsam/base/Testable.h>
#include <gtsam/base/SymmetricBlockMatrix.h>
#include <gtsam/base/FastMap.h> #include <gtsam/base/FastMap.h>
#include <gtsam/base/SymmetricBlockMatrix.h>
#include <gtsam/base/Testable.h>
#include <gtsam/geometry/CalibratedCamera.h> // for Cheirality exception
#include <gtsam/geometry/Point3.h>
#include <gtsam/inference/Key.h> #include <gtsam/inference/Key.h>
#include <vector> #include <vector>
namespace gtsam { namespace gtsam {
@ -31,10 +32,10 @@ namespace gtsam {
/** /**
* @brief A set of cameras, all with their own calibration * @brief A set of cameras, all with their own calibration
*/ */
template<class CAMERA> template <class CAMERA>
class CameraSet : public std::vector<CAMERA, Eigen::aligned_allocator<CAMERA> > { class CameraSet : public std::vector<CAMERA, Eigen::aligned_allocator<CAMERA>> {
protected:
protected: using Base = std::vector<CAMERA, typename Eigen::aligned_allocator<CAMERA>>;
/** /**
* 2D measurement and noise model for each of the m views * 2D measurement and noise model for each of the m views
@ -43,13 +44,11 @@ protected:
typedef typename CAMERA::Measurement Z; typedef typename CAMERA::Measurement Z;
typedef typename CAMERA::MeasurementVector ZVector; typedef typename CAMERA::MeasurementVector ZVector;
static const int D = traits<CAMERA>::dimension; ///< Camera dimension static const int D = traits<CAMERA>::dimension; ///< Camera dimension
static const int ZDim = traits<Z>::dimension; ///< Measurement dimension static const int ZDim = traits<Z>::dimension; ///< Measurement dimension
/// Make a vector of re-projection errors /// Make a vector of re-projection errors
static Vector ErrorVector(const ZVector& predicted, static Vector ErrorVector(const ZVector& predicted, const ZVector& measured) {
const ZVector& measured) {
// Check size // Check size
size_t m = predicted.size(); size_t m = predicted.size();
if (measured.size() != m) if (measured.size() != m)
@ -59,7 +58,8 @@ protected:
Vector b(ZDim * m); Vector b(ZDim * m);
for (size_t i = 0, row = 0; i < m; i++, row += ZDim) { for (size_t i = 0, row = 0; i < m; i++, row += ZDim) {
Vector bi = traits<Z>::Local(measured[i], predicted[i]); Vector bi = traits<Z>::Local(measured[i], predicted[i]);
if(ZDim==3 && std::isnan(bi(1))){ // if it is a stereo point and the right pixel is missing (nan) if (ZDim == 3 && std::isnan(bi(1))) { // if it is a stereo point and the
// right pixel is missing (nan)
bi(1) = 0; bi(1) = 0;
} }
b.segment<ZDim>(row) = bi; b.segment<ZDim>(row) = bi;
@ -67,7 +67,8 @@ protected:
return b; return b;
} }
public: public:
using Base::Base; // Inherit the vector constructors
/// Destructor /// Destructor
virtual ~CameraSet() = default; virtual ~CameraSet() = default;
@ -83,18 +84,15 @@ public:
*/ */
virtual void print(const std::string& s = "") const { virtual void print(const std::string& s = "") const {
std::cout << s << "CameraSet, cameras = \n"; std::cout << s << "CameraSet, cameras = \n";
for (size_t k = 0; k < this->size(); ++k) for (size_t k = 0; k < this->size(); ++k) this->at(k).print(s);
this->at(k).print(s);
} }
/// equals /// equals
bool equals(const CameraSet& p, double tol = 1e-9) const { bool equals(const CameraSet& p, double tol = 1e-9) const {
if (this->size() != p.size()) if (this->size() != p.size()) return false;
return false;
bool camerasAreEqual = true; bool camerasAreEqual = true;
for (size_t i = 0; i < this->size(); i++) { for (size_t i = 0; i < this->size(); i++) {
if (this->at(i).equals(p.at(i), tol) == false) if (this->at(i).equals(p.at(i), tol) == false) camerasAreEqual = false;
camerasAreEqual = false;
break; break;
} }
return camerasAreEqual; return camerasAreEqual;
@ -106,11 +104,10 @@ public:
* matrix this function returns the diagonal blocks. * matrix this function returns the diagonal blocks.
* throws CheiralityException * throws CheiralityException
*/ */
template<class POINT> template <class POINT>
ZVector project2(const POINT& point, // ZVector project2(const POINT& point, //
boost::optional<FBlocks&> Fs = boost::none, // boost::optional<FBlocks&> Fs = boost::none, //
boost::optional<Matrix&> E = boost::none) const { boost::optional<Matrix&> E = boost::none) const {
static const int N = FixedDimension<POINT>::value; static const int N = FixedDimension<POINT>::value;
// Allocate result // Allocate result
@ -135,19 +132,19 @@ public:
} }
/// Calculate vector [project2(point)-z] of re-projection errors /// Calculate vector [project2(point)-z] of re-projection errors
template<class POINT> template <class POINT>
Vector reprojectionError(const POINT& point, const ZVector& measured, Vector reprojectionError(const POINT& point, const ZVector& measured,
boost::optional<FBlocks&> Fs = boost::none, // boost::optional<FBlocks&> Fs = boost::none, //
boost::optional<Matrix&> E = boost::none) const { boost::optional<Matrix&> E = boost::none) const {
return ErrorVector(project2(point, Fs, E), measured); return ErrorVector(project2(point, Fs, E), measured);
} }
/** /**
* Do Schur complement, given Jacobian as Fs,E,P, return SymmetricBlockMatrix * Do Schur complement, given Jacobian as Fs,E,P, return SymmetricBlockMatrix
* G = F' * F - F' * E * P * E' * F * G = F' * F - F' * E * P * E' * F
* g = F' * (b - E * P * E' * b) * g = F' * (b - E * P * E' * b)
* Fixed size version * Fixed size version
*/ */
template <int N, template <int N,
int ND> // N = 2 or 3 (point dimension), ND is the camera dimension int ND> // N = 2 or 3 (point dimension), ND is the camera dimension
static SymmetricBlockMatrix SchurComplement( static SymmetricBlockMatrix SchurComplement(
@ -158,38 +155,47 @@ public:
// a single point is observed in m cameras // a single point is observed in m cameras
size_t m = Fs.size(); size_t m = Fs.size();
// Create a SymmetricBlockMatrix (augmented hessian, with extra row/column with info vector) // Create a SymmetricBlockMatrix (augmented hessian, with extra row/column
// with info vector)
size_t M1 = ND * m + 1; size_t M1 = ND * m + 1;
std::vector<DenseIndex> dims(m + 1); // this also includes the b term std::vector<DenseIndex> dims(m + 1); // this also includes the b term
std::fill(dims.begin(), dims.end() - 1, ND); std::fill(dims.begin(), dims.end() - 1, ND);
dims.back() = 1; dims.back() = 1;
SymmetricBlockMatrix augmentedHessian(dims, Matrix::Zero(M1, M1)); SymmetricBlockMatrix augmentedHessian(dims, Matrix::Zero(M1, M1));
// Blockwise Schur complement // Blockwise Schur complement
for (size_t i = 0; i < m; i++) { // for each camera for (size_t i = 0; i < m; i++) { // for each camera
const Eigen::Matrix<double, ZDim, ND>& Fi = Fs[i]; const Eigen::Matrix<double, ZDim, ND>& Fi = Fs[i];
const auto FiT = Fi.transpose(); const auto FiT = Fi.transpose();
const Eigen::Matrix<double, ZDim, N> Ei_P = // const Eigen::Matrix<double, ZDim, N> Ei_P = //
E.block(ZDim * i, 0, ZDim, N) * P; E.block(ZDim * i, 0, ZDim, N) * P;
// D = (Dx2) * ZDim // D = (Dx2) * ZDim
augmentedHessian.setOffDiagonalBlock(i, m, FiT * b.segment<ZDim>(ZDim * i) // F' * b augmentedHessian.setOffDiagonalBlock(
- FiT * (Ei_P * (E.transpose() * b))); // D = (DxZDim) * (ZDimx3) * (N*ZDimm) * (ZDimm x 1) i, m,
FiT * b.segment<ZDim>(ZDim * i) // F' * b
-
FiT *
(Ei_P *
(E.transpose() *
b))); // D = (DxZDim) * (ZDimx3) * (N*ZDimm) * (ZDimm x 1)
// (DxD) = (DxZDim) * ( (ZDimxD) - (ZDimx3) * (3xZDim) * (ZDimxD) ) // (DxD) = (DxZDim) * ( (ZDimxD) - (ZDimx3) * (3xZDim) * (ZDimxD) )
augmentedHessian.setDiagonalBlock(i, FiT augmentedHessian.setDiagonalBlock(
* (Fi - Ei_P * E.block(ZDim * i, 0, ZDim, N).transpose() * Fi)); i,
FiT * (Fi - Ei_P * E.block(ZDim * i, 0, ZDim, N).transpose() * Fi));
// upper triangular part of the hessian // upper triangular part of the hessian
for (size_t j = i + 1; j < m; j++) { // for each camera for (size_t j = i + 1; j < m; j++) { // for each camera
const Eigen::Matrix<double, ZDim, ND>& Fj = Fs[j]; const Eigen::Matrix<double, ZDim, ND>& Fj = Fs[j];
// (DxD) = (Dx2) * ( (2x2) * (2xD) ) // (DxD) = (Dx2) * ( (2x2) * (2xD) )
augmentedHessian.setOffDiagonalBlock(i, j, -FiT augmentedHessian.setOffDiagonalBlock(
* (Ei_P * E.block(ZDim * j, 0, ZDim, N).transpose() * Fj)); i, j,
-FiT * (Ei_P * E.block(ZDim * j, 0, ZDim, N).transpose() * Fj));
} }
} // end of for over cameras } // end of for over cameras
augmentedHessian.diagonalBlock(m)(0, 0) += b.squaredNorm(); augmentedHessian.diagonalBlock(m)(0, 0) += b.squaredNorm();
return augmentedHessian; return augmentedHessian;
@ -297,20 +303,21 @@ public:
* g = F' * (b - E * P * E' * b) * g = F' * (b - E * P * E' * b)
* Fixed size version * Fixed size version
*/ */
template<int N> // N = 2 or 3 template <int N> // N = 2 or 3
static SymmetricBlockMatrix SchurComplement(const FBlocks& Fs, static SymmetricBlockMatrix SchurComplement(
const Matrix& E, const Eigen::Matrix<double, N, N>& P, const Vector& b) { const FBlocks& Fs, const Matrix& E, const Eigen::Matrix<double, N, N>& P,
return SchurComplement<N,D>(Fs, E, P, b); const Vector& b) {
return SchurComplement<N, D>(Fs, E, P, b);
} }
/// Computes Point Covariance P, with lambda parameter /// Computes Point Covariance P, with lambda parameter
template<int N> // N = 2 or 3 (point dimension) template <int N> // N = 2 or 3 (point dimension)
static void ComputePointCovariance(Eigen::Matrix<double, N, N>& P, static void ComputePointCovariance(Eigen::Matrix<double, N, N>& P,
const Matrix& E, double lambda, bool diagonalDamping = false) { const Matrix& E, double lambda,
bool diagonalDamping = false) {
Matrix EtE = E.transpose() * E; Matrix EtE = E.transpose() * E;
if (diagonalDamping) { // diagonal of the hessian if (diagonalDamping) { // diagonal of the hessian
EtE.diagonal() += lambda * EtE.diagonal(); EtE.diagonal() += lambda * EtE.diagonal();
} else { } else {
DenseIndex n = E.cols(); DenseIndex n = E.cols();
@ -322,7 +329,7 @@ public:
/// Computes Point Covariance P, with lambda parameter, dynamic version /// Computes Point Covariance P, with lambda parameter, dynamic version
static Matrix PointCov(const Matrix& E, const double lambda = 0.0, static Matrix PointCov(const Matrix& E, const double lambda = 0.0,
bool diagonalDamping = false) { bool diagonalDamping = false) {
if (E.cols() == 2) { if (E.cols() == 2) {
Matrix2 P2; Matrix2 P2;
ComputePointCovariance<2>(P2, E, lambda, diagonalDamping); ComputePointCovariance<2>(P2, E, lambda, diagonalDamping);
@ -339,8 +346,9 @@ public:
* Dynamic version * Dynamic version
*/ */
static SymmetricBlockMatrix SchurComplement(const FBlocks& Fblocks, static SymmetricBlockMatrix SchurComplement(const FBlocks& Fblocks,
const Matrix& E, const Vector& b, const double lambda = 0.0, const Matrix& E, const Vector& b,
bool diagonalDamping = false) { const double lambda = 0.0,
bool diagonalDamping = false) {
if (E.cols() == 2) { if (E.cols() == 2) {
Matrix2 P; Matrix2 P;
ComputePointCovariance<2>(P, E, lambda, diagonalDamping); ComputePointCovariance<2>(P, E, lambda, diagonalDamping);
@ -353,17 +361,17 @@ public:
} }
/** /**
* Applies Schur complement (exploiting block structure) to get a smart factor on cameras, * Applies Schur complement (exploiting block structure) to get a smart factor
* and adds the contribution of the smart factor to a pre-allocated augmented Hessian. * on cameras, and adds the contribution of the smart factor to a
* pre-allocated augmented Hessian.
*/ */
template<int N> // N = 2 or 3 (point dimension) template <int N> // N = 2 or 3 (point dimension)
static void UpdateSchurComplement(const FBlocks& Fs, const Matrix& E, static void UpdateSchurComplement(
const Eigen::Matrix<double, N, N>& P, const Vector& b, const FBlocks& Fs, const Matrix& E, const Eigen::Matrix<double, N, N>& P,
const KeyVector& allKeys, const KeyVector& keys, const Vector& b, const KeyVector& allKeys, const KeyVector& keys,
/*output ->*/SymmetricBlockMatrix& augmentedHessian) { /*output ->*/ SymmetricBlockMatrix& augmentedHessian) {
assert(keys.size() == Fs.size());
assert(keys.size()==Fs.size()); assert(keys.size() <= allKeys.size());
assert(keys.size()<=allKeys.size());
FastMap<Key, size_t> KeySlotMap; FastMap<Key, size_t> KeySlotMap;
for (size_t slot = 0; slot < allKeys.size(); slot++) for (size_t slot = 0; slot < allKeys.size(); slot++)
@ -374,39 +382,49 @@ public:
// g = F' * (b - E * P * E' * b) // g = F' * (b - E * P * E' * b)
// a single point is observed in m cameras // a single point is observed in m cameras
size_t m = Fs.size(); // cameras observing current point size_t m = Fs.size(); // cameras observing current point
size_t M = (augmentedHessian.rows() - 1) / D; // all cameras in the group size_t M = (augmentedHessian.rows() - 1) / D; // all cameras in the group
assert(allKeys.size()==M); assert(allKeys.size() == M);
// Blockwise Schur complement // Blockwise Schur complement
for (size_t i = 0; i < m; i++) { // for each camera in the current factor for (size_t i = 0; i < m; i++) { // for each camera in the current factor
const MatrixZD& Fi = Fs[i]; const MatrixZD& Fi = Fs[i];
const auto FiT = Fi.transpose(); const auto FiT = Fi.transpose();
const Eigen::Matrix<double, 2, N> Ei_P = E.template block<ZDim, N>( const Eigen::Matrix<double, 2, N> Ei_P =
ZDim * i, 0) * P; E.template block<ZDim, N>(ZDim * i, 0) * P;
// D = (DxZDim) * (ZDim) // D = (DxZDim) * (ZDim)
// allKeys are the list of all camera keys in the group, e.g, (1,3,4,5,7) // allKeys are the list of all camera keys in the group, e.g, (1,3,4,5,7)
// we should map those to a slot in the local (grouped) hessian (0,1,2,3,4) // we should map those to a slot in the local (grouped) hessian
// Key cameraKey_i = this->keys_[i]; // (0,1,2,3,4) Key cameraKey_i = this->keys_[i];
DenseIndex aug_i = KeySlotMap.at(keys[i]); DenseIndex aug_i = KeySlotMap.at(keys[i]);
// information vector - store previous vector // information vector - store previous vector
// vectorBlock = augmentedHessian(aug_i, aug_m).knownOffDiagonal(); // vectorBlock = augmentedHessian(aug_i, aug_m).knownOffDiagonal();
// add contribution of current factor // add contribution of current factor
augmentedHessian.updateOffDiagonalBlock(aug_i, M, augmentedHessian.updateOffDiagonalBlock(
FiT * b.segment<ZDim>(ZDim * i) // F' * b aug_i, M,
- FiT * (Ei_P * (E.transpose() * b))); // D = (DxZDim) * (ZDimx3) * (N*ZDimm) * (ZDimm x 1) FiT * b.segment<ZDim>(ZDim * i) // F' * b
-
FiT *
(Ei_P *
(E.transpose() *
b))); // D = (DxZDim) * (ZDimx3) * (N*ZDimm) * (ZDimm x 1)
// (DxD) += (DxZDim) * ( (ZDimxD) - (ZDimx3) * (3xZDim) * (ZDimxD) ) // (DxD) += (DxZDim) * ( (ZDimxD) - (ZDimx3) * (3xZDim) * (ZDimxD) )
// add contribution of current factor // add contribution of current factor
// TODO(gareth): Eigen doesn't let us pass the expression. Call eval() for now... // TODO(gareth): Eigen doesn't let us pass the expression. Call eval() for
augmentedHessian.updateDiagonalBlock(aug_i, // now...
((FiT * (Fi - Ei_P * E.template block<ZDim, N>(ZDim * i, 0).transpose() * Fi))).eval()); augmentedHessian.updateDiagonalBlock(
aug_i,
((FiT *
(Fi -
Ei_P * E.template block<ZDim, N>(ZDim * i, 0).transpose() * Fi)))
.eval());
// upper triangular part of the hessian // upper triangular part of the hessian
for (size_t j = i + 1; j < m; j++) { // for each camera for (size_t j = i + 1; j < m; j++) { // for each camera
const MatrixZD& Fj = Fs[j]; const MatrixZD& Fj = Fs[j];
DenseIndex aug_j = KeySlotMap.at(keys[j]); DenseIndex aug_j = KeySlotMap.at(keys[j]);
@ -415,39 +433,38 @@ public:
// off diagonal block - store previous block // off diagonal block - store previous block
// matrixBlock = augmentedHessian(aug_i, aug_j).knownOffDiagonal(); // matrixBlock = augmentedHessian(aug_i, aug_j).knownOffDiagonal();
// add contribution of current factor // add contribution of current factor
augmentedHessian.updateOffDiagonalBlock(aug_i, aug_j, augmentedHessian.updateOffDiagonalBlock(
-FiT * (Ei_P * E.template block<ZDim, N>(ZDim * j, 0).transpose() * Fj)); aug_i, aug_j,
-FiT * (Ei_P * E.template block<ZDim, N>(ZDim * j, 0).transpose() *
Fj));
} }
} // end of for over cameras } // end of for over cameras
augmentedHessian.diagonalBlock(M)(0, 0) += b.squaredNorm(); augmentedHessian.diagonalBlock(M)(0, 0) += b.squaredNorm();
} }
private: private:
/// Serialization function /// Serialization function
friend class boost::serialization::access; friend class boost::serialization::access;
template<class ARCHIVE> template <class ARCHIVE>
void serialize(ARCHIVE & ar, const unsigned int /*version*/) { void serialize(ARCHIVE& ar, const unsigned int /*version*/) {
ar & (*this); ar&(*this);
} }
public: public:
GTSAM_MAKE_ALIGNED_OPERATOR_NEW GTSAM_MAKE_ALIGNED_OPERATOR_NEW
}; };
template<class CAMERA> template <class CAMERA>
const int CameraSet<CAMERA>::D; const int CameraSet<CAMERA>::D;
template<class CAMERA> template <class CAMERA>
const int CameraSet<CAMERA>::ZDim; const int CameraSet<CAMERA>::ZDim;
template<class CAMERA> template <class CAMERA>
struct traits<CameraSet<CAMERA> > : public Testable<CameraSet<CAMERA> > { struct traits<CameraSet<CAMERA>> : public Testable<CameraSet<CAMERA>> {};
};
template<class CAMERA> template <class CAMERA>
struct traits<const CameraSet<CAMERA> > : public Testable<CameraSet<CAMERA> > { struct traits<const CameraSet<CAMERA>> : public Testable<CameraSet<CAMERA>> {};
};
} // \ namespace gtsam } // namespace gtsam

View File

@ -20,12 +20,9 @@
#include <gtsam/geometry/OrientedPlane3.h> #include <gtsam/geometry/OrientedPlane3.h>
#include <gtsam/base/numericalDerivative.h> #include <gtsam/base/numericalDerivative.h>
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/vector.hpp>
using namespace boost::assign;
using namespace std::placeholders; using namespace std::placeholders;
using namespace gtsam; using namespace gtsam;
using namespace std;
using boost::none; using boost::none;
GTSAM_CONCEPT_TESTABLE_INST(OrientedPlane3) GTSAM_CONCEPT_TESTABLE_INST(OrientedPlane3)

View File

@ -23,12 +23,10 @@
#include <gtsam/geometry/Pose2.h> #include <gtsam/geometry/Pose2.h>
#include <gtsam/geometry/Rot2.h> #include <gtsam/geometry/Rot2.h>
#include <boost/assign/std/vector.hpp> // for operator +=
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <cmath> #include <cmath>
#include <iostream> #include <iostream>
using namespace boost::assign;
using namespace gtsam; using namespace gtsam;
using namespace std; using namespace std;
@ -749,11 +747,10 @@ namespace align_3 {
TEST(Pose2, align_3) { TEST(Pose2, align_3) {
using namespace align_3; using namespace align_3;
Point2Pairs ab_pairs;
Point2Pair ab1(make_pair(a1, b1)); Point2Pair ab1(make_pair(a1, b1));
Point2Pair ab2(make_pair(a2, b2)); Point2Pair ab2(make_pair(a2, b2));
Point2Pair ab3(make_pair(a3, b3)); Point2Pair ab3(make_pair(a3, b3));
ab_pairs += ab1, ab2, ab3; const Point2Pairs ab_pairs{ab1, ab2, ab3};
boost::optional<Pose2> aTb = Pose2::Align(ab_pairs); boost::optional<Pose2> aTb = Pose2::Align(ab_pairs);
EXPECT(assert_equal(expected, *aTb)); EXPECT(assert_equal(expected, *aTb));
@ -778,9 +775,7 @@ namespace {
TEST(Pose2, align_4) { TEST(Pose2, align_4) {
using namespace align_3; using namespace align_3;
Point2Vector as, bs; Point2Vector as{a1, a2, a3}, bs{b3, b1, b2}; // note in 3,1,2 order !
as += a1, a2, a3;
bs += b3, b1, b2; // note in 3,1,2 order !
Triangle t1; t1.i_=0; t1.j_=1; t1.k_=2; Triangle t1; t1.i_=0; t1.j_=1; t1.k_=2;
Triangle t2; t2.i_=1; t2.j_=2; t2.k_=0; Triangle t2; t2.i_=1; t2.j_=2; t2.k_=0;

View File

@ -20,15 +20,13 @@
#include <gtsam/base/lieProxies.h> #include <gtsam/base/lieProxies.h>
#include <gtsam/base/TestableAssertions.h> #include <gtsam/base/TestableAssertions.h>
#include <boost/assign/std/vector.hpp> // for operator +=
using namespace boost::assign;
using namespace std::placeholders;
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <cmath> #include <cmath>
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;
using namespace std::placeholders;
GTSAM_CONCEPT_TESTABLE_INST(Pose3) GTSAM_CONCEPT_TESTABLE_INST(Pose3)
GTSAM_CONCEPT_LIE_INST(Pose3) GTSAM_CONCEPT_LIE_INST(Pose3)
@ -809,11 +807,10 @@ TEST( Pose3, adjointMap) {
TEST(Pose3, Align1) { TEST(Pose3, Align1) {
Pose3 expected(Rot3(), Point3(10,10,0)); Pose3 expected(Rot3(), Point3(10,10,0));
vector<Point3Pair> correspondences; Point3Pair ab1(Point3(10,10,0), Point3(0,0,0));
Point3Pair ab1(make_pair(Point3(10,10,0), Point3(0,0,0))); Point3Pair ab2(Point3(30,20,0), Point3(20,10,0));
Point3Pair ab2(make_pair(Point3(30,20,0), Point3(20,10,0))); Point3Pair ab3(Point3(20,30,0), Point3(10,20,0));
Point3Pair ab3(make_pair(Point3(20,30,0), Point3(10,20,0))); const vector<Point3Pair> correspondences{ab1, ab2, ab3};
correspondences += ab1, ab2, ab3;
boost::optional<Pose3> actual = Pose3::Align(correspondences); boost::optional<Pose3> actual = Pose3::Align(correspondences);
EXPECT(assert_equal(expected, *actual)); EXPECT(assert_equal(expected, *actual));
@ -825,15 +822,12 @@ TEST(Pose3, Align2) {
Rot3 R = Rot3::RzRyRx(0.3, 0.2, 0.1); Rot3 R = Rot3::RzRyRx(0.3, 0.2, 0.1);
Pose3 expected(R, t); Pose3 expected(R, t);
vector<Point3Pair> correspondences;
Point3 p1(0,0,1), p2(10,0,2), p3(20,-10,30); Point3 p1(0,0,1), p2(10,0,2), p3(20,-10,30);
Point3 q1 = expected.transformFrom(p1), Point3 q1 = expected.transformFrom(p1),
q2 = expected.transformFrom(p2), q2 = expected.transformFrom(p2),
q3 = expected.transformFrom(p3); q3 = expected.transformFrom(p3);
Point3Pair ab1(make_pair(q1, p1)); const Point3Pair ab1{q1, p1}, ab2{q2, p2}, ab3{q3, p3};
Point3Pair ab2(make_pair(q2, p2)); const vector<Point3Pair> correspondences{ab1, ab2, ab3};
Point3Pair ab3(make_pair(q3, p3));
correspondences += ab1, ab2, ab3;
boost::optional<Pose3> actual = Pose3::Align(correspondences); boost::optional<Pose3> actual = Pose3::Align(correspondences);
EXPECT(assert_equal(expected, *actual, 1e-5)); EXPECT(assert_equal(expected, *actual, 1e-5));

View File

@ -30,12 +30,8 @@
#include <gtsam/nonlinear/LevenbergMarquardtOptimizer.h> #include <gtsam/nonlinear/LevenbergMarquardtOptimizer.h>
#include <gtsam/slam/StereoFactor.h> #include <gtsam/slam/StereoFactor.h>
#include <boost/assign.hpp>
#include <boost/assign/std/vector.hpp>
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;
using namespace boost::assign;
// Some common constants // Some common constants
@ -51,34 +47,34 @@ static const PinholeCamera<Cal3_S2> kCamera1(kPose1, *kSharedCal);
static const Pose3 kPose2 = kPose1 * Pose3(Rot3(), Point3(1, 0, 0)); static const Pose3 kPose2 = kPose1 * Pose3(Rot3(), Point3(1, 0, 0));
static const PinholeCamera<Cal3_S2> kCamera2(kPose2, *kSharedCal); static const PinholeCamera<Cal3_S2> kCamera2(kPose2, *kSharedCal);
// landmark ~5 meters infront of camera static const std::vector<Pose3> kPoses = {kPose1, kPose2};
// landmark ~5 meters in front of camera
static const Point3 kLandmark(5, 0.5, 1.2); static const Point3 kLandmark(5, 0.5, 1.2);
// 1. Project two landmarks into two cameras and triangulate // 1. Project two landmarks into two cameras and triangulate
static const Point2 kZ1 = kCamera1.project(kLandmark); static const Point2 kZ1 = kCamera1.project(kLandmark);
static const Point2 kZ2 = kCamera2.project(kLandmark); static const Point2 kZ2 = kCamera2.project(kLandmark);
static const Point2Vector kMeasurements{kZ1, kZ2};
//****************************************************************************** //******************************************************************************
// Simple test with a well-behaved two camera situation // Simple test with a well-behaved two camera situation
TEST(triangulation, twoPoses) { TEST(triangulation, twoPoses) {
vector<Pose3> poses; Point2Vector measurements = kMeasurements;
Point2Vector measurements;
poses += kPose1, kPose2;
measurements += kZ1, kZ2;
double rank_tol = 1e-9; double rank_tol = 1e-9;
// 1. Test simple DLT, perfect in no noise situation // 1. Test simple DLT, perfect in no noise situation
bool optimize = false; bool optimize = false;
boost::optional<Point3> actual1 = // boost::optional<Point3> actual1 = //
triangulatePoint3<Cal3_S2>(poses, kSharedCal, measurements, rank_tol, optimize); triangulatePoint3<Cal3_S2>(kPoses, kSharedCal, measurements, rank_tol, optimize);
EXPECT(assert_equal(kLandmark, *actual1, 1e-7)); EXPECT(assert_equal(kLandmark, *actual1, 1e-7));
// 2. test with optimization on, same answer // 2. test with optimization on, same answer
optimize = true; optimize = true;
boost::optional<Point3> actual2 = // boost::optional<Point3> actual2 = //
triangulatePoint3<Cal3_S2>(poses, kSharedCal, measurements, rank_tol, optimize); triangulatePoint3<Cal3_S2>(kPoses, kSharedCal, measurements, rank_tol, optimize);
EXPECT(assert_equal(kLandmark, *actual2, 1e-7)); EXPECT(assert_equal(kLandmark, *actual2, 1e-7));
// 3. Add some noise and try again: result should be ~ (4.995, // 3. Add some noise and try again: result should be ~ (4.995,
@ -87,13 +83,13 @@ TEST(triangulation, twoPoses) {
measurements.at(1) += Point2(-0.2, 0.3); measurements.at(1) += Point2(-0.2, 0.3);
optimize = false; optimize = false;
boost::optional<Point3> actual3 = // boost::optional<Point3> actual3 = //
triangulatePoint3<Cal3_S2>(poses, kSharedCal, measurements, rank_tol, optimize); triangulatePoint3<Cal3_S2>(kPoses, kSharedCal, measurements, rank_tol, optimize);
EXPECT(assert_equal(Point3(4.995, 0.499167, 1.19814), *actual3, 1e-4)); EXPECT(assert_equal(Point3(4.995, 0.499167, 1.19814), *actual3, 1e-4));
// 4. Now with optimization on // 4. Now with optimization on
optimize = true; optimize = true;
boost::optional<Point3> actual4 = // boost::optional<Point3> actual4 = //
triangulatePoint3<Cal3_S2>(poses, kSharedCal, measurements, rank_tol, optimize); triangulatePoint3<Cal3_S2>(kPoses, kSharedCal, measurements, rank_tol, optimize);
EXPECT(assert_equal(Point3(4.995, 0.499167, 1.19814), *actual4, 1e-4)); EXPECT(assert_equal(Point3(4.995, 0.499167, 1.19814), *actual4, 1e-4));
} }
@ -102,7 +98,7 @@ TEST(triangulation, twoCamerasUsingLOST) {
cameras.push_back(kCamera1); cameras.push_back(kCamera1);
cameras.push_back(kCamera2); cameras.push_back(kCamera2);
Point2Vector measurements = {kZ1, kZ2}; Point2Vector measurements = kMeasurements;
SharedNoiseModel measurementNoise = noiseModel::Isotropic::Sigma(2, 1e-4); SharedNoiseModel measurementNoise = noiseModel::Isotropic::Sigma(2, 1e-4);
double rank_tol = 1e-9; double rank_tol = 1e-9;
@ -175,25 +171,21 @@ TEST(triangulation, twoPosesCal3DS2) {
Point2 z1Distorted = camera1Distorted.project(kLandmark); Point2 z1Distorted = camera1Distorted.project(kLandmark);
Point2 z2Distorted = camera2Distorted.project(kLandmark); Point2 z2Distorted = camera2Distorted.project(kLandmark);
vector<Pose3> poses; Point2Vector measurements{z1Distorted, z2Distorted};
Point2Vector measurements;
poses += kPose1, kPose2;
measurements += z1Distorted, z2Distorted;
double rank_tol = 1e-9; double rank_tol = 1e-9;
// 1. Test simple DLT, perfect in no noise situation // 1. Test simple DLT, perfect in no noise situation
bool optimize = false; bool optimize = false;
boost::optional<Point3> actual1 = // boost::optional<Point3> actual1 = //
triangulatePoint3<Cal3DS2>(poses, sharedDistortedCal, measurements, triangulatePoint3<Cal3DS2>(kPoses, sharedDistortedCal, measurements,
rank_tol, optimize); rank_tol, optimize);
EXPECT(assert_equal(kLandmark, *actual1, 1e-7)); EXPECT(assert_equal(kLandmark, *actual1, 1e-7));
// 2. test with optimization on, same answer // 2. test with optimization on, same answer
optimize = true; optimize = true;
boost::optional<Point3> actual2 = // boost::optional<Point3> actual2 = //
triangulatePoint3<Cal3DS2>(poses, sharedDistortedCal, measurements, triangulatePoint3<Cal3DS2>(kPoses, sharedDistortedCal, measurements,
rank_tol, optimize); rank_tol, optimize);
EXPECT(assert_equal(kLandmark, *actual2, 1e-7)); EXPECT(assert_equal(kLandmark, *actual2, 1e-7));
@ -203,14 +195,14 @@ TEST(triangulation, twoPosesCal3DS2) {
measurements.at(1) += Point2(-0.2, 0.3); measurements.at(1) += Point2(-0.2, 0.3);
optimize = false; optimize = false;
boost::optional<Point3> actual3 = // boost::optional<Point3> actual3 = //
triangulatePoint3<Cal3DS2>(poses, sharedDistortedCal, measurements, triangulatePoint3<Cal3DS2>(kPoses, sharedDistortedCal, measurements,
rank_tol, optimize); rank_tol, optimize);
EXPECT(assert_equal(Point3(4.995, 0.499167, 1.19814), *actual3, 1e-3)); EXPECT(assert_equal(Point3(4.995, 0.499167, 1.19814), *actual3, 1e-3));
// 4. Now with optimization on // 4. Now with optimization on
optimize = true; optimize = true;
boost::optional<Point3> actual4 = // boost::optional<Point3> actual4 = //
triangulatePoint3<Cal3DS2>(poses, sharedDistortedCal, measurements, triangulatePoint3<Cal3DS2>(kPoses, sharedDistortedCal, measurements,
rank_tol, optimize); rank_tol, optimize);
EXPECT(assert_equal(Point3(4.995, 0.499167, 1.19814), *actual4, 1e-3)); EXPECT(assert_equal(Point3(4.995, 0.499167, 1.19814), *actual4, 1e-3));
} }
@ -232,25 +224,21 @@ TEST(triangulation, twoPosesFisheye) {
Point2 z1Distorted = camera1Distorted.project(kLandmark); Point2 z1Distorted = camera1Distorted.project(kLandmark);
Point2 z2Distorted = camera2Distorted.project(kLandmark); Point2 z2Distorted = camera2Distorted.project(kLandmark);
vector<Pose3> poses; Point2Vector measurements{z1Distorted, z2Distorted};
Point2Vector measurements;
poses += kPose1, kPose2;
measurements += z1Distorted, z2Distorted;
double rank_tol = 1e-9; double rank_tol = 1e-9;
// 1. Test simple DLT, perfect in no noise situation // 1. Test simple DLT, perfect in no noise situation
bool optimize = false; bool optimize = false;
boost::optional<Point3> actual1 = // boost::optional<Point3> actual1 = //
triangulatePoint3<Calibration>(poses, sharedDistortedCal, measurements, triangulatePoint3<Calibration>(kPoses, sharedDistortedCal, measurements,
rank_tol, optimize); rank_tol, optimize);
EXPECT(assert_equal(kLandmark, *actual1, 1e-7)); EXPECT(assert_equal(kLandmark, *actual1, 1e-7));
// 2. test with optimization on, same answer // 2. test with optimization on, same answer
optimize = true; optimize = true;
boost::optional<Point3> actual2 = // boost::optional<Point3> actual2 = //
triangulatePoint3<Calibration>(poses, sharedDistortedCal, measurements, triangulatePoint3<Calibration>(kPoses, sharedDistortedCal, measurements,
rank_tol, optimize); rank_tol, optimize);
EXPECT(assert_equal(kLandmark, *actual2, 1e-7)); EXPECT(assert_equal(kLandmark, *actual2, 1e-7));
@ -260,14 +248,14 @@ TEST(triangulation, twoPosesFisheye) {
measurements.at(1) += Point2(-0.2, 0.3); measurements.at(1) += Point2(-0.2, 0.3);
optimize = false; optimize = false;
boost::optional<Point3> actual3 = // boost::optional<Point3> actual3 = //
triangulatePoint3<Calibration>(poses, sharedDistortedCal, measurements, triangulatePoint3<Calibration>(kPoses, sharedDistortedCal, measurements,
rank_tol, optimize); rank_tol, optimize);
EXPECT(assert_equal(Point3(4.995, 0.499167, 1.19814), *actual3, 1e-3)); EXPECT(assert_equal(Point3(4.995, 0.499167, 1.19814), *actual3, 1e-3));
// 4. Now with optimization on // 4. Now with optimization on
optimize = true; optimize = true;
boost::optional<Point3> actual4 = // boost::optional<Point3> actual4 = //
triangulatePoint3<Calibration>(poses, sharedDistortedCal, measurements, triangulatePoint3<Calibration>(kPoses, sharedDistortedCal, measurements,
rank_tol, optimize); rank_tol, optimize);
EXPECT(assert_equal(Point3(4.995, 0.499167, 1.19814), *actual4, 1e-3)); EXPECT(assert_equal(Point3(4.995, 0.499167, 1.19814), *actual4, 1e-3));
} }
@ -284,17 +272,13 @@ TEST(triangulation, twoPosesBundler) {
Point2 z1 = camera1.project(kLandmark); Point2 z1 = camera1.project(kLandmark);
Point2 z2 = camera2.project(kLandmark); Point2 z2 = camera2.project(kLandmark);
vector<Pose3> poses; Point2Vector measurements{z1, z2};
Point2Vector measurements;
poses += kPose1, kPose2;
measurements += z1, z2;
bool optimize = true; bool optimize = true;
double rank_tol = 1e-9; double rank_tol = 1e-9;
boost::optional<Point3> actual = // boost::optional<Point3> actual = //
triangulatePoint3<Cal3Bundler>(poses, bundlerCal, measurements, rank_tol, triangulatePoint3<Cal3Bundler>(kPoses, bundlerCal, measurements, rank_tol,
optimize); optimize);
EXPECT(assert_equal(kLandmark, *actual, 1e-7)); EXPECT(assert_equal(kLandmark, *actual, 1e-7));
@ -303,19 +287,15 @@ TEST(triangulation, twoPosesBundler) {
measurements.at(1) += Point2(-0.2, 0.3); measurements.at(1) += Point2(-0.2, 0.3);
boost::optional<Point3> actual2 = // boost::optional<Point3> actual2 = //
triangulatePoint3<Cal3Bundler>(poses, bundlerCal, measurements, rank_tol, triangulatePoint3<Cal3Bundler>(kPoses, bundlerCal, measurements, rank_tol,
optimize); optimize);
EXPECT(assert_equal(Point3(4.995, 0.499167, 1.19847), *actual2, 1e-3)); EXPECT(assert_equal(Point3(4.995, 0.499167, 1.19847), *actual2, 1e-3));
} }
//****************************************************************************** //******************************************************************************
TEST(triangulation, fourPoses) { TEST(triangulation, fourPoses) {
vector<Pose3> poses; Pose3Vector poses = kPoses;
Point2Vector measurements; Point2Vector measurements = kMeasurements;
poses += kPose1, kPose2;
measurements += kZ1, kZ2;
boost::optional<Point3> actual = boost::optional<Point3> actual =
triangulatePoint3<Cal3_S2>(poses, kSharedCal, measurements); triangulatePoint3<Cal3_S2>(poses, kSharedCal, measurements);
EXPECT(assert_equal(kLandmark, *actual, 1e-2)); EXPECT(assert_equal(kLandmark, *actual, 1e-2));
@ -334,8 +314,8 @@ TEST(triangulation, fourPoses) {
PinholeCamera<Cal3_S2> camera3(pose3, *kSharedCal); PinholeCamera<Cal3_S2> camera3(pose3, *kSharedCal);
Point2 z3 = camera3.project(kLandmark); Point2 z3 = camera3.project(kLandmark);
poses += pose3; poses.push_back(pose3);
measurements += z3 + Point2(0.1, -0.1); measurements.push_back(z3 + Point2(0.1, -0.1));
boost::optional<Point3> triangulated_3cameras = // boost::optional<Point3> triangulated_3cameras = //
triangulatePoint3<Cal3_S2>(poses, kSharedCal, measurements); triangulatePoint3<Cal3_S2>(poses, kSharedCal, measurements);
@ -353,8 +333,8 @@ TEST(triangulation, fourPoses) {
#ifdef GTSAM_THROW_CHEIRALITY_EXCEPTION #ifdef GTSAM_THROW_CHEIRALITY_EXCEPTION
CHECK_EXCEPTION(camera4.project(kLandmark), CheiralityException); CHECK_EXCEPTION(camera4.project(kLandmark), CheiralityException);
poses += pose4; poses.push_back(pose4);
measurements += Point2(400, 400); measurements.emplace_back(400, 400);
CHECK_EXCEPTION(triangulatePoint3<Cal3_S2>(poses, kSharedCal, measurements), CHECK_EXCEPTION(triangulatePoint3<Cal3_S2>(poses, kSharedCal, measurements),
TriangulationCheiralityException); TriangulationCheiralityException);
@ -368,10 +348,8 @@ TEST(triangulation, threePoses_robustNoiseModel) {
PinholeCamera<Cal3_S2> camera3(pose3, *kSharedCal); PinholeCamera<Cal3_S2> camera3(pose3, *kSharedCal);
Point2 z3 = camera3.project(kLandmark); Point2 z3 = camera3.project(kLandmark);
vector<Pose3> poses; const vector<Pose3> poses{kPose1, kPose2, pose3};
Point2Vector measurements; Point2Vector measurements{kZ1, kZ2, z3};
poses += kPose1, kPose2, pose3;
measurements += kZ1, kZ2, z3;
// noise free, so should give exactly the landmark // noise free, so should give exactly the landmark
boost::optional<Point3> actual = boost::optional<Point3> actual =
@ -410,10 +388,9 @@ TEST(triangulation, fourPoses_robustNoiseModel) {
PinholeCamera<Cal3_S2> camera3(pose3, *kSharedCal); PinholeCamera<Cal3_S2> camera3(pose3, *kSharedCal);
Point2 z3 = camera3.project(kLandmark); Point2 z3 = camera3.project(kLandmark);
vector<Pose3> poses; const vector<Pose3> poses{kPose1, kPose1, kPose2, pose3};
Point2Vector measurements; // 2 measurements from pose 1:
poses += kPose1, kPose1, kPose2, pose3; // 2 measurements from pose 1 Point2Vector measurements{kZ1, kZ1, kZ2, z3};
measurements += kZ1, kZ1, kZ2, z3;
// noise free, so should give exactly the landmark // noise free, so should give exactly the landmark
boost::optional<Point3> actual = boost::optional<Point3> actual =
@ -463,11 +440,8 @@ TEST(triangulation, fourPoses_distinct_Ks) {
Point2 z1 = camera1.project(kLandmark); Point2 z1 = camera1.project(kLandmark);
Point2 z2 = camera2.project(kLandmark); Point2 z2 = camera2.project(kLandmark);
CameraSet<PinholeCamera<Cal3_S2>> cameras; CameraSet<PinholeCamera<Cal3_S2>> cameras{camera1, camera2};
Point2Vector measurements; Point2Vector measurements{z1, z2};
cameras += camera1, camera2;
measurements += z1, z2;
boost::optional<Point3> actual = // boost::optional<Point3> actual = //
triangulatePoint3<Cal3_S2>(cameras, measurements); triangulatePoint3<Cal3_S2>(cameras, measurements);
@ -488,8 +462,8 @@ TEST(triangulation, fourPoses_distinct_Ks) {
PinholeCamera<Cal3_S2> camera3(pose3, K3); PinholeCamera<Cal3_S2> camera3(pose3, K3);
Point2 z3 = camera3.project(kLandmark); Point2 z3 = camera3.project(kLandmark);
cameras += camera3; cameras.push_back(camera3);
measurements += z3 + Point2(0.1, -0.1); measurements.push_back(z3 + Point2(0.1, -0.1));
boost::optional<Point3> triangulated_3cameras = // boost::optional<Point3> triangulated_3cameras = //
triangulatePoint3<Cal3_S2>(cameras, measurements); triangulatePoint3<Cal3_S2>(cameras, measurements);
@ -508,8 +482,8 @@ TEST(triangulation, fourPoses_distinct_Ks) {
#ifdef GTSAM_THROW_CHEIRALITY_EXCEPTION #ifdef GTSAM_THROW_CHEIRALITY_EXCEPTION
CHECK_EXCEPTION(camera4.project(kLandmark), CheiralityException); CHECK_EXCEPTION(camera4.project(kLandmark), CheiralityException);
cameras += camera4; cameras.push_back(camera4);
measurements += Point2(400, 400); measurements.emplace_back(400, 400);
CHECK_EXCEPTION(triangulatePoint3<Cal3_S2>(cameras, measurements), CHECK_EXCEPTION(triangulatePoint3<Cal3_S2>(cameras, measurements),
TriangulationCheiralityException); TriangulationCheiralityException);
#endif #endif
@ -529,11 +503,8 @@ TEST(triangulation, fourPoses_distinct_Ks_distortion) {
Point2 z1 = camera1.project(kLandmark); Point2 z1 = camera1.project(kLandmark);
Point2 z2 = camera2.project(kLandmark); Point2 z2 = camera2.project(kLandmark);
CameraSet<PinholeCamera<Cal3DS2>> cameras; const CameraSet<PinholeCamera<Cal3DS2>> cameras{camera1, camera2};
Point2Vector measurements; const Point2Vector measurements{z1, z2};
cameras += camera1, camera2;
measurements += z1, z2;
boost::optional<Point3> actual = // boost::optional<Point3> actual = //
triangulatePoint3<Cal3DS2>(cameras, measurements); triangulatePoint3<Cal3DS2>(cameras, measurements);
@ -554,11 +525,8 @@ TEST(triangulation, outliersAndFarLandmarks) {
Point2 z1 = camera1.project(kLandmark); Point2 z1 = camera1.project(kLandmark);
Point2 z2 = camera2.project(kLandmark); Point2 z2 = camera2.project(kLandmark);
CameraSet<PinholeCamera<Cal3_S2>> cameras; CameraSet<PinholeCamera<Cal3_S2>> cameras{camera1, camera2};
Point2Vector measurements; Point2Vector measurements{z1, z2};
cameras += camera1, camera2;
measurements += z1, z2;
double landmarkDistanceThreshold = 10; // landmark is closer than that double landmarkDistanceThreshold = 10; // landmark is closer than that
TriangulationParameters params( TriangulationParameters params(
@ -582,8 +550,8 @@ TEST(triangulation, outliersAndFarLandmarks) {
PinholeCamera<Cal3_S2> camera3(pose3, K3); PinholeCamera<Cal3_S2> camera3(pose3, K3);
Point2 z3 = camera3.project(kLandmark); Point2 z3 = camera3.project(kLandmark);
cameras += camera3; cameras.push_back(camera3);
measurements += z3 + Point2(10, -10); measurements.push_back(z3 + Point2(10, -10));
landmarkDistanceThreshold = 10; // landmark is closer than that landmarkDistanceThreshold = 10; // landmark is closer than that
double outlierThreshold = 100; // loose, the outlier is going to pass double outlierThreshold = 100; // loose, the outlier is going to pass
@ -608,11 +576,8 @@ TEST(triangulation, twoIdenticalPoses) {
// 1. Project two landmarks into two cameras and triangulate // 1. Project two landmarks into two cameras and triangulate
Point2 z1 = camera1.project(kLandmark); Point2 z1 = camera1.project(kLandmark);
vector<Pose3> poses; const vector<Pose3> poses{kPose1, kPose1};
Point2Vector measurements; const Point2Vector measurements{z1, z1};
poses += kPose1, kPose1;
measurements += z1, z1;
CHECK_EXCEPTION(triangulatePoint3<Cal3_S2>(poses, kSharedCal, measurements), CHECK_EXCEPTION(triangulatePoint3<Cal3_S2>(poses, kSharedCal, measurements),
TriangulationUnderconstrainedException); TriangulationUnderconstrainedException);
@ -623,22 +588,19 @@ TEST(triangulation, onePose) {
// we expect this test to fail with a TriangulationUnderconstrainedException // we expect this test to fail with a TriangulationUnderconstrainedException
// because there's only one camera observation // because there's only one camera observation
vector<Pose3> poses; const vector<Pose3> poses{Pose3()};
Point2Vector measurements; const Point2Vector measurements {{0,0}};
poses += Pose3();
measurements += Point2(0, 0);
CHECK_EXCEPTION(triangulatePoint3<Cal3_S2>(poses, kSharedCal, measurements), CHECK_EXCEPTION(triangulatePoint3<Cal3_S2>(poses, kSharedCal, measurements),
TriangulationUnderconstrainedException); TriangulationUnderconstrainedException);
} }
//****************************************************************************** //******************************************************************************
TEST(triangulation, StereotriangulateNonlinear) { TEST(triangulation, StereoTriangulateNonlinear) {
auto stereoK = boost::make_shared<Cal3_S2Stereo>(1733.75, 1733.75, 0, 689.645, auto stereoK = boost::make_shared<Cal3_S2Stereo>(1733.75, 1733.75, 0, 689.645,
508.835, 0.0699612); 508.835, 0.0699612);
// two camera poses m1, m2 // two camera kPoses m1, m2
Matrix4 m1, m2; Matrix4 m1, m2;
m1 << 0.796888717, 0.603404026, -0.0295271487, 46.6673779, 0.592783835, m1 << 0.796888717, 0.603404026, -0.0295271487, 46.6673779, 0.592783835,
-0.77156583, 0.230856632, 66.2186159, 0.116517574, -0.201470143, -0.77156583, 0.230856632, 66.2186159, 0.116517574, -0.201470143,
@ -648,14 +610,12 @@ TEST(triangulation, StereotriangulateNonlinear) {
0.947083213, 0.131587097, 65.843136, -0.0206094928, 0.131334858, 0.947083213, 0.131587097, 65.843136, -0.0206094928, 0.131334858,
-0.991123524, -4.3525033, 0, 0, 0, 1; -0.991123524, -4.3525033, 0, 0, 0, 1;
typedef CameraSet<StereoCamera> Cameras; typedef CameraSet<StereoCamera> StereoCameras;
Cameras cameras; const StereoCameras cameras{{Pose3(m1), stereoK}, {Pose3(m2), stereoK}};
cameras.push_back(StereoCamera(Pose3(m1), stereoK));
cameras.push_back(StereoCamera(Pose3(m2), stereoK));
StereoPoint2Vector measurements; StereoPoint2Vector measurements;
measurements += StereoPoint2(226.936, 175.212, 424.469); measurements.push_back(StereoPoint2(226.936, 175.212, 424.469));
measurements += StereoPoint2(339.571, 285.547, 669.973); measurements.push_back(StereoPoint2(339.571, 285.547, 669.973));
Point3 initial = Point3 initial =
Point3(46.0536958, 66.4621179, -6.56285929); // error: 96.5715555191 Point3(46.0536958, 66.4621179, -6.56285929); // error: 96.5715555191
@ -741,8 +701,6 @@ TEST(triangulation, StereotriangulateNonlinear) {
//****************************************************************************** //******************************************************************************
// Simple test with a well-behaved two camera situation // Simple test with a well-behaved two camera situation
TEST(triangulation, twoPoses_sphericalCamera) { TEST(triangulation, twoPoses_sphericalCamera) {
vector<Pose3> poses;
std::vector<Unit3> measurements;
// Project landmark into two cameras and triangulate // Project landmark into two cameras and triangulate
SphericalCamera cam1(kPose1); SphericalCamera cam1(kPose1);
@ -750,8 +708,7 @@ TEST(triangulation, twoPoses_sphericalCamera) {
Unit3 u1 = cam1.project(kLandmark); Unit3 u1 = cam1.project(kLandmark);
Unit3 u2 = cam2.project(kLandmark); Unit3 u2 = cam2.project(kLandmark);
poses += kPose1, kPose2; std::vector<Unit3> measurements{u1, u2};
measurements += u1, u2;
CameraSet<SphericalCamera> cameras; CameraSet<SphericalCamera> cameras;
cameras.push_back(cam1); cameras.push_back(cam1);
@ -803,9 +760,6 @@ TEST(triangulation, twoPoses_sphericalCamera) {
//****************************************************************************** //******************************************************************************
TEST(triangulation, twoPoses_sphericalCamera_extremeFOV) { TEST(triangulation, twoPoses_sphericalCamera_extremeFOV) {
vector<Pose3> poses;
std::vector<Unit3> measurements;
// Project landmark into two cameras and triangulate // Project landmark into two cameras and triangulate
Pose3 poseA = Pose3( Pose3 poseA = Pose3(
Rot3::Ypr(-M_PI / 2, 0., -M_PI / 2), Rot3::Ypr(-M_PI / 2, 0., -M_PI / 2),
@ -825,8 +779,7 @@ TEST(triangulation, twoPoses_sphericalCamera_extremeFOV) {
EXPECT(assert_equal(Unit3(Point3(1.0, 0.0, -1.0)), u2, EXPECT(assert_equal(Unit3(Point3(1.0, 0.0, -1.0)), u2,
1e-7)); // behind and to the right of PoseB 1e-7)); // behind and to the right of PoseB
poses += kPose1, kPose2; const std::vector<Unit3> measurements{u1, u2};
measurements += u1, u2;
CameraSet<SphericalCamera> cameras; CameraSet<SphericalCamera> cameras;
cameras.push_back(cam1); cameras.push_back(cam1);

View File

@ -31,12 +31,9 @@
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/vector.hpp>
#include <cmath> #include <cmath>
#include <random> #include <random>
using namespace boost::assign;
using namespace std::placeholders; using namespace std::placeholders;
using namespace gtsam; using namespace gtsam;
using namespace std; using namespace std;
@ -51,9 +48,8 @@ Point3 point3_(const Unit3& p) {
} }
TEST(Unit3, point3) { TEST(Unit3, point3) {
vector<Point3> ps; const vector<Point3> ps{Point3(1, 0, 0), Point3(0, 1, 0), Point3(0, 0, 1),
ps += Point3(1, 0, 0), Point3(0, 1, 0), Point3(0, 0, 1), Point3(1, 1, 0) Point3(1, 1, 0) / sqrt(2.0)};
/ sqrt(2.0);
Matrix actualH, expectedH; Matrix actualH, expectedH;
for(Point3 p: ps) { for(Point3 p: ps) {
Unit3 s(p); Unit3 s(p);

View File

@ -36,12 +36,12 @@ const DiscreteKey mode{M(0), 2};
* num_measurements is the number of measurements of the continuous variable x0. * num_measurements is the number of measurements of the continuous variable x0.
* If manyModes is true, then we introduce one mode per measurement. * If manyModes is true, then we introduce one mode per measurement.
*/ */
inline HybridBayesNet createHybridBayesNet(int num_measurements = 1, inline HybridBayesNet createHybridBayesNet(size_t num_measurements = 1,
bool manyModes = false) { bool manyModes = false) {
HybridBayesNet bayesNet; HybridBayesNet bayesNet;
// Create Gaussian mixture z_i = x0 + noise for each measurement. // Create Gaussian mixture z_i = x0 + noise for each measurement.
for (int i = 0; i < num_measurements; i++) { for (size_t i = 0; i < num_measurements; i++) {
const auto mode_i = manyModes ? DiscreteKey{M(i), 2} : mode; const auto mode_i = manyModes ? DiscreteKey{M(i), 2} : mode;
bayesNet.emplace_back( bayesNet.emplace_back(
new GaussianMixture({Z(i)}, {X(0)}, {mode_i}, new GaussianMixture({Z(i)}, {X(0)}, {mode_i},
@ -57,7 +57,7 @@ inline HybridBayesNet createHybridBayesNet(int num_measurements = 1,
// Add prior on mode. // Add prior on mode.
const size_t nrModes = manyModes ? num_measurements : 1; const size_t nrModes = manyModes ? num_measurements : 1;
for (int i = 0; i < nrModes; i++) { for (size_t i = 0; i < nrModes; i++) {
bayesNet.emplace_back(new DiscreteConditional({M(i), 2}, "4/6")); bayesNet.emplace_back(new DiscreteConditional({M(i), 2}, "4/6"));
} }
return bayesNet; return bayesNet;
@ -70,7 +70,7 @@ inline HybridBayesNet createHybridBayesNet(int num_measurements = 1,
* the generative Bayes net model HybridBayesNet::Example(num_measurements) * the generative Bayes net model HybridBayesNet::Example(num_measurements)
*/ */
inline HybridGaussianFactorGraph createHybridGaussianFactorGraph( inline HybridGaussianFactorGraph createHybridGaussianFactorGraph(
int num_measurements = 1, size_t num_measurements = 1,
boost::optional<VectorValues> measurements = boost::none, boost::optional<VectorValues> measurements = boost::none,
bool manyModes = false) { bool manyModes = false) {
auto bayesNet = createHybridBayesNet(num_measurements, manyModes); auto bayesNet = createHybridBayesNet(num_measurements, manyModes);

View File

@ -39,7 +39,7 @@ class BayesNet : public FactorGraph<CONDITIONAL> {
sharedConditional; ///< A shared pointer to a conditional sharedConditional; ///< A shared pointer to a conditional
protected: protected:
/// @name Standard Constructors /// @name Protected Constructors
/// @{ /// @{
/** Default constructor as an empty BayesNet */ /** Default constructor as an empty BayesNet */
@ -50,6 +50,12 @@ class BayesNet : public FactorGraph<CONDITIONAL> {
BayesNet(ITERATOR firstConditional, ITERATOR lastConditional) BayesNet(ITERATOR firstConditional, ITERATOR lastConditional)
: Base(firstConditional, lastConditional) {} : Base(firstConditional, lastConditional) {}
/**
* Constructor that takes an initializer list of shared pointers.
* BayesNet<SymbolicConditional> bn = {make_shared<SymbolicConditional>(), ...};
*/
BayesNet(std::initializer_list<sharedConditional> conditionals): Base(conditionals) {}
/// @} /// @}
public: public:

View File

@ -26,11 +26,8 @@
#include <gtsam/base/timing.h> #include <gtsam/base/timing.h>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/assign/list_of.hpp>
#include <fstream> #include <fstream>
using boost::assign::cref_list_of;
namespace gtsam { namespace gtsam {
/* ************************************************************************* */ /* ************************************************************************* */
@ -281,8 +278,8 @@ namespace gtsam {
FactorGraphType cliqueMarginal = clique->marginal2(function); FactorGraphType cliqueMarginal = clique->marginal2(function);
// Now, marginalize out everything that is not variable j // Now, marginalize out everything that is not variable j
BayesNetType marginalBN = *cliqueMarginal.marginalMultifrontalBayesNet( BayesNetType marginalBN =
Ordering(cref_list_of<1,Key>(j)), function); *cliqueMarginal.marginalMultifrontalBayesNet(Ordering{j}, function);
// The Bayes net should contain only one conditional for variable j, so return it // The Bayes net should contain only one conditional for variable j, so return it
return marginalBN.front(); return marginalBN.front();
@ -403,7 +400,7 @@ namespace gtsam {
} }
// now, marginalize out everything that is not variable j1 or j2 // now, marginalize out everything that is not variable j1 or j2
return p_BC1C2.marginalMultifrontalBayesNet(Ordering(cref_list_of<2,Key>(j1)(j2)), function); return p_BC1C2.marginalMultifrontalBayesNet(Ordering{j1, j2}, function);
} }
/* ************************************************************************* */ /* ************************************************************************* */

View File

@ -17,6 +17,7 @@
#pragma once #pragma once
#include <gtsam/inference/BayesTreeCliqueBase.h> #include <gtsam/inference/BayesTreeCliqueBase.h>
#include <gtsam/inference/FactorGraph-inst.h>
#include <gtsam/base/timing.h> #include <gtsam/base/timing.h>
namespace gtsam { namespace gtsam {

View File

@ -154,10 +154,22 @@ class FactorGraph {
/// @} /// @}
public: public:
/// @name Constructors
/// @{
/// Default destructor /// Default destructor
// Public and virtual so boost serialization can call it. /// Public and virtual so boost serialization can call it.
virtual ~FactorGraph() = default; virtual ~FactorGraph() = default;
/**
* Constructor that takes an initializer list of shared pointers.
* FactorGraph fg = {make_shared<MyFactor>(), ...};
*/
template <class DERIVEDFACTOR, typename = IsDerived<DERIVEDFACTOR>>
FactorGraph(std::initializer_list<boost::shared_ptr<DERIVEDFACTOR>> sharedFactors)
: factors_(sharedFactors) {}
/// @}
/// @name Adding Single Factors /// @name Adding Single Factors
/// @{ /// @{

View File

@ -50,18 +50,14 @@ public:
Ordering() { Ordering() {
} }
using KeyVector::KeyVector; // Inherit the KeyVector's constructors
/// Create from a container /// Create from a container
template<typename KEYS> template<typename KEYS>
explicit Ordering(const KEYS& keys) : explicit Ordering(const KEYS& keys) :
Base(keys.begin(), keys.end()) { Base(keys.begin(), keys.end()) {
} }
/// Create an ordering using iterators over keys
template<typename ITERATOR>
Ordering(ITERATOR firstKey, ITERATOR lastKey) :
Base(firstKey, lastKey) {
}
/// Add new variables to the ordering as ordering += key1, key2, ... Equivalent to calling /// Add new variables to the ordering as ordering += key1, key2, ... Equivalent to calling
/// push_back. /// push_back.
boost::assign::list_inserter<boost::assign_detail::call_push_back<This> > operator+=( boost::assign::list_inserter<boost::assign_detail::call_push_back<This> > operator+=(
@ -195,7 +191,7 @@ public:
KeySet src = fg.keys(); KeySet src = fg.keys();
KeyVector keys(src.begin(), src.end()); KeyVector keys(src.begin(), src.end());
std::stable_sort(keys.begin(), keys.end()); std::stable_sort(keys.begin(), keys.end());
return Ordering(keys); return Ordering(keys.begin(), keys.end());
} }
/// METIS Formatting function /// METIS Formatting function

View File

@ -21,11 +21,8 @@
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/list.hpp> // for operator +=
#include <sstream> #include <sstream>
using namespace boost::assign;
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;

View File

@ -19,9 +19,7 @@
#include <gtsam/base/TestableAssertions.h> #include <gtsam/base/TestableAssertions.h>
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/list.hpp> // for operator +=
using namespace boost::assign;
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;

View File

@ -22,11 +22,8 @@
#include <gtsam/base/TestableAssertions.h> #include <gtsam/base/TestableAssertions.h>
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/std.hpp>
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;
using namespace boost::assign;
namespace example { namespace example {
SymbolicFactorGraph symbolicChain() { SymbolicFactorGraph symbolicChain() {
@ -47,33 +44,33 @@ TEST(Ordering, constrained_ordering) {
// unconstrained version // unconstrained version
{ {
Ordering actual = Ordering::Colamd(symbolicGraph); Ordering actual = Ordering::Colamd(symbolicGraph);
Ordering expected = Ordering(list_of(0)(1)(2)(3)(4)(5)); Ordering expected{0, 1, 2, 3, 4, 5};
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
} }
// constrained version - push one set to the end // constrained version - push one set to the end
{ {
Ordering actual = Ordering::ColamdConstrainedLast(symbolicGraph, list_of(2)(4)); Ordering actual = Ordering::ColamdConstrainedLast(symbolicGraph, {2, 4});
Ordering expected = Ordering(list_of(0)(1)(5)(3)(4)(2)); Ordering expected = Ordering({0, 1, 5, 3, 4, 2});
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
} }
// constrained version - push one set to the start // constrained version - push one set to the start
{ {
Ordering actual = Ordering::ColamdConstrainedFirst(symbolicGraph, list_of(2)(4)); Ordering actual = Ordering::ColamdConstrainedFirst(symbolicGraph, {2, 4});
Ordering expected = Ordering(list_of(2)(4)(0)(1)(3)(5)); Ordering expected = Ordering({2, 4, 0, 1, 3, 5});
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
} }
// Make sure giving empty constraints does not break the code // Make sure giving empty constraints does not break the code
{ {
Ordering actual = Ordering::ColamdConstrainedLast(symbolicGraph, {}); Ordering actual = Ordering::ColamdConstrainedLast(symbolicGraph, {});
Ordering expected = Ordering(list_of(0)(1)(2)(3)(4)(5)); Ordering expected = Ordering({0, 1, 2, 3, 4, 5});
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
} }
{ {
Ordering actual = Ordering::ColamdConstrainedFirst(symbolicGraph, {}); Ordering actual = Ordering::ColamdConstrainedFirst(symbolicGraph, {});
Ordering expected = Ordering(list_of(0)(1)(2)(3)(4)(5)); Ordering expected = Ordering({0, 1, 2, 3, 4, 5});
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
} }
@ -81,11 +78,11 @@ TEST(Ordering, constrained_ordering) {
SymbolicFactorGraph emptyGraph; SymbolicFactorGraph emptyGraph;
Ordering empty; Ordering empty;
{ {
Ordering actual = Ordering::ColamdConstrainedLast(emptyGraph, list_of(2)(4)); Ordering actual = Ordering::ColamdConstrainedLast(emptyGraph, {2, 4});
EXPECT(assert_equal(empty, actual)); EXPECT(assert_equal(empty, actual));
} }
{ {
Ordering actual = Ordering::ColamdConstrainedFirst(emptyGraph, list_of(2)(4)); Ordering actual = Ordering::ColamdConstrainedFirst(emptyGraph, {2, 4});
EXPECT(assert_equal(empty, actual)); EXPECT(assert_equal(empty, actual));
} }
} }
@ -105,7 +102,7 @@ TEST(Ordering, grouped_constrained_ordering) {
constraints[5] = 2; constraints[5] = 2;
Ordering actual = Ordering::ColamdConstrained(symbolicGraph, constraints); Ordering actual = Ordering::ColamdConstrained(symbolicGraph, constraints);
Ordering expected = list_of(0)(1)(3)(2)(4)(5); Ordering expected{0, 1, 3, 2, 4, 5};
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
} }
@ -139,9 +136,11 @@ TEST(Ordering, csr_format) {
MetisIndex mi(symbolicGraph); MetisIndex mi(symbolicGraph);
vector<int> xadjExpected, adjExpected; const vector<int> xadjExpected{0, 2, 5, 8, 11, 13, 16, 20,
xadjExpected += 0, 2, 5, 8, 11, 13, 16, 20, 24, 28, 31, 33, 36, 39, 42, 44; 24, 28, 31, 33, 36, 39, 42, 44},
adjExpected += 1, 5, 0, 2, 6, 1, 3, 7, 2, 4, 8, 3, 9, 0, 6, 10, 1, 5, 7, 11, 2, 6, 8, 12, 3, 7, 9, 13, 4, 8, 14, 5, 11, 6, 10, 12, 7, 11, 13, 8, 12, 14, 9, 13; adjExpected{1, 5, 0, 2, 6, 1, 3, 7, 2, 4, 8, 3, 9, 0, 6,
10, 1, 5, 7, 11, 2, 6, 8, 12, 3, 7, 9, 13, 4, 8,
14, 5, 11, 6, 10, 12, 7, 11, 13, 8, 12, 14, 9, 13};
EXPECT(xadjExpected == mi.xadj()); EXPECT(xadjExpected == mi.xadj());
EXPECT(adjExpected.size() == mi.adj().size()); EXPECT(adjExpected.size() == mi.adj().size());
@ -161,9 +160,8 @@ TEST(Ordering, csr_format_2) {
MetisIndex mi(symbolicGraph); MetisIndex mi(symbolicGraph);
vector<int> xadjExpected, adjExpected; const std::vector<int> xadjExpected{0, 1, 4, 6, 8, 10},
xadjExpected += 0, 1, 4, 6, 8, 10; adjExpected{1, 0, 2, 4, 1, 3, 2, 4, 1, 3};
adjExpected += 1, 0, 2, 4, 1, 3, 2, 4, 1, 3;
EXPECT(xadjExpected == mi.xadj()); EXPECT(xadjExpected == mi.xadj());
EXPECT(adjExpected.size() == mi.adj().size()); EXPECT(adjExpected.size() == mi.adj().size());
@ -183,9 +181,8 @@ TEST(Ordering, csr_format_3) {
MetisIndex mi(symbolicGraph); MetisIndex mi(symbolicGraph);
vector<int> xadjExpected, adjExpected; const std::vector<int> xadjExpected{0, 1, 4, 6, 8, 10},
xadjExpected += 0, 1, 4, 6, 8, 10; adjExpected{1, 0, 2, 4, 1, 3, 2, 4, 1, 3};
adjExpected += 1, 0, 2, 4, 1, 3, 2, 4, 1, 3;
//size_t minKey = mi.minKey(); //size_t minKey = mi.minKey();
vector<int> adjAcutal = mi.adj(); vector<int> adjAcutal = mi.adj();
@ -202,24 +199,18 @@ TEST(Ordering, csr_format_3) {
/* ************************************************************************* */ /* ************************************************************************* */
TEST(Ordering, AppendVector) { TEST(Ordering, AppendVector) {
using symbol_shorthand::X; using symbol_shorthand::X;
KeyVector keys{X(0), X(1), X(2)};
Ordering actual; Ordering actual;
KeyVector keys = {X(0), X(1), X(2)};
actual += keys; actual += keys;
Ordering expected; Ordering expected{X(0), X(1), X(2)};
expected += X(0);
expected += X(1);
expected += X(2);
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST(Ordering, Contains) { TEST(Ordering, Contains) {
using symbol_shorthand::X; using symbol_shorthand::X;
Ordering ordering; Ordering ordering{X(0), X(1), X(2)};
ordering += X(0);
ordering += X(1);
ordering += X(2);
EXPECT(ordering.contains(X(1))); EXPECT(ordering.contains(X(1)));
EXPECT(!ordering.contains(X(4))); EXPECT(!ordering.contains(X(4)));
@ -239,9 +230,8 @@ TEST(Ordering, csr_format_4) {
MetisIndex mi(symbolicGraph); MetisIndex mi(symbolicGraph);
vector<int> xadjExpected, adjExpected; const vector<int> xadjExpected{0, 1, 3, 5, 7, 9, 10},
xadjExpected += 0, 1, 3, 5, 7, 9, 10; adjExpected{1, 0, 2, 1, 3, 2, 4, 3, 5, 4};
adjExpected += 1, 0, 2, 1, 3, 2, 4, 3, 5, 4;
vector<int> adjAcutal = mi.adj(); vector<int> adjAcutal = mi.adj();
vector<int> xadjActual = mi.xadj(); vector<int> xadjActual = mi.xadj();
@ -274,9 +264,7 @@ TEST(Ordering, metis) {
MetisIndex mi(symbolicGraph); MetisIndex mi(symbolicGraph);
vector<int> xadjExpected, adjExpected; const vector<int> xadjExpected{0, 1, 3, 4}, adjExpected{1, 0, 2, 1};
xadjExpected += 0, 1, 3, 4;
adjExpected += 1, 0, 2, 1;
EXPECT(xadjExpected == mi.xadj()); EXPECT(xadjExpected == mi.xadj());
EXPECT(adjExpected.size() == mi.adj().size()); EXPECT(adjExpected.size() == mi.adj().size());
@ -303,7 +291,7 @@ TEST(Ordering, MetisLoop) {
// | - P( 4 | 0 3) // | - P( 4 | 0 3)
// | | - P( 5 | 0 4) // | | - P( 5 | 0 4)
// | - P( 2 | 1 3) // | - P( 2 | 1 3)
Ordering expected = Ordering(list_of(5)(4)(2)(1)(0)(3)); Ordering expected = Ordering({5, 4, 2, 1, 0, 3});
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
} }
#elif defined(_WIN32) #elif defined(_WIN32)
@ -313,7 +301,7 @@ TEST(Ordering, MetisLoop) {
// | - P( 3 | 5 2) // | - P( 3 | 5 2)
// | | - P( 4 | 5 3) // | | - P( 4 | 5 3)
// | - P( 1 | 0 2) // | - P( 1 | 0 2)
Ordering expected = Ordering(list_of(4)(3)(1)(0)(5)(2)); Ordering expected = Ordering({4, 3, 1, 0, 5, 2});
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
} }
#else #else
@ -323,7 +311,7 @@ TEST(Ordering, MetisLoop) {
// | - P( 2 | 4 1) // | - P( 2 | 4 1)
// | | - P( 3 | 4 2) // | | - P( 3 | 4 2)
// | - P( 5 | 0 1) // | - P( 5 | 0 1)
Ordering expected = Ordering(list_of(3)(2)(5)(0)(4)(1)); Ordering expected = Ordering({3, 2, 5, 0, 4, 1});
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
} }
#endif #endif
@ -347,7 +335,7 @@ TEST(Ordering, MetisSingleNode) {
symbolicGraph.push_factor(7); symbolicGraph.push_factor(7);
Ordering actual = Ordering::Create(Ordering::METIS, symbolicGraph); Ordering actual = Ordering::Create(Ordering::METIS, symbolicGraph);
Ordering expected = Ordering(list_of(7)); Ordering expected = Ordering({7});
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
} }
#endif #endif
@ -365,7 +353,7 @@ TEST(Ordering, Create) {
//| | | - P( 1 | 2) //| | | - P( 1 | 2)
//| | | | - P( 0 | 1) //| | | | - P( 0 | 1)
Ordering actual = Ordering::Create(Ordering::COLAMD, symbolicGraph); Ordering actual = Ordering::Create(Ordering::COLAMD, symbolicGraph);
Ordering expected = Ordering(list_of(0)(1)(2)(3)(4)(5)); Ordering expected = Ordering({0, 1, 2, 3, 4, 5});
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
} }
@ -376,7 +364,7 @@ TEST(Ordering, Create) {
//- P( 1 0 2) //- P( 1 0 2)
//| - P( 3 4 | 2) //| - P( 3 4 | 2)
//| | - P( 5 | 4) //| | - P( 5 | 4)
Ordering expected = Ordering(list_of(5)(3)(4)(1)(0)(2)); Ordering expected = Ordering({5, 3, 4, 1, 0, 2});
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
} }
#endif #endif

View File

@ -22,11 +22,8 @@
#include <gtsam/inference/VariableSlots.h> #include <gtsam/inference/VariableSlots.h>
#include <gtsam/symbolic/SymbolicFactorGraph.h> #include <gtsam/symbolic/SymbolicFactorGraph.h>
#include <boost/assign/std/vector.hpp>
using namespace gtsam; using namespace gtsam;
using namespace std; using namespace std;
using namespace boost::assign;
/* ************************************************************************* */ /* ************************************************************************* */
TEST(VariableSlots, constructor) { TEST(VariableSlots, constructor) {
@ -41,12 +38,12 @@ TEST(VariableSlots, constructor) {
static const size_t none = numeric_limits<size_t>::max(); static const size_t none = numeric_limits<size_t>::max();
VariableSlots expected((SymbolicFactorGraph())); VariableSlots expected((SymbolicFactorGraph()));
expected[0] += none, 0, 0, none; expected[0] = {none, 0, 0, none};
expected[1] += none, 1, none, none; expected[1] = {none, 1, none, none};
expected[2] += 0, none, 1, none; expected[2] = {0, none, 1, none};
expected[3] += 1, none, none, none; expected[3] = {1, none, none, none};
expected[5] += none, none, none, 0; expected[5] = {none, none, none, 0};
expected[9] += none, none, none, 1; expected[9] = {none, none, none, 1};
CHECK(assert_equal(expected, actual)); CHECK(assert_equal(expected, actual));
} }

View File

@ -26,19 +26,18 @@ using namespace std;
namespace gtsam { namespace gtsam {
/* ************************************************************************* */ /* ************************************************************************* */
Errors::Errors(){} Errors createErrors(const VectorValues& V) {
Errors result;
/* ************************************************************************* */ for (const Vector& e : V | boost::adaptors::map_values) {
Errors::Errors(const VectorValues& V) { result.push_back(e);
for(const Vector& e: V | boost::adaptors::map_values) {
push_back(e);
} }
return result;
} }
/* ************************************************************************* */ /* ************************************************************************* */
void Errors::print(const std::string& s) const { void print(const Errors& e, const string& s) {
cout << s << endl; cout << s << endl;
for(const Vector& v: *this) for(const Vector& v: e)
gtsam::print(v); gtsam::print(v);
} }
@ -51,50 +50,49 @@ struct equalsVector : public std::function<bool(const Vector&, const Vector&)> {
} }
}; };
bool Errors::equals(const Errors& expected, double tol) const { bool equality(const Errors& actual, const Errors& expected, double tol) {
if( size() != expected.size() ) return false; if (actual.size() != expected.size()) return false;
return equal(begin(),end(),expected.begin(),equalsVector(tol)); return equal(actual.begin(), actual.end(), expected.begin(),
equalsVector(tol));
} }
/* ************************************************************************* */ /* ************************************************************************* */
Errors Errors::operator+(const Errors& b) const { Errors operator+(const Errors& a, const Errors& b) {
#ifndef NDEBUG #ifndef NDEBUG
size_t m = size(); size_t m = a.size();
if (b.size()!=m) if (b.size()!=m)
throw(std::invalid_argument("Errors::operator+: incompatible sizes")); throw(std::invalid_argument("Errors::operator+: incompatible sizes"));
#endif #endif
Errors result; Errors result;
Errors::const_iterator it = b.begin(); Errors::const_iterator it = b.begin();
for(const Vector& ai: *this) for(const Vector& ai: a)
result.push_back(ai + *(it++)); result.push_back(ai + *(it++));
return result; return result;
} }
/* ************************************************************************* */ /* ************************************************************************* */
Errors Errors::operator-(const Errors& b) const { Errors operator-(const Errors& a, const Errors& b) {
#ifndef NDEBUG #ifndef NDEBUG
size_t m = size(); size_t m = a.size();
if (b.size()!=m) if (b.size()!=m)
throw(std::invalid_argument("Errors::operator-: incompatible sizes")); throw(std::invalid_argument("Errors::operator-: incompatible sizes"));
#endif #endif
Errors result; Errors result;
Errors::const_iterator it = b.begin(); Errors::const_iterator it = b.begin();
for(const Vector& ai: *this) for(const Vector& ai: a)
result.push_back(ai - *(it++)); result.push_back(ai - *(it++));
return result; return result;
} }
/* ************************************************************************* */ /* ************************************************************************* */
Errors Errors::operator-() const { Errors operator-(const Errors& a) {
Errors result; Errors result;
for(const Vector& ai: *this) for(const Vector& ai: a)
result.push_back(-ai); result.push_back(-ai);
return result; return result;
} }
/* ************************************************************************* */ /* ************************************************************************* */
double dot(const Errors& a, const Errors& b) { double dot(const Errors& a, const Errors& b) {
#ifndef NDEBUG #ifndef NDEBUG
@ -105,7 +103,7 @@ double dot(const Errors& a, const Errors& b) {
double result = 0.0; double result = 0.0;
Errors::const_iterator it = b.begin(); Errors::const_iterator it = b.begin();
for(const Vector& ai: a) for(const Vector& ai: a)
result += gtsam::dot(ai, *(it++)); result += gtsam::dot<Vector,Vector>(ai, *(it++));
return result; return result;
} }
@ -116,11 +114,6 @@ void axpy(double alpha, const Errors& x, Errors& y) {
yi += alpha * (*(it++)); yi += alpha * (*(it++));
} }
/* ************************************************************************* */
void print(const Errors& a, const string& s) {
a.print(s);
}
/* ************************************************************************* */ /* ************************************************************************* */
} // gtsam } // gtsam

View File

@ -20,59 +20,54 @@
#pragma once #pragma once
#include <gtsam/base/FastList.h> #include <gtsam/base/FastList.h>
#include <gtsam/base/Vector.h>
#include <gtsam/base/Testable.h> #include <gtsam/base/Testable.h>
#include <gtsam/base/Vector.h>
#include <string> #include <string>
namespace gtsam { namespace gtsam {
// Forward declarations // Forward declarations
class VectorValues; class VectorValues;
/** vector of errors */ /// Errors is a vector of errors.
class Errors : public FastList<Vector> { using Errors = FastList<Vector>;
public: /// Break V into pieces according to its start indices.
GTSAM_EXPORT Errors createErrors(const VectorValues& V);
GTSAM_EXPORT Errors() ; /// Print an Errors instance.
GTSAM_EXPORT void print(const Errors& e, const std::string& s = "Errors");
/** break V into pieces according to its start indices */ // Check equality for unit testing.
GTSAM_EXPORT Errors(const VectorValues&V); GTSAM_EXPORT bool equality(const Errors& actual, const Errors& expected,
double tol = 1e-9);
/** print */ /// Addition.
GTSAM_EXPORT void print(const std::string& s = "Errors") const; GTSAM_EXPORT Errors operator+(const Errors& a, const Errors& b);
/** equals, for unit testing */ /// Subtraction.
GTSAM_EXPORT bool equals(const Errors& expected, double tol=1e-9) const; GTSAM_EXPORT Errors operator-(const Errors& a, const Errors& b);
/** Addition */ /// Negation.
GTSAM_EXPORT Errors operator+(const Errors& b) const; GTSAM_EXPORT Errors operator-(const Errors& a);
/** subtraction */ /// Dot product.
GTSAM_EXPORT Errors operator-(const Errors& b) const; GTSAM_EXPORT double dot(const Errors& a, const Errors& b);
/** negation */ /// BLAS level 2 style AXPY, `y := alpha*x + y`
GTSAM_EXPORT Errors operator-() const ; GTSAM_EXPORT void axpy(double alpha, const Errors& x, Errors& y);
}; // Errors /// traits
template <>
struct traits<Errors> {
static void Print(const Errors& e, const std::string& str = "") {
print(e, str);
}
static bool Equals(const Errors& actual, const Errors& expected,
double tol = 1e-8) {
return equality(actual, expected, tol);
}
};
/** } // namespace gtsam
* dot product
*/
GTSAM_EXPORT double dot(const Errors& a, const Errors& b);
/**
* BLAS level 2 style
*/
GTSAM_EXPORT void axpy(double alpha, const Errors& x, Errors& y);
/** print with optional string */
GTSAM_EXPORT void print(const Errors& a, const std::string& s = "Error");
/// traits
template<>
struct traits<Errors> : public Testable<Errors> {
};
} //\ namespace gtsam

View File

@ -65,8 +65,17 @@ namespace gtsam {
explicit GaussianBayesNet(const FactorGraph<DERIVEDCONDITIONAL>& graph) explicit GaussianBayesNet(const FactorGraph<DERIVEDCONDITIONAL>& graph)
: Base(graph) {} : Base(graph) {}
/**
* Constructor that takes an initializer list of shared pointers.
* BayesNet bn = {make_shared<Conditional>(), ...};
*/
template <class DERIVEDCONDITIONAL>
GaussianBayesNet(
std::initializer_list<boost::shared_ptr<DERIVEDCONDITIONAL> > conditionals)
: Base(conditionals) {}
/// Destructor /// Destructor
virtual ~GaussianBayesNet() {} virtual ~GaussianBayesNet() = default;
/// @} /// @}

View File

@ -80,9 +80,20 @@ namespace gtsam {
typedef EliminateableFactorGraph<This> BaseEliminateable; ///< Typedef to base elimination class typedef EliminateableFactorGraph<This> BaseEliminateable; ///< Typedef to base elimination class
typedef boost::shared_ptr<This> shared_ptr; ///< shared_ptr to this class typedef boost::shared_ptr<This> shared_ptr; ///< shared_ptr to this class
/// @name Constructors
/// @{
/** Default constructor */ /** Default constructor */
GaussianFactorGraph() {} GaussianFactorGraph() {}
/**
* Construct from an initializer lists of GaussianFactor shared pointers.
* Example:
* GaussianFactorGraph graph = { factor1, factor2, factor3 };
*/
GaussianFactorGraph(std::initializer_list<sharedFactor> factors) : Base(factors) {}
/** Construct from iterator over factors */ /** Construct from iterator over factors */
template<typename ITERATOR> template<typename ITERATOR>
GaussianFactorGraph(ITERATOR firstFactor, ITERATOR lastFactor) : Base(firstFactor, lastFactor) {} GaussianFactorGraph(ITERATOR firstFactor, ITERATOR lastFactor) : Base(firstFactor, lastFactor) {}
@ -98,6 +109,7 @@ namespace gtsam {
/** Virtual destructor */ /** Virtual destructor */
virtual ~GaussianFactorGraph() {} virtual ~GaussianFactorGraph() {}
/// @}
/// @name Testable /// @name Testable
/// @{ /// @{

View File

@ -32,7 +32,6 @@
#include <boost/format.hpp> #include <boost/format.hpp>
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/range/adaptor/transformed.hpp> #include <boost/range/adaptor/transformed.hpp>
#include <boost/range/adaptor/map.hpp> #include <boost/range/adaptor/map.hpp>
#include <boost/range/algorithm/copy.hpp> #include <boost/range/algorithm/copy.hpp>
@ -41,7 +40,6 @@
#include <limits> #include <limits>
using namespace std; using namespace std;
using namespace boost::assign;
namespace br { namespace br {
using namespace boost::range; using namespace boost::range;
using namespace boost::adaptors; using namespace boost::adaptors;
@ -49,6 +47,9 @@ using namespace boost::adaptors;
namespace gtsam { namespace gtsam {
// Typedefs used in constructors below.
using Dims = std::vector<Eigen::Index>;
/* ************************************************************************* */ /* ************************************************************************* */
void HessianFactor::Allocate(const Scatter& scatter) { void HessianFactor::Allocate(const Scatter& scatter) {
gttic(HessianFactor_Allocate); gttic(HessianFactor_Allocate);
@ -74,14 +75,14 @@ HessianFactor::HessianFactor(const Scatter& scatter) {
/* ************************************************************************* */ /* ************************************************************************* */
HessianFactor::HessianFactor() : HessianFactor::HessianFactor() :
info_(cref_list_of<1>(1)) { info_(Dims{1}) {
assert(info_.rows() == 1); assert(info_.rows() == 1);
constantTerm() = 0.0; constantTerm() = 0.0;
} }
/* ************************************************************************* */ /* ************************************************************************* */
HessianFactor::HessianFactor(Key j, const Matrix& G, const Vector& g, double f) : HessianFactor::HessianFactor(Key j, const Matrix& G, const Vector& g, double f)
GaussianFactor(cref_list_of<1>(j)), info_(cref_list_of<2>(G.cols())(1)) { : GaussianFactor(KeyVector{j}), info_(Dims{G.cols(), 1}) {
if (G.rows() != G.cols() || G.rows() != g.size()) if (G.rows() != G.cols() || G.rows() != g.size())
throw invalid_argument( throw invalid_argument(
"Attempting to construct HessianFactor with inconsistent matrix and/or vector dimensions"); "Attempting to construct HessianFactor with inconsistent matrix and/or vector dimensions");
@ -93,8 +94,8 @@ HessianFactor::HessianFactor(Key j, const Matrix& G, const Vector& g, double f)
/* ************************************************************************* */ /* ************************************************************************* */
// error is 0.5*(x-mu)'*inv(Sigma)*(x-mu) = 0.5*(x'*G*x - 2*x'*G*mu + mu'*G*mu) // error is 0.5*(x-mu)'*inv(Sigma)*(x-mu) = 0.5*(x'*G*x - 2*x'*G*mu + mu'*G*mu)
// where G = inv(Sigma), g = G*mu, f = mu'*G*mu = mu'*g // where G = inv(Sigma), g = G*mu, f = mu'*G*mu = mu'*g
HessianFactor::HessianFactor(Key j, const Vector& mu, const Matrix& Sigma) : HessianFactor::HessianFactor(Key j, const Vector& mu, const Matrix& Sigma)
GaussianFactor(cref_list_of<1>(j)), info_(cref_list_of<2>(Sigma.cols())(1)) { : GaussianFactor(KeyVector{j}), info_(Dims{Sigma.cols(), 1}) {
if (Sigma.rows() != Sigma.cols() || Sigma.rows() != mu.size()) if (Sigma.rows() != Sigma.cols() || Sigma.rows() != mu.size())
throw invalid_argument( throw invalid_argument(
"Attempting to construct HessianFactor with inconsistent matrix and/or vector dimensions"); "Attempting to construct HessianFactor with inconsistent matrix and/or vector dimensions");
@ -107,8 +108,8 @@ HessianFactor::HessianFactor(Key j, const Vector& mu, const Matrix& Sigma) :
HessianFactor::HessianFactor(Key j1, Key j2, const Matrix& G11, HessianFactor::HessianFactor(Key j1, Key j2, const Matrix& G11,
const Matrix& G12, const Vector& g1, const Matrix& G22, const Vector& g2, const Matrix& G12, const Vector& g1, const Matrix& G22, const Vector& g2,
double f) : double f) :
GaussianFactor(cref_list_of<2>(j1)(j2)), info_( GaussianFactor(KeyVector{j1,j2}), info_(
cref_list_of<3>(G11.cols())(G22.cols())(1)) { Dims{G11.cols(),G22.cols(),1}) {
info_.setDiagonalBlock(0, G11); info_.setDiagonalBlock(0, G11);
info_.setOffDiagonalBlock(0, 1, G12); info_.setOffDiagonalBlock(0, 1, G12);
info_.setDiagonalBlock(1, G22); info_.setDiagonalBlock(1, G22);
@ -121,8 +122,8 @@ HessianFactor::HessianFactor(Key j1, Key j2, Key j3, const Matrix& G11,
const Matrix& G12, const Matrix& G13, const Vector& g1, const Matrix& G22, const Matrix& G12, const Matrix& G13, const Vector& g1, const Matrix& G22,
const Matrix& G23, const Vector& g2, const Matrix& G33, const Vector& g3, const Matrix& G23, const Vector& g2, const Matrix& G33, const Vector& g3,
double f) : double f) :
GaussianFactor(cref_list_of<3>(j1)(j2)(j3)), info_( GaussianFactor(KeyVector{j1,j2,j3}), info_(
cref_list_of<4>(G11.cols())(G22.cols())(G33.cols())(1)) { Dims{G11.cols(),G22.cols(),G33.cols(),1}) {
if (G11.rows() != G11.cols() || G11.rows() != G12.rows() if (G11.rows() != G11.cols() || G11.rows() != G12.rows()
|| G11.rows() != G13.rows() || G11.rows() != g1.size() || G11.rows() != G13.rows() || G11.rows() != g1.size()
|| G22.cols() != G12.cols() || G33.cols() != G13.cols() || G22.cols() != G12.cols() || G33.cols() != G13.cols()

View File

@ -31,7 +31,6 @@
#include <gtsam/base/FastMap.h> #include <gtsam/base/FastMap.h>
#include <gtsam/base/cholesky.h> #include <gtsam/base/cholesky.h>
#include <boost/assign/list_of.hpp>
#include <boost/format.hpp> #include <boost/format.hpp>
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
#include <boost/array.hpp> #include <boost/array.hpp>
@ -44,13 +43,16 @@
#include <stdexcept> #include <stdexcept>
using namespace std; using namespace std;
using namespace boost::assign;
namespace gtsam { namespace gtsam {
// Typedefs used in constructors below.
using Dims = std::vector<Eigen::Index>;
using Pairs = std::vector<std::pair<Eigen::Index, Matrix>>;
/* ************************************************************************* */ /* ************************************************************************* */
JacobianFactor::JacobianFactor() : JacobianFactor::JacobianFactor() :
Ab_(cref_list_of<1>(1), 0) { Ab_(Dims{1}, 0) {
getb().setZero(); getb().setZero();
} }
@ -68,29 +70,27 @@ JacobianFactor::JacobianFactor(const GaussianFactor& gf) {
/* ************************************************************************* */ /* ************************************************************************* */
JacobianFactor::JacobianFactor(const Vector& b_in) : JacobianFactor::JacobianFactor(const Vector& b_in) :
Ab_(cref_list_of<1>(1), b_in.size()) { Ab_(Dims{1}, b_in.size()) {
getb() = b_in; getb() = b_in;
} }
/* ************************************************************************* */ /* ************************************************************************* */
JacobianFactor::JacobianFactor(Key i1, const Matrix& A1, const Vector& b, JacobianFactor::JacobianFactor(Key i1, const Matrix& A1, const Vector& b,
const SharedDiagonal& model) { const SharedDiagonal& model) {
fillTerms(cref_list_of<1>(make_pair(i1, A1)), b, model); fillTerms(Pairs{{i1, A1}}, b, model);
} }
/* ************************************************************************* */ /* ************************************************************************* */
JacobianFactor::JacobianFactor(const Key i1, const Matrix& A1, Key i2, JacobianFactor::JacobianFactor(const Key i1, const Matrix& A1, Key i2,
const Matrix& A2, const Vector& b, const SharedDiagonal& model) { const Matrix& A2, const Vector& b, const SharedDiagonal& model) {
fillTerms(cref_list_of<2>(make_pair(i1, A1))(make_pair(i2, A2)), b, model); fillTerms(Pairs{{i1, A1}, {i2, A2}}, b, model);
} }
/* ************************************************************************* */ /* ************************************************************************* */
JacobianFactor::JacobianFactor(const Key i1, const Matrix& A1, Key i2, JacobianFactor::JacobianFactor(const Key i1, const Matrix& A1, Key i2,
const Matrix& A2, Key i3, const Matrix& A3, const Vector& b, const Matrix& A2, Key i3, const Matrix& A3, const Vector& b,
const SharedDiagonal& model) { const SharedDiagonal& model) {
fillTerms( fillTerms(Pairs{{i1, A1}, {i2, A2}, {i3, A3}}, b, model);
cref_list_of<3>(make_pair(i1, A1))(make_pair(i2, A2))(make_pair(i3, A3)),
b, model);
} }
/* ************************************************************************* */ /* ************************************************************************* */

View File

@ -27,9 +27,7 @@
#include <gtsam/base/Testable.h> #include <gtsam/base/Testable.h>
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
#include <boost/assign/list_of.hpp>
using namespace boost::assign;
using namespace std; using namespace std;
namespace gtsam { namespace gtsam {

View File

@ -110,7 +110,7 @@ VectorValues SubgraphPreconditioner::x(const VectorValues& y) const {
/* ************************************************************************* */ /* ************************************************************************* */
double SubgraphPreconditioner::error(const VectorValues& y) const { double SubgraphPreconditioner::error(const VectorValues& y) const {
Errors e(y); Errors e = createErrors(y);
VectorValues x = this->x(y); VectorValues x = this->x(y);
Errors e2 = Ab2_.gaussianErrors(x); Errors e2 = Ab2_.gaussianErrors(x);
return 0.5 * (dot(e, e) + dot(e2,e2)); return 0.5 * (dot(e, e) + dot(e2,e2));
@ -129,7 +129,7 @@ VectorValues SubgraphPreconditioner::gradient(const VectorValues &y) const {
/* ************************************************************************* */ /* ************************************************************************* */
// Apply operator A, A*y = [I;A2*inv(R1)]*y = [y; A2*inv(R1)*y] // Apply operator A, A*y = [I;A2*inv(R1)]*y = [y; A2*inv(R1)*y]
Errors SubgraphPreconditioner::operator*(const VectorValues &y) const { Errors SubgraphPreconditioner::operator*(const VectorValues &y) const {
Errors e(y); Errors e = createErrors(y);
VectorValues x = Rc1_.backSubstitute(y); /* x=inv(R1)*y */ VectorValues x = Rc1_.backSubstitute(y); /* x=inv(R1)*y */
Errors e2 = Ab2_ * x; /* A2*x */ Errors e2 = Ab2_ * x; /* A2*x */
e.splice(e.end(), e2); e.splice(e.end(), e2);

View File

@ -92,11 +92,8 @@ namespace gtsam {
VectorValues() {} VectorValues() {}
/// Construct from initializer list. /// Construct from initializer list.
VectorValues(std::initializer_list<std::pair<Key, Vector>> init) { VectorValues(std::initializer_list<std::pair<Key, Vector>> init)
for (const auto& p : init) { : values_(init.begin(), init.end()) {}
values_.insert(p); // Insert key-value pair into map
}
}
/** Merge two VectorValues into one, this is more efficient than inserting /** Merge two VectorValues into one, this is more efficient than inserting
* elements one by one. */ * elements one by one. */

View File

@ -625,17 +625,6 @@ virtual class GaussianBayesTree {
gtsam::GaussianBayesNet* jointBayesNet(size_t key1, size_t key2) const; gtsam::GaussianBayesNet* jointBayesNet(size_t key1, size_t key2) const;
}; };
#include <gtsam/linear/Errors.h>
class Errors {
//Constructors
Errors();
Errors(const gtsam::VectorValues& V);
//Testable
void print(string s = "Errors");
bool equals(const gtsam::Errors& expected, double tol) const;
};
#include <gtsam/linear/GaussianISAM.h> #include <gtsam/linear/GaussianISAM.h>
class GaussianISAM { class GaussianISAM {
//Constructor //Constructor

View File

@ -15,9 +15,6 @@
* @author Frank Dellaert * @author Frank Dellaert
*/ */
#include <boost/assign/std/list.hpp> // for +=
using namespace boost::assign;
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <gtsam/base/Testable.h> #include <gtsam/base/Testable.h>
#include <gtsam/linear/Errors.h> #include <gtsam/linear/Errors.h>
@ -26,16 +23,13 @@ using namespace std;
using namespace gtsam; using namespace gtsam;
/* ************************************************************************* */ /* ************************************************************************* */
TEST( Errors, arithmetic ) TEST(Errors, arithmetic) {
{ Errors e = {Vector2(1.0, 2.0), Vector3(3.0, 4.0, 5.0)};
Errors e; DOUBLES_EQUAL(1 + 4 + 9 + 16 + 25, dot(e, e), 1e-9);
e += Vector2(1.0,2.0), Vector3(3.0,4.0,5.0);
DOUBLES_EQUAL(1+4+9+16+25,dot(e,e),1e-9);
axpy(2.0, e, e); axpy(2.0, e, e);
Errors expected; const Errors expected = {Vector2(3.0, 6.0), Vector3(9.0, 12.0, 15.0)};
expected += Vector2(3.0,6.0), Vector3(9.0,12.0,15.0); CHECK(assert_equal(expected, e));
CHECK(assert_equal(expected,e));
} }
/* ************************************************************************* */ /* ************************************************************************* */

View File

@ -25,15 +25,12 @@
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/assign/std/list.hpp> // for operator +=
#include <boost/bind/bind.hpp> #include <boost/bind/bind.hpp>
// STL/C++ // STL/C++
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
using namespace boost::assign;
using namespace std::placeholders; using namespace std::placeholders;
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;
@ -41,15 +38,15 @@ using symbol_shorthand::X;
static const Key _x_ = 11, _y_ = 22, _z_ = 33; static const Key _x_ = 11, _y_ = 22, _z_ = 33;
static GaussianBayesNet smallBayesNet = static GaussianBayesNet smallBayesNet = {
list_of(GaussianConditional(_x_, Vector1::Constant(9), I_1x1, _y_, I_1x1))( boost::make_shared<GaussianConditional>(_x_, Vector1::Constant(9), I_1x1, _y_, I_1x1),
GaussianConditional(_y_, Vector1::Constant(5), I_1x1)); boost::make_shared<GaussianConditional>(_y_, Vector1::Constant(5), I_1x1)};
static GaussianBayesNet noisyBayesNet = static GaussianBayesNet noisyBayesNet = {
list_of(GaussianConditional(_x_, Vector1::Constant(9), I_1x1, _y_, I_1x1, boost::make_shared<GaussianConditional>(_x_, Vector1::Constant(9), I_1x1, _y_, I_1x1,
noiseModel::Isotropic::Sigma(1, 2.0)))( noiseModel::Isotropic::Sigma(1, 2.0)),
GaussianConditional(_y_, Vector1::Constant(5), I_1x1, boost::make_shared<GaussianConditional>(_y_, Vector1::Constant(5), I_1x1,
noiseModel::Isotropic::Sigma(1, 3.0))); noiseModel::Isotropic::Sigma(1, 3.0))};
/* ************************************************************************* */ /* ************************************************************************* */
TEST( GaussianBayesNet, Matrix ) TEST( GaussianBayesNet, Matrix )
@ -115,11 +112,11 @@ TEST( GaussianBayesNet, NoisyMatrix )
/* ************************************************************************* */ /* ************************************************************************* */
TEST(GaussianBayesNet, Optimize) { TEST(GaussianBayesNet, Optimize) {
VectorValues expected = const VectorValues expected{{_x_, Vector1::Constant(4)},
map_list_of<Key, Vector>(_x_, Vector1::Constant(4))(_y_, Vector1::Constant(5)); {_y_, Vector1::Constant(5)}};
VectorValues actual = smallBayesNet.optimize(); const VectorValues actual = smallBayesNet.optimize();
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST(GaussianBayesNet, NoisyOptimize) { TEST(GaussianBayesNet, NoisyOptimize) {
@ -127,7 +124,7 @@ TEST(GaussianBayesNet, NoisyOptimize) {
Vector d; Vector d;
boost::tie(R, d) = noisyBayesNet.matrix(); // find matrix and RHS boost::tie(R, d) = noisyBayesNet.matrix(); // find matrix and RHS
const Vector x = R.inverse() * d; const Vector x = R.inverse() * d;
VectorValues expected = map_list_of<Key, Vector>(_x_, x.head(1))(_y_, x.tail(1)); const VectorValues expected{{_x_, x.head(1)}, {_y_, x.tail(1)}};
VectorValues actual = noisyBayesNet.optimize(); VectorValues actual = noisyBayesNet.optimize();
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
@ -136,17 +133,16 @@ TEST(GaussianBayesNet, NoisyOptimize) {
/* ************************************************************************* */ /* ************************************************************************* */
TEST( GaussianBayesNet, optimizeIncomplete ) TEST( GaussianBayesNet, optimizeIncomplete )
{ {
static GaussianBayesNet incompleteBayesNet = list_of static GaussianBayesNet incompleteBayesNet;
(GaussianConditional(_x_, Vector1::Constant(9), I_1x1, _y_, I_1x1)); incompleteBayesNet.emplace_shared<GaussianConditional>(
_x_, Vector1::Constant(9), I_1x1, _y_, I_1x1);
VectorValues solutionForMissing = map_list_of<Key, Vector> VectorValues solutionForMissing { {_y_, Vector1::Constant(5)} };
(_y_, Vector1::Constant(5));
VectorValues actual = incompleteBayesNet.optimize(solutionForMissing); VectorValues actual = incompleteBayesNet.optimize(solutionForMissing);
VectorValues expected = map_list_of<Key, Vector> VectorValues expected{{_x_, Vector1::Constant(4)},
(_x_, Vector1::Constant(4)) {_y_, Vector1::Constant(5)}};
(_y_, Vector1::Constant(5));
EXPECT(assert_equal(expected,actual)); EXPECT(assert_equal(expected,actual));
} }
@ -159,14 +155,11 @@ TEST( GaussianBayesNet, optimize3 )
// 5 1 5 // 5 1 5
// NOTE: we are supplying a new RHS here // NOTE: we are supplying a new RHS here
VectorValues expected = map_list_of<Key, Vector> VectorValues expected { {_x_, Vector1::Constant(-1)},
(_x_, Vector1::Constant(-1)) {_y_, Vector1::Constant(5)} };
(_y_, Vector1::Constant(5));
// Test different RHS version // Test different RHS version
VectorValues gx = map_list_of<Key, Vector> VectorValues gx{{_x_, Vector1::Constant(4)}, {_y_, Vector1::Constant(5)}};
(_x_, Vector1::Constant(4))
(_y_, Vector1::Constant(5));
VectorValues actual = smallBayesNet.backSubstitute(gx); VectorValues actual = smallBayesNet.backSubstitute(gx);
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
} }
@ -176,9 +169,9 @@ namespace sampling {
static Matrix A1 = (Matrix(2, 2) << 1., 2., 3., 4.).finished(); static Matrix A1 = (Matrix(2, 2) << 1., 2., 3., 4.).finished();
static const Vector2 mean(20, 40), b(10, 10); static const Vector2 mean(20, 40), b(10, 10);
static const double sigma = 0.01; static const double sigma = 0.01;
static const GaussianBayesNet gbn = static const GaussianBayesNet gbn = {
list_of(GaussianConditional::FromMeanAndStddev(X(0), A1, X(1), b, sigma))( GaussianConditional::sharedMeanAndStddev(X(0), A1, X(1), b, sigma),
GaussianDensity::FromMeanAndStddev(X(1), mean, sigma)); GaussianDensity::sharedMeanAndStddev(X(1), mean, sigma)};
} // namespace sampling } // namespace sampling
/* ************************************************************************* */ /* ************************************************************************* */
@ -253,13 +246,9 @@ TEST( GaussianBayesNet, backSubstituteTranspose )
// x=R'*y, expected=inv(R')*x // x=R'*y, expected=inv(R')*x
// 2 = 1 2 // 2 = 1 2
// 5 1 1 3 // 5 1 1 3
VectorValues const VectorValues x{{_x_, Vector1::Constant(2)},
x = map_list_of<Key, Vector> {_y_, Vector1::Constant(5)}},
(_x_, Vector1::Constant(2)) expected{{_x_, Vector1::Constant(2)}, {_y_, Vector1::Constant(3)}};
(_y_, Vector1::Constant(5)),
expected = map_list_of<Key, Vector>
(_x_, Vector1::Constant(2))
(_y_, Vector1::Constant(3));
VectorValues actual = smallBayesNet.backSubstituteTranspose(x); VectorValues actual = smallBayesNet.backSubstituteTranspose(x);
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
@ -276,13 +265,8 @@ TEST( GaussianBayesNet, backSubstituteTransposeNoisy )
// x=R'*y, expected=inv(R')*x // x=R'*y, expected=inv(R')*x
// 2 = 1 2 // 2 = 1 2
// 5 1 1 3 // 5 1 1 3
VectorValues VectorValues x{{_x_, Vector1::Constant(2)}, {_y_, Vector1::Constant(5)}},
x = map_list_of<Key, Vector> expected{{_x_, Vector1::Constant(4)}, {_y_, Vector1::Constant(9)}};
(_x_, Vector1::Constant(2))
(_y_, Vector1::Constant(5)),
expected = map_list_of<Key, Vector>
(_x_, Vector1::Constant(4))
(_y_, Vector1::Constant(9));
VectorValues actual = noisyBayesNet.backSubstituteTranspose(x); VectorValues actual = noisyBayesNet.backSubstituteTranspose(x);
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));

View File

@ -23,43 +23,45 @@
#include <gtsam/linear/GaussianConditional.h> #include <gtsam/linear/GaussianConditional.h>
#include <gtsam/linear/GaussianJunctionTree.h> #include <gtsam/linear/GaussianJunctionTree.h>
#include <boost/assign/list_of.hpp>
#include <boost/assign/std/list.hpp> // for operator +=
#include <boost/assign/std/set.hpp> // for operator +=
#include <iostream> #include <iostream>
#include <vector>
using namespace boost::assign;
using namespace std::placeholders; using namespace std::placeholders;
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;
using Pairs = std::vector<std::pair<Key, Matrix>>;
namespace { namespace {
const Key x1=1, x2=2, x3=3, x4=4; const Key x1=1, x2=2, x3=3, x4=4;
const SharedDiagonal chainNoise = noiseModel::Isotropic::Sigma(1, 0.5); const SharedDiagonal chainNoise = noiseModel::Isotropic::Sigma(1, 0.5);
const GaussianFactorGraph chain = list_of const GaussianFactorGraph chain = {
(JacobianFactor(x2, (Matrix(1, 1) << 1.).finished(), x1, (Matrix(1, 1) << 1.).finished(), (Vector(1) << 1.).finished(), chainNoise)) boost::make_shared<JacobianFactor>(
(JacobianFactor(x2, (Matrix(1, 1) << 1.).finished(), x3, (Matrix(1, 1) << 1.).finished(), (Vector(1) << 1.).finished(), chainNoise)) x2, I_1x1, x1, I_1x1, (Vector(1) << 1.).finished(), chainNoise),
(JacobianFactor(x3, (Matrix(1, 1) << 1.).finished(), x4, (Matrix(1, 1) << 1.).finished(), (Vector(1) << 1.).finished(), chainNoise)) boost::make_shared<JacobianFactor>(
(JacobianFactor(x4, (Matrix(1, 1) << 1.).finished(), (Vector(1) << 1.).finished(), chainNoise)); x2, I_1x1, x3, I_1x1, (Vector(1) << 1.).finished(), chainNoise),
const Ordering chainOrdering = Ordering(list_of(x2)(x1)(x3)(x4)); boost::make_shared<JacobianFactor>(
x3, I_1x1, x4, I_1x1, (Vector(1) << 1.).finished(), chainNoise),
boost::make_shared<JacobianFactor>(
x4, I_1x1, (Vector(1) << 1.).finished(), chainNoise)};
const Ordering chainOrdering {x2, x1, x3, x4};
/* ************************************************************************* */ /* ************************************************************************* */
// Helper functions for below // Helper functions for below
GaussianBayesTreeClique::shared_ptr MakeClique(const GaussianConditional& conditional) GaussianBayesTreeClique::shared_ptr LeafClique(const GaussianConditional& conditional)
{ {
return boost::make_shared<GaussianBayesTreeClique>( return boost::make_shared<GaussianBayesTreeClique>(
boost::make_shared<GaussianConditional>(conditional)); boost::make_shared<GaussianConditional>(conditional));
} }
template<typename CHILDREN> typedef std::vector<GaussianBayesTreeClique::shared_ptr> Children;
GaussianBayesTreeClique::shared_ptr MakeClique( GaussianBayesTreeClique::shared_ptr MakeClique(
const GaussianConditional& conditional, const CHILDREN& children) const GaussianConditional& conditional, const Children& children)
{ {
GaussianBayesTreeClique::shared_ptr clique = auto clique = LeafClique(conditional);
boost::make_shared<GaussianBayesTreeClique>(
boost::make_shared<GaussianConditional>(conditional));
clique->children.assign(children.begin(), children.end()); clique->children.assign(children.begin(), children.end());
for(typename CHILDREN::const_iterator child = children.begin(); child != children.end(); ++child) for(Children::const_iterator child = children.begin(); child != children.end(); ++child)
(*child)->parent_ = clique; (*child)->parent_ = clique;
return clique; return clique;
} }
@ -90,23 +92,25 @@ TEST( GaussianBayesTree, eliminate )
EXPECT_LONGS_EQUAL(3, scatter.at(2).key); EXPECT_LONGS_EQUAL(3, scatter.at(2).key);
EXPECT_LONGS_EQUAL(4, scatter.at(3).key); EXPECT_LONGS_EQUAL(4, scatter.at(3).key);
Matrix two = (Matrix(1, 1) << 2.).finished(); const Matrix two = (Matrix(1, 1) << 2.).finished();
Matrix one = (Matrix(1, 1) << 1.).finished(); const Matrix one = I_1x1;
const GaussianConditional gc1(
std::map<Key, Matrix>{
{x3, (Matrix21() << 2., 0.).finished()},
{x4, (Matrix21() << 2., 2.).finished()},
},
2, Vector2(2., 2.));
const GaussianConditional gc2(
Pairs{
{x2, (Matrix21() << -2. * sqrt(2.), 0.).finished()},
{x1, (Matrix21() << -sqrt(2.), -sqrt(2.)).finished()},
{x3, (Matrix21() << -sqrt(2.), sqrt(2.)).finished()},
},
2, (Vector(2) << -2. * sqrt(2.), 0.).finished());
GaussianBayesTree bayesTree_expected; GaussianBayesTree bayesTree_expected;
bayesTree_expected.insertRoot( bayesTree_expected.insertRoot(MakeClique(gc1, Children{LeafClique(gc2)}));
MakeClique(
GaussianConditional(
pair_list_of<Key, Matrix>(x3, (Matrix21() << 2., 0.).finished())(
x4, (Matrix21() << 2., 2.).finished()), 2, Vector2(2., 2.)),
list_of(
MakeClique(
GaussianConditional(
pair_list_of<Key, Matrix>(x2,
(Matrix21() << -2. * sqrt(2.), 0.).finished())(x1,
(Matrix21() << -sqrt(2.), -sqrt(2.)).finished())(x3,
(Matrix21() << -sqrt(2.), sqrt(2.)).finished()), 2,
(Vector(2) << -2. * sqrt(2.), 0.).finished())))));
EXPECT(assert_equal(bayesTree_expected, bt)); EXPECT(assert_equal(bayesTree_expected, bt));
} }
@ -114,11 +118,10 @@ TEST( GaussianBayesTree, eliminate )
/* ************************************************************************* */ /* ************************************************************************* */
TEST( GaussianBayesTree, optimizeMultiFrontal ) TEST( GaussianBayesTree, optimizeMultiFrontal )
{ {
VectorValues expected = pair_list_of<Key, Vector> VectorValues expected = {{x1, (Vector(1) << 0.).finished()},
(x1, (Vector(1) << 0.).finished()) {x2, (Vector(1) << 1.).finished()},
(x2, (Vector(1) << 1.).finished()) {x3, (Vector(1) << 0.).finished()},
(x3, (Vector(1) << 0.).finished()) {x4, (Vector(1) << 1.).finished()}};
(x4, (Vector(1) << 1.).finished());
VectorValues actual = chain.eliminateMultifrontal(chainOrdering)->optimize(); VectorValues actual = chain.eliminateMultifrontal(chainOrdering)->optimize();
EXPECT(assert_equal(expected,actual)); EXPECT(assert_equal(expected,actual));
@ -126,40 +129,61 @@ TEST( GaussianBayesTree, optimizeMultiFrontal )
/* ************************************************************************* */ /* ************************************************************************* */
TEST(GaussianBayesTree, complicatedMarginal) { TEST(GaussianBayesTree, complicatedMarginal) {
// Create the conditionals to go in the BayesTree // Create the conditionals to go in the BayesTree
const GaussianConditional gc1(
Pairs{{11, (Matrix(3, 1) << 0.0971, 0, 0).finished()},
{12, (Matrix(3, 2) << 0.3171, 0.4387, 0.9502, 0.3816, 0, 0.7655)
.finished()}},
2, Vector3(0.2638, 0.1455, 0.1361));
const GaussianConditional gc2(
Pairs{
{9, (Matrix(3, 1) << 0.7952, 0, 0).finished()},
{10, (Matrix(3, 2) << 0.4456, 0.7547, 0.6463, 0.2760, 0, 0.6797)
.finished()},
{11, (Matrix(3, 1) << 0.6551, 0.1626, 0.1190).finished()},
{12, (Matrix(3, 2) << 0.4984, 0.5853, 0.9597, 0.2238, 0.3404, 0.7513)
.finished()}},
2, Vector3(0.4314, 0.9106, 0.1818));
const GaussianConditional gc3(
Pairs{{7, (Matrix(3, 1) << 0.2551, 0, 0).finished()},
{8, (Matrix(3, 2) << 0.8909, 0.1386, 0.9593, 0.1493, 0, 0.2575)
.finished()},
{11, (Matrix(3, 1) << 0.8407, 0.2543, 0.8143).finished()}},
2, Vector3(0.3998, 0.2599, 0.8001));
const GaussianConditional gc4(
Pairs{{5, (Matrix(3, 1) << 0.2435, 0, 0).finished()},
{6, (Matrix(3, 2) << 0.4733, 0.1966, 0.3517, 0.2511, 0.8308, 0.0)
.finished()},
// NOTE the non-upper-triangular form
// here since this test was written when we had column permutations
// from LDL. The code still works currently (does not enfore
// upper-triangularity in this case) but this test will need to be
// redone if this stops working in the future
{7, (Matrix(3, 1) << 0.5853, 0.5497, 0.9172).finished()},
{8, (Matrix(3, 2) << 0.2858, 0.3804, 0.7572, 0.5678, 0.7537, 0.0759)
.finished()}},
2, Vector3(0.8173, 0.8687, 0.0844));
const GaussianConditional gc5(
Pairs{{3, (Matrix(3, 1) << 0.0540, 0, 0).finished()},
{4, (Matrix(3, 2) << 0.9340, 0.4694, 0.1299, 0.0119, 0, 0.3371)
.finished()},
{6, (Matrix(3, 2) << 0.1622, 0.5285, 0.7943, 0.1656, 0.3112, 0.6020)
.finished()}},
2, Vector3(0.9619, 0.0046, 0.7749));
const GaussianConditional gc6(
Pairs{{1, (Matrix(3, 1) << 0.2630, 0, 0).finished()},
{2, (Matrix(3, 2) << 0.7482, 0.2290, 0.4505, 0.9133, 0, 0.1524)
.finished()},
{5, (Matrix(3, 1) << 0.8258, 0.5383, 0.9961).finished()}},
2, Vector3(0.0782, 0.4427, 0.1067));
// Create the bayes tree:
GaussianBayesTree bt; GaussianBayesTree bt;
bt.insertRoot( bt.insertRoot(MakeClique(
MakeClique(GaussianConditional(pair_list_of<Key, Matrix> (11, (Matrix(3,1) << 0.0971, 0, 0).finished()) gc1, Children{LeafClique(gc2),
(12, (Matrix(3,2) << 0.3171, 0.4387, 0.9502, 0.3816, 0, 0.7655).finished()), MakeClique(gc3, Children{MakeClique(
2, Vector3(0.2638, 0.1455, 0.1361)), list_of gc4, Children{LeafClique(gc5),
(MakeClique(GaussianConditional(pair_list_of<Key, Matrix> (9, (Matrix(3,1) << 0.7952, 0, 0).finished()) LeafClique(gc6)})})}));
(10, (Matrix(3,2) << 0.4456, 0.7547, 0.6463, 0.2760, 0, 0.6797).finished())
(11, (Matrix(3,1) << 0.6551, 0.1626, 0.1190).finished())
(12, (Matrix(3,2) << 0.4984, 0.5853, 0.9597, 0.2238, 0.3404, 0.7513).finished()),
2, Vector3(0.4314, 0.9106, 0.1818))))
(MakeClique(GaussianConditional(pair_list_of<Key, Matrix> (7, (Matrix(3,1) << 0.2551, 0, 0).finished())
(8, (Matrix(3,2) << 0.8909, 0.1386, 0.9593, 0.1493, 0, 0.2575).finished())
(11, (Matrix(3,1) << 0.8407, 0.2543, 0.8143).finished()),
2, Vector3(0.3998, 0.2599, 0.8001)), list_of
(MakeClique(GaussianConditional(pair_list_of<Key, Matrix> (5, (Matrix(3,1) << 0.2435, 0, 0).finished())
(6, (Matrix(3,2) << 0.4733, 0.1966, 0.3517, 0.2511, 0.8308, 0.0).finished())
// NOTE the non-upper-triangular form
// here since this test was written when we had column permutations
// from LDL. The code still works currently (does not enfore
// upper-triangularity in this case) but this test will need to be
// redone if this stops working in the future
(7, (Matrix(3,1) << 0.5853, 0.5497, 0.9172).finished())
(8, (Matrix(3,2) << 0.2858, 0.3804, 0.7572, 0.5678, 0.7537, 0.0759).finished()),
2, Vector3(0.8173, 0.8687, 0.0844)), list_of
(MakeClique(GaussianConditional(pair_list_of<Key, Matrix> (3, (Matrix(3,1) << 0.0540, 0, 0).finished())
(4, (Matrix(3,2) << 0.9340, 0.4694, 0.1299, 0.0119, 0, 0.3371).finished())
(6, (Matrix(3,2) << 0.1622, 0.5285, 0.7943, 0.1656, 0.3112, 0.6020).finished()),
2, Vector3(0.9619, 0.0046, 0.7749))))
(MakeClique(GaussianConditional(pair_list_of<Key, Matrix> (1, (Matrix(3,1) << 0.2630, 0, 0).finished())
(2, (Matrix(3,2) << 0.7482, 0.2290, 0.4505, 0.9133, 0, 0.1524).finished())
(5, (Matrix(3,1) << 0.8258, 0.5383, 0.9961).finished()),
2, Vector3(0.0782, 0.4427, 0.1067))))))))));
// Marginal on 5 // Marginal on 5
Matrix expectedCov = (Matrix(1,1) << 236.5166).finished(); Matrix expectedCov = (Matrix(1,1) << 236.5166).finished();
@ -201,61 +225,33 @@ double computeError(const GaussianBayesTree& gbt, const Vector10& values) {
/* ************************************************************************* */ /* ************************************************************************* */
TEST(GaussianBayesTree, ComputeSteepestDescentPointBT) { TEST(GaussianBayesTree, ComputeSteepestDescentPointBT) {
const GaussianConditional gc1(
Pairs{{2, (Matrix(6, 2) << 31.0, 32.0, 0.0, 34.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0)
.finished()},
{3, (Matrix(6, 2) << 35.0, 36.0, 37.0, 38.0, 41.0, 42.0, 0.0, 44.0,
0.0, 0.0, 0.0, 0.0)
.finished()},
{4, (Matrix(6, 2) << 0.0, 0.0, 0.0, 0.0, 45.0, 46.0, 47.0, 48.0,
51.0, 52.0, 0.0, 54.0)
.finished()}},
3, (Vector(6) << 29.0, 30.0, 39.0, 40.0, 49.0, 50.0).finished()),
gc2(Pairs{{0, (Matrix(4, 2) << 3.0, 4.0, 0.0, 6.0, 0.0, 0.0, 0.0, 0.0)
.finished()},
{1, (Matrix(4, 2) << 0.0, 0.0, 0.0, 0.0, 17.0, 18.0, 0.0, 20.0)
.finished()},
{2, (Matrix(4, 2) << 0.0, 0.0, 0.0, 0.0, 21.0, 22.0, 23.0, 24.0)
.finished()},
{3, (Matrix(4, 2) << 7.0, 8.0, 9.0, 10.0, 0.0, 0.0, 0.0, 0.0)
.finished()},
{4, (Matrix(4, 2) << 11.0, 12.0, 13.0, 14.0, 25.0, 26.0, 27.0,
28.0)
.finished()}},
2, (Vector(4) << 1.0, 2.0, 15.0, 16.0).finished());
// Create an arbitrary Bayes Tree // Create an arbitrary Bayes Tree
GaussianBayesTree bt; GaussianBayesTree bt;
bt.insertRoot(MakeClique(GaussianConditional( bt.insertRoot(MakeClique(gc1, Children{LeafClique(gc2)}));
pair_list_of<Key, Matrix>
(2, (Matrix(6, 2) <<
31.0,32.0,
0.0,34.0,
0.0,0.0,
0.0,0.0,
0.0,0.0,
0.0,0.0).finished())
(3, (Matrix(6, 2) <<
35.0,36.0,
37.0,38.0,
41.0,42.0,
0.0,44.0,
0.0,0.0,
0.0,0.0).finished())
(4, (Matrix(6, 2) <<
0.0,0.0,
0.0,0.0,
45.0,46.0,
47.0,48.0,
51.0,52.0,
0.0,54.0).finished()),
3, (Vector(6) << 29.0,30.0,39.0,40.0,49.0,50.0).finished()), list_of
(MakeClique(GaussianConditional(
pair_list_of<Key, Matrix>
(0, (Matrix(4, 2) <<
3.0,4.0,
0.0,6.0,
0.0,0.0,
0.0,0.0).finished())
(1, (Matrix(4, 2) <<
0.0,0.0,
0.0,0.0,
17.0,18.0,
0.0,20.0).finished())
(2, (Matrix(4, 2) <<
0.0,0.0,
0.0,0.0,
21.0,22.0,
23.0,24.0).finished())
(3, (Matrix(4, 2) <<
7.0,8.0,
9.0,10.0,
0.0,0.0,
0.0,0.0).finished())
(4, (Matrix(4, 2) <<
11.0,12.0,
13.0,14.0,
25.0,26.0,
27.0,28.0).finished()),
2, (Vector(4) << 1.0,2.0,15.0,16.0).finished())))));
// Compute the Hessian numerically // Compute the Hessian numerically
Matrix hessian = numericalHessian<Vector10>( Matrix hessian = numericalHessian<Vector10>(
@ -276,12 +272,11 @@ TEST(GaussianBayesTree, ComputeSteepestDescentPointBT) {
Vector expected = gradient * step; Vector expected = gradient * step;
// Known steepest descent point from Bayes' net version // Known steepest descent point from Bayes' net version
VectorValues expectedFromBN = pair_list_of<Key, Vector> VectorValues expectedFromBN{{0, Vector2(0.000129034, 0.000688183)},
(0, Vector2(0.000129034, 0.000688183)) {1, Vector2(0.0109679, 0.0253767)},
(1, Vector2(0.0109679, 0.0253767)) {2, Vector2(0.0680441, 0.114496)},
(2, Vector2(0.0680441, 0.114496)) {3, Vector2(0.16125, 0.241294)},
(3, Vector2(0.16125, 0.241294)) {4, Vector2(0.300134, 0.423233)}};
(4, Vector2(0.300134, 0.423233));
// Compute the steepest descent point with the dogleg function // Compute the steepest descent point with the dogleg function
VectorValues actual = bt.optimizeGradientSearch(); VectorValues actual = bt.optimizeGradientSearch();

View File

@ -26,11 +26,7 @@
#include <gtsam/linear/GaussianDensity.h> #include <gtsam/linear/GaussianDensity.h>
#include <gtsam/linear/GaussianBayesNet.h> #include <gtsam/linear/GaussianBayesNet.h>
#include <boost/assign/std/list.hpp>
#include <boost/assign/std/vector.hpp>
#include <boost/assign/list_inserter.hpp>
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
#include <boost/assign/list_of.hpp>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
@ -38,7 +34,6 @@
using namespace gtsam; using namespace gtsam;
using namespace std; using namespace std;
using namespace boost::assign;
using symbol_shorthand::X; using symbol_shorthand::X;
using symbol_shorthand::Y; using symbol_shorthand::Y;
@ -48,6 +43,8 @@ static Matrix R = (Matrix(2, 2) <<
-12.1244, -5.1962, -12.1244, -5.1962,
0., 4.6904).finished(); 0., 4.6904).finished();
using Dims = std::vector<Eigen::Index>;
/* ************************************************************************* */ /* ************************************************************************* */
TEST(GaussianConditional, constructor) TEST(GaussianConditional, constructor)
{ {
@ -64,11 +61,7 @@ TEST(GaussianConditional, constructor)
Vector d = Vector2(1.0, 2.0); Vector d = Vector2(1.0, 2.0);
SharedDiagonal s = noiseModel::Diagonal::Sigmas(Vector2(3.0, 4.0)); SharedDiagonal s = noiseModel::Diagonal::Sigmas(Vector2(3.0, 4.0));
vector<pair<Key, Matrix> > terms = pair_list_of vector<pair<Key, Matrix> > terms = {{1, R}, {3, S1}, {5, S2}, {7, S3}};
(1, R)
(3, S1)
(5, S2)
(7, S3);
GaussianConditional actual(terms, 1, d, s); GaussianConditional actual(terms, 1, d, s);
@ -223,14 +216,10 @@ TEST( GaussianConditional, solve )
Vector sx1(2); sx1 << 1.0, 1.0; Vector sx1(2); sx1 << 1.0, 1.0;
Vector sl1(2); sl1 << 1.0, 1.0; Vector sl1(2); sl1 << 1.0, 1.0;
VectorValues expected = map_list_of VectorValues expected = {{1, expectedX}, {2, sx1}, {10, sl1}};
(1, expectedX)
(2, sx1)
(10, sl1);
VectorValues solution = map_list_of VectorValues solution = {{2, sx1}, // parents
(2, sx1) // parents {10, sl1}};
(10, sl1);
solution.insert(cg.solve(solution)); solution.insert(cg.solve(solution));
EXPECT(assert_equal(expected, solution, tol)); EXPECT(assert_equal(expected, solution, tol));
@ -240,7 +229,7 @@ TEST( GaussianConditional, solve )
TEST( GaussianConditional, solve_simple ) TEST( GaussianConditional, solve_simple )
{ {
// 2 variables, frontal has dim=4 // 2 variables, frontal has dim=4
VerticalBlockMatrix blockMatrix(list_of(4)(2)(1), 4); VerticalBlockMatrix blockMatrix(Dims{4, 2, 1}, 4);
blockMatrix.matrix() << blockMatrix.matrix() <<
1.0, 0.0, 2.0, 0.0, 3.0, 0.0, 0.1, 1.0, 0.0, 2.0, 0.0, 3.0, 0.0, 0.1,
0.0, 1.0, 0.0, 2.0, 0.0, 3.0, 0.2, 0.0, 1.0, 0.0, 2.0, 0.0, 3.0, 0.2,
@ -248,18 +237,16 @@ TEST( GaussianConditional, solve_simple )
0.0, 0.0, 0.0, 3.0, 0.0, 4.0, 0.4; 0.0, 0.0, 0.0, 3.0, 0.0, 4.0, 0.4;
// solve system as a non-multifrontal version first // solve system as a non-multifrontal version first
GaussianConditional cg(list_of(1)(2), 1, blockMatrix); GaussianConditional cg(KeyVector{1,2}, 1, blockMatrix);
// partial solution // partial solution
Vector sx1 = Vector2(9.0, 10.0); Vector sx1 = Vector2(9.0, 10.0);
// elimination order: 1, 2 // elimination order: 1, 2
VectorValues actual = map_list_of VectorValues actual = {{2, sx1}}; // parent
(2, sx1); // parent
VectorValues expected = map_list_of<Key, Vector> VectorValues expected = {
(2, sx1) {2, sx1}, {1, (Vector(4) << -3.1, -3.4, -11.9, -13.2).finished()}};
(1, (Vector(4) << -3.1,-3.4,-11.9,-13.2).finished());
// verify indices/size // verify indices/size
EXPECT_LONGS_EQUAL(2, (long)cg.size()); EXPECT_LONGS_EQUAL(2, (long)cg.size());
@ -274,7 +261,7 @@ TEST( GaussianConditional, solve_simple )
TEST( GaussianConditional, solve_multifrontal ) TEST( GaussianConditional, solve_multifrontal )
{ {
// create full system, 3 variables, 2 frontals, all 2 dim // create full system, 3 variables, 2 frontals, all 2 dim
VerticalBlockMatrix blockMatrix(list_of(2)(2)(2)(1), 4); VerticalBlockMatrix blockMatrix(Dims{2, 2, 2, 1}, 4);
blockMatrix.matrix() << blockMatrix.matrix() <<
1.0, 0.0, 2.0, 0.0, 3.0, 0.0, 0.1, 1.0, 0.0, 2.0, 0.0, 3.0, 0.0, 0.1,
0.0, 1.0, 0.0, 2.0, 0.0, 3.0, 0.2, 0.0, 1.0, 0.0, 2.0, 0.0, 3.0, 0.2,
@ -282,7 +269,7 @@ TEST( GaussianConditional, solve_multifrontal )
0.0, 0.0, 0.0, 3.0, 0.0, 4.0, 0.4; 0.0, 0.0, 0.0, 3.0, 0.0, 4.0, 0.4;
// 3 variables, all dim=2 // 3 variables, all dim=2
GaussianConditional cg(list_of(1)(2)(10), 2, blockMatrix); GaussianConditional cg(KeyVector{1, 2, 10}, 2, blockMatrix);
EXPECT(assert_equal(Vector(blockMatrix.full().rightCols(1)), cg.d())); EXPECT(assert_equal(Vector(blockMatrix.full().rightCols(1)), cg.d()));
@ -290,13 +277,10 @@ TEST( GaussianConditional, solve_multifrontal )
Vector sl1 = Vector2(9.0, 10.0); Vector sl1 = Vector2(9.0, 10.0);
// elimination order; _x_, _x1_, _l1_ // elimination order; _x_, _x1_, _l1_
VectorValues actual = map_list_of VectorValues actual = {{10, sl1}}; // parent
(10, sl1); // parent
VectorValues expected = map_list_of<Key, Vector> VectorValues expected = {
(1, Vector2(-3.1,-3.4)) {1, Vector2(-3.1, -3.4)}, {2, Vector2(-11.9, -13.2)}, {10, sl1}};
(2, Vector2(-11.9,-13.2))
(10, sl1);
// verify indices/size // verify indices/size
EXPECT_LONGS_EQUAL(3, (long)cg.size()); EXPECT_LONGS_EQUAL(3, (long)cg.size());
@ -322,21 +306,18 @@ TEST( GaussianConditional, solveTranspose ) {
d2(0) = 5; d2(0) = 5;
// define nodes and specify in reverse topological sort (i.e. parents last) // define nodes and specify in reverse topological sort (i.e. parents last)
GaussianBayesNet cbn = list_of GaussianBayesNet cbn;
(GaussianConditional(1, d1, R11, 2, S12)) cbn.emplace_shared<GaussianConditional>(1, d1, R11, 2, S12);
(GaussianConditional(1, d2, R22)); cbn.emplace_shared<GaussianConditional>(1, d2, R22);
// x=R'*y, y=inv(R')*x // x=R'*y, y=inv(R')*x
// 2 = 1 2 // 2 = 1 2
// 5 1 1 3 // 5 1 1 3
VectorValues VectorValues x = {{1, (Vector(1) << 2.).finished()},
x = map_list_of<Key, Vector> {2, (Vector(1) << 5.).finished()}},
(1, (Vector(1) << 2.).finished()) y = {{1, (Vector(1) << 2.).finished()},
(2, (Vector(1) << 5.).finished()), {2, (Vector(1) << 3.).finished()}};
y = map_list_of<Key, Vector>
(1, (Vector(1) << 2.).finished())
(2, (Vector(1) << 3.).finished());
// test functional version // test functional version
VectorValues actual = cbn.backSubstituteTranspose(x); VectorValues actual = cbn.backSubstituteTranspose(x);
@ -395,7 +376,7 @@ TEST(GaussianConditional, FromMeanAndStddev) {
const Vector2 b(20, 40), x0(1, 2), x1(3, 4), x2(5, 6); const Vector2 b(20, 40), x0(1, 2), x1(3, 4), x2(5, 6);
const double sigma = 3; const double sigma = 3;
VectorValues values = map_list_of(X(0), x0)(X(1), x1)(X(2), x2); VectorValues values{{X(0), x0}, {X(1), x1}, {X(2), x2}};
auto conditional1 = auto conditional1 =
GaussianConditional::FromMeanAndStddev(X(0), A1, X(1), b, sigma); GaussianConditional::FromMeanAndStddev(X(0), A1, X(1), b, sigma);

View File

@ -26,10 +26,6 @@
#include <gtsam/base/debug.h> #include <gtsam/base/debug.h>
#include <gtsam/base/VerticalBlockMatrix.h> #include <gtsam/base/VerticalBlockMatrix.h>
#include <boost/assign/list_of.hpp>
#include <boost/assign/std/list.hpp> // for operator +=
using namespace boost::assign;
#include <gtsam/base/TestableAssertions.h> #include <gtsam/base/TestableAssertions.h>
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
@ -212,8 +208,9 @@ TEST(GaussianFactorGraph, gradient) {
// 2*f(x) = 100*(x1+c[X(1)])^2 + 100*(x2-x1-[0.2;-0.1])^2 + 25*(l1-x1-[0.0;0.2])^2 + // 2*f(x) = 100*(x1+c[X(1)])^2 + 100*(x2-x1-[0.2;-0.1])^2 + 25*(l1-x1-[0.0;0.2])^2 +
// 25*(l1-x2-[-0.2;0.3])^2 // 25*(l1-x2-[-0.2;0.3])^2
// worked out: df/dx1 = 100*[0.1;0.1] + 100*[0.2;-0.1]) + 25*[0.0;0.2] = [10+20;10-10+5] = [30;5] // worked out: df/dx1 = 100*[0.1;0.1] + 100*[0.2;-0.1]) + 25*[0.0;0.2] = [10+20;10-10+5] = [30;5]
VectorValues expected = map_list_of<Key, Vector>(1, Vector2(5.0, -12.5))(2, Vector2(30.0, 5.0))( VectorValues expected{{1, Vector2(5.0, -12.5)},
0, Vector2(-25.0, 17.5)); {2, Vector2(30.0, 5.0)},
{0, Vector2(-25.0, 17.5)}};
// Check the gradient at delta=0 // Check the gradient at delta=0
VectorValues zero = VectorValues::Zero(expected); VectorValues zero = VectorValues::Zero(expected);
@ -231,8 +228,8 @@ TEST(GaussianFactorGraph, gradient) {
TEST(GaussianFactorGraph, transposeMultiplication) { TEST(GaussianFactorGraph, transposeMultiplication) {
GaussianFactorGraph A = createSimpleGaussianFactorGraph(); GaussianFactorGraph A = createSimpleGaussianFactorGraph();
Errors e; Errors e = {Vector2(0.0, 0.0), Vector2(15.0, 0.0), Vector2(0.0, -5.0),
e += Vector2(0.0, 0.0), Vector2(15.0, 0.0), Vector2(0.0, -5.0), Vector2(-7.5, -5.0); Vector2(-7.5, -5.0)};
VectorValues expected; VectorValues expected;
expected.insert(1, Vector2(-37.5, -50.0)); expected.insert(1, Vector2(-37.5, -50.0));
@ -288,7 +285,7 @@ TEST(GaussianFactorGraph, matrices2) {
TEST(GaussianFactorGraph, multiplyHessianAdd) { TEST(GaussianFactorGraph, multiplyHessianAdd) {
GaussianFactorGraph gfg = createSimpleGaussianFactorGraph(); GaussianFactorGraph gfg = createSimpleGaussianFactorGraph();
VectorValues x = map_list_of<Key, Vector>(0, Vector2(1, 2))(1, Vector2(3, 4))(2, Vector2(5, 6)); const VectorValues x{{0, Vector2(1, 2)}, {1, Vector2(3, 4)}, {2, Vector2(5, 6)}};
VectorValues expected; VectorValues expected;
expected.insert(0, Vector2(-450, -450)); expected.insert(0, Vector2(-450, -450));
@ -307,8 +304,8 @@ TEST(GaussianFactorGraph, multiplyHessianAdd) {
/* ************************************************************************* */ /* ************************************************************************* */
static GaussianFactorGraph createGaussianFactorGraphWithHessianFactor() { static GaussianFactorGraph createGaussianFactorGraphWithHessianFactor() {
GaussianFactorGraph gfg = createSimpleGaussianFactorGraph(); GaussianFactorGraph gfg = createSimpleGaussianFactorGraph();
gfg += HessianFactor(1, 2, 100*I_2x2, Z_2x2, Vector2(0.0, 1.0), gfg.emplace_shared<HessianFactor>(1, 2, 100 * I_2x2, Z_2x2, Vector2(0.0, 1.0),
400*I_2x2, Vector2(1.0, 1.0), 3.0); 400 * I_2x2, Vector2(1.0, 1.0), 3.0);
return gfg; return gfg;
} }
@ -326,8 +323,7 @@ TEST(GaussianFactorGraph, multiplyHessianAdd2) {
Y << -450, -450, 300, 400, 2950, 3450; Y << -450, -450, 300, 400, 2950, 3450;
EXPECT(assert_equal(Y, AtA * X)); EXPECT(assert_equal(Y, AtA * X));
VectorValues x = map_list_of<Key, Vector>(0, Vector2(1, 2))(1, Vector2(3, 4))(2, Vector2(5, 6)); const VectorValues x {{0, Vector2(1, 2)}, {1, Vector2(3, 4)}, {2, Vector2(5, 6)}};
VectorValues expected; VectorValues expected;
expected.insert(0, Vector2(-450, -450)); expected.insert(0, Vector2(-450, -450));
expected.insert(1, Vector2(300, 400)); expected.insert(1, Vector2(300, 400));
@ -371,10 +367,10 @@ TEST(GaussianFactorGraph, gradientAtZero) {
/* ************************************************************************* */ /* ************************************************************************* */
TEST(GaussianFactorGraph, clone) { TEST(GaussianFactorGraph, clone) {
// 2 variables, frontal has dim=4 // 2 variables, frontal has dim=4
VerticalBlockMatrix blockMatrix(list_of(4)(2)(1), 4); VerticalBlockMatrix blockMatrix(KeyVector{4, 2, 1}, 4);
blockMatrix.matrix() << 1.0, 0.0, 2.0, 0.0, 3.0, 0.0, 0.1, 0.0, 1.0, 0.0, 2.0, 0.0, 3.0, 0.2, 0.0, blockMatrix.matrix() << 1.0, 0.0, 2.0, 0.0, 3.0, 0.0, 0.1, 0.0, 1.0, 0.0, 2.0, 0.0, 3.0, 0.2, 0.0,
0.0, 3.0, 0.0, 4.0, 0.0, 0.3, 0.0, 0.0, 0.0, 3.0, 0.0, 4.0, 0.4; 0.0, 3.0, 0.0, 4.0, 0.0, 0.3, 0.0, 0.0, 0.0, 3.0, 0.0, 4.0, 0.4;
GaussianConditional cg(list_of(1)(2), 1, blockMatrix); GaussianConditional cg(KeyVector{1, 2}, 1, blockMatrix);
GaussianFactorGraph init_graph = createGaussianFactorGraphWithHessianFactor(); GaussianFactorGraph init_graph = createGaussianFactorGraphWithHessianFactor();
init_graph.push_back(GaussianFactor::shared_ptr()); /// Add null factor init_graph.push_back(GaussianFactor::shared_ptr()); /// Add null factor

View File

@ -25,11 +25,6 @@
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/list_of.hpp>
#include <boost/assign/std/vector.hpp>
#include <boost/assign/std/map.hpp>
using namespace boost::assign;
#include <vector> #include <vector>
#include <utility> #include <utility>
@ -38,6 +33,8 @@ using namespace gtsam;
const double tol = 1e-5; const double tol = 1e-5;
using Dims = std::vector<Eigen::Index>; // For constructing block matrices
/* ************************************************************************* */ /* ************************************************************************* */
TEST(HessianFactor, Slot) TEST(HessianFactor, Slot)
{ {
@ -61,8 +58,8 @@ TEST(HessianFactor, emptyConstructor)
/* ************************************************************************* */ /* ************************************************************************* */
TEST(HessianFactor, ConversionConstructor) TEST(HessianFactor, ConversionConstructor)
{ {
HessianFactor expected(list_of(0)(1), HessianFactor expected(KeyVector{0, 1},
SymmetricBlockMatrix(list_of(2)(4)(1), (Matrix(7,7) << SymmetricBlockMatrix(Dims{2, 4, 1}, (Matrix(7,7) <<
125.0000, 0.0, -25.0000, 0.0, -100.0000, 0.0, 25.0000, 125.0000, 0.0, -25.0000, 0.0, -100.0000, 0.0, 25.0000,
0.0, 125.0000, 0.0, -25.0000, 0.0, -100.0000, -17.5000, 0.0, 125.0000, 0.0, -25.0000, 0.0, -100.0000, -17.5000,
-25.0000, 0.0, 25.0000, 0.0, 0.0, 0.0, -5.0000, -25.0000, 0.0, 25.0000, 0.0, 0.0, 0.0, -5.0000,
@ -85,9 +82,7 @@ TEST(HessianFactor, ConversionConstructor)
HessianFactor actual(jacobian); HessianFactor actual(jacobian);
VectorValues values = pair_list_of<Key, Vector> VectorValues values{{0, Vector2(1.0, 2.0)}, {1, Vector4(3.0, 4.0, 5.0, 6.0)}};
(0, Vector2(1.0, 2.0))
(1, (Vector(4) << 3.0, 4.0, 5.0, 6.0).finished());
EXPECT_LONGS_EQUAL(2, (long)actual.size()); EXPECT_LONGS_EQUAL(2, (long)actual.size());
EXPECT(assert_equal(expected, actual, 1e-9)); EXPECT(assert_equal(expected, actual, 1e-9));
@ -108,7 +103,7 @@ TEST(HessianFactor, Constructor1)
EXPECT(assert_equal(g, Vector(factor.linearTerm()))); EXPECT(assert_equal(g, Vector(factor.linearTerm())));
EXPECT_LONGS_EQUAL(1, (long)factor.size()); EXPECT_LONGS_EQUAL(1, (long)factor.size());
VectorValues dx = pair_list_of<Key, Vector>(0, Vector2(1.5, 2.5)); VectorValues dx{{0, Vector2(1.5, 2.5)}};
// error 0.5*(f - 2*x'*g + x'*G*x) // error 0.5*(f - 2*x'*g + x'*G*x)
double expected = 80.375; double expected = 80.375;
@ -150,9 +145,7 @@ TEST(HessianFactor, Constructor2)
Vector dx0 = (Vector(1) << 0.5).finished(); Vector dx0 = (Vector(1) << 0.5).finished();
Vector dx1 = Vector2(1.5, 2.5); Vector dx1 = Vector2(1.5, 2.5);
VectorValues dx = pair_list_of VectorValues dx{{0, dx0}, {1, dx1}};
(0, dx0)
(1, dx1);
HessianFactor factor(0, 1, G11, G12, g1, G22, g2, f); HessianFactor factor(0, 1, G11, G12, g1, G22, g2, f);
@ -171,10 +164,7 @@ TEST(HessianFactor, Constructor2)
EXPECT(assert_equal(G22, factor.info().diagonalBlock(1))); EXPECT(assert_equal(G22, factor.info().diagonalBlock(1)));
// Check case when vector values is larger than factor // Check case when vector values is larger than factor
VectorValues dxLarge = pair_list_of<Key, Vector> VectorValues dxLarge {{0, dx0}, {1, dx1}, {2, Vector2(0.1, 0.2)}};
(0, dx0)
(1, dx1)
(2, Vector2(0.1, 0.2));
EXPECT_DOUBLES_EQUAL(expected, factor.error(dxLarge), 1e-10); EXPECT_DOUBLES_EQUAL(expected, factor.error(dxLarge), 1e-10);
} }
@ -200,11 +190,7 @@ TEST(HessianFactor, Constructor3)
Vector dx1 = Vector2(1.5, 2.5); Vector dx1 = Vector2(1.5, 2.5);
Vector dx2 = Vector3(1.5, 2.5, 3.5); Vector dx2 = Vector3(1.5, 2.5, 3.5);
VectorValues dx = pair_list_of VectorValues dx {{0, dx0}, {1, dx1}, {2, dx2}};
(0, dx0)
(1, dx1)
(2, dx2);
HessianFactor factor(0, 1, 2, G11, G12, G13, g1, G22, G23, g2, G33, g3, f); HessianFactor factor(0, 1, 2, G11, G12, G13, g1, G22, G23, g2, G33, g3, f);
double expected = 371.3750; double expected = 371.3750;
@ -247,10 +233,7 @@ TEST(HessianFactor, ConstructorNWay)
Vector dx1 = Vector2(1.5, 2.5); Vector dx1 = Vector2(1.5, 2.5);
Vector dx2 = Vector3(1.5, 2.5, 3.5); Vector dx2 = Vector3(1.5, 2.5, 3.5);
VectorValues dx = pair_list_of VectorValues dx {{0, dx0}, {1, dx1}, {2, dx2}};
(0, dx0)
(1, dx1)
(2, dx2);
KeyVector js {0, 1, 2}; KeyVector js {0, 1, 2};
std::vector<Matrix> Gs; std::vector<Matrix> Gs;
@ -309,7 +292,7 @@ TEST(HessianFactor, CombineAndEliminate1) {
hessian.augmentedInformation(), 1e-9)); hessian.augmentedInformation(), 1e-9));
// perform elimination on jacobian // perform elimination on jacobian
Ordering ordering = list_of(1); Ordering ordering {1};
GaussianConditional::shared_ptr expectedConditional; GaussianConditional::shared_ptr expectedConditional;
JacobianFactor::shared_ptr expectedFactor; JacobianFactor::shared_ptr expectedFactor;
boost::tie(expectedConditional, expectedFactor) = jacobian.eliminate(ordering); boost::tie(expectedConditional, expectedFactor) = jacobian.eliminate(ordering);
@ -372,7 +355,7 @@ TEST(HessianFactor, CombineAndEliminate2) {
hessian.augmentedInformation(), 1e-9)); hessian.augmentedInformation(), 1e-9));
// perform elimination on jacobian // perform elimination on jacobian
Ordering ordering = list_of(0); Ordering ordering {0};
GaussianConditional::shared_ptr expectedConditional; GaussianConditional::shared_ptr expectedConditional;
JacobianFactor::shared_ptr expectedFactor; JacobianFactor::shared_ptr expectedFactor;
boost::tie(expectedConditional, expectedFactor) = // boost::tie(expectedConditional, expectedFactor) = //
@ -437,10 +420,10 @@ TEST(HessianFactor, eliminate2 )
// eliminate the combined factor // eliminate the combined factor
HessianFactor::shared_ptr combinedLF_Chol(new HessianFactor(combined)); HessianFactor::shared_ptr combinedLF_Chol(new HessianFactor(combined));
GaussianFactorGraph combinedLFG_Chol = list_of(combinedLF_Chol); GaussianFactorGraph combinedLFG_Chol {combinedLF_Chol};
std::pair<GaussianConditional::shared_ptr, HessianFactor::shared_ptr> actual_Chol = std::pair<GaussianConditional::shared_ptr, HessianFactor::shared_ptr> actual_Chol =
EliminateCholesky(combinedLFG_Chol, Ordering(list_of(0))); EliminateCholesky(combinedLFG_Chol, Ordering{0});
// create expected Conditional Gaussian // create expected Conditional Gaussian
double oldSigma = 0.0894427; // from when R was made unit double oldSigma = 0.0894427; // from when R was made unit
@ -483,8 +466,8 @@ TEST(HessianFactor, combine) {
0.0, -8.94427191).finished(); 0.0, -8.94427191).finished();
Vector b = Vector2(2.23606798,-1.56524758); Vector b = Vector2(2.23606798,-1.56524758);
SharedDiagonal model = noiseModel::Diagonal::Sigmas(Vector::Ones(2)); SharedDiagonal model = noiseModel::Diagonal::Sigmas(Vector::Ones(2));
GaussianFactor::shared_ptr f(new JacobianFactor(0, A0, 1, A1, 2, A2, b, model)); GaussianFactorGraph factors{
GaussianFactorGraph factors = list_of(f); boost::make_shared<JacobianFactor>(0, A0, 1, A1, 2, A2, b, model)};
// Form Ab' * Ab // Form Ab' * Ab
HessianFactor actual(factors); HessianFactor actual(factors);
@ -514,7 +497,7 @@ TEST(HessianFactor, gradientAtZero)
HessianFactor factor(0, 1, G11, G12, g1, G22, g2, f); HessianFactor factor(0, 1, G11, G12, g1, G22, g2, f);
// test gradient at zero // test gradient at zero
VectorValues expectedG = pair_list_of<Key, Vector>(0, -g1) (1, -g2); VectorValues expectedG{{0, -g1}, {1, -g2}};
Matrix A; Vector b; boost::tie(A,b) = factor.jacobian(); Matrix A; Vector b; boost::tie(A,b) = factor.jacobian();
KeyVector keys {0, 1}; KeyVector keys {0, 1};
EXPECT(assert_equal(-A.transpose()*b, expectedG.vector(keys))); EXPECT(assert_equal(-A.transpose()*b, expectedG.vector(keys)));
@ -537,7 +520,7 @@ TEST(HessianFactor, gradient)
// test gradient // test gradient
Vector x0 = (Vector(1) << 3.0).finished(); Vector x0 = (Vector(1) << 3.0).finished();
Vector x1 = (Vector(2) << -3.5, 7.1).finished(); Vector x1 = (Vector(2) << -3.5, 7.1).finished();
VectorValues x = pair_list_of<Key, Vector>(0, x0) (1, x1); VectorValues x {{0, x0}, {1, x1}};
Vector expectedGrad0 = (Vector(1) << 10.0).finished(); Vector expectedGrad0 = (Vector(1) << 10.0).finished();
Vector expectedGrad1 = (Vector(2) << 4.5, 16.1).finished(); Vector expectedGrad1 = (Vector(2) << 4.5, 16.1).finished();

View File

@ -25,26 +25,24 @@
#include <gtsam/linear/GaussianConditional.h> #include <gtsam/linear/GaussianConditional.h>
#include <gtsam/linear/VectorValues.h> #include <gtsam/linear/VectorValues.h>
#include <boost/assign/std/vector.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/range/iterator_range.hpp> #include <boost/range/iterator_range.hpp>
#include <boost/range/adaptor/map.hpp> #include <boost/range/adaptor/map.hpp>
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;
using namespace boost::assign;
using Dims = std::vector<Eigen::Index>; // For constructing block matrices
namespace { namespace {
namespace simple { namespace simple {
// Terms we'll use // Terms we'll use
const vector<pair<Key, Matrix> > terms = list_of<pair<Key,Matrix> > const vector<pair<Key, Matrix> > terms{
(make_pair(5, Matrix3::Identity())) {5, I_3x3}, {10, 2 * I_3x3}, {15, 3 * I_3x3}};
(make_pair(10, 2*Matrix3::Identity()))
(make_pair(15, 3*Matrix3::Identity()));
// RHS and sigmas // RHS and sigmas
const Vector b = Vector3(1., 2., 3.); const Vector b = Vector3(1., 2., 3.);
const SharedDiagonal noise = noiseModel::Diagonal::Sigmas(Vector3(0.5, 0.5, 0.5)); const SharedDiagonal noise =
noiseModel::Diagonal::Sigmas(Vector3(0.5, 0.5, 0.5));
} }
} }
@ -128,7 +126,7 @@ TEST(JacobianFactor, constructors_and_accessors)
// VerticalBlockMatrix constructor // VerticalBlockMatrix constructor
JacobianFactor expected( JacobianFactor expected(
boost::make_iterator_range(terms.begin(), terms.begin() + 3), b, noise); boost::make_iterator_range(terms.begin(), terms.begin() + 3), b, noise);
VerticalBlockMatrix blockMatrix(list_of(3)(3)(3)(1), 3); VerticalBlockMatrix blockMatrix(Dims{3, 3, 3, 1}, 3);
blockMatrix(0) = terms[0].second; blockMatrix(0) = terms[0].second;
blockMatrix(1) = terms[1].second; blockMatrix(1) = terms[1].second;
blockMatrix(2) = terms[2].second; blockMatrix(2) = terms[2].second;
@ -191,22 +189,25 @@ Key keyX(10), keyY(8), keyZ(12);
double sigma1 = 0.1; double sigma1 = 0.1;
Matrix A11 = I_2x2; Matrix A11 = I_2x2;
Vector2 b1(2, -1); Vector2 b1(2, -1);
JacobianFactor factor1(keyX, A11, b1, noiseModel::Isotropic::Sigma(2, sigma1)); auto factor1 = boost::make_shared<JacobianFactor>(
keyX, A11, b1, noiseModel::Isotropic::Sigma(2, sigma1));
double sigma2 = 0.5; double sigma2 = 0.5;
Matrix A21 = -2 * I_2x2; Matrix A21 = -2 * I_2x2;
Matrix A22 = 3 * I_2x2; Matrix A22 = 3 * I_2x2;
Vector2 b2(4, -5); Vector2 b2(4, -5);
JacobianFactor factor2(keyX, A21, keyY, A22, b2, noiseModel::Isotropic::Sigma(2, sigma2)); auto factor2 = boost::make_shared<JacobianFactor>(
keyX, A21, keyY, A22, b2, noiseModel::Isotropic::Sigma(2, sigma2));
double sigma3 = 1.0; double sigma3 = 1.0;
Matrix A32 = -4 * I_2x2; Matrix A32 = -4 * I_2x2;
Matrix A33 = 5 * I_2x2; Matrix A33 = 5 * I_2x2;
Vector2 b3(3, -6); Vector2 b3(3, -6);
JacobianFactor factor3(keyY, A32, keyZ, A33, b3, noiseModel::Isotropic::Sigma(2, sigma3)); auto factor3 = boost::make_shared<JacobianFactor>(
keyY, A32, keyZ, A33, b3, noiseModel::Isotropic::Sigma(2, sigma3));
GaussianFactorGraph factors(list_of(factor1)(factor2)(factor3)); const GaussianFactorGraph factors { factor1, factor2, factor3 };
Ordering ordering(list_of(keyX)(keyY)(keyZ)); const Ordering ordering { keyX, keyY, keyZ };
} }
/* ************************************************************************* */ /* ************************************************************************* */
@ -436,11 +437,11 @@ TEST(JacobianFactor, eliminate)
Vector9 sigmas; sigmas << s1, s0, s2; Vector9 sigmas; sigmas << s1, s0, s2;
JacobianFactor combinedFactor(0, A0, 1, A1, b, noiseModel::Diagonal::Sigmas(sigmas, true)); JacobianFactor combinedFactor(0, A0, 1, A1, b, noiseModel::Diagonal::Sigmas(sigmas, true));
GaussianFactorGraph::EliminationResult expected = combinedFactor.eliminate(list_of(0)); GaussianFactorGraph::EliminationResult expected = combinedFactor.eliminate(Ordering{0});
JacobianFactor::shared_ptr expectedJacobian = boost::dynamic_pointer_cast< JacobianFactor::shared_ptr expectedJacobian = boost::dynamic_pointer_cast<
JacobianFactor>(expected.second); JacobianFactor>(expected.second);
GaussianFactorGraph::EliminationResult actual = EliminateQR(gfg, list_of(0)); GaussianFactorGraph::EliminationResult actual = EliminateQR(gfg, Ordering{0});
JacobianFactor::shared_ptr actualJacobian = boost::dynamic_pointer_cast< JacobianFactor::shared_ptr actualJacobian = boost::dynamic_pointer_cast<
JacobianFactor>(actual.second); JacobianFactor>(actual.second);
@ -487,7 +488,7 @@ TEST(JacobianFactor, eliminate2 )
// eliminate the combined factor // eliminate the combined factor
pair<GaussianConditional::shared_ptr, JacobianFactor::shared_ptr> pair<GaussianConditional::shared_ptr, JacobianFactor::shared_ptr>
actual = combined.eliminate(Ordering(list_of(2))); actual = combined.eliminate(Ordering{2});
// create expected Conditional Gaussian // create expected Conditional Gaussian
double oldSigma = 0.0894427; // from when R was made unit double oldSigma = 0.0894427; // from when R was made unit
@ -539,11 +540,11 @@ TEST(JacobianFactor, EliminateQR)
// Create factor graph // Create factor graph
const SharedDiagonal sig_4D = noiseModel::Isotropic::Sigma(4, 0.5); const SharedDiagonal sig_4D = noiseModel::Isotropic::Sigma(4, 0.5);
const SharedDiagonal sig_2D = noiseModel::Isotropic::Sigma(2, 0.5); const SharedDiagonal sig_2D = noiseModel::Isotropic::Sigma(2, 0.5);
GaussianFactorGraph factors = list_of GaussianFactorGraph factors = {
(JacobianFactor(list_of(3)(5)(7)(9)(11), VerticalBlockMatrix(list_of(2)(2)(2)(2)(2)(1), Ab.block(0, 0, 4, 11)), sig_4D)) boost::make_shared<JacobianFactor>(KeyVector{3, 5, 7, 9, 11}, VerticalBlockMatrix(Dims{2, 2, 2, 2, 2, 1}, Ab.block(0, 0, 4, 11)), sig_4D),
(JacobianFactor(list_of(5)(7)(9)(11), VerticalBlockMatrix(list_of(2)(2)(2)(2)(1), Ab.block(4, 2, 4, 9)), sig_4D)) boost::make_shared<JacobianFactor>(KeyVector{5, 7, 9, 11}, VerticalBlockMatrix(Dims{2, 2, 2, 2, 1}, Ab.block(4, 2, 4, 9)), sig_4D),
(JacobianFactor(list_of(7)(9)(11), VerticalBlockMatrix(list_of(2)(2)(2)(1), Ab.block(8, 4, 4, 7)), sig_4D)) boost::make_shared<JacobianFactor>(KeyVector{7, 9, 11}, VerticalBlockMatrix(Dims{2, 2, 2, 1}, Ab.block(8, 4, 4, 7)), sig_4D),
(JacobianFactor(list_of(11), VerticalBlockMatrix(list_of(2)(1), Ab.block(12, 8, 2, 3)), sig_2D)); boost::make_shared<JacobianFactor>(KeyVector{11}, VerticalBlockMatrix(Dims{2, 1}, Ab.block(12, 8, 2, 3)), sig_2D)};
// extract the dense matrix for the graph // extract the dense matrix for the graph
Matrix actualDense = factors.augmentedJacobian(); Matrix actualDense = factors.augmentedJacobian();
@ -562,12 +563,12 @@ TEST(JacobianFactor, EliminateQR)
0., 0., 0., 0., 0., 0., 0., 0., 8.2503, 3.3757, 6.8476, 0., 0., 0., 0., 0., 0., 0., 0., 8.2503, 3.3757, 6.8476,
0., 0., 0., 0., 0., 0., 0., 0., 0., -5.7095, -0.0090).finished(); 0., 0., 0., 0., 0., 0., 0., 0., 0., -5.7095, -0.0090).finished();
GaussianConditional expectedFragment(list_of(3)(5)(7)(9)(11), 3, GaussianConditional expectedFragment(KeyVector{3,5,7,9,11}, 3,
VerticalBlockMatrix(list_of(2)(2)(2)(2)(2)(1), R.topRows(6)), VerticalBlockMatrix(Dims{2, 2, 2, 2, 2, 1}, R.topRows(6)),
noiseModel::Unit::Create(6)); noiseModel::Unit::Create(6));
// Eliminate (3 frontal variables, 6 scalar columns) using QR !!!! // Eliminate (3 frontal variables, 6 scalar columns) using QR !!!!
GaussianFactorGraph::EliminationResult actual = EliminateQR(factors, list_of(3)(5)(7)); GaussianFactorGraph::EliminationResult actual = EliminateQR(factors, Ordering{3, 5, 7});
const JacobianFactor &actualJF = dynamic_cast<const JacobianFactor&>(*actual.second); const JacobianFactor &actualJF = dynamic_cast<const JacobianFactor&>(*actual.second);
EXPECT(assert_equal(expectedFragment, *actual.first, 0.001)); EXPECT(assert_equal(expectedFragment, *actual.first, 0.001));
@ -589,7 +590,7 @@ TEST ( JacobianFactor, constraint_eliminate1 )
// eliminate it // eliminate it
pair<GaussianConditional::shared_ptr, JacobianFactor::shared_ptr> pair<GaussianConditional::shared_ptr, JacobianFactor::shared_ptr>
actual = lc.eliminate(list_of(1)); actual = lc.eliminate(Ordering{1});
// verify linear factor is a null ptr // verify linear factor is a null ptr
EXPECT(actual.second->empty()); EXPECT(actual.second->empty());
@ -617,7 +618,7 @@ TEST ( JacobianFactor, constraint_eliminate2 )
// eliminate x and verify results // eliminate x and verify results
pair<GaussianConditional::shared_ptr, JacobianFactor::shared_ptr> pair<GaussianConditional::shared_ptr, JacobianFactor::shared_ptr>
actual = lc.eliminate(list_of(1)); actual = lc.eliminate(Ordering{1});
// LF should be empty // LF should be empty
// It's tricky to create Eigen matrices that are only zero along one dimension // It's tricky to create Eigen matrices that are only zero along one dimension
@ -648,7 +649,7 @@ TEST(JacobianFactor, OverdeterminedEliminate) {
SharedDiagonal diagonal = noiseModel::Diagonal::Sigmas(sigmas); SharedDiagonal diagonal = noiseModel::Diagonal::Sigmas(sigmas);
JacobianFactor factor(0, Ab.leftCols(3), Ab.col(3), diagonal); JacobianFactor factor(0, Ab.leftCols(3), Ab.col(3), diagonal);
GaussianFactorGraph::EliminationResult actual = factor.eliminate(list_of(0)); GaussianFactorGraph::EliminationResult actual = factor.eliminate(Ordering{0});
Matrix expectedRd(3, 4); Matrix expectedRd(3, 4);
expectedRd << -2.64575131, -2.64575131, -2.64575131, -2.64575131, // expectedRd << -2.64575131, -2.64575131, -2.64575131, -2.64575131, //

View File

@ -22,20 +22,17 @@
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/vector.hpp>
#include <iostream> #include <iostream>
#include <limits> #include <limits>
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;
using namespace noiseModel; using namespace noiseModel;
using namespace boost::assign;
static const double kSigma = 2, kInverseSigma = 1.0 / kSigma, static const double kSigma = 2, kInverseSigma = 1.0 / kSigma,
kVariance = kSigma * kSigma, prc = 1.0 / kVariance; kVariance = kSigma * kSigma, prc = 1.0 / kVariance;
static const Matrix R = Matrix3::Identity() * kInverseSigma; static const Matrix R = I_3x3 * kInverseSigma;
static const Matrix kCovariance = Matrix3::Identity() * kVariance; static const Matrix kCovariance = I_3x3 * kVariance;
static const Vector3 kSigmas(kSigma, kSigma, kSigma); static const Vector3 kSigmas(kSigma, kSigma, kSigma);
/* ************************************************************************* */ /* ************************************************************************* */
@ -723,7 +720,7 @@ TEST(NoiseModel, NonDiagonalGaussian)
const Matrix3 info = R.transpose() * R; const Matrix3 info = R.transpose() * R;
const Matrix3 cov = info.inverse(); const Matrix3 cov = info.inverse();
const Vector3 e(1, 1, 1), white = R * e; const Vector3 e(1, 1, 1), white = R * e;
Matrix I = Matrix3::Identity(); Matrix I = I_3x3;
{ {

View File

@ -21,13 +21,8 @@
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/vector.hpp>
#include <boost/assign/std/map.hpp>
#include <boost/assign/list_of.hpp>
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;
using namespace boost::assign;
/* ************************************************************************* */ /* ************************************************************************* */
TEST(RegularHessianFactor, Constructors) TEST(RegularHessianFactor, Constructors)
@ -36,8 +31,7 @@ TEST(RegularHessianFactor, Constructors)
// 0.5*|x0 + x1 + x3 - [1;2]|^2 = 0.5*|A*x-b|^2, with A=[I I I] // 0.5*|x0 + x1 + x3 - [1;2]|^2 = 0.5*|A*x-b|^2, with A=[I I I]
Matrix A1 = I_2x2, A2 = I_2x2, A3 = I_2x2; Matrix A1 = I_2x2, A2 = I_2x2, A3 = I_2x2;
Vector2 b(1,2); Vector2 b(1,2);
vector<pair<Key, Matrix> > terms; const vector<pair<Key, Matrix> > terms {{0, A1}, {1, A2}, {3, A3}};
terms += make_pair(0, A1), make_pair(1, A2), make_pair(3, A3);
RegularJacobianFactor<2> jf(terms, b); RegularJacobianFactor<2> jf(terms, b);
// Test conversion from JacobianFactor // Test conversion from JacobianFactor
@ -65,8 +59,8 @@ TEST(RegularHessianFactor, Constructors)
// Test n-way constructor // Test n-way constructor
KeyVector keys {0, 1, 3}; KeyVector keys {0, 1, 3};
vector<Matrix> Gs; Gs += G11, G12, G13, G22, G23, G33; vector<Matrix> Gs {G11, G12, G13, G22, G23, G33};
vector<Vector> gs; gs += g1, g2, g3; vector<Vector> gs {g1, g2, g3};
RegularHessianFactor<2> factor3(keys, Gs, gs, f); RegularHessianFactor<2> factor3(keys, Gs, gs, f);
EXPECT(assert_equal(factor, factor3)); EXPECT(assert_equal(factor, factor3));
@ -82,7 +76,7 @@ TEST(RegularHessianFactor, Constructors)
// Test constructor from Information matrix // Test constructor from Information matrix
Matrix info = factor.augmentedInformation(); Matrix info = factor.augmentedInformation();
vector<size_t> dims; dims += 2, 2, 2; vector<size_t> dims {2, 2, 2};
SymmetricBlockMatrix sym(dims, info, true); SymmetricBlockMatrix sym(dims, info, true);
RegularHessianFactor<2> factor6(keys, sym); RegularHessianFactor<2> factor6(keys, sym);
EXPECT(assert_equal(factor, factor6)); EXPECT(assert_equal(factor, factor6));
@ -97,10 +91,7 @@ TEST(RegularHessianFactor, Constructors)
Vector Y(6); Y << 9, 12, 9, 12, 9, 12; Vector Y(6); Y << 9, 12, 9, 12, 9, 12;
EXPECT(assert_equal(Y,AtA*X)); EXPECT(assert_equal(Y,AtA*X));
VectorValues x = map_list_of<Key, Vector> VectorValues x{{0, Vector2(1, 2)}, {1, Vector2(3, 4)}, {3, Vector2(5, 6)}};
(0, Vector2(1,2))
(1, Vector2(3,4))
(3, Vector2(5,6));
VectorValues expected; VectorValues expected;
expected.insert(0, Y.segment<2>(0)); expected.insert(0, Y.segment<2>(0));

View File

@ -24,14 +24,11 @@
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/vector.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/range/iterator_range.hpp> #include <boost/range/iterator_range.hpp>
#include <boost/range/adaptor/map.hpp> #include <boost/range/adaptor/map.hpp>
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;
using namespace boost::assign;
static const size_t fixedDim = 3; static const size_t fixedDim = 3;
static const size_t nrKeys = 3; static const size_t nrKeys = 3;
@ -40,10 +37,8 @@ static const size_t nrKeys = 3;
namespace { namespace {
namespace simple { namespace simple {
// Terms we'll use // Terms we'll use
const vector<pair<Key, Matrix> > terms = list_of<pair<Key,Matrix> > const vector<pair<Key, Matrix> > terms{
(make_pair(0, Matrix3::Identity())) {0, 1 * I_3x3}, {1, 2 * I_3x3}, {2, 3 * I_3x3}};
(make_pair(1, 2*Matrix3::Identity()))
(make_pair(2, 3*Matrix3::Identity()));
// RHS and sigmas // RHS and sigmas
const Vector b = (Vector(3) << 1., 2., 3.).finished(); const Vector b = (Vector(3) << 1., 2., 3.).finished();
@ -52,10 +47,8 @@ namespace {
namespace simple2 { namespace simple2 {
// Terms // Terms
const vector<pair<Key, Matrix> > terms2 = list_of<pair<Key,Matrix> > const vector<pair<Key, Matrix> > terms2{
(make_pair(0, 2*Matrix3::Identity())) {0, 2 * I_3x3}, {1, 4 * I_3x3}, {2, 6 * I_3x3}};
(make_pair(1, 4*Matrix3::Identity()))
(make_pair(2, 6*Matrix3::Identity()));
// RHS // RHS
const Vector b2 = (Vector(3) << 2., 4., 6.).finished(); const Vector b2 = (Vector(3) << 2., 4., 6.).finished();

View File

@ -22,9 +22,6 @@
#include <gtsam/linear/GaussianISAM.h> #include <gtsam/linear/GaussianISAM.h>
#include <gtsam/linear/NoiseModel.h> #include <gtsam/linear/NoiseModel.h>
#include <boost/assign/list_of.hpp>
using namespace boost::assign;
#include <gtsam/base/serializationTestHelpers.h> #include <gtsam/base/serializationTestHelpers.h>
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
@ -228,13 +225,13 @@ TEST(Serialization, gaussian_bayes_net) {
/* ************************************************************************* */ /* ************************************************************************* */
TEST (Serialization, gaussian_bayes_tree) { TEST (Serialization, gaussian_bayes_tree) {
const Key x1=1, x2=2, x3=3, x4=4; const Key x1=1, x2=2, x3=3, x4=4;
const Ordering chainOrdering = Ordering(list_of(x2)(x1)(x3)(x4)); const Ordering chainOrdering {x2, x1, x3, x4};
const SharedDiagonal chainNoise = noiseModel::Isotropic::Sigma(1, 0.5); const SharedDiagonal chainNoise = noiseModel::Isotropic::Sigma(1, 0.5);
const GaussianFactorGraph chain = list_of const GaussianFactorGraph chain = {
(JacobianFactor(x2, (Matrix(1, 1) << 1.).finished(), x1, (Matrix(1, 1) << 1.).finished(), (Vector(1) << 1.).finished(), chainNoise)) boost::make_shared<JacobianFactor>(x2, (Matrix(1, 1) << 1.).finished(), x1, (Matrix(1, 1) << 1.).finished(), (Vector(1) << 1.).finished(), chainNoise),
(JacobianFactor(x2, (Matrix(1, 1) << 1.).finished(), x3, (Matrix(1, 1) << 1.).finished(), (Vector(1) << 1.).finished(), chainNoise)) boost::make_shared<JacobianFactor>(x2, (Matrix(1, 1) << 1.).finished(), x3, (Matrix(1, 1) << 1.).finished(), (Vector(1) << 1.).finished(), chainNoise),
(JacobianFactor(x3, (Matrix(1, 1) << 1.).finished(), x4, (Matrix(1, 1) << 1.).finished(), (Vector(1) << 1.).finished(), chainNoise)) boost::make_shared<JacobianFactor>(x3, (Matrix(1, 1) << 1.).finished(), x4, (Matrix(1, 1) << 1.).finished(), (Vector(1) << 1.).finished(), chainNoise),
(JacobianFactor(x4, (Matrix(1, 1) << 1.).finished(), (Vector(1) << 1.).finished(), chainNoise)); boost::make_shared<JacobianFactor>(x4, (Matrix(1, 1) << 1.).finished(), (Vector(1) << 1.).finished(), chainNoise)};
GaussianBayesTree init = *chain.eliminateMultifrontal(chainOrdering); GaussianBayesTree init = *chain.eliminateMultifrontal(chainOrdering);
GaussianBayesTree expected = *chain.eliminateMultifrontal(chainOrdering); GaussianBayesTree expected = *chain.eliminateMultifrontal(chainOrdering);

View File

@ -21,9 +21,6 @@
#include <gtsam/linear/GaussianFactorGraph.h> #include <gtsam/linear/GaussianFactorGraph.h>
#include <gtsam/linear/SparseEigen.h> #include <gtsam/linear/SparseEigen.h>
#include <boost/assign/list_of.hpp>
using boost::assign::list_of;
#include <gtsam/base/TestableAssertions.h> #include <gtsam/base/TestableAssertions.h>
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
@ -49,7 +46,7 @@ TEST(SparseEigen, sparseJacobianEigen) {
EXPECT(assert_equal(gfg.augmentedJacobian(), Matrix(sparseResult))); EXPECT(assert_equal(gfg.augmentedJacobian(), Matrix(sparseResult)));
// Call sparseJacobian with optional ordering... // Call sparseJacobian with optional ordering...
auto ordering = Ordering(list_of(x45)(x123)); const Ordering ordering{x45, x123};
// Eigen Sparse with optional ordering // Eigen Sparse with optional ordering
EXPECT(assert_equal(gfg.augmentedJacobian(ordering), EXPECT(assert_equal(gfg.augmentedJacobian(ordering),

View File

@ -21,14 +21,11 @@
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/vector.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/range/adaptor/map.hpp> #include <boost/range/adaptor/map.hpp>
#include <sstream> #include <sstream>
using namespace std; using namespace std;
using namespace boost::assign;
using boost::adaptors::map_keys; using boost::adaptors::map_keys;
using namespace gtsam; using namespace gtsam;

View File

@ -18,11 +18,9 @@
#include <gtsam/base/timing.h> #include <gtsam/base/timing.h>
#include <gtsam/navigation/ScenarioRunner.h> #include <gtsam/navigation/ScenarioRunner.h>
#include <boost/assign.hpp>
#include <cmath> #include <cmath>
using namespace std; using namespace std;
using namespace boost::assign;
namespace gtsam { namespace gtsam {

View File

@ -29,12 +29,9 @@
#include <gtsam/base/utilities.h> // boost::index_sequence #include <gtsam/base/utilities.h> // boost::index_sequence
#include <boost/serialization/base_object.hpp> #include <boost/serialization/base_object.hpp>
#include <boost/assign/list_of.hpp>
namespace gtsam { namespace gtsam {
using boost::assign::cref_list_of;
/* ************************************************************************* */ /* ************************************************************************* */
/** /**

View File

@ -29,9 +29,6 @@
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/list_of.hpp>
using boost::assign::list_of;
using boost::assign::map_list_of;
namespace gtsam { namespace gtsam {
@ -253,8 +250,7 @@ TEST(AdaptAutoDiff, SnavelyExpression) {
internal::upAligned(RecordSize) + P.traceSize() + X.traceSize(), internal::upAligned(RecordSize) + P.traceSize() + X.traceSize(),
expression.traceSize()); expression.traceSize());
set<Key> expected = list_of(1)(2); const set<Key> expected{1, 2};
EXPECT(expected == expression.keys()); EXPECT(expected == expression.keys());
} }

View File

@ -25,10 +25,6 @@
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/list_of.hpp>
using boost::assign::list_of;
using boost::assign::map_list_of;
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;
@ -90,7 +86,7 @@ Vector f3(const Point3& p, OptionalJacobian<Eigen::Dynamic, 3> H) {
return p; return p;
} }
Point3_ pointExpression(1); Point3_ pointExpression(1);
set<Key> expected = list_of(1); const set<Key> expected{1};
} // namespace unary } // namespace unary
// Create a unary expression that takes another expression as a single argument. // Create a unary expression that takes another expression as a single argument.
@ -190,14 +186,14 @@ TEST(Expression, BinaryToDouble) {
/* ************************************************************************* */ /* ************************************************************************* */
// Check keys of an expression created from class method. // Check keys of an expression created from class method.
TEST(Expression, BinaryKeys) { TEST(Expression, BinaryKeys) {
set<Key> expected = list_of(1)(2); const set<Key> expected{1, 2};
EXPECT(expected == binary::p_cam.keys()); EXPECT(expected == binary::p_cam.keys());
} }
/* ************************************************************************* */ /* ************************************************************************* */
// Check dimensions by calling `dims` method. // Check dimensions by calling `dims` method.
TEST(Expression, BinaryDimensions) { TEST(Expression, BinaryDimensions) {
map<Key, int> actual, expected = map_list_of<Key, int>(1, 6)(2, 3); map<Key, int> actual, expected{{1, 6}, {2, 3}};
binary::p_cam.dims(actual); binary::p_cam.dims(actual);
EXPECT(actual == expected); EXPECT(actual == expected);
} }
@ -227,14 +223,14 @@ Expression<Point2> uv_hat(uncalibrate<Cal3_S2>, K, projection);
/* ************************************************************************* */ /* ************************************************************************* */
// keys // keys
TEST(Expression, TreeKeys) { TEST(Expression, TreeKeys) {
set<Key> expected = list_of(1)(2)(3); const set<Key> expected{1, 2, 3};
EXPECT(expected == tree::uv_hat.keys()); EXPECT(expected == tree::uv_hat.keys());
} }
/* ************************************************************************* */ /* ************************************************************************* */
// dimensions // dimensions
TEST(Expression, TreeDimensions) { TEST(Expression, TreeDimensions) {
map<Key, int> actual, expected = map_list_of<Key, int>(1, 6)(2, 3)(3, 5); map<Key, int> actual, expected{{1, 6}, {2, 3}, {3, 5}};
tree::uv_hat.dims(actual); tree::uv_hat.dims(actual);
EXPECT(actual == expected); EXPECT(actual == expected);
} }
@ -265,7 +261,7 @@ TEST(Expression, compose1) {
Rot3_ R3 = R1 * R2; Rot3_ R3 = R1 * R2;
// Check keys // Check keys
set<Key> expected = list_of(1)(2); const set<Key> expected{1, 2};
EXPECT(expected == R3.keys()); EXPECT(expected == R3.keys());
} }
@ -277,7 +273,7 @@ TEST(Expression, compose2) {
Rot3_ R3 = R1 * R2; Rot3_ R3 = R1 * R2;
// Check keys // Check keys
set<Key> expected = list_of(1); const set<Key> expected{1};
EXPECT(expected == R3.keys()); EXPECT(expected == R3.keys());
} }
@ -289,7 +285,7 @@ TEST(Expression, compose3) {
Rot3_ R3 = R1 * R2; Rot3_ R3 = R1 * R2;
// Check keys // Check keys
set<Key> expected = list_of(3); const set<Key> expected{3};
EXPECT(expected == R3.keys()); EXPECT(expected == R3.keys());
} }
@ -302,7 +298,7 @@ TEST(Expression, compose4) {
Double_ R3 = R1 * R2; Double_ R3 = R1 * R2;
// Check keys // Check keys
set<Key> expected = list_of(1); const set<Key> expected{1};
EXPECT(expected == R3.keys()); EXPECT(expected == R3.keys());
} }
@ -326,7 +322,7 @@ TEST(Expression, ternary) {
Rot3_ ABC(composeThree, A, B, C); Rot3_ ABC(composeThree, A, B, C);
// Check keys // Check keys
set<Key> expected = list_of(1)(2)(3); const set<Key> expected {1, 2, 3};
EXPECT(expected == ABC.keys()); EXPECT(expected == ABC.keys());
} }
@ -336,10 +332,10 @@ TEST(Expression, ScalarMultiply) {
const Key key(67); const Key key(67);
const Point3_ expr = 23 * Point3_(key); const Point3_ expr = 23 * Point3_(key);
set<Key> expected_keys = list_of(key); const set<Key> expected_keys{key};
EXPECT(expected_keys == expr.keys()); EXPECT(expected_keys == expr.keys());
map<Key, int> actual_dims, expected_dims = map_list_of<Key, int>(key, 3); map<Key, int> actual_dims, expected_dims {{key, 3}};
expr.dims(actual_dims); expr.dims(actual_dims);
EXPECT(actual_dims == expected_dims); EXPECT(actual_dims == expected_dims);
@ -367,10 +363,10 @@ TEST(Expression, BinarySum) {
const Key key(67); const Key key(67);
const Point3_ sum_ = Point3_(key) + Point3_(Point3(1, 1, 1)); const Point3_ sum_ = Point3_(key) + Point3_(Point3(1, 1, 1));
set<Key> expected_keys = list_of(key); const set<Key> expected_keys{key};
EXPECT(expected_keys == sum_.keys()); EXPECT(expected_keys == sum_.keys());
map<Key, int> actual_dims, expected_dims = map_list_of<Key, int>(key, 3); map<Key, int> actual_dims, expected_dims {{key, 3}};
sum_.dims(actual_dims); sum_.dims(actual_dims);
EXPECT(actual_dims == expected_dims); EXPECT(actual_dims == expected_dims);
@ -462,7 +458,7 @@ TEST(Expression, UnaryOfSum) {
const Point3_ sum_ = Point3_(key1) + Point3_(key2); const Point3_ sum_ = Point3_(key1) + Point3_(key2);
const Double_ norm_(&gtsam::norm3, sum_); const Double_ norm_(&gtsam::norm3, sum_);
map<Key, int> actual_dims, expected_dims = map_list_of<Key, int>(key1, 3)(key2, 3); map<Key, int> actual_dims, expected_dims = {{key1, 3}, {key2, 3}};
norm_.dims(actual_dims); norm_.dims(actual_dims);
EXPECT(actual_dims == expected_dims); EXPECT(actual_dims == expected_dims);
@ -485,7 +481,7 @@ TEST(Expression, WeightedSum) {
const Key key1(42), key2(67); const Key key1(42), key2(67);
const Point3_ weighted_sum_ = 17 * Point3_(key1) + 23 * Point3_(key2); const Point3_ weighted_sum_ = 17 * Point3_(key1) + 23 * Point3_(key2);
map<Key, int> actual_dims, expected_dims = map_list_of<Key, int>(key1, 3)(key2, 3); map<Key, int> actual_dims, expected_dims {{key1, 3}, {key2, 3}};
weighted_sum_.dims(actual_dims); weighted_sum_.dims(actual_dims);
EXPECT(actual_dims == expected_dims); EXPECT(actual_dims == expected_dims);

View File

@ -15,10 +15,7 @@
#include <gtsam/nonlinear/LinearContainerFactor.h> #include <gtsam/nonlinear/LinearContainerFactor.h>
#include <gtsam/slam/BetweenFactor.h> #include <gtsam/slam/BetweenFactor.h>
#include <boost/assign/std/vector.hpp>
using namespace std; using namespace std;
using namespace boost::assign;
using namespace gtsam; using namespace gtsam;
const gtsam::noiseModel::Diagonal::shared_ptr diag_model2 = noiseModel::Diagonal::Sigmas(Vector2(1.0, 1.0)); const gtsam::noiseModel::Diagonal::shared_ptr diag_model2 = noiseModel::Diagonal::Sigmas(Vector2(1.0, 1.0));

View File

@ -25,15 +25,11 @@
#include <gtsam/base/TestableAssertions.h> #include <gtsam/base/TestableAssertions.h>
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/list.hpp> // for operator +=
#include <boost/assign/std/vector.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/bind/bind.hpp> #include <boost/bind/bind.hpp>
#include <stdexcept> #include <stdexcept>
#include <limits> #include <limits>
#include <type_traits> #include <type_traits>
using namespace boost::assign;
using namespace std::placeholders; using namespace std::placeholders;
using namespace gtsam; using namespace gtsam;
using namespace std; using namespace std;
@ -224,9 +220,8 @@ TEST(Values, retract_full)
config0.insert(key1, Vector3(1.0, 2.0, 3.0)); config0.insert(key1, Vector3(1.0, 2.0, 3.0));
config0.insert(key2, Vector3(5.0, 6.0, 7.0)); config0.insert(key2, Vector3(5.0, 6.0, 7.0));
VectorValues delta = pair_list_of<Key, Vector> VectorValues delta {{key1, Vector3(1.0, 1.1, 1.2)},
(key1, Vector3(1.0, 1.1, 1.2)) {key2, Vector3(1.3, 1.4, 1.5)}};
(key2, Vector3(1.3, 1.4, 1.5));
Values expected; Values expected;
expected.insert(key1, Vector3(2.0, 3.1, 4.2)); expected.insert(key1, Vector3(2.0, 3.1, 4.2));
@ -243,8 +238,7 @@ TEST(Values, retract_partial)
config0.insert(key1, Vector3(1.0, 2.0, 3.0)); config0.insert(key1, Vector3(1.0, 2.0, 3.0));
config0.insert(key2, Vector3(5.0, 6.0, 7.0)); config0.insert(key2, Vector3(5.0, 6.0, 7.0));
VectorValues delta = pair_list_of<Key, Vector> VectorValues delta {{key2, Vector3(1.3, 1.4, 1.5)}};
(key2, Vector3(1.3, 1.4, 1.5));
Values expected; Values expected;
expected.insert(key1, Vector3(1.0, 2.0, 3.0)); expected.insert(key1, Vector3(1.0, 2.0, 3.0));
@ -279,9 +273,8 @@ TEST(Values, localCoordinates)
valuesA.insert(key1, Vector3(1.0, 2.0, 3.0)); valuesA.insert(key1, Vector3(1.0, 2.0, 3.0));
valuesA.insert(key2, Vector3(5.0, 6.0, 7.0)); valuesA.insert(key2, Vector3(5.0, 6.0, 7.0));
VectorValues expDelta = pair_list_of<Key, Vector> VectorValues expDelta{{key1, Vector3(0.1, 0.2, 0.3)},
(key1, Vector3(0.1, 0.2, 0.3)) {key2, Vector3(0.4, 0.5, 0.6)}};
(key2, Vector3(0.4, 0.5, 0.6));
Values valuesB = valuesA.retract(expDelta); Values valuesB = valuesA.retract(expDelta);

View File

@ -18,8 +18,6 @@
#include <gtsam/base/Testable.h> #include <gtsam/base/Testable.h>
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/list.hpp> // for operator +=
using namespace boost::assign;
using namespace gtsam; using namespace gtsam;
using namespace std; using namespace std;

View File

@ -22,8 +22,6 @@
#include <gtsam/linear/JacobianFactor.h> #include <gtsam/linear/JacobianFactor.h>
#include <gtsam/nonlinear/NonlinearFactor.h> #include <gtsam/nonlinear/NonlinearFactor.h>
#include <boost/assign/list_of.hpp>
namespace gtsam { namespace gtsam {
/** /**
* The ShonanGaugeFactor creates a constraint on a single SO(n) to avoid moving * The ShonanGaugeFactor creates a constraint on a single SO(n) to avoid moving
@ -59,7 +57,7 @@ public:
*/ */
ShonanGaugeFactor(Key key, size_t p, size_t d = 3, ShonanGaugeFactor(Key key, size_t p, size_t d = 3,
boost::optional<double> gamma = boost::none) boost::optional<double> gamma = boost::none)
: NonlinearFactor(boost::assign::cref_list_of<1>(key)) { : NonlinearFactor(KeyVector{key}) {
if (p < d) { if (p < d) {
throw std::invalid_argument("ShonanGaugeFactor must have p>=d."); throw std::invalid_argument("ShonanGaugeFactor must have p>=d.");
} }

View File

@ -41,7 +41,6 @@
#include <gtsam/base/Vector.h> #include <gtsam/base/Vector.h>
#include <gtsam/base/types.h> #include <gtsam/base/types.h>
#include <boost/assign/list_inserter.hpp>
#include <boost/filesystem/operations.hpp> #include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>

View File

@ -28,10 +28,8 @@
#include <gtsam/inference/Symbol.h> #include <gtsam/inference/Symbol.h>
#include <gtsam/base/Testable.h> #include <gtsam/base/Testable.h>
#include <boost/assign/std/vector.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
using namespace boost::assign;
#include <iostream> #include <iostream>
#include <vector> #include <vector>
@ -456,8 +454,8 @@ TEST(GeneralSFMFactor, BinaryJacobianFactor) {
using namespace noiseModel; using namespace noiseModel;
Rot2 R = Rot2::fromAngle(0.3); Rot2 R = Rot2::fromAngle(0.3);
Matrix2 cov = R.matrix() * R.matrix().transpose(); Matrix2 cov = R.matrix() * R.matrix().transpose();
models += SharedNoiseModel(), Unit::Create(2), // models = {SharedNoiseModel(), Unit::Create(2), Isotropic::Sigma(2, 0.5),
Isotropic::Sigma(2, 0.5), Constrained::All(2), Gaussian::Covariance(cov); Constrained::All(2), Gaussian::Covariance(cov)};
} }
// Now loop over all these noise models // Now loop over all these noise models

View File

@ -29,7 +29,6 @@
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;
using namespace boost::assign;
static Symbol x0('x', 0), x1('x', 1), x2('x', 2), x3('x', 3); static Symbol x0('x', 0), x1('x', 1), x2('x', 2), x3('x', 3);
static SharedNoiseModel model(noiseModel::Isotropic::Sigma(6, 0.1)); static SharedNoiseModel model(noiseModel::Isotropic::Sigma(6, 0.1));
@ -156,7 +155,7 @@ TEST( InitializePose3, orientationsGradientSymbolicGraph ) {
/* *************************************************************************** */ /* *************************************************************************** */
TEST( InitializePose3, singleGradient ) { TEST( InitializePose3, singleGradient ) {
Rot3 R1 = Rot3(); Rot3 R1 = Rot3();
Matrix M = Matrix3::Zero(); Matrix M = Z_3x3;
M(0,1) = -1; M(1,0) = 1; M(2,2) = 1; M(0,1) = -1; M(1,0) = 1; M(2,2) = 1;
Rot3 R2 = Rot3(M); Rot3 R2 = Rot3(M);
double a = 6.010534238540223; double a = 6.010534238540223;

View File

@ -31,7 +31,6 @@
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;
using namespace boost::assign;
static Symbol x0('x', 0), x1('x', 1), x2('x', 2), x3('x', 3); static Symbol x0('x', 0), x1('x', 1), x2('x', 2), x3('x', 3);
static SharedNoiseModel model(noiseModel::Isotropic::Sigma(3, 0.1)); static SharedNoiseModel model(noiseModel::Isotropic::Sigma(3, 0.1));

View File

@ -25,10 +25,6 @@
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/vector.hpp>
#include <boost/assign/std.hpp>
using namespace boost::assign;
using namespace std::placeholders; using namespace std::placeholders;
using namespace gtsam; using namespace gtsam;
using namespace std; using namespace std;

View File

@ -27,14 +27,11 @@
#include <gtsam/linear/GaussianFactor.h> #include <gtsam/linear/GaussianFactor.h>
#include <gtsam/base/timing.h> #include <gtsam/base/timing.h>
#include <boost/assign/list_of.hpp>
#include <boost/assign/std/vector.hpp>
#include <boost/range/iterator_range.hpp> #include <boost/range/iterator_range.hpp>
#include <boost/range/adaptor/map.hpp> #include <boost/range/adaptor/map.hpp>
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
using namespace std; using namespace std;
using namespace boost::assign;
using namespace gtsam; using namespace gtsam;
// F // F
@ -68,17 +65,15 @@ TEST( regularImplicitSchurFactor, addHessianMultiply ) {
Matrix3 P = (E.transpose() * E).inverse(); Matrix3 P = (E.transpose() * E).inverse();
double alpha = 0.5; double alpha = 0.5;
VectorValues xvalues = map_list_of // VectorValues xvalues{{0, Vector::Constant(6, 2)}, //
(0, Vector::Constant(6, 2))// {1, Vector::Constant(6, 4)}, //
(1, Vector::Constant(6, 4))// {2, Vector::Constant(6, 0)}, // distractor
(2, Vector::Constant(6, 0))// distractor {3, Vector::Constant(6, 8)}};
(3, Vector::Constant(6, 8));
VectorValues yExpected = map_list_of// VectorValues yExpected{{0, Vector::Constant(6, 27)}, //
(0, Vector::Constant(6, 27))// {1, Vector::Constant(6, -40)}, //
(1, Vector::Constant(6, -40))// {2, Vector::Constant(6, 0)}, // distractor
(2, Vector::Constant(6, 0))// distractor {3, Vector::Constant(6, 279)}};
(3, Vector::Constant(6, 279));
// Create full F // Create full F
size_t M=4, m = 3, d = 6; size_t M=4, m = 3, d = 6;

View File

@ -12,11 +12,9 @@
#include <gtsam/base/numericalDerivative.h> #include <gtsam/base/numericalDerivative.h>
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/vector.hpp>
#include <vector> #include <vector>
using namespace std; using namespace std;
using namespace boost::assign;
using namespace std::placeholders; using namespace std::placeholders;
using namespace gtsam; using namespace gtsam;

View File

@ -25,7 +25,6 @@
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/map.hpp>
#include <iostream> #include <iostream>
namespace { namespace {

View File

@ -23,11 +23,8 @@
#include <gtsam/slam/SmartProjectionFactor.h> #include <gtsam/slam/SmartProjectionFactor.h>
#include <gtsam/nonlinear/LevenbergMarquardtOptimizer.h> #include <gtsam/nonlinear/LevenbergMarquardtOptimizer.h>
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/map.hpp>
#include <iostream> #include <iostream>
using namespace boost::assign;
namespace { namespace {
static const bool isDebugTest = false; static const bool isDebugTest = false;
static const Symbol l1('l', 1), l2('l', 2), l3('l', 3); static const Symbol l1('l', 1), l2('l', 2), l3('l', 3);
@ -802,9 +799,9 @@ TEST(SmartProjectionFactor, implicitJacobianFactor ) {
Implicit9& implicitSchurFactor = Implicit9& implicitSchurFactor =
dynamic_cast<Implicit9&>(*gaussianImplicitSchurFactor); dynamic_cast<Implicit9&>(*gaussianImplicitSchurFactor);
VectorValues x = map_list_of(c1, VectorValues x{
(Vector(9) << 1, 2, 3, 4, 5, 6, 7, 8, 9).finished())(c2, {c1, (Vector(9) << 1, 2, 3, 4, 5, 6, 7, 8, 9).finished()},
(Vector(9) << 11, 12, 13, 14, 15, 16, 17, 18, 19).finished()); {c2, (Vector(9) << 11, 12, 13, 14, 15, 16, 17, 18, 19).finished()}};
VectorValues yExpected, yActual; VectorValues yExpected, yActual;
double alpha = 1.0; double alpha = 1.0;

View File

@ -25,10 +25,8 @@
#include <gtsam/nonlinear/LevenbergMarquardtOptimizer.h> #include <gtsam/nonlinear/LevenbergMarquardtOptimizer.h>
#include <gtsam/base/numericalDerivative.h> #include <gtsam/base/numericalDerivative.h>
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/map.hpp>
#include <iostream> #include <iostream>
using namespace boost::assign;
using namespace std::placeholders; using namespace std::placeholders;
namespace { namespace {
@ -437,7 +435,7 @@ TEST( SmartProjectionPoseFactor, Factors ) {
E(2, 0) = 10; E(2, 0) = 10;
E(2, 2) = 1; E(2, 2) = 1;
E(3, 1) = 10; E(3, 1) = 10;
SmartFactor::FBlocks Fs = list_of<Matrix>(F1)(F2); SmartFactor::FBlocks Fs {F1, F2};
Vector b(4); Vector b(4);
b.setZero(); b.setZero();

View File

@ -25,13 +25,11 @@
#include <gtsam/nonlinear/LevenbergMarquardtOptimizer.h> #include <gtsam/nonlinear/LevenbergMarquardtOptimizer.h>
#include <gtsam/slam/PoseTranslationPrior.h> #include <gtsam/slam/PoseTranslationPrior.h>
#include <boost/assign/std/map.hpp>
#include <iostream> #include <iostream>
#include "smartFactorScenarios.h" #include "smartFactorScenarios.h"
#define DISABLE_TIMING #define DISABLE_TIMING
using namespace boost::assign;
using namespace std::placeholders; using namespace std::placeholders;
static const double rankTol = 1.0; static const double rankTol = 1.0;

View File

@ -25,13 +25,10 @@
#include <gtsam/base/numericalDerivative.h> #include <gtsam/base/numericalDerivative.h>
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign.hpp>
#include <boost/assign/std/vector.hpp>
#include <boost/bind/bind.hpp> #include <boost/bind/bind.hpp>
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;
using namespace boost::assign;
using namespace std::placeholders; using namespace std::placeholders;
// Some common constants // Some common constants

View File

@ -60,6 +60,29 @@ namespace gtsam {
explicit SymbolicBayesNet(const FactorGraph<DERIVEDCONDITIONAL>& graph) explicit SymbolicBayesNet(const FactorGraph<DERIVEDCONDITIONAL>& graph)
: Base(graph) {} : Base(graph) {}
/**
* Constructor that takes an initializer list of shared pointers.
* SymbolicBayesNet bn = {make_shared<SymbolicConditional>(), ...};
*/
SymbolicBayesNet(std::initializer_list<boost::shared_ptr<SymbolicConditional>> conditionals)
: Base(conditionals) {}
/// Construct from a single conditional
SymbolicBayesNet(SymbolicConditional&& c) {
push_back(boost::make_shared<SymbolicConditional>(c));
}
/**
* @brief Add a single conditional and return a reference.
* This allows for chaining, e.g.,
* SymbolicBayesNet bn =
* SymbolicBayesNet(SymbolicConditional(...))(SymbolicConditional(...));
*/
SymbolicBayesNet& operator()(SymbolicConditional&& c) {
push_back(boost::make_shared<SymbolicConditional>(c));
return *this;
}
/// Destructor /// Destructor
virtual ~SymbolicBayesNet() {} virtual ~SymbolicBayesNet() {}

View File

@ -22,7 +22,6 @@
#include <gtsam/base/Testable.h> #include <gtsam/base/Testable.h>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
#include <utility> #include <utility>
@ -55,27 +54,27 @@ namespace gtsam {
/** Construct unary factor */ /** Construct unary factor */
explicit SymbolicFactor(Key j) : explicit SymbolicFactor(Key j) :
Base(boost::assign::cref_list_of<1>(j)) {} Base(KeyVector{j}) {}
/** Construct binary factor */ /** Construct binary factor */
SymbolicFactor(Key j1, Key j2) : SymbolicFactor(Key j1, Key j2) :
Base(boost::assign::cref_list_of<2>(j1)(j2)) {} Base(KeyVector{j1, j2}) {}
/** Construct ternary factor */ /** Construct ternary factor */
SymbolicFactor(Key j1, Key j2, Key j3) : SymbolicFactor(Key j1, Key j2, Key j3) :
Base(boost::assign::cref_list_of<3>(j1)(j2)(j3)) {} Base(KeyVector{j1, j2, j3}) {}
/** Construct 4-way factor */ /** Construct 4-way factor */
SymbolicFactor(Key j1, Key j2, Key j3, Key j4) : SymbolicFactor(Key j1, Key j2, Key j3, Key j4) :
Base(boost::assign::cref_list_of<4>(j1)(j2)(j3)(j4)) {} Base(KeyVector{j1, j2, j3, j4}) {}
/** Construct 5-way factor */ /** Construct 5-way factor */
SymbolicFactor(Key j1, Key j2, Key j3, Key j4, Key j5) : SymbolicFactor(Key j1, Key j2, Key j3, Key j4, Key j5) :
Base(boost::assign::cref_list_of<5>(j1)(j2)(j3)(j4)(j5)) {} Base(KeyVector{j1, j2, j3, j4, j5}) {}
/** Construct 6-way factor */ /** Construct 6-way factor */
SymbolicFactor(Key j1, Key j2, Key j3, Key j4, Key j5, Key j6) : SymbolicFactor(Key j1, Key j2, Key j3, Key j4, Key j5, Key j6) :
Base(boost::assign::cref_list_of<6>(j1)(j2)(j3)(j4)(j5)(j6)) {} Base(KeyVector{j1, j2, j3, j4, j5, j6}) {}
/** Create symbolic version of any factor */ /** Create symbolic version of any factor */
explicit SymbolicFactor(const Factor& factor) : Base(factor.keys()) {} explicit SymbolicFactor(const Factor& factor) : Base(factor.keys()) {}
@ -125,15 +124,15 @@ namespace gtsam {
return result; return result;
} }
/** Constructor from a collection of keys - compatible with boost::assign::list_of and /** Constructor from a collection of keys - compatible with boost assign::list_of and
* boost::assign::cref_list_of */ * boost assign::cref_list_of */
template<class CONTAINER> template<class CONTAINER>
static SymbolicFactor FromKeys(const CONTAINER& keys) { static SymbolicFactor FromKeys(const CONTAINER& keys) {
return SymbolicFactor(Base::FromKeys(keys)); return SymbolicFactor(Base::FromKeys(keys));
} }
/** Constructor from a collection of keys - compatible with boost::assign::list_of and /** Constructor from a collection of keys - compatible with boost assign::list_of and
* boost::assign::cref_list_of */ * boost assign::cref_list_of */
template<class CONTAINER> template<class CONTAINER>
static SymbolicFactor::shared_ptr FromKeysShared(const CONTAINER& keys) { static SymbolicFactor::shared_ptr FromKeysShared(const CONTAINER& keys) {
return FromIteratorsShared(keys.begin(), keys.end()); return FromIteratorsShared(keys.begin(), keys.end());

View File

@ -87,6 +87,30 @@ namespace gtsam {
template<class DERIVEDFACTOR> template<class DERIVEDFACTOR>
SymbolicFactorGraph(const FactorGraph<DERIVEDFACTOR>& graph) : Base(graph) {} SymbolicFactorGraph(const FactorGraph<DERIVEDFACTOR>& graph) : Base(graph) {}
/**
* Constructor that takes an initializer list of shared pointers.
* FactorGraph fg = {make_shared<MyFactor>(), ...};
*/
SymbolicFactorGraph(
std::initializer_list<boost::shared_ptr<SymbolicFactor>> sharedFactors)
: Base(sharedFactors) {}
/// Construct from a single factor
SymbolicFactorGraph(SymbolicFactor&& c) {
push_back(boost::make_shared<SymbolicFactor>(c));
}
/**
* @brief Add a single factor and return a reference.
* This allows for chaining, e.g.,
* SymbolicFactorGraph bn =
* SymbolicFactorGraph(SymbolicFactor(...))(SymbolicFactor(...));
*/
SymbolicFactorGraph& operator()(SymbolicFactor&& c) {
push_back(boost::make_shared<SymbolicFactor>(c));
return *this;
}
/// Destructor /// Destructor
virtual ~SymbolicFactorGraph() {} virtual ~SymbolicFactorGraph() {}

View File

@ -1,6 +1,6 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* GTSAM Copyright 2010, Georgia Tech Research Corporation, * GTSAM Copyright 2010-2023, Georgia Tech Research Corporation,
* Atlanta, Georgia 30332-0415 * Atlanta, Georgia 30332-0415
* All Rights Reserved * All Rights Reserved
* Authors: Frank Dellaert, et al. (see THANKS for the full author list) * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
@ -10,7 +10,7 @@
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
/* /*
* @file symbolicExampleGraphs.cpp * @file symbolicExampleGraphs.h
* @date sept 15, 2012 * @date sept 15, 2012
* @author Frank Dellaert * @author Frank Dellaert
* @author Michael Kaess * @author Michael Kaess
@ -20,58 +20,74 @@
#pragma once #pragma once
#include <gtsam/base/FastDefaultAllocator.h>
#include <gtsam/symbolic/SymbolicFactorGraph.h> #include <gtsam/symbolic/SymbolicFactorGraph.h>
#include <gtsam/symbolic/SymbolicFactor.h> #include <gtsam/symbolic/SymbolicFactor.h>
#include <gtsam/symbolic/SymbolicConditional.h> #include <gtsam/symbolic/SymbolicConditional.h>
#include <gtsam/symbolic/SymbolicBayesTree.h> #include <gtsam/symbolic/SymbolicBayesTree.h>
#include <gtsam/inference/Ordering.h> #include <gtsam/inference/Ordering.h>
#include <gtsam/inference/Symbol.h> #include <gtsam/inference/Symbol.h>
#include <boost/assign/list_of.hpp>
namespace gtsam { namespace gtsam {
namespace { namespace {
const SymbolicFactorGraph simpleTestGraph1 = boost::assign::list_of // A small helper class to replace Boost's `list_of` function.
(boost::make_shared<SymbolicFactor>(0,1)) template <typename T>
(boost::make_shared<SymbolicFactor>(0,2)) struct ChainedVector {
(boost::make_shared<SymbolicFactor>(1,4)) using Result = std::vector<T, typename internal::FastDefaultAllocator<T>::type>;
(boost::make_shared<SymbolicFactor>(2,4)) Result result;
(boost::make_shared<SymbolicFactor>(3,4));
const SymbolicBayesNet simpleTestGraph1BayesNet = boost::assign::list_of ChainedVector(const T& c) { result.push_back(c); }
(boost::make_shared<SymbolicConditional>(0,1,2))
(boost::make_shared<SymbolicConditional>(1,2,4))
(boost::make_shared<SymbolicConditional>(2,4))
(boost::make_shared<SymbolicConditional>(3,4))
(boost::make_shared<SymbolicConditional>(4));
const SymbolicFactorGraph simpleTestGraph2 = boost::assign::list_of ChainedVector& operator()(const T& c) {
(boost::make_shared<SymbolicFactor>(0,1)) result.push_back(c);
(boost::make_shared<SymbolicFactor>(0,2)) return *this;
(boost::make_shared<SymbolicFactor>(1,3)) }
(boost::make_shared<SymbolicFactor>(1,4))
(boost::make_shared<SymbolicFactor>(2,3)) operator Result() { return result; }
(boost::make_shared<SymbolicFactor>(4,5)); };
const SymbolicFactorGraph simpleTestGraph1 {
boost::make_shared<SymbolicFactor>(0,1),
boost::make_shared<SymbolicFactor>(0,2),
boost::make_shared<SymbolicFactor>(1,4),
boost::make_shared<SymbolicFactor>(2,4),
boost::make_shared<SymbolicFactor>(3,4)};
const SymbolicBayesNet simpleTestGraph1BayesNet {
boost::make_shared<SymbolicConditional>(0,1,2),
boost::make_shared<SymbolicConditional>(1,2,4),
boost::make_shared<SymbolicConditional>(2,4),
boost::make_shared<SymbolicConditional>(3,4),
boost::make_shared<SymbolicConditional>(4)};
const SymbolicFactorGraph simpleTestGraph2 {
boost::make_shared<SymbolicFactor>(0,1),
boost::make_shared<SymbolicFactor>(0,2),
boost::make_shared<SymbolicFactor>(1,3),
boost::make_shared<SymbolicFactor>(1,4),
boost::make_shared<SymbolicFactor>(2,3),
boost::make_shared<SymbolicFactor>(4,5)};
/** 1 - 0 - 2 - 3 */ /** 1 - 0 - 2 - 3 */
const SymbolicFactorGraph simpleChain = boost::assign::list_of const SymbolicFactorGraph simpleChain {
(boost::make_shared<SymbolicFactor>(1,0)) boost::make_shared<SymbolicFactor>(1,0),
(boost::make_shared<SymbolicFactor>(0,2)) boost::make_shared<SymbolicFactor>(0,2),
(boost::make_shared<SymbolicFactor>(2,3)); boost::make_shared<SymbolicFactor>(2,3)};
/* ************************************************************************* * /* ************************************************************************* *
* 2 3 * 2 3
* 0 1 : 2 * 0 1 : 2
****************************************************************************/ ****************************************************************************/
SymbolicBayesTree __simpleChainBayesTree() { SymbolicBayesTree __simpleChainBayesTree() {
SymbolicBayesTree result; SymbolicBayesTree result;
result.insertRoot(boost::make_shared<SymbolicBayesTreeClique>( result.insertRoot(boost::make_shared<SymbolicBayesTreeClique>(
boost::make_shared<SymbolicConditional>( boost::make_shared<SymbolicConditional>(
SymbolicConditional::FromKeys(boost::assign::list_of(2)(3), 2)))); SymbolicConditional::FromKeys(KeyVector{2,3}, 2))));
result.addClique(boost::make_shared<SymbolicBayesTreeClique>( result.addClique(boost::make_shared<SymbolicBayesTreeClique>(
boost::make_shared<SymbolicConditional>( boost::make_shared<SymbolicConditional>(
SymbolicConditional::FromKeys(boost::assign::list_of(0)(1)(2), 2))), SymbolicConditional::FromKeys(KeyVector{0,1,2}, 2))),
result.roots().front()); result.roots().front());
return result; return result;
} }
@ -79,52 +95,67 @@ namespace gtsam {
/* ************************************************************************* */ /* ************************************************************************* */
// Keys for ASIA example from the tutorial with A and D evidence // Keys for ASIA example from the tutorial with A and D evidence
const Key _X_=gtsam::symbol_shorthand::X(0), _T_=gtsam::symbol_shorthand::T(0), const Key _X_ = symbol_shorthand::X(0),
_S_=gtsam::symbol_shorthand::S(0), _E_=gtsam::symbol_shorthand::E(0), _T_ = symbol_shorthand::T(0),
_L_=gtsam::symbol_shorthand::L(0), _B_=gtsam::symbol_shorthand::B(0); _S_ = symbol_shorthand::S(0),
_E_ = symbol_shorthand::E(0),
_L_ = symbol_shorthand::L(0),
_B_ = symbol_shorthand::B(0);
// Factor graph for Asia example // Factor graph for Asia example
const SymbolicFactorGraph asiaGraph = boost::assign::list_of const SymbolicFactorGraph asiaGraph = {
(boost::make_shared<SymbolicFactor>(_T_)) boost::make_shared<SymbolicFactor>(_T_),
(boost::make_shared<SymbolicFactor>(_S_)) boost::make_shared<SymbolicFactor>(_S_),
(boost::make_shared<SymbolicFactor>(_T_, _E_, _L_)) boost::make_shared<SymbolicFactor>(_T_, _E_, _L_),
(boost::make_shared<SymbolicFactor>(_L_, _S_)) boost::make_shared<SymbolicFactor>(_L_, _S_),
(boost::make_shared<SymbolicFactor>(_S_, _B_)) boost::make_shared<SymbolicFactor>(_S_, _B_),
(boost::make_shared<SymbolicFactor>(_E_, _B_)) boost::make_shared<SymbolicFactor>(_E_, _B_),
(boost::make_shared<SymbolicFactor>(_E_, _X_)); boost::make_shared<SymbolicFactor>(_E_, _X_)};
const SymbolicBayesNet asiaBayesNet = boost::assign::list_of const SymbolicBayesNet asiaBayesNet = {
(boost::make_shared<SymbolicConditional>(_T_, _E_, _L_)) boost::make_shared<SymbolicConditional>(_T_, _E_, _L_),
(boost::make_shared<SymbolicConditional>(_X_, _E_)) boost::make_shared<SymbolicConditional>(_X_, _E_),
(boost::make_shared<SymbolicConditional>(_E_, _B_, _L_)) boost::make_shared<SymbolicConditional>(_E_, _B_, _L_),
(boost::make_shared<SymbolicConditional>(_S_, _B_, _L_)) boost::make_shared<SymbolicConditional>(_S_, _B_, _L_),
(boost::make_shared<SymbolicConditional>(_L_, _B_)) boost::make_shared<SymbolicConditional>(_L_, _B_),
(boost::make_shared<SymbolicConditional>(_B_)); boost::make_shared<SymbolicConditional>(_B_)};
/* ************************************************************************* */
// Allow creating Cliques and Keys in `list_of` chaining style:
using sharedClique = SymbolicBayesTreeClique::shared_ptr;
using Children = ChainedVector<sharedClique>;
using Keys = ChainedVector<Key>;
inline sharedClique LeafClique(const Keys::Result& keys,
DenseIndex nrFrontals) {
return boost::make_shared<SymbolicBayesTreeClique>(
boost::make_shared<SymbolicConditional>(
SymbolicConditional::FromKeys(keys, nrFrontals)));
}
inline sharedClique NodeClique(const Keys::Result& keys,
DenseIndex nrFrontals,
const Children::Result& children) {
sharedClique clique = LeafClique(keys, nrFrontals);
clique->children.assign(children.begin(), children.end());
for (auto&& child : children) child->parent_ = clique;
return clique;
}
/* ************************************************************************* */
// BayesTree for Asia example
SymbolicBayesTree __asiaBayesTree() { SymbolicBayesTree __asiaBayesTree() {
SymbolicBayesTree result; SymbolicBayesTree result;
result.insertRoot(boost::make_shared<SymbolicBayesTreeClique>( result.insertRoot(LeafClique({_E_, _L_, _B_}, 3));
boost::make_shared<SymbolicConditional>( result.addClique(LeafClique({_S_, _B_, _L_}, 1), result.roots().front());
SymbolicConditional::FromKeys(boost::assign::list_of(_E_)(_L_)(_B_), 3)))); result.addClique(LeafClique({_T_, _E_, _L_}, 1), result.roots().front());
result.addClique(boost::make_shared<SymbolicBayesTreeClique>( result.addClique(LeafClique({_X_, _E_}, 1), result.roots().front());
boost::make_shared<SymbolicConditional>(
SymbolicConditional::FromKeys(boost::assign::list_of(_S_)(_B_) (_L_), 1))),
result.roots().front());
result.addClique(boost::make_shared<SymbolicBayesTreeClique>(
boost::make_shared<SymbolicConditional>(
SymbolicConditional::FromKeys(boost::assign::list_of(_T_)(_E_)(_L_), 1))),
result.roots().front());
result.addClique(boost::make_shared<SymbolicBayesTreeClique>(
boost::make_shared<SymbolicConditional>(
SymbolicConditional::FromKeys(boost::assign::list_of(_X_)(_E_), 1))),
result.roots().front());
return result; return result;
} }
const SymbolicBayesTree asiaBayesTree = __asiaBayesTree(); const SymbolicBayesTree asiaBayesTree = __asiaBayesTree();
/* ************************************************************************* */ /* ************************************************************************* */
const Ordering asiaOrdering = boost::assign::list_of(_X_)(_T_)(_S_)(_E_)(_L_)(_B_); const Ordering asiaOrdering{_X_, _T_, _S_, _E_, _L_, _B_};
} // namespace
} } // namespace gtsam
}

View File

@ -17,16 +17,12 @@
* @author Viorela Ila * @author Viorela Ila
*/ */
#include <gtsam/symbolic/SymbolicBayesTree.h>
#include <gtsam/symbolic/SymbolicBayesNet.h>
#include <gtsam/inference/Symbol.h> #include <gtsam/inference/Symbol.h>
#include <gtsam/symbolic/SymbolicBayesNet.h>
#include <gtsam/symbolic/SymbolicBayesTree.h>
#include <gtsam/symbolic/tests/symbolicExampleGraphs.h> #include <gtsam/symbolic/tests/symbolicExampleGraphs.h>
#include <boost/assign/list_of.hpp>
#include <boost/assign/std/vector.hpp>
#include <boost/assign/std/list.hpp>
#include <boost/range/adaptor/indirected.hpp> #include <boost/range/adaptor/indirected.hpp>
using namespace boost::assign;
using boost::adaptors::indirected; using boost::adaptors::indirected;
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
@ -38,37 +34,8 @@ using namespace gtsam::symbol_shorthand;
static bool debug = false; static bool debug = false;
namespace {
/* ************************************************************************* */
// Helper functions for below
template<typename KEYS>
SymbolicBayesTreeClique::shared_ptr MakeClique(const KEYS& keys, DenseIndex nrFrontals)
{
return boost::make_shared<SymbolicBayesTreeClique>(
boost::make_shared<SymbolicConditional>(
SymbolicConditional::FromKeys(keys, nrFrontals)));
}
template<typename KEYS, typename CHILDREN>
SymbolicBayesTreeClique::shared_ptr MakeClique(
const KEYS& keys, DenseIndex nrFrontals, const CHILDREN& children)
{
SymbolicBayesTreeClique::shared_ptr clique =
boost::make_shared<SymbolicBayesTreeClique>(
boost::make_shared<SymbolicConditional>(
SymbolicConditional::FromKeys(keys, nrFrontals)));
clique->children.assign(children.begin(), children.end());
for(typename CHILDREN::const_iterator child = children.begin(); child != children.end(); ++child)
(*child)->parent_ = clique;
return clique;
}
}
/* ************************************************************************* */ /* ************************************************************************* */
TEST(SymbolicBayesTree, clear) TEST(SymbolicBayesTree, clear) {
{
SymbolicBayesTree bayesTree = asiaBayesTree; SymbolicBayesTree bayesTree = asiaBayesTree;
bayesTree.clear(); bayesTree.clear();
@ -79,34 +46,35 @@ TEST(SymbolicBayesTree, clear)
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST(SymbolicBayesTree, clique_structure) TEST(SymbolicBayesTree, clique_structure) {
{
// l1 l2 // l1 l2
// / | / | // / | / |
// x1 --- x2 --- x3 --- x4 --- x5 // x1 --- x2 --- x3 --- x4 --- x5
// \ | // \ |
// l3 // l3
SymbolicFactorGraph graph; SymbolicFactorGraph graph;
graph += SymbolicFactor(X(1), L(1)); graph.emplace_shared<SymbolicFactor>(X(1), L(1));
graph += SymbolicFactor(X(1), X(2)); graph.emplace_shared<SymbolicFactor>(X(1), X(2));
graph += SymbolicFactor(X(2), L(1)); graph.emplace_shared<SymbolicFactor>(X(2), L(1));
graph += SymbolicFactor(X(2), X(3)); graph.emplace_shared<SymbolicFactor>(X(2), X(3));
graph += SymbolicFactor(X(3), X(4)); graph.emplace_shared<SymbolicFactor>(X(3), X(4));
graph += SymbolicFactor(X(4), L(2)); graph.emplace_shared<SymbolicFactor>(X(4), L(2));
graph += SymbolicFactor(X(4), X(5)); graph.emplace_shared<SymbolicFactor>(X(4), X(5));
graph += SymbolicFactor(L(2), X(5)); graph.emplace_shared<SymbolicFactor>(L(2), X(5));
graph += SymbolicFactor(X(4), L(3)); graph.emplace_shared<SymbolicFactor>(X(4), L(3));
graph += SymbolicFactor(X(5), L(3)); graph.emplace_shared<SymbolicFactor>(X(5), L(3));
SymbolicBayesTree expected; SymbolicBayesTree expected;
expected.insertRoot( expected.insertRoot(
MakeClique(list_of(X(2)) (X(3)), 2, list_of NodeClique(Keys(X(2))(X(3)), 2,
(MakeClique(list_of(X(4)) (X(3)), 1, list_of Children(NodeClique(
(MakeClique(list_of(X(5)) (L(2)) (X(4)), 2, list_of Keys(X(4))(X(3)), 1,
(MakeClique(list_of(L(3)) (X(4)) (X(5)), 1)))))) Children(NodeClique(
(MakeClique(list_of(X(1)) (L(1)) (X(2)), 2)))); Keys(X(5))(L(2))(X(4)), 2,
Children(LeafClique(Keys(L(3))(X(4))(X(5)), 1))))))(
LeafClique(Keys(X(1))(L(1))(X(2)), 2))));
Ordering order = list_of(X(1)) (L(3)) (L(1)) (X(5)) (X(2)) (L(2)) (X(4)) (X(3)); Ordering order{X(1), L(3), L(1), X(5), X(2), L(2), X(4), X(3)};
SymbolicBayesTree actual = *graph.eliminateMultifrontal(order); SymbolicBayesTree actual = *graph.eliminateMultifrontal(order);
@ -120,56 +88,51 @@ Bayes Tree for testing conversion to a forest of orphans needed for incremental.
D|C F|E D|C F|E
*/ */
/* ************************************************************************* */ /* ************************************************************************* */
TEST( BayesTree, removePath ) TEST(BayesTree, removePath) {
{ const Key _A_ = A(0), _B_ = B(0), _C_ = C(0), _D_ = D(0), _E_ = E(0),
const Key _A_=A(0), _B_=B(0), _C_=C(0), _D_=D(0), _E_=E(0), _F_=F(0); _F_ = F(0);
SymbolicBayesTree bayesTreeOrig; SymbolicBayesTree bayesTreeOrig;
bayesTreeOrig.insertRoot( auto left = NodeClique(Keys(_C_)(_A_), 1, {LeafClique(Keys(_D_)(_C_), 1)});
MakeClique(list_of(_A_)(_B_), 2, list_of auto right = NodeClique(Keys(_E_)(_B_), 1, {LeafClique(Keys(_F_)(_E_), 1)});
(MakeClique(list_of(_C_)(_A_), 1, list_of bayesTreeOrig.insertRoot(NodeClique(Keys(_A_)(_B_), 2, {left, right}));
(MakeClique(list_of(_D_)(_C_), 1))))
(MakeClique(list_of(_E_)(_B_), 1, list_of
(MakeClique(list_of(_F_)(_E_), 1))))));
SymbolicBayesTree bayesTree = bayesTreeOrig; SymbolicBayesTree bayesTree = bayesTreeOrig;
// remove C, expected outcome: factor graph with ABC, // remove C, expected outcome: factor graph with ABC,
// Bayes Tree now contains two orphan trees: D|C and E|B,F|E // Bayes Tree now contains two orphan trees: D|C and E|B,F|E
SymbolicFactorGraph expected; SymbolicFactorGraph expected;
expected += SymbolicFactor(_A_,_B_); expected.emplace_shared<SymbolicFactor>(_A_, _B_);
expected += SymbolicFactor(_C_,_A_); expected.emplace_shared<SymbolicFactor>(_C_, _A_);
SymbolicBayesTree::Cliques expectedOrphans; SymbolicBayesTree::Cliques expectedOrphans{bayesTree[_D_], bayesTree[_E_]};
expectedOrphans += bayesTree[_D_], bayesTree[_E_];
SymbolicBayesNet bn; SymbolicBayesNet bn;
SymbolicBayesTree::Cliques orphans; SymbolicBayesTree::Cliques orphans;
bayesTree.removePath(bayesTree[_C_], &bn, &orphans); bayesTree.removePath(bayesTree[_C_], &bn, &orphans);
SymbolicFactorGraph factors(bn); SymbolicFactorGraph factors(bn);
CHECK(assert_equal(expected, factors)); CHECK(assert_equal(expected, factors));
CHECK(assert_container_equal(expectedOrphans|indirected, orphans|indirected)); CHECK(assert_container_equal(expectedOrphans | indirected,
orphans | indirected));
bayesTree = bayesTreeOrig; bayesTree = bayesTreeOrig;
// remove E: factor graph with EB; E|B removed from second orphan tree // remove E: factor graph with EB; E|B removed from second orphan tree
SymbolicFactorGraph expected2; SymbolicFactorGraph expected2;
expected2 += SymbolicFactor(_A_,_B_); expected2.emplace_shared<SymbolicFactor>(_A_, _B_);
expected2 += SymbolicFactor(_E_,_B_); expected2.emplace_shared<SymbolicFactor>(_E_, _B_);
SymbolicBayesTree::Cliques expectedOrphans2; SymbolicBayesTree::Cliques expectedOrphans2{bayesTree[_F_], bayesTree[_C_]};
expectedOrphans2 += bayesTree[_F_];
expectedOrphans2 += bayesTree[_C_];
SymbolicBayesNet bn2; SymbolicBayesNet bn2;
SymbolicBayesTree::Cliques orphans2; SymbolicBayesTree::Cliques orphans2;
bayesTree.removePath(bayesTree[_E_], &bn2, &orphans2); bayesTree.removePath(bayesTree[_E_], &bn2, &orphans2);
SymbolicFactorGraph factors2(bn2); SymbolicFactorGraph factors2(bn2);
CHECK(assert_equal(expected2, factors2)); CHECK(assert_equal(expected2, factors2));
CHECK(assert_container_equal(expectedOrphans2|indirected, orphans2|indirected)); CHECK(assert_container_equal(expectedOrphans2 | indirected,
orphans2 | indirected));
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST( BayesTree, removePath2 ) TEST(BayesTree, removePath2) {
{
SymbolicBayesTree bayesTree = asiaBayesTree; SymbolicBayesTree bayesTree = asiaBayesTree;
// Call remove-path with clique B // Call remove-path with clique B
@ -180,16 +143,16 @@ TEST( BayesTree, removePath2 )
// Check expected outcome // Check expected outcome
SymbolicFactorGraph expected; SymbolicFactorGraph expected;
expected += SymbolicFactor(_E_,_L_,_B_); expected.emplace_shared<SymbolicFactor>(_E_, _L_, _B_);
CHECK(assert_equal(expected, factors)); CHECK(assert_equal(expected, factors));
SymbolicBayesTree::Cliques expectedOrphans; SymbolicBayesTree::Cliques expectedOrphans{bayesTree[_S_], bayesTree[_T_],
expectedOrphans += bayesTree[_S_], bayesTree[_T_], bayesTree[_X_]; bayesTree[_X_]};
CHECK(assert_container_equal(expectedOrphans|indirected, orphans|indirected)); CHECK(assert_container_equal(expectedOrphans | indirected,
orphans | indirected));
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST(BayesTree, removePath3) TEST(BayesTree, removePath3) {
{
SymbolicBayesTree bayesTree = asiaBayesTree; SymbolicBayesTree bayesTree = asiaBayesTree;
// Call remove-path with clique T // Call remove-path with clique T
@ -200,199 +163,183 @@ TEST(BayesTree, removePath3)
// Check expected outcome // Check expected outcome
SymbolicFactorGraph expected; SymbolicFactorGraph expected;
expected += SymbolicFactor(_E_, _L_, _B_); expected.emplace_shared<SymbolicFactor>(_E_, _L_, _B_);
expected += SymbolicFactor(_T_, _E_, _L_); expected.emplace_shared<SymbolicFactor>(_T_, _E_, _L_);
CHECK(assert_equal(expected, factors)); CHECK(assert_equal(expected, factors));
SymbolicBayesTree::Cliques expectedOrphans; SymbolicBayesTree::Cliques expectedOrphans{bayesTree[_S_], bayesTree[_X_]};
expectedOrphans += bayesTree[_S_], bayesTree[_X_]; CHECK(assert_container_equal(expectedOrphans | indirected,
CHECK(assert_container_equal(expectedOrphans|indirected, orphans|indirected)); orphans | indirected));
} }
void getAllCliques(const SymbolicBayesTree::sharedClique& subtree, SymbolicBayesTree::Cliques& cliques) { void getAllCliques(const SymbolicBayesTree::sharedClique& subtree,
SymbolicBayesTree::Cliques& cliques) {
// Check if subtree exists // Check if subtree exists
if (subtree) { if (subtree) {
cliques.push_back(subtree); cliques.push_back(subtree);
// Recursive call over all child cliques // Recursive call over all child cliques
for(SymbolicBayesTree::sharedClique& childClique: subtree->children) { for (SymbolicBayesTree::sharedClique& childClique : subtree->children) {
getAllCliques(childClique,cliques); getAllCliques(childClique, cliques);
} }
} }
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST( BayesTree, shortcutCheck ) TEST(BayesTree, shortcutCheck) {
{ const Key _A_ = 6, _B_ = 5, _C_ = 4, _D_ = 3, _E_ = 2, _F_ = 1, _G_ = 0;
const Key _A_=6, _B_=5, _C_=4, _D_=3, _E_=2, _F_=1, _G_=0; auto chain = SymbolicFactorGraph(SymbolicFactor(_A_)) //
SymbolicFactorGraph chain = list_of (SymbolicFactor(_B_, _A_)) //
(SymbolicFactor(_A_)) (SymbolicFactor(_C_, _A_)) //
(SymbolicFactor(_B_, _A_)) (SymbolicFactor(_D_, _C_)) //
(SymbolicFactor(_C_, _A_)) (SymbolicFactor(_E_, _B_)) //
(SymbolicFactor(_D_, _C_)) (SymbolicFactor(_F_, _E_)) //
(SymbolicFactor(_E_, _B_)) (SymbolicFactor(_G_, _F_));
(SymbolicFactor(_F_, _E_)) Ordering ordering{_G_, _F_, _E_, _D_, _C_, _B_, _A_};
(SymbolicFactor(_G_, _F_));
Ordering ordering(list_of(_G_)(_F_)(_E_)(_D_)(_C_)(_B_)(_A_));
SymbolicBayesTree bayesTree = *chain.eliminateMultifrontal(ordering); SymbolicBayesTree bayesTree = *chain.eliminateMultifrontal(ordering);
//bayesTree.saveGraph("BT1.dot"); // bayesTree.saveGraph("BT1.dot");
SymbolicBayesTree::sharedClique rootClique = bayesTree.roots().front(); SymbolicBayesTree::sharedClique rootClique = bayesTree.roots().front();
//rootClique->printTree(); // rootClique->printTree();
SymbolicBayesTree::Cliques allCliques; SymbolicBayesTree::Cliques allCliques;
getAllCliques(rootClique,allCliques); getAllCliques(rootClique, allCliques);
for(SymbolicBayesTree::sharedClique& clique: allCliques) { for (SymbolicBayesTree::sharedClique& clique : allCliques) {
//clique->print("Clique#"); // clique->print("Clique#");
SymbolicBayesNet bn = clique->shortcut(rootClique); SymbolicBayesNet bn = clique->shortcut(rootClique);
//bn.print("Shortcut:\n"); // bn.print("Shortcut:\n");
//cout << endl; // cout << endl;
} }
// Check if all the cached shortcuts are cleared // Check if all the cached shortcuts are cleared
rootClique->deleteCachedShortcuts(); rootClique->deleteCachedShortcuts();
for(SymbolicBayesTree::sharedClique& clique: allCliques) { for (SymbolicBayesTree::sharedClique& clique : allCliques) {
bool notCleared = clique->cachedSeparatorMarginal().is_initialized(); bool notCleared = clique->cachedSeparatorMarginal().is_initialized();
CHECK( notCleared == false); CHECK(notCleared == false);
} }
EXPECT_LONGS_EQUAL(0, (long)rootClique->numCachedSeparatorMarginals()); EXPECT_LONGS_EQUAL(0, (long)rootClique->numCachedSeparatorMarginals());
// for(SymbolicBayesTree::sharedClique& clique: allCliques) { // for(SymbolicBayesTree::sharedClique& clique: allCliques) {
// clique->print("Clique#"); // clique->print("Clique#");
// if(clique->cachedShortcut()){ // if(clique->cachedShortcut()){
// bn = clique->cachedShortcut().get(); // bn = clique->cachedShortcut().get();
// bn.print("Shortcut:\n"); // bn.print("Shortcut:\n");
// } // }
// else // else
// cout << "Not Initialized" << endl; // cout << "Not Initialized" << endl;
// cout << endl; // cout << endl;
// } // }
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST( BayesTree, removeTop ) TEST(BayesTree, removeTop) {
{
SymbolicBayesTree bayesTree = asiaBayesTree; SymbolicBayesTree bayesTree = asiaBayesTree;
// create a new factor to be inserted // create a new factor to be inserted
//boost::shared_ptr<IndexFactor> newFactor(new IndexFactor(_S_,_B_)); // boost::shared_ptr<IndexFactor> newFactor(new IndexFactor(_S_,_B_));
// Remove the contaminated part of the Bayes tree // Remove the contaminated part of the Bayes tree
SymbolicBayesNet bn; SymbolicBayesNet bn;
SymbolicBayesTree::Cliques orphans; SymbolicBayesTree::Cliques orphans;
bayesTree.removeTop(list_of(_B_)(_S_), &bn, &orphans); bayesTree.removeTop(Keys(_B_)(_S_), &bn, &orphans);
// Check expected outcome // Check expected outcome
SymbolicBayesNet expected; SymbolicBayesNet expected;
expected += SymbolicConditional::FromKeys(list_of(_E_)(_L_)(_B_), 3); expected += SymbolicConditional::FromKeys<KeyVector>(Keys(_E_)(_L_)(_B_), 3);
expected += SymbolicConditional::FromKeys(list_of(_S_)(_B_)(_L_), 1); expected += SymbolicConditional::FromKeys<KeyVector>(Keys(_S_)(_B_)(_L_), 1);
CHECK(assert_equal(expected, bn)); CHECK(assert_equal(expected, bn));
SymbolicBayesTree::Cliques expectedOrphans; SymbolicBayesTree::Cliques expectedOrphans{bayesTree[_T_], bayesTree[_X_]};
expectedOrphans += bayesTree[_T_], bayesTree[_X_]; CHECK(assert_container_equal(expectedOrphans | indirected,
CHECK(assert_container_equal(expectedOrphans|indirected, orphans|indirected)); orphans | indirected));
// Try removeTop again with a factor that should not change a thing // Try removeTop again with a factor that should not change a thing
//boost::shared_ptr<IndexFactor> newFactor2(new IndexFactor(_B_)); // boost::shared_ptr<IndexFactor> newFactor2(new IndexFactor(_B_));
SymbolicBayesNet bn2; SymbolicBayesNet bn2;
SymbolicBayesTree::Cliques orphans2; SymbolicBayesTree::Cliques orphans2;
bayesTree.removeTop(list_of(_B_), &bn2, &orphans2); bayesTree.removeTop(Keys(_B_), &bn2, &orphans2);
SymbolicFactorGraph factors2(bn2); SymbolicFactorGraph factors2(bn2);
SymbolicFactorGraph expected2; SymbolicFactorGraph expected2;
CHECK(assert_equal(expected2, factors2)); CHECK(assert_equal(expected2, factors2));
SymbolicBayesTree::Cliques expectedOrphans2; SymbolicBayesTree::Cliques expectedOrphans2;
CHECK(assert_container_equal(expectedOrphans2|indirected, orphans2|indirected)); CHECK(assert_container_equal(expectedOrphans2 | indirected,
orphans2 | indirected));
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST( BayesTree, removeTop2 ) TEST(BayesTree, removeTop2) {
{
SymbolicBayesTree bayesTree = asiaBayesTree; SymbolicBayesTree bayesTree = asiaBayesTree;
// create two factors to be inserted // create two factors to be inserted
//SymbolicFactorGraph newFactors; // SymbolicFactorGraph newFactors;
//newFactors.push_factor(_B_); // newFactors.push_factor(_B_);
//newFactors.push_factor(_S_); // newFactors.push_factor(_S_);
// Remove the contaminated part of the Bayes tree // Remove the contaminated part of the Bayes tree
SymbolicBayesNet bn; SymbolicBayesNet bn;
SymbolicBayesTree::Cliques orphans; SymbolicBayesTree::Cliques orphans;
bayesTree.removeTop(list_of(_T_), &bn, &orphans); bayesTree.removeTop(Keys(_T_), &bn, &orphans);
// Check expected outcome // Check expected outcome
SymbolicBayesNet expected = list_of auto expected = SymbolicBayesNet(
(SymbolicConditional::FromKeys(list_of(_E_)(_L_)(_B_), 3)) SymbolicConditional::FromKeys<KeyVector>(Keys(_E_)(_L_)(_B_), 3))(
(SymbolicConditional::FromKeys(list_of(_T_)(_E_)(_L_), 1)); SymbolicConditional::FromKeys<KeyVector>(Keys(_T_)(_E_)(_L_), 1));
CHECK(assert_equal(expected, bn)); CHECK(assert_equal(expected, bn));
SymbolicBayesTree::Cliques expectedOrphans; SymbolicBayesTree::Cliques expectedOrphans{bayesTree[_S_], bayesTree[_X_]};
expectedOrphans += bayesTree[_S_], bayesTree[_X_]; CHECK(assert_container_equal(expectedOrphans | indirected,
CHECK(assert_container_equal(expectedOrphans|indirected, orphans|indirected)); orphans | indirected));
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST( BayesTree, removeTop3 ) TEST(BayesTree, removeTop3) {
{ auto graph = SymbolicFactorGraph(SymbolicFactor(L(5)))(SymbolicFactor(
SymbolicFactorGraph graph = list_of X(4), L(5)))(SymbolicFactor(X(2), X(4)))(SymbolicFactor(X(3), X(2)));
(SymbolicFactor(L(5))) Ordering ordering{X(3), X(2), X(4), L(5)};
(SymbolicFactor(X(4), L(5)))
(SymbolicFactor(X(2), X(4)))
(SymbolicFactor(X(3), X(2)));
Ordering ordering(list_of (X(3)) (X(2)) (X(4)) (L(5)) );
SymbolicBayesTree bayesTree = *graph.eliminateMultifrontal(ordering); SymbolicBayesTree bayesTree = *graph.eliminateMultifrontal(ordering);
// remove all // remove all
SymbolicBayesNet bn; SymbolicBayesNet bn;
SymbolicBayesTree::Cliques orphans; SymbolicBayesTree::Cliques orphans;
bayesTree.removeTop(list_of(L(5))(X(4))(X(2))(X(3)), &bn, &orphans); bayesTree.removeTop(Keys(L(5))(X(4))(X(2))(X(3)), &bn, &orphans);
SymbolicBayesNet expectedBn = list_of auto expectedBn = SymbolicBayesNet(
(SymbolicConditional::FromKeys(list_of(X(4))(L(5)), 2)) SymbolicConditional::FromKeys<KeyVector>(Keys(X(4))(L(5)), 2))(
(SymbolicConditional(X(2), X(4))) SymbolicConditional(X(2), X(4)))(SymbolicConditional(X(3), X(2)));
(SymbolicConditional(X(3), X(2)));
EXPECT(assert_equal(expectedBn, bn)); EXPECT(assert_equal(expectedBn, bn));
EXPECT(orphans.empty()); EXPECT(orphans.empty());
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST( BayesTree, removeTop4 ) TEST(BayesTree, removeTop4) {
{ auto graph = SymbolicFactorGraph(SymbolicFactor(L(5)))(SymbolicFactor(
SymbolicFactorGraph graph = list_of X(4), L(5)))(SymbolicFactor(X(2), X(4)))(SymbolicFactor(X(3), X(2)));
(SymbolicFactor(L(5))) Ordering ordering{X(3), X(2), X(4), L(5)};
(SymbolicFactor(X(4), L(5)))
(SymbolicFactor(X(2), X(4)))
(SymbolicFactor(X(3), X(2)));
Ordering ordering(list_of (X(3)) (X(2)) (X(4)) (L(5)) );
SymbolicBayesTree bayesTree = *graph.eliminateMultifrontal(ordering); SymbolicBayesTree bayesTree = *graph.eliminateMultifrontal(ordering);
// remove all // remove all
SymbolicBayesNet bn; SymbolicBayesNet bn;
SymbolicBayesTree::Cliques orphans; SymbolicBayesTree::Cliques orphans;
bayesTree.removeTop(list_of(X(2))(L(5))(X(4))(X(3)), &bn, &orphans); bayesTree.removeTop(Keys(X(2))(L(5))(X(4))(X(3)), &bn, &orphans);
SymbolicBayesNet expectedBn = list_of auto expectedBn = SymbolicBayesNet(
(SymbolicConditional::FromKeys(list_of(X(4))(L(5)), 2)) SymbolicConditional::FromKeys<KeyVector>(Keys(X(4))(L(5)), 2))(
(SymbolicConditional(X(2), X(4))) SymbolicConditional(X(2), X(4)))(SymbolicConditional(X(3), X(2)));
(SymbolicConditional(X(3), X(2)));
EXPECT(assert_equal(expectedBn, bn)); EXPECT(assert_equal(expectedBn, bn));
EXPECT(orphans.empty()); EXPECT(orphans.empty());
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST( BayesTree, removeTop5 ) TEST(BayesTree, removeTop5) {
{
// Remove top called with variables that are not in the Bayes tree // Remove top called with variables that are not in the Bayes tree
SymbolicFactorGraph graph = list_of auto graph = SymbolicFactorGraph(SymbolicFactor(L(5)))(SymbolicFactor(
(SymbolicFactor(L(5))) X(4), L(5)))(SymbolicFactor(X(2), X(4)))(SymbolicFactor(X(3), X(2)));
(SymbolicFactor(X(4), L(5))) Ordering ordering{X(3), X(2), X(4), L(5)};
(SymbolicFactor(X(2), X(4)))
(SymbolicFactor(X(3), X(2)));
Ordering ordering(list_of (X(3)) (X(2)) (X(4)) (L(5)) );
SymbolicBayesTree bayesTree = *graph.eliminateMultifrontal(ordering); SymbolicBayesTree bayesTree = *graph.eliminateMultifrontal(ordering);
// Remove nonexistant // Remove nonexistant
SymbolicBayesNet bn; SymbolicBayesNet bn;
SymbolicBayesTree::Cliques orphans; SymbolicBayesTree::Cliques orphans;
bayesTree.removeTop(list_of(X(10)), &bn, &orphans); bayesTree.removeTop(Keys(X(10)), &bn, &orphans);
SymbolicBayesNet expectedBn; SymbolicBayesNet expectedBn;
EXPECT(assert_equal(expectedBn, bn)); EXPECT(assert_equal(expectedBn, bn));
@ -400,29 +347,28 @@ TEST( BayesTree, removeTop5 )
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST( SymbolicBayesTree, thinTree ) { TEST(SymbolicBayesTree, thinTree) {
// create a thin-tree Bayes net, a la Jean-Guillaume
// create a thin-tree Bayesnet, a la Jean-Guillaume
SymbolicBayesNet bayesNet; SymbolicBayesNet bayesNet;
bayesNet.push_back(boost::make_shared<SymbolicConditional>(14)); bayesNet.emplace_shared<SymbolicConditional>(14);
bayesNet.push_back(boost::make_shared<SymbolicConditional>(13, 14)); bayesNet.emplace_shared<SymbolicConditional>(13, 14);
bayesNet.push_back(boost::make_shared<SymbolicConditional>(12, 14)); bayesNet.emplace_shared<SymbolicConditional>(12, 14);
bayesNet.push_back(boost::make_shared<SymbolicConditional>(11, 13, 14)); bayesNet.emplace_shared<SymbolicConditional>(11, 13, 14);
bayesNet.push_back(boost::make_shared<SymbolicConditional>(10, 13, 14)); bayesNet.emplace_shared<SymbolicConditional>(10, 13, 14);
bayesNet.push_back(boost::make_shared<SymbolicConditional>(9, 12, 14)); bayesNet.emplace_shared<SymbolicConditional>(9, 12, 14);
bayesNet.push_back(boost::make_shared<SymbolicConditional>(8, 12, 14)); bayesNet.emplace_shared<SymbolicConditional>(8, 12, 14);
bayesNet.push_back(boost::make_shared<SymbolicConditional>(7, 11, 13)); bayesNet.emplace_shared<SymbolicConditional>(7, 11, 13);
bayesNet.push_back(boost::make_shared<SymbolicConditional>(6, 11, 13)); bayesNet.emplace_shared<SymbolicConditional>(6, 11, 13);
bayesNet.push_back(boost::make_shared<SymbolicConditional>(5, 10, 13)); bayesNet.emplace_shared<SymbolicConditional>(5, 10, 13);
bayesNet.push_back(boost::make_shared<SymbolicConditional>(4, 10, 13)); bayesNet.emplace_shared<SymbolicConditional>(4, 10, 13);
bayesNet.push_back(boost::make_shared<SymbolicConditional>(3, 9, 12)); bayesNet.emplace_shared<SymbolicConditional>(3, 9, 12);
bayesNet.push_back(boost::make_shared<SymbolicConditional>(2, 9, 12)); bayesNet.emplace_shared<SymbolicConditional>(2, 9, 12);
bayesNet.push_back(boost::make_shared<SymbolicConditional>(1, 8, 12)); bayesNet.emplace_shared<SymbolicConditional>(1, 8, 12);
bayesNet.push_back(boost::make_shared<SymbolicConditional>(0, 8, 12)); bayesNet.emplace_shared<SymbolicConditional>(0, 8, 12);
if (debug) { if (debug) {
GTSAM_PRINT(bayesNet); GTSAM_PRINT(bayesNet);
@ -430,7 +376,8 @@ TEST( SymbolicBayesTree, thinTree ) {
} }
// create a BayesTree out of a Bayes net // create a BayesTree out of a Bayes net
SymbolicBayesTree bayesTree = *SymbolicFactorGraph(bayesNet).eliminateMultifrontal(); SymbolicBayesTree bayesTree =
*SymbolicFactorGraph(bayesNet).eliminateMultifrontal();
if (debug) { if (debug) {
GTSAM_PRINT(bayesTree); GTSAM_PRINT(bayesTree);
bayesTree.saveGraph("/tmp/SymbolicBayesTree.dot"); bayesTree.saveGraph("/tmp/SymbolicBayesTree.dot");
@ -442,7 +389,7 @@ TEST( SymbolicBayesTree, thinTree ) {
// check shortcut P(S9||R) to root // check shortcut P(S9||R) to root
SymbolicBayesTree::Clique::shared_ptr c = bayesTree[9]; SymbolicBayesTree::Clique::shared_ptr c = bayesTree[9];
SymbolicBayesNet shortcut = c->shortcut(R); SymbolicBayesNet shortcut = c->shortcut(R);
SymbolicBayesNet expected = list_of(SymbolicConditional(14, 11, 13)); auto expected = SymbolicBayesNet(SymbolicConditional(14, 11, 13));
EXPECT(assert_equal(expected, shortcut)); EXPECT(assert_equal(expected, shortcut));
} }
@ -450,9 +397,8 @@ TEST( SymbolicBayesTree, thinTree ) {
// check shortcut P(S8||R) to root // check shortcut P(S8||R) to root
SymbolicBayesTree::Clique::shared_ptr c = bayesTree[8]; SymbolicBayesTree::Clique::shared_ptr c = bayesTree[8];
SymbolicBayesNet shortcut = c->shortcut(R); SymbolicBayesNet shortcut = c->shortcut(R);
SymbolicBayesNet expected = list_of auto expected = SymbolicBayesNet(SymbolicConditional(12, 14))(
(SymbolicConditional(12, 14)) SymbolicConditional(14, 11, 13));
(SymbolicConditional(14, 11, 13));
EXPECT(assert_equal(expected, shortcut)); EXPECT(assert_equal(expected, shortcut));
} }
@ -460,7 +406,7 @@ TEST( SymbolicBayesTree, thinTree ) {
// check shortcut P(S4||R) to root // check shortcut P(S4||R) to root
SymbolicBayesTree::Clique::shared_ptr c = bayesTree[4]; SymbolicBayesTree::Clique::shared_ptr c = bayesTree[4];
SymbolicBayesNet shortcut = c->shortcut(R); SymbolicBayesNet shortcut = c->shortcut(R);
SymbolicBayesNet expected = list_of(SymbolicConditional(10, 11, 13)); auto expected = SymbolicBayesNet(SymbolicConditional(10, 11, 13));
EXPECT(assert_equal(expected, shortcut)); EXPECT(assert_equal(expected, shortcut));
} }
@ -468,8 +414,8 @@ TEST( SymbolicBayesTree, thinTree ) {
// check shortcut P(S2||R) to root // check shortcut P(S2||R) to root
SymbolicBayesTree::Clique::shared_ptr c = bayesTree[2]; SymbolicBayesTree::Clique::shared_ptr c = bayesTree[2];
SymbolicBayesNet shortcut = c->shortcut(R); SymbolicBayesNet shortcut = c->shortcut(R);
SymbolicBayesNet expected = list_of(SymbolicConditional(9, 11, 12, 13)) auto expected = SymbolicBayesNet(SymbolicConditional(9, 11, 12, 13))(
(SymbolicConditional(12, 11, 13)); SymbolicConditional(12, 11, 13));
EXPECT(assert_equal(expected, shortcut)); EXPECT(assert_equal(expected, shortcut));
} }
@ -477,28 +423,28 @@ TEST( SymbolicBayesTree, thinTree ) {
// check shortcut P(S0||R) to root // check shortcut P(S0||R) to root
SymbolicBayesTree::Clique::shared_ptr c = bayesTree[0]; SymbolicBayesTree::Clique::shared_ptr c = bayesTree[0];
SymbolicBayesNet shortcut = c->shortcut(R); SymbolicBayesNet shortcut = c->shortcut(R);
SymbolicBayesNet expected = list_of(SymbolicConditional(8, 11, 12, 13)) auto expected = SymbolicBayesNet(SymbolicConditional(8, 11, 12, 13))(
(SymbolicConditional(12, 11, 13)); SymbolicConditional(12, 11, 13));
EXPECT(assert_equal(expected, shortcut)); EXPECT(assert_equal(expected, shortcut));
} }
SymbolicBayesNet::shared_ptr actualJoint; SymbolicBayesNet::shared_ptr actualJoint;
// Check joint P(8,2) // Check joint P(8,2)
if (false) { // TODO, not disjoint if (false) { // TODO, not disjoint
actualJoint = bayesTree.jointBayesNet(8, 2); actualJoint = bayesTree.jointBayesNet(8, 2);
SymbolicBayesNet expected; SymbolicBayesNet expected;
expected.push_back(boost::make_shared<SymbolicConditional>(8)); expected.emplace_shared<SymbolicConditional>(8);
expected.push_back(boost::make_shared<SymbolicConditional>(2, 8)); expected.emplace_shared<SymbolicConditional>(2, 8);
EXPECT(assert_equal(expected, *actualJoint)); EXPECT(assert_equal(expected, *actualJoint));
} }
// Check joint P(1,2) // Check joint P(1,2)
if (false) { // TODO, not disjoint if (false) { // TODO, not disjoint
actualJoint = bayesTree.jointBayesNet(1, 2); actualJoint = bayesTree.jointBayesNet(1, 2);
SymbolicBayesNet expected; SymbolicBayesNet expected;
expected.push_back(boost::make_shared<SymbolicConditional>(2)); expected.emplace_shared<SymbolicConditional>(2);
expected.push_back(boost::make_shared<SymbolicConditional>(1, 2)); expected.emplace_shared<SymbolicConditional>(1, 2);
EXPECT(assert_equal(expected, *actualJoint)); EXPECT(assert_equal(expected, *actualJoint));
} }
@ -506,35 +452,33 @@ TEST( SymbolicBayesTree, thinTree ) {
if (true) { if (true) {
actualJoint = bayesTree.jointBayesNet(2, 6); actualJoint = bayesTree.jointBayesNet(2, 6);
SymbolicBayesNet expected; SymbolicBayesNet expected;
expected.push_back(boost::make_shared<SymbolicConditional>(2, 6)); expected.emplace_shared<SymbolicConditional>(2, 6);
expected.push_back(boost::make_shared<SymbolicConditional>(6)); expected.emplace_shared<SymbolicConditional>(6);
EXPECT(assert_equal(expected, *actualJoint)); EXPECT(assert_equal(expected, *actualJoint));
} }
// Check joint P(4,6) // Check joint P(4,6)
if (false) { // TODO, not disjoint if (false) { // TODO, not disjoint
actualJoint = bayesTree.jointBayesNet(4, 6); actualJoint = bayesTree.jointBayesNet(4, 6);
SymbolicBayesNet expected; SymbolicBayesNet expected;
expected.push_back(boost::make_shared<SymbolicConditional>(6)); expected.emplace_shared<SymbolicConditional>(6);
expected.push_back(boost::make_shared<SymbolicConditional>(4, 6)); expected.emplace_shared<SymbolicConditional>(4, 6);
EXPECT(assert_equal(expected, *actualJoint)); EXPECT(assert_equal(expected, *actualJoint));
} }
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST(SymbolicBayesTree, forest_joint) TEST(SymbolicBayesTree, forest_joint) {
{
// Create forest // Create forest
SymbolicBayesTreeClique::shared_ptr root1 = MakeClique(list_of(1), 1); sharedClique root1 = LeafClique(Keys(1), 1);
SymbolicBayesTreeClique::shared_ptr root2 = MakeClique(list_of(2), 1); sharedClique root2 = LeafClique(Keys(2), 1);
SymbolicBayesTree bayesTree; SymbolicBayesTree bayesTree;
bayesTree.insertRoot(root1); bayesTree.insertRoot(root1);
bayesTree.insertRoot(root2); bayesTree.insertRoot(root2);
// Check joint // Check joint
SymbolicBayesNet expected = list_of auto expected =
(SymbolicConditional(1)) SymbolicBayesNet(SymbolicConditional(1))(SymbolicConditional(2));
(SymbolicConditional(2));
SymbolicBayesNet actual = *bayesTree.jointBayesNet(1, 2); SymbolicBayesNet actual = *bayesTree.jointBayesNet(1, 2);
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
@ -550,7 +494,7 @@ TEST(SymbolicBayesTree, forest_joint)
C6 0 : 1 C6 0 : 1
**************************************************************************** */ **************************************************************************** */
TEST( SymbolicBayesTree, linear_smoother_shortcuts ) { TEST(SymbolicBayesTree, linear_smoother_shortcuts) {
// Create smoother with 7 nodes // Create smoother with 7 nodes
SymbolicFactorGraph smoother; SymbolicFactorGraph smoother;
smoother.push_factor(0); smoother.push_factor(0);
@ -581,7 +525,8 @@ TEST( SymbolicBayesTree, linear_smoother_shortcuts ) {
{ {
// check shortcut P(S2||R) to root // check shortcut P(S2||R) to root
SymbolicBayesTree::Clique::shared_ptr c = bayesTree[4]; // 4 is frontal in C2 SymbolicBayesTree::Clique::shared_ptr c =
bayesTree[4]; // 4 is frontal in C2
SymbolicBayesNet shortcut = c->shortcut(R); SymbolicBayesNet shortcut = c->shortcut(R);
SymbolicBayesNet expected; SymbolicBayesNet expected;
EXPECT(assert_equal(expected, shortcut)); EXPECT(assert_equal(expected, shortcut));
@ -589,45 +534,46 @@ TEST( SymbolicBayesTree, linear_smoother_shortcuts ) {
{ {
// check shortcut P(S3||R) to root // check shortcut P(S3||R) to root
SymbolicBayesTree::Clique::shared_ptr c = bayesTree[3]; // 3 is frontal in C3 SymbolicBayesTree::Clique::shared_ptr c =
bayesTree[3]; // 3 is frontal in C3
SymbolicBayesNet shortcut = c->shortcut(R); SymbolicBayesNet shortcut = c->shortcut(R);
SymbolicBayesNet expected = list_of(SymbolicConditional(4, 5)); auto expected = SymbolicBayesNet(SymbolicConditional(4, 5));
EXPECT(assert_equal(expected, shortcut)); EXPECT(assert_equal(expected, shortcut));
} }
{ {
// check shortcut P(S4||R) to root // check shortcut P(S4||R) to root
SymbolicBayesTree::Clique::shared_ptr c = bayesTree[2]; // 2 is frontal in C4 SymbolicBayesTree::Clique::shared_ptr c =
bayesTree[2]; // 2 is frontal in C4
SymbolicBayesNet shortcut = c->shortcut(R); SymbolicBayesNet shortcut = c->shortcut(R);
SymbolicBayesNet expected = list_of(SymbolicConditional(3, 5)); auto expected = SymbolicBayesNet(SymbolicConditional(3, 5));
EXPECT(assert_equal(expected, shortcut)); EXPECT(assert_equal(expected, shortcut));
} }
} }
/* ************************************************************************* */ /* ************************************************************************* */
// from testSymbolicJunctionTree, which failed at one point // from testSymbolicJunctionTree, which failed at one point
TEST(SymbolicBayesTree, complicatedMarginal) TEST(SymbolicBayesTree, complicatedMarginal) {
{
// Create the conditionals to go in the BayesTree // Create the conditionals to go in the BayesTree
SymbolicBayesTreeClique::shared_ptr cur; sharedClique cur;
SymbolicBayesTreeClique::shared_ptr root = MakeClique(list_of(11)(12), 2); sharedClique root = LeafClique(Keys(11)(12), 2);
cur = root; cur = root;
root->children += MakeClique(list_of(9)(10)(11)(12), 2); root->children.push_back(LeafClique(Keys(9)(10)(11)(12), 2));
root->children.back()->parent_ = root; root->children.back()->parent_ = root;
root->children += MakeClique(list_of(7)(8)(11), 2); root->children.push_back(LeafClique(Keys(7)(8)(11), 2));
root->children.back()->parent_ = root; root->children.back()->parent_ = root;
cur = root->children.back(); cur = root->children.back();
cur->children += MakeClique(list_of(5)(6)(7)(8), 2); cur->children.push_back(LeafClique(Keys(5)(6)(7)(8), 2));
cur->children.back()->parent_ = cur; cur->children.back()->parent_ = cur;
cur = cur->children.back(); cur = cur->children.back();
cur->children += MakeClique(list_of(3)(4)(6), 2); cur->children.push_back(LeafClique(Keys(3)(4)(6), 2));
cur->children.back()->parent_ = cur; cur->children.back()->parent_ = cur;
cur->children += MakeClique(list_of(1)(2)(5), 2); cur->children.push_back(LeafClique(Keys(1)(2)(5), 2));
cur->children.back()->parent_ = cur; cur->children.back()->parent_ = cur;
// Create Bayes Tree // Create Bayes Tree
@ -656,9 +602,8 @@ TEST(SymbolicBayesTree, complicatedMarginal)
{ {
SymbolicBayesTree::Clique::shared_ptr c = bt[5]; SymbolicBayesTree::Clique::shared_ptr c = bt[5];
SymbolicBayesNet shortcut = c->shortcut(root); SymbolicBayesNet shortcut = c->shortcut(root);
SymbolicBayesNet expected = list_of auto expected = SymbolicBayesNet(SymbolicConditional(7, 8, 11))(
(SymbolicConditional(7, 8, 11)) SymbolicConditional(8, 11));
(SymbolicConditional(8, 11));
EXPECT(assert_equal(expected, shortcut)); EXPECT(assert_equal(expected, shortcut));
} }
@ -666,7 +611,7 @@ TEST(SymbolicBayesTree, complicatedMarginal)
{ {
SymbolicBayesTree::Clique::shared_ptr c = bt[3]; SymbolicBayesTree::Clique::shared_ptr c = bt[3];
SymbolicBayesNet shortcut = c->shortcut(root); SymbolicBayesNet shortcut = c->shortcut(root);
SymbolicBayesNet expected = list_of(SymbolicConditional(6, 11)); auto expected = SymbolicBayesNet(SymbolicConditional(6, 11));
EXPECT(assert_equal(expected, shortcut)); EXPECT(assert_equal(expected, shortcut));
} }
@ -674,7 +619,7 @@ TEST(SymbolicBayesTree, complicatedMarginal)
{ {
SymbolicBayesTree::Clique::shared_ptr c = bt[1]; SymbolicBayesTree::Clique::shared_ptr c = bt[1];
SymbolicBayesNet shortcut = c->shortcut(root); SymbolicBayesNet shortcut = c->shortcut(root);
SymbolicBayesNet expected = list_of(SymbolicConditional(5, 11)); auto expected = SymbolicBayesNet(SymbolicConditional(5, 11));
EXPECT(assert_equal(expected, shortcut)); EXPECT(assert_equal(expected, shortcut));
} }
@ -689,12 +634,10 @@ TEST(SymbolicBayesTree, complicatedMarginal)
SymbolicFactor::shared_ptr actual = bt.marginalFactor(6); SymbolicFactor::shared_ptr actual = bt.marginalFactor(6);
EXPECT(assert_equal(SymbolicFactor(6), *actual, 1e-1)); EXPECT(assert_equal(SymbolicFactor(6), *actual, 1e-1));
} }
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST(SymbolicBayesTree, COLAMDvsMETIS) { TEST(SymbolicBayesTree, COLAMDvsMETIS) {
// create circular graph // create circular graph
SymbolicFactorGraph sfg; SymbolicFactorGraph sfg;
sfg.push_factor(0, 1); sfg.push_factor(0, 1);
@ -707,20 +650,23 @@ TEST(SymbolicBayesTree, COLAMDvsMETIS) {
// COLAMD // COLAMD
{ {
Ordering ordering = Ordering::Create(Ordering::COLAMD, sfg); Ordering ordering = Ordering::Create(Ordering::COLAMD, sfg);
EXPECT(assert_equal(Ordering(list_of(0)(5)(1)(4)(2)(3)), ordering)); EXPECT(assert_equal(Ordering{0, 5, 1, 4, 2, 3}, ordering));
// - P( 4 2 3) // - P( 4 2 3)
// | - P( 1 | 2 4) // | - P( 1 | 2 4)
// | | - P( 5 | 1 4) // | | - P( 5 | 1 4)
// | | | - P( 0 | 1 5) // | | | - P( 0 | 1 5)
SymbolicBayesTree expected; SymbolicBayesTree expected;
expected.insertRoot( expected.insertRoot( //
MakeClique(list_of(4)(2)(3), 3, NodeClique(
list_of( Keys(4)(2)(3), 3,
MakeClique(list_of(1)(2)(4), 1, Children( //
list_of( NodeClique(
MakeClique(list_of(5)(1)(4), 1, Keys(1)(2)(4), 1,
list_of(MakeClique(list_of(0)(1)(5), 1)))))))); Children( //
NodeClique(Keys(5)(1)(4), 1,
Children( //
LeafClique(Keys(0)(1)(5), 1))))))));
SymbolicBayesTree actual = *sfg.eliminateMultifrontal(ordering); SymbolicBayesTree actual = *sfg.eliminateMultifrontal(ordering);
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
@ -730,13 +676,13 @@ TEST(SymbolicBayesTree, COLAMDvsMETIS) {
// METIS // METIS
{ {
Ordering ordering = Ordering::Create(Ordering::METIS, sfg); Ordering ordering = Ordering::Create(Ordering::METIS, sfg);
// Linux and Mac split differently when using mettis // Linux and Mac split differently when using Metis
#if defined(__APPLE__) #if defined(__APPLE__)
EXPECT(assert_equal(Ordering(list_of(5)(4)(2)(1)(0)(3)), ordering)); EXPECT(assert_equal(Ordering{5, 4, 2, 1, 0, 3}, ordering));
#elif defined(_WIN32) #elif defined(_WIN32)
EXPECT(assert_equal(Ordering(list_of(4)(3)(1)(0)(5)(2)), ordering)); EXPECT(assert_equal(Ordering{4, 3, 1, 0, 5, 2}, ordering));
#else #else
EXPECT(assert_equal(Ordering(list_of(3)(2)(5)(0)(4)(1)), ordering)); EXPECT(assert_equal(Ordering{3, 2, 5, 0, 4, 1}, ordering));
#endif #endif
// - P( 1 0 3) // - P( 1 0 3)
@ -746,25 +692,25 @@ TEST(SymbolicBayesTree, COLAMDvsMETIS) {
SymbolicBayesTree expected; SymbolicBayesTree expected;
#if defined(__APPLE__) #if defined(__APPLE__)
expected.insertRoot( expected.insertRoot(
MakeClique(list_of(1)(0)(3), 3, NodeClique(Keys(1)(0)(3), 3,
list_of( Children( //
MakeClique(list_of(4)(0)(3), 1, NodeClique(Keys(4)(0)(3), 1, //
list_of(MakeClique(list_of(5)(0)(4), 1))))( {LeafClique(Keys(5)(0)(4), 1)}))(
MakeClique(list_of(2)(1)(3), 1)))); LeafClique(Keys(2)(1)(3), 1))));
#elif defined(_WIN32) #elif defined(_WIN32)
expected.insertRoot( expected.insertRoot(
MakeClique(list_of(3)(5)(2), 3, NodeClique(Keys(3)(5)(2), 3,
list_of( Children( //
MakeClique(list_of(4)(3)(5), 1, NodeClique(Keys(4)(3)(5), 1, //
list_of(MakeClique(list_of(0)(2)(5), 1))))( {LeafClique(Keys(0)(2)(5), 1)}))(
MakeClique(list_of(1)(0)(2), 1)))); LeafClique(Keys(1)(0)(2), 1))));
#else #else
expected.insertRoot( expected.insertRoot(
MakeClique(list_of(2)(4)(1), 3, NodeClique(Keys(2)(4)(1), 3,
list_of( Children( //
MakeClique(list_of(0)(1)(4), 1, NodeClique(Keys(0)(1)(4), 1, //
list_of(MakeClique(list_of(5)(0)(4), 1))))( {LeafClique(Keys(5)(0)(4), 1)}))(
MakeClique(list_of(3)(2)(4), 1)))); LeafClique(Keys(3)(2)(4), 1))));
#endif #endif
SymbolicBayesTree actual = *sfg.eliminateMultifrontal(ordering); SymbolicBayesTree actual = *sfg.eliminateMultifrontal(ordering);
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
@ -778,4 +724,3 @@ int main() {
return TestRegistry::runAllTests(tr); return TestRegistry::runAllTests(tr);
} }
/* ************************************************************************* */ /* ************************************************************************* */

View File

@ -15,8 +15,6 @@
* @author Frank Dellaert * @author Frank Dellaert
*/ */
#include <boost/assign/list_of.hpp>
using namespace boost::assign;
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
@ -69,8 +67,7 @@ TEST( SymbolicConditional, threeParents )
/* ************************************************************************* */ /* ************************************************************************* */
TEST( SymbolicConditional, fourParents ) TEST( SymbolicConditional, fourParents )
{ {
SymbolicConditional c0 = SymbolicConditional::FromKeys( auto c0 = SymbolicConditional::FromKeys(KeyVector{0, 1, 2, 3, 4}, 1);
list_of(0)(1)(2)(3)(4), 1);
LONGS_EQUAL(1, (long)c0.nrFrontals()); LONGS_EQUAL(1, (long)c0.nrFrontals());
LONGS_EQUAL(4, (long)c0.nrParents()); LONGS_EQUAL(4, (long)c0.nrParents());
} }
@ -78,9 +75,8 @@ TEST( SymbolicConditional, fourParents )
/* ************************************************************************* */ /* ************************************************************************* */
TEST( SymbolicConditional, FromRange ) TEST( SymbolicConditional, FromRange )
{ {
SymbolicConditional::shared_ptr c0 = auto c0 = boost::make_shared<SymbolicConditional>(
boost::make_shared<SymbolicConditional>( SymbolicConditional::FromKeys(KeyVector{1, 2, 3, 4, 5}, 2));
SymbolicConditional::FromKeys(list_of(1)(2)(3)(4)(5), 2));
LONGS_EQUAL(2, (long)c0->nrFrontals()); LONGS_EQUAL(2, (long)c0->nrFrontals());
LONGS_EQUAL(3, (long)c0->nrParents()); LONGS_EQUAL(3, (long)c0->nrParents());
} }

View File

@ -17,47 +17,48 @@
*/ */
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <vector>
#include <boost/make_shared.hpp>
#include <boost/assign/list_of.hpp>
#include <gtsam/base/TestableAssertions.h> #include <gtsam/base/TestableAssertions.h>
#include <gtsam/symbolic/SymbolicEliminationTree.h>
#include <gtsam/inference/Symbol.h> #include <gtsam/inference/Symbol.h>
#include <gtsam/symbolic/SymbolicEliminationTree.h>
#include <boost/make_shared.hpp>
#include <vector>
#include "symbolicExampleGraphs.h" #include "symbolicExampleGraphs.h"
using namespace gtsam; using namespace gtsam;
using namespace gtsam::symbol_shorthand; using namespace gtsam::symbol_shorthand;
using namespace std; using namespace std;
using boost::assign::list_of; using sharedNode = SymbolicEliminationTree::sharedNode;
// Use list_of replacement defined in symbolicExampleGraphs.h
using ChildNodes = ChainedVector<sharedNode>;
class EliminationTreeTester { class EliminationTreeTester {
public: public:
// build hardcoded tree // build hardcoded tree
static SymbolicEliminationTree buildHardcodedTree(const SymbolicFactorGraph& fg) { static SymbolicEliminationTree buildHardcodedTree(
const SymbolicFactorGraph& fg) {
SymbolicEliminationTree::sharedNode leaf0(new SymbolicEliminationTree::Node); sharedNode leaf0(new SymbolicEliminationTree::Node);
leaf0->key = 0; leaf0->key = 0;
leaf0->factors.push_back(fg[0]); leaf0->factors.push_back(fg[0]);
leaf0->factors.push_back(fg[1]); leaf0->factors.push_back(fg[1]);
SymbolicEliminationTree::sharedNode node1(new SymbolicEliminationTree::Node); sharedNode node1(new SymbolicEliminationTree::Node);
node1->key = 1; node1->key = 1;
node1->factors.push_back(fg[2]); node1->factors.push_back(fg[2]);
node1->children.push_back(leaf0); node1->children.push_back(leaf0);
SymbolicEliminationTree::sharedNode node2(new SymbolicEliminationTree::Node); sharedNode node2(new SymbolicEliminationTree::Node);
node2->key = 2; node2->key = 2;
node2->factors.push_back(fg[3]); node2->factors.push_back(fg[3]);
node2->children.push_back(node1); node2->children.push_back(node1);
SymbolicEliminationTree::sharedNode leaf3(new SymbolicEliminationTree::Node); sharedNode leaf3(new SymbolicEliminationTree::Node);
leaf3->key = 3; leaf3->key = 3;
leaf3->factors.push_back(fg[4]); leaf3->factors.push_back(fg[4]);
SymbolicEliminationTree::sharedNode root(new SymbolicEliminationTree::Node); sharedNode root(new SymbolicEliminationTree::Node);
root->key = 4; root->key = 4;
root->children.push_back(leaf3); root->children.push_back(leaf3);
root->children.push_back(node2); root->children.push_back(node2);
@ -67,85 +68,100 @@ public:
return tree; return tree;
} }
template<typename ROOTS> static SymbolicEliminationTree MakeTree(const ChildNodes::Result& roots) {
static SymbolicEliminationTree MakeTree(const ROOTS& roots)
{
SymbolicEliminationTree et; SymbolicEliminationTree et;
et.roots_.assign(roots.begin(), roots.end()); et.roots_.assign(roots.begin(), roots.end());
return et; return et;
} }
}; };
template<typename FACTORS> // Create a leaf node.
static SymbolicEliminationTree::sharedNode MakeNode(Key key, const FACTORS& factors) static sharedNode Leaf(Key key, const SymbolicFactorGraph& factors) {
{ sharedNode node(new SymbolicEliminationTree::Node());
SymbolicEliminationTree::sharedNode node = boost::make_shared<SymbolicEliminationTree::Node>();
node->key = key; node->key = key;
SymbolicFactorGraph factorsAsGraph = factors; node->factors.assign(factors.begin(), factors.end());
node->factors.assign(factorsAsGraph.begin(), factorsAsGraph.end());
return node; return node;
} }
template<typename FACTORS, typename CHILDREN> // Create a node with children.
static SymbolicEliminationTree::sharedNode MakeNode(Key key, const FACTORS& factors, const CHILDREN& children) static sharedNode Node(Key key, const SymbolicFactorGraph& factors,
{ const ChildNodes::Result& children) {
SymbolicEliminationTree::sharedNode node = boost::make_shared<SymbolicEliminationTree::Node>(); sharedNode node = Leaf(key, factors);
node->key = key;
SymbolicFactorGraph factorsAsGraph = factors;
node->factors.assign(factorsAsGraph.begin(), factorsAsGraph.end());
node->children.assign(children.begin(), children.end()); node->children.assign(children.begin(), children.end());
return node; return node;
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST(EliminationTree, Create) TEST(EliminationTree, Create) {
{
SymbolicEliminationTree expected = SymbolicEliminationTree expected =
EliminationTreeTester::buildHardcodedTree(simpleTestGraph1); EliminationTreeTester::buildHardcodedTree(simpleTestGraph1);
// Build from factor graph // Build from factor graph
Ordering order; const Ordering order{0, 1, 2, 3, 4};
order += 0,1,2,3,4;
SymbolicEliminationTree actual(simpleTestGraph1, order); SymbolicEliminationTree actual(simpleTestGraph1, order);
CHECK(assert_equal(expected, actual)); CHECK(assert_equal(expected, actual));
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST(EliminationTree, Create2) TEST(EliminationTree, Create2) {
{
// l1 l2 // l1 l2
// / | / | // / | / |
// x1 --- x2 --- x3 --- x4 --- x5 // x1 --- x2 --- x3 --- x4 --- x5
// \ | // \ |
// l3 // l3
SymbolicFactorGraph graph; SymbolicFactorGraph graph;
graph += SymbolicFactor(X(1), L(1)); auto binary = [](Key j1, Key j2) -> SymbolicFactor {
graph += SymbolicFactor(X(1), X(2)); return SymbolicFactor(j1, j2);
graph += SymbolicFactor(X(2), L(1)); };
graph += SymbolicFactor(X(2), X(3)); graph += binary(X(1), L(1));
graph += SymbolicFactor(X(3), X(4)); graph += binary(X(1), X(2));
graph += SymbolicFactor(X(4), L(2)); graph += binary(X(2), L(1));
graph += SymbolicFactor(X(4), X(5)); graph += binary(X(2), X(3));
graph += SymbolicFactor(L(2), X(5)); graph += binary(X(3), X(4));
graph += SymbolicFactor(X(4), L(3)); graph += binary(X(4), L(2));
graph += SymbolicFactor(X(5), L(3)); graph += binary(X(4), X(5));
graph += binary(L(2), X(5));
graph += binary(X(4), L(3));
graph += binary(X(5), L(3));
SymbolicEliminationTree expected = EliminationTreeTester::MakeTree(list_of SymbolicEliminationTree expected = EliminationTreeTester::MakeTree( //
(MakeNode(X(3), SymbolicFactorGraph(), list_of ChildNodes( //
(MakeNode(X(2), list_of(SymbolicFactor(X(2), X(3))), list_of Node(X(3), SymbolicFactorGraph(),
(MakeNode(L(1), list_of(SymbolicFactor(X(2), L(1))), list_of ChildNodes( //
(MakeNode(X(1), list_of(SymbolicFactor(X(1), L(1))) (SymbolicFactor(X(1), X(2))))))))) Node(X(2), SymbolicFactorGraph(binary(X(2), X(3))),
(MakeNode(X(4), list_of(SymbolicFactor(X(3), X(4))), list_of ChildNodes( //
(MakeNode(L(2), list_of(SymbolicFactor(X(4), L(2))), list_of Node(L(1), SymbolicFactorGraph(binary(X(2), L(1))),
(MakeNode(X(5), list_of(SymbolicFactor(X(4), X(5))) (SymbolicFactor(L(2), X(5))), list_of ChildNodes( //
(MakeNode(L(3), list_of(SymbolicFactor(X(4), L(3))) (SymbolicFactor(X(5), L(3)))))))))))))); Leaf(X(1), SymbolicFactorGraph(
binary(X(1), L(1)))(
Ordering order = list_of(X(1)) (L(3)) (L(1)) (X(5)) (X(2)) (L(2)) (X(4)) (X(3)); binary(X(1), X(2)))))))))(
Node(X(4), SymbolicFactorGraph(binary(X(3), X(4))),
ChildNodes( //
Node(L(2), SymbolicFactorGraph(binary(X(4), L(2))),
ChildNodes( //
Node(X(5),
SymbolicFactorGraph(binary(
X(4), X(5)))(binary(L(2), X(5))),
ChildNodes( //
Leaf(L(3),
SymbolicFactorGraph(
binary(X(4), L(3)))(
binary(X(5), L(3))) //
) //
) //
) //
) //
) //
) //
) //
) //
) //
) //
);
const Ordering order{X(1), L(3), L(1), X(5), X(2), L(2), X(4), X(3)};
SymbolicEliminationTree actual(graph, order); SymbolicEliminationTree actual(graph, order);
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
} }

View File

@ -21,14 +21,11 @@
#include <gtsam/symbolic/SymbolicConditional.h> #include <gtsam/symbolic/SymbolicConditional.h>
#include <gtsam/symbolic/SymbolicFactorGraph.h> #include <gtsam/symbolic/SymbolicFactorGraph.h>
#include <boost/assign/std/vector.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;
using namespace boost::assign;
/* ************************************************************************* */ /* ************************************************************************* */
#ifdef TRACK_ELIMINATE #ifdef TRACK_ELIMINATE
@ -70,19 +67,19 @@ TEST(SymbolicFactor, Constructors)
/* ************************************************************************* */ /* ************************************************************************* */
TEST(SymbolicFactor, EliminateSymbolic) TEST(SymbolicFactor, EliminateSymbolic)
{ {
const SymbolicFactorGraph factors = list_of const SymbolicFactorGraph factors = {
(SymbolicFactor(2,4,6)) boost::make_shared<SymbolicFactor>(2, 4, 6),
(SymbolicFactor(1,2,5)) boost::make_shared<SymbolicFactor>(1, 2, 5),
(SymbolicFactor(0,3)); boost::make_shared<SymbolicFactor>(0, 3)};
const SymbolicFactor expectedFactor(4,5,6); const SymbolicFactor expectedFactor(4,5,6);
const SymbolicConditional expectedConditional = const SymbolicConditional expectedConditional =
SymbolicConditional::FromKeys(list_of(0)(1)(2)(3)(4)(5)(6), 4); SymbolicConditional::FromKeys(KeyVector{0,1,2,3,4,5,6}, 4);
SymbolicFactor::shared_ptr actualFactor; SymbolicFactor::shared_ptr actualFactor;
SymbolicConditional::shared_ptr actualConditional; SymbolicConditional::shared_ptr actualConditional;
boost::tie(actualConditional, actualFactor) = boost::tie(actualConditional, actualFactor) =
EliminateSymbolic(factors, list_of(0)(1)(2)(3)); EliminateSymbolic(factors, Ordering{0, 1, 2, 3});
CHECK(assert_equal(expectedConditional, *actualConditional)); CHECK(assert_equal(expectedConditional, *actualConditional));
CHECK(assert_equal(expectedFactor, *actualFactor)); CHECK(assert_equal(expectedFactor, *actualFactor));

View File

@ -15,34 +15,29 @@
* @author Christian Potthast * @author Christian Potthast
**/ **/
#include <gtsam/symbolic/SymbolicFactorGraph.h> #include <CppUnitLite/TestHarness.h>
#include <gtsam/base/TestableAssertions.h> #include <gtsam/base/TestableAssertions.h>
#include <gtsam/symbolic/SymbolicBayesNet.h> #include <gtsam/symbolic/SymbolicBayesNet.h>
#include <gtsam/symbolic/SymbolicBayesTree.h> #include <gtsam/symbolic/SymbolicBayesTree.h>
#include <gtsam/symbolic/SymbolicConditional.h> #include <gtsam/symbolic/SymbolicConditional.h>
#include <gtsam/symbolic/SymbolicFactorGraph.h>
#include <gtsam/symbolic/tests/symbolicExampleGraphs.h> #include <gtsam/symbolic/tests/symbolicExampleGraphs.h>
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/set.hpp>
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;
using namespace boost::assign;
/* ************************************************************************* */ /* ************************************************************************* */
TEST(SymbolicFactorGraph, keys1) { TEST(SymbolicFactorGraph, keys1) {
KeySet expected; KeySet expected{0, 1, 2, 3, 4};
expected += 0, 1, 2, 3, 4;
KeySet actual = simpleTestGraph1.keys(); KeySet actual = simpleTestGraph1.keys();
EXPECT(expected == actual); EXPECT(expected == actual);
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST(SymbolicFactorGraph, keys2) { TEST(SymbolicFactorGraph, keys2) {
KeySet expected; KeySet expected{0, 1, 2, 3, 4, 5};
expected += 0, 1, 2, 3, 4, 5;
KeySet actual = simpleTestGraph2.keys(); KeySet actual = simpleTestGraph2.keys();
EXPECT(expected == actual); EXPECT(expected == actual);
} }
@ -50,8 +45,7 @@ TEST(SymbolicFactorGraph, keys2) {
/* ************************************************************************* */ /* ************************************************************************* */
TEST(SymbolicFactorGraph, eliminateFullSequential) { TEST(SymbolicFactorGraph, eliminateFullSequential) {
// Test with simpleTestGraph1 // Test with simpleTestGraph1
Ordering order; Ordering order{0, 1, 2, 3, 4};
order += 0, 1, 2, 3, 4;
SymbolicBayesNet actual1 = *simpleTestGraph1.eliminateSequential(order); SymbolicBayesNet actual1 = *simpleTestGraph1.eliminateSequential(order);
EXPECT(assert_equal(simpleTestGraph1BayesNet, actual1)); EXPECT(assert_equal(simpleTestGraph1BayesNet, actual1));
@ -63,18 +57,18 @@ TEST(SymbolicFactorGraph, eliminateFullSequential) {
/* ************************************************************************* */ /* ************************************************************************* */
TEST(SymbolicFactorGraph, eliminatePartialSequential) { TEST(SymbolicFactorGraph, eliminatePartialSequential) {
// Eliminate 0 and 1 // Eliminate 0 and 1
const Ordering order = list_of(0)(1); const Ordering order{0, 1};
const SymbolicBayesNet expectedBayesNet = const auto expectedBayesNet = SymbolicBayesNet(SymbolicConditional(0, 1, 2))(
list_of(SymbolicConditional(0, 1, 2))(SymbolicConditional(1, 2, 3, 4)); SymbolicConditional(1, 2, 3, 4));
const SymbolicFactorGraph expectedSfg = list_of(SymbolicFactor(2, 3))( const auto expectedSfg = SymbolicFactorGraph(SymbolicFactor(2, 3))(
SymbolicFactor(4, 5))(SymbolicFactor(2, 3, 4)); SymbolicFactor(4, 5))(SymbolicFactor(2, 3, 4));
SymbolicBayesNet::shared_ptr actualBayesNet; SymbolicBayesNet::shared_ptr actualBayesNet;
SymbolicFactorGraph::shared_ptr actualSfg; SymbolicFactorGraph::shared_ptr actualSfg;
boost::tie(actualBayesNet, actualSfg) = boost::tie(actualBayesNet, actualSfg) =
simpleTestGraph2.eliminatePartialSequential(Ordering(list_of(0)(1))); simpleTestGraph2.eliminatePartialSequential(Ordering{0, 1});
EXPECT(assert_equal(expectedSfg, *actualSfg)); EXPECT(assert_equal(expectedSfg, *actualSfg));
EXPECT(assert_equal(expectedBayesNet, *actualBayesNet)); EXPECT(assert_equal(expectedBayesNet, *actualBayesNet));
@ -82,8 +76,7 @@ TEST(SymbolicFactorGraph, eliminatePartialSequential) {
SymbolicBayesNet::shared_ptr actualBayesNet2; SymbolicBayesNet::shared_ptr actualBayesNet2;
SymbolicFactorGraph::shared_ptr actualSfg2; SymbolicFactorGraph::shared_ptr actualSfg2;
boost::tie(actualBayesNet2, actualSfg2) = boost::tie(actualBayesNet2, actualSfg2) =
simpleTestGraph2.eliminatePartialSequential( simpleTestGraph2.eliminatePartialSequential(Ordering{0, 1});
list_of(0)(1).convert_to_container<KeyVector>());
EXPECT(assert_equal(expectedSfg, *actualSfg2)); EXPECT(assert_equal(expectedSfg, *actualSfg2));
EXPECT(assert_equal(expectedBayesNet, *actualBayesNet2)); EXPECT(assert_equal(expectedBayesNet, *actualBayesNet2));
@ -105,18 +98,18 @@ TEST(SymbolicFactorGraph, eliminatePartialMultifrontal) {
SymbolicBayesTree expectedBayesTree; SymbolicBayesTree expectedBayesTree;
SymbolicConditional::shared_ptr root = SymbolicConditional::shared_ptr root =
boost::make_shared<SymbolicConditional>( boost::make_shared<SymbolicConditional>(
SymbolicConditional::FromKeys(list_of(4)(5)(1), 2)); SymbolicConditional::FromKeys(KeyVector{4, 5, 1}, 2));
expectedBayesTree.insertRoot( expectedBayesTree.insertRoot(
boost::make_shared<SymbolicBayesTreeClique>(root)); boost::make_shared<SymbolicBayesTreeClique>(root));
SymbolicFactorGraph expectedFactorGraph = const auto expectedFactorGraph =
list_of(SymbolicFactor(0, 1))(SymbolicFactor(0, 2))(SymbolicFactor(1, 3))( SymbolicFactorGraph(SymbolicFactor(0, 1))(SymbolicFactor(0, 2))(
SymbolicFactor(2, 3))(SymbolicFactor(1)); SymbolicFactor(1, 3))(SymbolicFactor(2, 3))(SymbolicFactor(1));
SymbolicBayesTree::shared_ptr actualBayesTree; SymbolicBayesTree::shared_ptr actualBayesTree;
SymbolicFactorGraph::shared_ptr actualFactorGraph; SymbolicFactorGraph::shared_ptr actualFactorGraph;
boost::tie(actualBayesTree, actualFactorGraph) = boost::tie(actualBayesTree, actualFactorGraph) =
simpleTestGraph2.eliminatePartialMultifrontal(Ordering(list_of(4)(5))); simpleTestGraph2.eliminatePartialMultifrontal(Ordering{4, 5});
EXPECT(assert_equal(expectedFactorGraph, *actualFactorGraph)); EXPECT(assert_equal(expectedFactorGraph, *actualFactorGraph));
EXPECT(assert_equal(expectedBayesTree, *actualBayesTree)); EXPECT(assert_equal(expectedBayesTree, *actualBayesTree));
@ -132,8 +125,7 @@ TEST(SymbolicFactorGraph, eliminatePartialMultifrontal) {
SymbolicBayesTree::shared_ptr actualBayesTree2; SymbolicBayesTree::shared_ptr actualBayesTree2;
SymbolicFactorGraph::shared_ptr actualFactorGraph2; SymbolicFactorGraph::shared_ptr actualFactorGraph2;
boost::tie(actualBayesTree2, actualFactorGraph2) = boost::tie(actualBayesTree2, actualFactorGraph2) =
simpleTestGraph2.eliminatePartialMultifrontal( simpleTestGraph2.eliminatePartialMultifrontal(KeyVector{4, 5});
list_of<Key>(4)(5).convert_to_container<KeyVector>());
EXPECT(assert_equal(expectedFactorGraph, *actualFactorGraph2)); EXPECT(assert_equal(expectedFactorGraph, *actualFactorGraph2));
EXPECT(assert_equal(expectedBayesTree2, *actualBayesTree2)); EXPECT(assert_equal(expectedBayesTree2, *actualBayesTree2));
@ -141,12 +133,12 @@ TEST(SymbolicFactorGraph, eliminatePartialMultifrontal) {
/* ************************************************************************* */ /* ************************************************************************* */
TEST(SymbolicFactorGraph, marginalMultifrontalBayesNet) { TEST(SymbolicFactorGraph, marginalMultifrontalBayesNet) {
SymbolicBayesNet expectedBayesNet = auto expectedBayesNet =
list_of(SymbolicConditional(0, 1, 2))(SymbolicConditional(1, 2, 3))( SymbolicBayesNet(SymbolicConditional(0, 1, 2))(SymbolicConditional(
SymbolicConditional(2, 3))(SymbolicConditional(3)); 1, 2, 3))(SymbolicConditional(2, 3))(SymbolicConditional(3));
SymbolicBayesNet actual1 = *simpleTestGraph2.marginalMultifrontalBayesNet( SymbolicBayesNet actual1 =
Ordering(list_of(0)(1)(2)(3))); *simpleTestGraph2.marginalMultifrontalBayesNet(Ordering{0, 1, 2, 3});
EXPECT(assert_equal(expectedBayesNet, actual1)); EXPECT(assert_equal(expectedBayesNet, actual1));
} }
@ -184,7 +176,7 @@ TEST(SymbolicFactorGraph, marginals) {
fg.push_factor(3, 4); fg.push_factor(3, 4);
// eliminate // eliminate
Ordering ord(list_of(3)(4)(2)(1)(0)); Ordering ord{3, 4, 2, 1, 0};
auto actual = fg.eliminateSequential(ord); auto actual = fg.eliminateSequential(ord);
SymbolicBayesNet expected; SymbolicBayesNet expected;
expected.emplace_shared<SymbolicConditional>(3, 4); expected.emplace_shared<SymbolicConditional>(3, 4);
@ -196,7 +188,7 @@ TEST(SymbolicFactorGraph, marginals) {
{ {
// jointBayesNet // jointBayesNet
Ordering ord(list_of(0)(4)(3)); Ordering ord{0, 4, 3};
auto actual = fg.eliminatePartialSequential(ord); auto actual = fg.eliminatePartialSequential(ord);
SymbolicBayesNet expectedBN; SymbolicBayesNet expectedBN;
expectedBN.emplace_shared<SymbolicConditional>(0, 1, 2); expectedBN.emplace_shared<SymbolicConditional>(0, 1, 2);
@ -207,7 +199,7 @@ TEST(SymbolicFactorGraph, marginals) {
{ {
// jointBayesNet // jointBayesNet
Ordering ord(list_of(0)(2)(3)); Ordering ord{0, 2, 3};
auto actual = fg.eliminatePartialSequential(ord); auto actual = fg.eliminatePartialSequential(ord);
SymbolicBayesNet expectedBN; SymbolicBayesNet expectedBN;
expectedBN.emplace_shared<SymbolicConditional>(0, 1, 2); expectedBN.emplace_shared<SymbolicConditional>(0, 1, 2);
@ -218,7 +210,7 @@ TEST(SymbolicFactorGraph, marginals) {
{ {
// conditionalBayesNet // conditionalBayesNet
Ordering ord(list_of(0)(2)); Ordering ord{0, 2};
auto actual = fg.eliminatePartialSequential(ord); auto actual = fg.eliminatePartialSequential(ord);
SymbolicBayesNet expectedBN; SymbolicBayesNet expectedBN;
expectedBN.emplace_shared<SymbolicConditional>(0, 1, 2); expectedBN.emplace_shared<SymbolicConditional>(0, 1, 2);
@ -306,7 +298,7 @@ TEST(SymbolicFactorGraph, add_factors) {
expected.push_factor(1); expected.push_factor(1);
expected.push_factor(11); expected.push_factor(11);
expected.push_factor(2); expected.push_factor(2);
const FactorIndices expectedIndices = list_of(1)(3); const FactorIndices expectedIndices{1, 3};
const FactorIndices actualIndices = fg1.add_factors(fg2, true); const FactorIndices actualIndices = fg1.add_factors(fg2, true);
EXPECT(assert_equal(expected, fg1)); EXPECT(assert_equal(expected, fg1));
@ -314,7 +306,7 @@ TEST(SymbolicFactorGraph, add_factors) {
expected.push_factor(1); expected.push_factor(1);
expected.push_factor(2); expected.push_factor(2);
const FactorIndices expectedIndices2 = list_of(4)(5); const FactorIndices expectedIndices2{4, 5};
const FactorIndices actualIndices2 = fg1.add_factors(fg2, false); const FactorIndices actualIndices2 = fg1.add_factors(fg2, false);
EXPECT(assert_equal(expected, fg1)); EXPECT(assert_equal(expected, fg1));

View File

@ -20,9 +20,6 @@
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/list.hpp> // for operator +=
using namespace boost::assign;
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;
@ -86,7 +83,7 @@ TEST( SymbolicISAM, iSAM )
fullGraph += SymbolicFactor(_B_, _S_); fullGraph += SymbolicFactor(_B_, _S_);
// This ordering is chosen to match the one chosen by COLAMD during the ISAM update // This ordering is chosen to match the one chosen by COLAMD during the ISAM update
Ordering ordering(list_of(_X_)(_B_)(_S_)(_E_)(_L_)(_T_)); Ordering ordering {_X_, _B_, _S_, _E_, _L_, _T_};
SymbolicBayesTree expected = *fullGraph.eliminateMultifrontal(ordering); SymbolicBayesTree expected = *fullGraph.eliminateMultifrontal(ordering);
// Add factor on B and S // Add factor on B and S

View File

@ -23,9 +23,6 @@
#include <gtsam/symbolic/SymbolicEliminationTree.h> #include <gtsam/symbolic/SymbolicEliminationTree.h>
#include <gtsam/symbolic/SymbolicJunctionTree.h> #include <gtsam/symbolic/SymbolicJunctionTree.h>
#include <boost/assign/list_of.hpp>
using namespace boost::assign;
#include "symbolicExampleGraphs.h" #include "symbolicExampleGraphs.h"
using namespace gtsam; using namespace gtsam;
@ -43,9 +40,9 @@ TEST( JunctionTree, constructor )
SymbolicJunctionTree actual(SymbolicEliminationTree(simpleChain, order)); SymbolicJunctionTree actual(SymbolicEliminationTree(simpleChain, order));
SymbolicJunctionTree::Node::Keys SymbolicJunctionTree::Node::Keys
frontal1 = list_of(2)(3), frontal1 {2, 3},
frontal2 = list_of(0)(1), frontal2 {0, 1},
sep1, sep2 = list_of(2); sep1, sep2 {2};
EXPECT(assert_container_equality(frontal1, actual.roots().front()->orderedFrontalKeys)); EXPECT(assert_container_equality(frontal1, actual.roots().front()->orderedFrontalKeys));
//EXPECT(assert_equal(sep1, actual.roots().front()->separator)); //EXPECT(assert_equal(sep1, actual.roots().front()->separator));
LONGS_EQUAL(1, (long)actual.roots().front()->factors.size()); LONGS_EQUAL(1, (long)actual.roots().front()->factors.size());

View File

@ -22,10 +22,6 @@
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/list.hpp>
#include <boost/assign/list_of.hpp>
using namespace boost::assign;
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;
@ -79,7 +75,7 @@ TEST(VariableIndex, augment2) {
VariableIndex expected(fgCombined); VariableIndex expected(fgCombined);
FactorIndices newIndices = list_of(5)(6)(7)(8); FactorIndices newIndices {5, 6, 7, 8};
VariableIndex actual(fg1); VariableIndex actual(fg1);
actual.augment(fg2, newIndices); actual.augment(fg2, newIndices);
@ -108,7 +104,7 @@ TEST(VariableIndex, remove) {
vector<size_t> indices; vector<size_t> indices;
indices.push_back(0); indices.push_back(1); indices.push_back(2); indices.push_back(3); indices.push_back(0); indices.push_back(1); indices.push_back(2); indices.push_back(3);
actual.remove(indices.begin(), indices.end(), fg1); actual.remove(indices.begin(), indices.end(), fg1);
std::list<Key> unusedVariables; unusedVariables += 0, 9; std::list<Key> unusedVariables{0, 9};
actual.removeUnusedVariables(unusedVariables.begin(), unusedVariables.end()); actual.removeUnusedVariables(unusedVariables.begin(), unusedVariables.end());
CHECK(assert_equal(expected, actual)); CHECK(assert_equal(expected, actual));
@ -135,7 +131,7 @@ TEST(VariableIndex, deep_copy) {
vector<size_t> indices; vector<size_t> indices;
indices.push_back(0); indices.push_back(1); indices.push_back(2); indices.push_back(3); indices.push_back(0); indices.push_back(1); indices.push_back(2); indices.push_back(3);
clone.remove(indices.begin(), indices.end(), fg1); clone.remove(indices.begin(), indices.end(), fg1);
std::list<Key> unusedVariables; unusedVariables += 0, 9; std::list<Key> unusedVariables{0, 9};
clone.removeUnusedVariables(unusedVariables.begin(), unusedVariables.end()); clone.removeUnusedVariables(unusedVariables.begin(), unusedVariables.end());
// When modifying the clone, the original should have stayed the same // When modifying the clone, the original should have stayed the same

View File

@ -17,12 +17,12 @@
*/ */
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/assign/std/list.hpp> // for +=
using namespace boost::assign;
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <gtsam_unstable/base/BTree.h> #include <gtsam_unstable/base/BTree.h>
#include <list>
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;
@ -147,13 +147,12 @@ TEST( BTree, iterating )
// acid iterator test // acid iterator test
int sum = 0; int sum = 0;
for(const KeyInt& p: tree) for (const KeyInt& p : tree) sum += p.second;
sum += p.second;
LONGS_EQUAL(15,sum) LONGS_EQUAL(15,sum)
// STL iterator test // STL iterator test
list<KeyInt> expected, actual; auto expected = std::list<KeyInt> {p1, p2, p3, p4, p5};
expected += p1,p2,p3,p4,p5; std::list<KeyInt> actual;
copy (tree.begin(),tree.end(),back_inserter(actual)); copy (tree.begin(),tree.end(),back_inserter(actual));
CHECK(actual==expected) CHECK(actual==expected)
} }
@ -181,7 +180,7 @@ TEST( BTree, stress )
tree = tree.add(key, value); tree = tree.add(key, value);
LONGS_EQUAL(i,tree.size()) LONGS_EQUAL(i,tree.size())
CHECK(tree.find(key) == value) CHECK(tree.find(key) == value)
expected += make_pair(key, value); expected.emplace_back(key, value);
} }
// Check height is log(N) // Check height is log(N)

View File

@ -20,10 +20,6 @@
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/list.hpp>
#include <boost/assign/std/set.hpp>
using namespace boost::assign;
#include <iostream> #include <iostream>
using namespace std; using namespace std;
@ -88,7 +84,7 @@ TEST(DSF, makePair) {
/* ************************************************************************* */ /* ************************************************************************* */
TEST(DSF, makeList) { TEST(DSF, makeList) {
DSFInt dsf; DSFInt dsf;
list<int> keys; keys += 5, 6, 7; list<int> keys{5, 6, 7};
dsf = dsf.makeList(keys); dsf = dsf.makeList(keys);
EXPECT(dsf.findSet(5) == dsf.findSet(7)); EXPECT(dsf.findSet(5) == dsf.findSet(7));
} }
@ -112,7 +108,7 @@ TEST(DSF, sets) {
map<int, set<int> > sets = dsf.sets(); map<int, set<int> > sets = dsf.sets();
LONGS_EQUAL(1, sets.size()); LONGS_EQUAL(1, sets.size());
set<int> expected; expected += 5, 6; set<int> expected{5, 6};
EXPECT(expected == sets[dsf.findSet(5)]); EXPECT(expected == sets[dsf.findSet(5)]);
} }
@ -127,7 +123,7 @@ TEST(DSF, sets2) {
map<int, set<int> > sets = dsf.sets(); map<int, set<int> > sets = dsf.sets();
LONGS_EQUAL(1, sets.size()); LONGS_EQUAL(1, sets.size());
set<int> expected; expected += 5, 6, 7; set<int> expected{5, 6, 7};
EXPECT(expected == sets[dsf.findSet(5)]); EXPECT(expected == sets[dsf.findSet(5)]);
} }
@ -141,7 +137,7 @@ TEST(DSF, sets3) {
map<int, set<int> > sets = dsf.sets(); map<int, set<int> > sets = dsf.sets();
LONGS_EQUAL(2, sets.size()); LONGS_EQUAL(2, sets.size());
set<int> expected; expected += 5, 6; set<int> expected{5, 6};
EXPECT(expected == sets[dsf.findSet(5)]); EXPECT(expected == sets[dsf.findSet(5)]);
} }
@ -152,11 +148,11 @@ TEST(DSF, partition) {
dsf = dsf.makeSet(6); dsf = dsf.makeSet(6);
dsf = dsf.makeUnion(5,6); dsf = dsf.makeUnion(5,6);
list<int> keys; keys += 5; list<int> keys{5};
map<int, set<int> > partitions = dsf.partition(keys); map<int, set<int> > partitions = dsf.partition(keys);
LONGS_EQUAL(1, partitions.size()); LONGS_EQUAL(1, partitions.size());
set<int> expected; expected += 5; set<int> expected{5};
EXPECT(expected == partitions[dsf.findSet(5)]); EXPECT(expected == partitions[dsf.findSet(5)]);
} }
@ -168,11 +164,11 @@ TEST(DSF, partition2) {
dsf = dsf.makeSet(7); dsf = dsf.makeSet(7);
dsf = dsf.makeUnion(5,6); dsf = dsf.makeUnion(5,6);
list<int> keys; keys += 7; list<int> keys{7};
map<int, set<int> > partitions = dsf.partition(keys); map<int, set<int> > partitions = dsf.partition(keys);
LONGS_EQUAL(1, partitions.size()); LONGS_EQUAL(1, partitions.size());
set<int> expected; expected += 7; set<int> expected{7};
EXPECT(expected == partitions[dsf.findSet(7)]); EXPECT(expected == partitions[dsf.findSet(7)]);
} }
@ -184,11 +180,11 @@ TEST(DSF, partition3) {
dsf = dsf.makeSet(7); dsf = dsf.makeSet(7);
dsf = dsf.makeUnion(5,6); dsf = dsf.makeUnion(5,6);
list<int> keys; keys += 5, 7; list<int> keys{5, 7};
map<int, set<int> > partitions = dsf.partition(keys); map<int, set<int> > partitions = dsf.partition(keys);
LONGS_EQUAL(2, partitions.size()); LONGS_EQUAL(2, partitions.size());
set<int> expected; expected += 5; set<int> expected{5};
EXPECT(expected == partitions[dsf.findSet(5)]); EXPECT(expected == partitions[dsf.findSet(5)]);
} }
@ -202,7 +198,7 @@ TEST(DSF, set) {
set<int> set = dsf.set(5); set<int> set = dsf.set(5);
LONGS_EQUAL(2, set.size()); LONGS_EQUAL(2, set.size());
std::set<int> expected; expected += 5, 6; std::set<int> expected{5, 6};
EXPECT(expected == set); EXPECT(expected == set);
} }
@ -217,7 +213,7 @@ TEST(DSF, set2) {
set<int> set = dsf.set(5); set<int> set = dsf.set(5);
LONGS_EQUAL(3, set.size()); LONGS_EQUAL(3, set.size());
std::set<int> expected; expected += 5, 6, 7; std::set<int> expected{5, 6, 7};
EXPECT(expected == set); EXPECT(expected == set);
} }
@ -261,7 +257,7 @@ TEST(DSF, flatten) {
/* ************************************************************************* */ /* ************************************************************************* */
TEST(DSF, flatten2) { TEST(DSF, flatten2) {
static string x1("x1"), x2("x2"), x3("x3"), x4("x4"); static string x1("x1"), x2("x2"), x3("x3"), x4("x4");
list<string> keys; keys += x1,x2,x3,x4; list<string> keys{x1, x2, x3, x4};
DSF<string> dsf(keys); DSF<string> dsf(keys);
dsf = dsf.makeUnion(x1,x2); dsf = dsf.makeUnion(x1,x2);
dsf = dsf.makeUnion(x3,x4); dsf = dsf.makeUnion(x3,x4);
@ -285,13 +281,12 @@ TEST(DSF, mergePairwiseMatches) {
Measurement m22(2,2),m23(2,3),m25(2,5),m26(2,6); // in image 2 Measurement m22(2,2),m23(2,3),m25(2,5),m26(2,6); // in image 2
// Add them all // Add them all
list<Measurement> measurements; list<Measurement> measurements{m11, m12, m14, m22, m23, m25, m26};
measurements += m11,m12,m14, m22,m23,m25,m26;
// Create some "matches" // Create some "matches"
typedef pair<Measurement,Measurement> Match; typedef pair<Measurement,Measurement> Match;
list<Match> matches; list<Match> matches{Match(m11, m22), Match(m12, m23), Match(m14, m25),
matches += Match(m11,m22), Match(m12,m23), Match(m14,m25), Match(m14,m26); Match(m14, m26)};
// Merge matches // Merge matches
DSF<Measurement> dsf(measurements); DSF<Measurement> dsf(measurements);
@ -310,15 +305,15 @@ TEST(DSF, mergePairwiseMatches) {
// Check that we have three connected components // Check that we have three connected components
EXPECT_LONGS_EQUAL(3, dsf.numSets()); EXPECT_LONGS_EQUAL(3, dsf.numSets());
set<Measurement> expected1; expected1 += m11,m22; set<Measurement> expected1{m11,m22};
set<Measurement> actual1 = dsf.set(m11); set<Measurement> actual1 = dsf.set(m11);
EXPECT(expected1 == actual1); EXPECT(expected1 == actual1);
set<Measurement> expected2; expected2 += m12,m23; set<Measurement> expected2{m12,m23};
set<Measurement> actual2 = dsf.set(m12); set<Measurement> actual2 = dsf.set(m12);
EXPECT(expected2 == actual2); EXPECT(expected2 == actual2);
set<Measurement> expected3; expected3 += m14,m25,m26; set<Measurement> expected3{m14,m25,m26};
set<Measurement> actual3 = dsf.set(m14); set<Measurement> actual3 = dsf.set(m14);
EXPECT(expected3 == actual3); EXPECT(expected3 == actual3);
} }

View File

@ -21,7 +21,6 @@
#include <gtsam/discrete/DiscreteValues.h> #include <gtsam/discrete/DiscreteValues.h>
#include <gtsam_unstable/dllexport.h> #include <gtsam_unstable/dllexport.h>
#include <boost/assign.hpp>
#include <boost/format.hpp> #include <boost/format.hpp>
#include <map> #include <map>
@ -40,11 +39,10 @@ class GTSAM_UNSTABLE_EXPORT Constraint : public DiscreteFactor {
protected: protected:
/// Construct unary constraint factor. /// Construct unary constraint factor.
Constraint(Key j) : DiscreteFactor(boost::assign::cref_list_of<1>(j)) {} Constraint(Key j) : DiscreteFactor(KeyVector{j}) {}
/// Construct binary constraint factor. /// Construct binary constraint factor.
Constraint(Key j1, Key j2) Constraint(Key j1, Key j2) : DiscreteFactor(KeyVector{j1, j2}) {}
: DiscreteFactor(boost::assign::cref_list_of<2>(j1)(j2)) {}
/// Construct n-way constraint factor. /// Construct n-way constraint factor.
Constraint(const KeyVector& js) : DiscreteFactor(js) {} Constraint(const KeyVector& js) : DiscreteFactor(js) {}

View File

@ -37,8 +37,7 @@ double Domain::operator()(const DiscreteValues& values) const {
/* ************************************************************************* */ /* ************************************************************************* */
DecisionTreeFactor Domain::toDecisionTreeFactor() const { DecisionTreeFactor Domain::toDecisionTreeFactor() const {
DiscreteKeys keys; const DiscreteKeys keys{DiscreteKey(key(), cardinality_)};
keys += DiscreteKey(key(), cardinality_);
vector<double> table; vector<double> table;
for (size_t i1 = 0; i1 < cardinality_; ++i1) table.push_back(contains(i1)); for (size_t i1 = 0; i1 < cardinality_; ++i1) table.push_back(contains(i1));
DecisionTreeFactor converted(keys, table); DecisionTreeFactor converted(keys, table);

View File

@ -29,8 +29,7 @@ double SingleValue::operator()(const DiscreteValues& values) const {
/* ************************************************************************* */ /* ************************************************************************* */
DecisionTreeFactor SingleValue::toDecisionTreeFactor() const { DecisionTreeFactor SingleValue::toDecisionTreeFactor() const {
DiscreteKeys keys; const DiscreteKeys keys{DiscreteKey(keys_[0], cardinality_)};
keys += DiscreteKey(keys_[0], cardinality_);
vector<double> table; vector<double> table;
for (size_t i1 = 0; i1 < cardinality_; i1++) table.push_back(i1 == value_); for (size_t i1 = 0; i1 < cardinality_; i1++) table.push_back(i1 == value_);
DecisionTreeFactor converted(keys, table); DecisionTreeFactor converted(keys, table);

View File

@ -214,8 +214,7 @@ void sampleSolutions() {
vector<DiscreteBayesNet::shared_ptr> samplers(7); vector<DiscreteBayesNet::shared_ptr> samplers(7);
// Given the time-slots, we can create 7 independent samplers // Given the time-slots, we can create 7 independent samplers
vector<size_t> slots; vector<size_t> slots{16, 17, 11, 2, 0, 5, 9}; // given slots
slots += 16, 17, 11, 2, 0, 5, 9; // given slots
for (size_t i = 0; i < 7; i++) for (size_t i = 0; i < 7; i++)
samplers[i] = createSampler(i, slots[i], schedulers); samplers[i] = createSampler(i, slots[i], schedulers);
@ -296,8 +295,7 @@ void accomodateStudent() {
scheduler.print("scheduler"); scheduler.print("scheduler");
// rule out all occupied slots // rule out all occupied slots
vector<size_t> slots; vector<size_t> slots{16, 17, 11, 2, 0, 5, 9, 14};
slots += 16, 17, 11, 2, 0, 5, 9, 14;
vector<double> slotsAvailable(scheduler.nrTimeSlots(), 1.0); vector<double> slotsAvailable(scheduler.nrTimeSlots(), 1.0);
for(size_t s: slots) for(size_t s: slots)
slotsAvailable[s] = 0; slotsAvailable[s] = 0;

View File

@ -223,8 +223,7 @@ void sampleSolutions() {
vector<DiscreteBayesNet::shared_ptr> samplers(NRSTUDENTS); vector<DiscreteBayesNet::shared_ptr> samplers(NRSTUDENTS);
// Given the time-slots, we can create NRSTUDENTS independent samplers // Given the time-slots, we can create NRSTUDENTS independent samplers
vector<size_t> slots; vector<size_t> slots{3, 20, 2, 6, 5, 11, 1, 4}; // given slots
slots += 3, 20, 2, 6, 5, 11, 1, 4; // given slots
for (size_t i = 0; i < NRSTUDENTS; i++) for (size_t i = 0; i < NRSTUDENTS; i++)
samplers[i] = createSampler(i, slots[i], schedulers); samplers[i] = createSampler(i, slots[i], schedulers);

View File

@ -248,8 +248,7 @@ void sampleSolutions() {
vector<DiscreteBayesNet::shared_ptr> samplers(NRSTUDENTS); vector<DiscreteBayesNet::shared_ptr> samplers(NRSTUDENTS);
// Given the time-slots, we can create NRSTUDENTS independent samplers // Given the time-slots, we can create NRSTUDENTS independent samplers
vector<size_t> slots; vector<size_t> slots{12,11,13, 21,16,1, 3,2,6, 7,22,4}; // given slots
slots += 12,11,13, 21,16,1, 3,2,6, 7,22,4; // given slots
for (size_t i = 0; i < NRSTUDENTS; i++) for (size_t i = 0; i < NRSTUDENTS; i++)
samplers[i] = createSampler(i, slots[i], schedulers); samplers[i] = createSampler(i, slots[i], schedulers);

View File

@ -11,14 +11,12 @@
#include <gtsam/discrete/DiscreteConditional.h> #include <gtsam/discrete/DiscreteConditional.h>
#include <gtsam/inference/VariableIndex.h> #include <gtsam/inference/VariableIndex.h>
#include <boost/assign/list_of.hpp>
#include <boost/range/adaptor/map.hpp> #include <boost/range/adaptor/map.hpp>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
using namespace std; using namespace std;
using namespace boost; using namespace boost;
using namespace boost::assign;
using namespace gtsam; using namespace gtsam;
/** /**
@ -105,7 +103,7 @@ class LoopyBelief {
if (debug) subGraph.print("------- Subgraph:"); if (debug) subGraph.print("------- Subgraph:");
DiscreteFactor::shared_ptr message; DiscreteFactor::shared_ptr message;
boost::tie(dummyCond, message) = boost::tie(dummyCond, message) =
EliminateDiscrete(subGraph, Ordering(list_of(neighbor))); EliminateDiscrete(subGraph, Ordering{neighbor});
// store the new factor into messages // store the new factor into messages
messages.insert(make_pair(neighbor, message)); messages.insert(make_pair(neighbor, message));
if (debug) message->print("------- Message: "); if (debug) message->print("------- Message: ");
@ -230,7 +228,7 @@ TEST_UNSAFE(LoopyBelief, construction) {
// Map from key to DiscreteKey for building belief factor. // Map from key to DiscreteKey for building belief factor.
// TODO: this is bad! // TODO: this is bad!
std::map<Key, DiscreteKey> allKeys = map_list_of(0, C)(1, S)(2, R)(3, W); std::map<Key, DiscreteKey> allKeys{{0, C}, {1, S}, {2, R}, {3, W}};
// Build graph // Build graph
DecisionTreeFactor pC(C, "0.5 0.5"); DecisionTreeFactor pC(C, "0.5 0.5");

View File

@ -58,14 +58,14 @@ class Sudoku : public CSP {
// add row constraints // add row constraints
for (size_t i = 0; i < n; i++) { for (size_t i = 0; i < n; i++) {
DiscreteKeys dkeys; DiscreteKeys dkeys;
for (size_t j = 0; j < n; j++) dkeys += dkey(i, j); for (size_t j = 0; j < n; j++) dkeys.push_back(dkey(i, j));
addAllDiff(dkeys); addAllDiff(dkeys);
} }
// add col constraints // add col constraints
for (size_t j = 0; j < n; j++) { for (size_t j = 0; j < n; j++) {
DiscreteKeys dkeys; DiscreteKeys dkeys;
for (size_t i = 0; i < n; i++) dkeys += dkey(i, j); for (size_t i = 0; i < n; i++) dkeys.push_back(dkey(i, j));
addAllDiff(dkeys); addAllDiff(dkeys);
} }
@ -77,7 +77,7 @@ class Sudoku : public CSP {
// Box I,J // Box I,J
DiscreteKeys dkeys; DiscreteKeys dkeys;
for (size_t i = i0; i < i0 + N; i++) for (size_t i = i0; i < i0 + N; i++)
for (size_t j = j0; j < j0 + N; j++) dkeys += dkey(i, j); for (size_t j = j0; j < j0 + N; j++) dkeys.push_back(dkey(i, j));
addAllDiff(dkeys); addAllDiff(dkeys);
j0 += N; j0 += N;
} }

View File

@ -15,38 +15,31 @@
* @author Duy-Nguyen Ta * @author Duy-Nguyen Ta
**/ **/
#include <gtsam_unstable/linear/LinearEquality.h> #include <CppUnitLite/TestHarness.h>
#include <gtsam/base/TestableAssertions.h> #include <gtsam/base/TestableAssertions.h>
#include <gtsam/linear/HessianFactor.h> #include <gtsam/linear/HessianFactor.h>
#include <gtsam/linear/VectorValues.h> #include <gtsam/linear/VectorValues.h>
#include <CppUnitLite/TestHarness.h> #include <gtsam_unstable/linear/LinearEquality.h>
#include <boost/assign/std/vector.hpp>
#include <boost/assign/list_of.hpp>
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;
using namespace boost::assign;
GTSAM_CONCEPT_TESTABLE_INST (LinearEquality) GTSAM_CONCEPT_TESTABLE_INST(LinearEquality)
namespace { namespace {
namespace simple { namespace simple {
// Terms we'll use // Terms we'll use
const vector<pair<Key, Matrix> > terms = list_of < pair<Key, Matrix> const vector<pair<Key, Matrix> > terms{
> (make_pair(5, Matrix3::Identity()))( make_pair(5, I_3x3), make_pair(10, 2 * I_3x3), make_pair(15, 3 * I_3x3)};
make_pair(10, 2 * Matrix3::Identity()))(
make_pair(15, 3 * Matrix3::Identity()));
// RHS and sigmas // RHS and sigmas
const Vector b = (Vector(3) << 1., 2., 3.).finished(); const Vector b = (Vector(3) << 1., 2., 3.).finished();
const SharedDiagonal noise = noiseModel::Constrained::All(3); const SharedDiagonal noise = noiseModel::Constrained::All(3);
} } // namespace simple
} } // namespace
/* ************************************************************************* */ /* ************************************************************************* */
TEST(LinearEquality, constructors_and_accessors) TEST(LinearEquality, constructors_and_accessors) {
{
using namespace simple; using namespace simple;
// Test for using different numbers of terms // Test for using different numbers of terms
@ -66,8 +59,8 @@ TEST(LinearEquality, constructors_and_accessors)
// Two term constructor // Two term constructor
LinearEquality expected( LinearEquality expected(
boost::make_iterator_range(terms.begin(), terms.begin() + 2), b, 0); boost::make_iterator_range(terms.begin(), terms.begin() + 2), b, 0);
LinearEquality actual(terms[0].first, terms[0].second, LinearEquality actual(terms[0].first, terms[0].second, terms[1].first,
terms[1].first, terms[1].second, b, 0); terms[1].second, b, 0);
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
LONGS_EQUAL((long)terms[1].first, (long)actual.keys().back()); LONGS_EQUAL((long)terms[1].first, (long)actual.keys().back());
EXPECT(assert_equal(terms[1].second, actual.getA(actual.end() - 1))); EXPECT(assert_equal(terms[1].second, actual.getA(actual.end() - 1)));
@ -79,8 +72,9 @@ TEST(LinearEquality, constructors_and_accessors)
// Three term constructor // Three term constructor
LinearEquality expected( LinearEquality expected(
boost::make_iterator_range(terms.begin(), terms.begin() + 3), b, 0); boost::make_iterator_range(terms.begin(), terms.begin() + 3), b, 0);
LinearEquality actual(terms[0].first, terms[0].second, LinearEquality actual(terms[0].first, terms[0].second, terms[1].first,
terms[1].first, terms[1].second, terms[2].first, terms[2].second, b, 0); terms[1].second, terms[2].first, terms[2].second, b,
0);
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
LONGS_EQUAL((long)terms[2].first, (long)actual.keys().back()); LONGS_EQUAL((long)terms[2].first, (long)actual.keys().back());
EXPECT(assert_equal(terms[2].second, actual.getA(actual.end() - 1))); EXPECT(assert_equal(terms[2].second, actual.getA(actual.end() - 1)));
@ -92,39 +86,38 @@ TEST(LinearEquality, constructors_and_accessors)
/* ************************************************************************* */ /* ************************************************************************* */
TEST(LinearEquality, Hessian_conversion) { TEST(LinearEquality, Hessian_conversion) {
HessianFactor hessian(0, (Matrix(4,4) << HessianFactor hessian(
1.57, 2.695, -1.1, -2.35, 0,
2.695, 11.3125, -0.65, -10.225, (Matrix(4, 4) << 1.57, 2.695, -1.1, -2.35, 2.695, 11.3125, -0.65, -10.225,
-1.1, -0.65, 1, 0.5, -1.1, -0.65, 1, 0.5, -2.35, -10.225, 0.5, 9.25)
-2.35, -10.225, 0.5, 9.25).finished(), .finished(),
(Vector(4) << -7.885, -28.5175, 2.75, 25.675).finished(), (Vector(4) << -7.885, -28.5175, 2.75, 25.675).finished(), 73.1725);
73.1725);
try { try {
LinearEquality actual(hessian); LinearEquality actual(hessian);
EXPECT(false); EXPECT(false);
} } catch (const std::runtime_error& exception) {
catch (const std::runtime_error& exception) {
EXPECT(true); EXPECT(true);
} }
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST(LinearEquality, error) TEST(LinearEquality, error) {
{
LinearEquality factor(simple::terms, simple::b, 0); LinearEquality factor(simple::terms, simple::b, 0);
VectorValues values; VectorValues values;
values.insert(5, Vector::Constant(3, 1.0)); values.insert(5, Vector::Constant(3, 1.0));
values.insert(10, Vector::Constant(3, 0.5)); values.insert(10, Vector::Constant(3, 0.5));
values.insert(15, Vector::Constant(3, 1.0/3.0)); values.insert(15, Vector::Constant(3, 1.0 / 3.0));
Vector expected_unwhitened(3); expected_unwhitened << 2.0, 1.0, 0.0; Vector expected_unwhitened(3);
expected_unwhitened << 2.0, 1.0, 0.0;
Vector actual_unwhitened = factor.unweighted_error(values); Vector actual_unwhitened = factor.unweighted_error(values);
EXPECT(assert_equal(expected_unwhitened, actual_unwhitened)); EXPECT(assert_equal(expected_unwhitened, actual_unwhitened));
// whitened is meaningless in constraints // whitened is meaningless in constraints
Vector expected_whitened(3); expected_whitened = expected_unwhitened; Vector expected_whitened(3);
expected_whitened = expected_unwhitened;
Vector actual_whitened = factor.error_vector(values); Vector actual_whitened = factor.error_vector(values);
EXPECT(assert_equal(expected_whitened, actual_whitened)); EXPECT(assert_equal(expected_whitened, actual_whitened));
@ -134,13 +127,13 @@ TEST(LinearEquality, error)
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST(LinearEquality, matrices_NULL) TEST(LinearEquality, matrices_NULL) {
{
// Make sure everything works with nullptr noise model // Make sure everything works with nullptr noise model
LinearEquality factor(simple::terms, simple::b, 0); LinearEquality factor(simple::terms, simple::b, 0);
Matrix AExpected(3, 9); Matrix AExpected(3, 9);
AExpected << simple::terms[0].second, simple::terms[1].second, simple::terms[2].second; AExpected << simple::terms[0].second, simple::terms[1].second,
simple::terms[2].second;
Vector rhsExpected = simple::b; Vector rhsExpected = simple::b;
Matrix augmentedJacobianExpected(3, 10); Matrix augmentedJacobianExpected(3, 10);
augmentedJacobianExpected << AExpected, rhsExpected; augmentedJacobianExpected << AExpected, rhsExpected;
@ -153,24 +146,25 @@ TEST(LinearEquality, matrices_NULL)
// Unwhitened Jacobian // Unwhitened Jacobian
EXPECT(assert_equal(AExpected, factor.jacobianUnweighted().first)); EXPECT(assert_equal(AExpected, factor.jacobianUnweighted().first));
EXPECT(assert_equal(rhsExpected, factor.jacobianUnweighted().second)); EXPECT(assert_equal(rhsExpected, factor.jacobianUnweighted().second));
EXPECT(assert_equal(augmentedJacobianExpected, factor.augmentedJacobianUnweighted())); EXPECT(assert_equal(augmentedJacobianExpected,
factor.augmentedJacobianUnweighted()));
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST(LinearEquality, matrices) TEST(LinearEquality, matrices) {
{
// And now witgh a non-unit noise model // And now witgh a non-unit noise model
LinearEquality factor(simple::terms, simple::b, 0); LinearEquality factor(simple::terms, simple::b, 0);
Matrix jacobianExpected(3, 9); Matrix jacobianExpected(3, 9);
jacobianExpected << simple::terms[0].second, simple::terms[1].second, simple::terms[2].second; jacobianExpected << simple::terms[0].second, simple::terms[1].second,
simple::terms[2].second;
Vector rhsExpected = simple::b; Vector rhsExpected = simple::b;
Matrix augmentedJacobianExpected(3, 10); Matrix augmentedJacobianExpected(3, 10);
augmentedJacobianExpected << jacobianExpected, rhsExpected; augmentedJacobianExpected << jacobianExpected, rhsExpected;
Matrix augmentedHessianExpected = Matrix augmentedHessianExpected =
augmentedJacobianExpected.transpose() * simple::noise->R().transpose() augmentedJacobianExpected.transpose() * simple::noise->R().transpose() *
* simple::noise->R() * augmentedJacobianExpected; simple::noise->R() * augmentedJacobianExpected;
// Whitened Jacobian // Whitened Jacobian
EXPECT(assert_equal(jacobianExpected, factor.jacobian().first)); EXPECT(assert_equal(jacobianExpected, factor.jacobian().first));
@ -180,35 +174,37 @@ TEST(LinearEquality, matrices)
// Unwhitened Jacobian // Unwhitened Jacobian
EXPECT(assert_equal(jacobianExpected, factor.jacobianUnweighted().first)); EXPECT(assert_equal(jacobianExpected, factor.jacobianUnweighted().first));
EXPECT(assert_equal(rhsExpected, factor.jacobianUnweighted().second)); EXPECT(assert_equal(rhsExpected, factor.jacobianUnweighted().second));
EXPECT(assert_equal(augmentedJacobianExpected, factor.augmentedJacobianUnweighted())); EXPECT(assert_equal(augmentedJacobianExpected,
factor.augmentedJacobianUnweighted()));
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST(LinearEquality, operators ) TEST(LinearEquality, operators) {
{
Matrix I = I_2x2; Matrix I = I_2x2;
Vector b = (Vector(2) << 0.2,-0.1).finished(); Vector b = (Vector(2) << 0.2, -0.1).finished();
LinearEquality lf(1, -I, 2, I, b, 0); LinearEquality lf(1, -I, 2, I, b, 0);
VectorValues c; VectorValues c;
c.insert(1, (Vector(2) << 10.,20.).finished()); c.insert(1, (Vector(2) << 10., 20.).finished());
c.insert(2, (Vector(2) << 30.,60.).finished()); c.insert(2, (Vector(2) << 30., 60.).finished());
// test A*x // test A*x
Vector expectedE = (Vector(2) << 20.,40.).finished(); Vector expectedE = (Vector(2) << 20., 40.).finished();
Vector actualE = lf * c; Vector actualE = lf * c;
EXPECT(assert_equal(expectedE, actualE)); EXPECT(assert_equal(expectedE, actualE));
// test A^e // test A^e
VectorValues expectedX; VectorValues expectedX;
expectedX.insert(1, (Vector(2) << -20.,-40.).finished()); expectedX.insert(1, (Vector(2) << -20., -40.).finished());
expectedX.insert(2, (Vector(2) << 20., 40.).finished()); expectedX.insert(2, (Vector(2) << 20., 40.).finished());
VectorValues actualX = VectorValues::Zero(expectedX); VectorValues actualX = VectorValues::Zero(expectedX);
lf.transposeMultiplyAdd(1.0, actualE, actualX); lf.transposeMultiplyAdd(1.0, actualE, actualX);
EXPECT(assert_equal(expectedX, actualX)); EXPECT(assert_equal(expectedX, actualX));
// test gradient at zero // test gradient at zero
Matrix A; Vector b2; boost::tie(A,b2) = lf.jacobian(); Matrix A;
Vector b2;
boost::tie(A, b2) = lf.jacobian();
VectorValues expectedG; VectorValues expectedG;
expectedG.insert(1, (Vector(2) << 0.2, -0.1).finished()); expectedG.insert(1, (Vector(2) << 0.2, -0.1).finished());
expectedG.insert(2, (Vector(2) << -0.2, 0.1).finished()); expectedG.insert(2, (Vector(2) << -0.2, 0.1).finished());
@ -217,16 +213,14 @@ TEST(LinearEquality, operators )
} }
/* ************************************************************************* */ /* ************************************************************************* */
TEST(LinearEquality, default_error ) TEST(LinearEquality, default_error) {
{
LinearEquality f; LinearEquality f;
double actual = f.error(VectorValues()); double actual = f.error(VectorValues());
DOUBLES_EQUAL(0.0, actual, 1e-15); DOUBLES_EQUAL(0.0, actual, 1e-15);
} }
//* ************************************************************************* */ //* ************************************************************************* */
TEST(LinearEquality, empty ) TEST(LinearEquality, empty) {
{
// create an empty factor // create an empty factor
LinearEquality f; LinearEquality f;
EXPECT(f.empty()); EXPECT(f.empty());

View File

@ -6,10 +6,6 @@
* Description: unit tests for FindSeparator * Description: unit tests for FindSeparator
*/ */
#include <boost/assign/std/list.hpp> // for operator +=
#include <boost/assign/std/set.hpp> // for operator +=
#include <boost/assign/std/vector.hpp> // for operator +=
using namespace boost::assign;
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
@ -30,16 +26,16 @@ TEST ( Partition, separatorPartitionByMetis )
graph.push_back(boost::make_shared<GenericFactor2D>(2, NODE_POSE_2D, 4, NODE_LANDMARK_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(2, NODE_POSE_2D, 4, NODE_LANDMARK_2D));
graph.push_back(boost::make_shared<GenericFactor2D>(0, NODE_POSE_2D, 1, NODE_POSE_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(0, NODE_POSE_2D, 1, NODE_POSE_2D));
graph.push_back(boost::make_shared<GenericFactor2D>(1, NODE_POSE_2D, 2, NODE_POSE_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(1, NODE_POSE_2D, 2, NODE_POSE_2D));
std::vector<size_t> keys; keys += 0, 1, 2, 3, 4; std::vector<size_t> keys{0, 1, 2, 3, 4};
WorkSpace workspace(5); WorkSpace workspace(5);
boost::optional<MetisResult> actual = separatorPartitionByMetis<GenericGraph2D>(graph, keys, boost::optional<MetisResult> actual = separatorPartitionByMetis<GenericGraph2D>(graph, keys,
workspace, true); workspace, true);
CHECK(actual.is_initialized()); CHECK(actual.is_initialized());
vector<size_t> A_expected; A_expected += 0, 3; // frontal vector<size_t> A_expected{0, 3}; // frontal
vector<size_t> B_expected; B_expected += 2, 4; // frontal vector<size_t> B_expected{2, 4}; // frontal
vector<size_t> C_expected; C_expected += 1; // separator vector<size_t> C_expected{1}; // separator
CHECK(A_expected == actual->A); CHECK(A_expected == actual->A);
CHECK(B_expected == actual->B); CHECK(B_expected == actual->B);
CHECK(C_expected == actual->C); CHECK(C_expected == actual->C);
@ -55,16 +51,16 @@ TEST ( Partition, separatorPartitionByMetis2 )
graph.push_back(boost::make_shared<GenericFactor2D>(3, NODE_POSE_2D, 6, NODE_LANDMARK_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(3, NODE_POSE_2D, 6, NODE_LANDMARK_2D));
graph.push_back(boost::make_shared<GenericFactor2D>(1, NODE_POSE_2D, 2, NODE_POSE_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(1, NODE_POSE_2D, 2, NODE_POSE_2D));
graph.push_back(boost::make_shared<GenericFactor2D>(2, NODE_POSE_2D, 3, NODE_POSE_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(2, NODE_POSE_2D, 3, NODE_POSE_2D));
std::vector<size_t> keys; keys += 1, 2, 3, 5, 6; std::vector<size_t> keys{1, 2, 3, 5, 6};
WorkSpace workspace(8); WorkSpace workspace(8);
boost::optional<MetisResult> actual = separatorPartitionByMetis<GenericGraph2D>(graph, keys, boost::optional<MetisResult> actual = separatorPartitionByMetis<GenericGraph2D>(graph, keys,
workspace, true); workspace, true);
CHECK(actual.is_initialized()); CHECK(actual.is_initialized());
vector<size_t> A_expected; A_expected += 1, 5; // frontal vector<size_t> A_expected{1, 5}; // frontal
vector<size_t> B_expected; B_expected += 3, 6; // frontal vector<size_t> B_expected{3, 6}; // frontal
vector<size_t> C_expected; C_expected += 2; // separator vector<size_t> C_expected{2}; // separator
CHECK(A_expected == actual->A); CHECK(A_expected == actual->A);
CHECK(B_expected == actual->B); CHECK(B_expected == actual->B);
CHECK(C_expected == actual->C); CHECK(C_expected == actual->C);
@ -78,15 +74,15 @@ TEST ( Partition, edgePartitionByMetis )
graph.push_back(boost::make_shared<GenericFactor3D>(0, 1, 0, NODE_POSE_3D, NODE_POSE_3D)); graph.push_back(boost::make_shared<GenericFactor3D>(0, 1, 0, NODE_POSE_3D, NODE_POSE_3D));
graph.push_back(boost::make_shared<GenericFactor3D>(1, 2, 1, NODE_POSE_3D, NODE_POSE_3D)); graph.push_back(boost::make_shared<GenericFactor3D>(1, 2, 1, NODE_POSE_3D, NODE_POSE_3D));
graph.push_back(boost::make_shared<GenericFactor3D>(2, 3, 2, NODE_POSE_3D, NODE_POSE_3D)); graph.push_back(boost::make_shared<GenericFactor3D>(2, 3, 2, NODE_POSE_3D, NODE_POSE_3D));
std::vector<size_t> keys; keys += 0, 1, 2, 3; std::vector<size_t> keys{0, 1, 2, 3};
WorkSpace workspace(6); WorkSpace workspace(6);
boost::optional<MetisResult> actual = edgePartitionByMetis<GenericGraph3D>(graph, keys, boost::optional<MetisResult> actual = edgePartitionByMetis<GenericGraph3D>(graph, keys,
workspace, true); workspace, true);
CHECK(actual.is_initialized()); CHECK(actual.is_initialized());
vector<size_t> A_expected; A_expected += 0, 1; // frontal vector<size_t> A_expected{0, 1}; // frontal
vector<size_t> B_expected; B_expected += 2, 3; // frontal vector<size_t> B_expected{2, 3}; // frontal
vector<size_t> C_expected; // separator vector<size_t> C_expected; // separator
// for(const size_t a: actual->A) // for(const size_t a: actual->A)
// cout << a << " "; // cout << a << " ";
@ -109,14 +105,14 @@ TEST ( Partition, edgePartitionByMetis2 )
graph.push_back(boost::make_shared<GenericFactor3D>(1, 2, 1, NODE_POSE_3D, NODE_POSE_3D, 1)); graph.push_back(boost::make_shared<GenericFactor3D>(1, 2, 1, NODE_POSE_3D, NODE_POSE_3D, 1));
graph.push_back(boost::make_shared<GenericFactor3D>(2, 3, 2, NODE_POSE_3D, NODE_POSE_3D, 20)); graph.push_back(boost::make_shared<GenericFactor3D>(2, 3, 2, NODE_POSE_3D, NODE_POSE_3D, 20));
graph.push_back(boost::make_shared<GenericFactor3D>(3, 4, 3, NODE_POSE_3D, NODE_POSE_3D, 1)); graph.push_back(boost::make_shared<GenericFactor3D>(3, 4, 3, NODE_POSE_3D, NODE_POSE_3D, 1));
std::vector<size_t> keys; keys += 0, 1, 2, 3, 4; std::vector<size_t> keys{0, 1, 2, 3, 4};
WorkSpace workspace(6); WorkSpace workspace(6);
boost::optional<MetisResult> actual = edgePartitionByMetis<GenericGraph3D>(graph, keys, boost::optional<MetisResult> actual = edgePartitionByMetis<GenericGraph3D>(graph, keys,
workspace, true); workspace, true);
CHECK(actual.is_initialized()); CHECK(actual.is_initialized());
vector<size_t> A_expected; A_expected += 0, 1; // frontal vector<size_t> A_expected{0, 1}; // frontal
vector<size_t> B_expected; B_expected += 2, 3, 4; // frontal vector<size_t> B_expected{2, 3, 4}; // frontal
vector<size_t> C_expected; // separator vector<size_t> C_expected; // separator
CHECK(A_expected == actual->A); CHECK(A_expected == actual->A);
CHECK(B_expected == actual->B); CHECK(B_expected == actual->B);
@ -133,7 +129,7 @@ TEST ( Partition, findSeparator )
graph.push_back(boost::make_shared<GenericFactor2D>(2, NODE_POSE_2D, 4, NODE_LANDMARK_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(2, NODE_POSE_2D, 4, NODE_LANDMARK_2D));
graph.push_back(boost::make_shared<GenericFactor2D>(0, NODE_POSE_2D, 1, NODE_POSE_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(0, NODE_POSE_2D, 1, NODE_POSE_2D));
graph.push_back(boost::make_shared<GenericFactor2D>(1, NODE_POSE_2D, 2, NODE_POSE_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(1, NODE_POSE_2D, 2, NODE_POSE_2D));
std::vector<size_t> keys; keys += 0, 1, 2, 3, 4; std::vector<size_t> keys{0, 1, 2, 3, 4};
WorkSpace workspace(5); WorkSpace workspace(5);
int minNodesPerMap = -1; int minNodesPerMap = -1;
@ -159,7 +155,7 @@ TEST ( Partition, findSeparator2 )
graph.push_back(boost::make_shared<GenericFactor2D>(3, NODE_POSE_2D, 6, NODE_LANDMARK_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(3, NODE_POSE_2D, 6, NODE_LANDMARK_2D));
graph.push_back(boost::make_shared<GenericFactor2D>(1, NODE_POSE_2D, 2, NODE_POSE_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(1, NODE_POSE_2D, 2, NODE_POSE_2D));
graph.push_back(boost::make_shared<GenericFactor2D>(2, NODE_POSE_2D, 3, NODE_POSE_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(2, NODE_POSE_2D, 3, NODE_POSE_2D));
std::vector<size_t> keys; keys += 1, 2, 3, 5, 6; std::vector<size_t> keys{1, 2, 3, 5, 6};
WorkSpace workspace(8); WorkSpace workspace(8);
int minNodesPerMap = -1; int minNodesPerMap = -1;

View File

@ -10,10 +10,6 @@
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/list.hpp> // for operator +=
#include <boost/assign/std/set.hpp> // for operator +=
#include <boost/assign/std/vector.hpp> // for operator +=
using namespace boost::assign;
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
#include <map> #include <map>
@ -44,13 +40,13 @@ TEST ( GenerciGraph, findIslands )
graph.push_back(boost::make_shared<GenericFactor2D>(2, NODE_POSE_2D, 3, NODE_POSE_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(2, NODE_POSE_2D, 3, NODE_POSE_2D));
graph.push_back(boost::make_shared<GenericFactor2D>(4, NODE_POSE_2D, 5, NODE_POSE_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(4, NODE_POSE_2D, 5, NODE_POSE_2D));
graph.push_back(boost::make_shared<GenericFactor2D>(5, NODE_POSE_2D, 6, NODE_POSE_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(5, NODE_POSE_2D, 6, NODE_POSE_2D));
std::vector<size_t> keys; keys += 1, 2, 3, 4, 5, 6, 7, 8, 9; std::vector<size_t> keys{1, 2, 3, 4, 5, 6, 7, 8, 9};
WorkSpace workspace(10); // from 0 to 9 WorkSpace workspace(10); // from 0 to 9
list<vector<size_t> > islands = findIslands(graph, keys, workspace, 7, 2); list<vector<size_t> > islands = findIslands(graph, keys, workspace, 7, 2);
LONGS_EQUAL(2, islands.size()); LONGS_EQUAL(2, islands.size());
vector<size_t> island1; island1 += 1, 2, 3, 7, 8; vector<size_t> island1{1, 2, 3, 7, 8};
vector<size_t> island2; island2 += 4, 5, 6, 9; vector<size_t> island2{4, 5, 6, 9};
CHECK(island1 == islands.front()); CHECK(island1 == islands.front());
CHECK(island2 == islands.back()); CHECK(island2 == islands.back());
} }
@ -77,12 +73,12 @@ TEST( GenerciGraph, findIslands2 )
graph.push_back(boost::make_shared<GenericFactor2D>(2, NODE_POSE_2D, 3, NODE_POSE_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(2, NODE_POSE_2D, 3, NODE_POSE_2D));
graph.push_back(boost::make_shared<GenericFactor2D>(4, NODE_POSE_2D, 5, NODE_POSE_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(4, NODE_POSE_2D, 5, NODE_POSE_2D));
graph.push_back(boost::make_shared<GenericFactor2D>(5, NODE_POSE_2D, 6, NODE_POSE_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(5, NODE_POSE_2D, 6, NODE_POSE_2D));
std::vector<size_t> keys; keys += 1, 2, 3, 4, 5, 6, 7, 8; std::vector<size_t> keys{1, 2, 3, 4, 5, 6, 7, 8};
WorkSpace workspace(15); // from 0 to 8, but testing over-allocation here WorkSpace workspace(15); // from 0 to 8, but testing over-allocation here
list<vector<size_t> > islands = findIslands(graph, keys, workspace, 7, 2); list<vector<size_t> > islands = findIslands(graph, keys, workspace, 7, 2);
LONGS_EQUAL(1, islands.size()); LONGS_EQUAL(1, islands.size());
vector<size_t> island1; island1 += 1, 2, 3, 4, 5, 6, 7, 8; vector<size_t> island1{1, 2, 3, 4, 5, 6, 7, 8};
CHECK(island1 == islands.front()); CHECK(island1 == islands.front());
} }
@ -99,13 +95,13 @@ TEST ( GenerciGraph, findIslands3 )
graph.push_back(boost::make_shared<GenericFactor2D>(2, NODE_POSE_2D, 3, NODE_POSE_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(2, NODE_POSE_2D, 3, NODE_POSE_2D));
graph.push_back(boost::make_shared<GenericFactor2D>(3, NODE_POSE_2D, 4, NODE_POSE_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(3, NODE_POSE_2D, 4, NODE_POSE_2D));
std::vector<size_t> keys; keys += 1, 2, 3, 4, 5, 6; std::vector<size_t> keys{1, 2, 3, 4, 5, 6};
WorkSpace workspace(7); // from 0 to 9 WorkSpace workspace(7); // from 0 to 9
list<vector<size_t> > islands = findIslands(graph, keys, workspace, 7, 2); list<vector<size_t> > islands = findIslands(graph, keys, workspace, 7, 2);
LONGS_EQUAL(2, islands.size()); LONGS_EQUAL(2, islands.size());
vector<size_t> island1; island1 += 1, 5; vector<size_t> island1{1, 5};
vector<size_t> island2; island2 += 2, 3, 4, 6; vector<size_t> island2{2, 3, 4, 6};
CHECK(island1 == islands.front()); CHECK(island1 == islands.front());
CHECK(island2 == islands.back()); CHECK(island2 == islands.back());
} }
@ -119,13 +115,13 @@ TEST ( GenerciGraph, findIslands4 )
GenericGraph2D graph; GenericGraph2D graph;
graph.push_back(boost::make_shared<GenericFactor2D>(3, NODE_POSE_2D, 4, NODE_LANDMARK_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(3, NODE_POSE_2D, 4, NODE_LANDMARK_2D));
graph.push_back(boost::make_shared<GenericFactor2D>(7, NODE_POSE_2D, 7, NODE_LANDMARK_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(7, NODE_POSE_2D, 7, NODE_LANDMARK_2D));
std::vector<size_t> keys; keys += 3, 4, 7; std::vector<size_t> keys{3, 4, 7};
WorkSpace workspace(8); // from 0 to 7 WorkSpace workspace(8); // from 0 to 7
list<vector<size_t> > islands = findIslands(graph, keys, workspace, 7, 2); list<vector<size_t> > islands = findIslands(graph, keys, workspace, 7, 2);
LONGS_EQUAL(2, islands.size()); LONGS_EQUAL(2, islands.size());
vector<size_t> island1; island1 += 3, 4; vector<size_t> island1{3, 4};
vector<size_t> island2; island2 += 7; vector<size_t> island2{7};
CHECK(island1 == islands.front()); CHECK(island1 == islands.front());
CHECK(island2 == islands.back()); CHECK(island2 == islands.back());
} }
@ -147,13 +143,13 @@ TEST ( GenerciGraph, findIslands5 )
graph.push_back(boost::make_shared<GenericFactor2D>(1, NODE_POSE_2D, 3, NODE_POSE_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(1, NODE_POSE_2D, 3, NODE_POSE_2D));
graph.push_back(boost::make_shared<GenericFactor2D>(2, NODE_POSE_2D, 4, NODE_POSE_2D)); graph.push_back(boost::make_shared<GenericFactor2D>(2, NODE_POSE_2D, 4, NODE_POSE_2D));
std::vector<size_t> keys; keys += 1, 2, 3, 4, 5; std::vector<size_t> keys{1, 2, 3, 4, 5};
WorkSpace workspace(6); // from 0 to 5 WorkSpace workspace(6); // from 0 to 5
list<vector<size_t> > islands = findIslands(graph, keys, workspace, 7, 2); list<vector<size_t> > islands = findIslands(graph, keys, workspace, 7, 2);
LONGS_EQUAL(2, islands.size()); LONGS_EQUAL(2, islands.size());
vector<size_t> island1; island1 += 1, 3, 5; vector<size_t> island1{1, 3, 5};
vector<size_t> island2; island2 += 2, 4; vector<size_t> island2{2, 4};
CHECK(island1 == islands.front()); CHECK(island1 == islands.front());
CHECK(island2 == islands.back()); CHECK(island2 == islands.back());
} }
@ -235,8 +231,8 @@ TEST ( GenericGraph, reduceGenericGraph2 )
/* ************************************************************************* */ /* ************************************************************************* */
TEST ( GenerciGraph, hasCommonCamera ) TEST ( GenerciGraph, hasCommonCamera )
{ {
std::set<size_t> cameras1; cameras1 += 1, 2, 3, 4, 5; std::set<size_t> cameras1{1, 2, 3, 4, 5};
std::set<size_t> cameras2; cameras2 += 8, 7, 6, 5; std::set<size_t> cameras2{8, 7, 6, 5};
bool actual = hasCommonCamera(cameras1, cameras2); bool actual = hasCommonCamera(cameras1, cameras2);
CHECK(actual); CHECK(actual);
} }
@ -244,8 +240,8 @@ TEST ( GenerciGraph, hasCommonCamera )
/* ************************************************************************* */ /* ************************************************************************* */
TEST ( GenerciGraph, hasCommonCamera2 ) TEST ( GenerciGraph, hasCommonCamera2 )
{ {
std::set<size_t> cameras1; cameras1 += 1, 3, 5, 7; std::set<size_t> cameras1{1, 3, 5, 7};
std::set<size_t> cameras2; cameras2 += 2, 4, 6, 8, 10; std::set<size_t> cameras2{2, 4, 6, 8, 10};
bool actual = hasCommonCamera(cameras1, cameras2); bool actual = hasCommonCamera(cameras1, cameras2);
CHECK(!actual); CHECK(!actual);
} }

View File

@ -6,10 +6,6 @@
* Description: unit tests for NestedDissection * Description: unit tests for NestedDissection
*/ */
#include <boost/assign/std/list.hpp> // for operator +=
#include <boost/assign/std/set.hpp> // for operator +=
#include <boost/assign/std/vector.hpp> // for operator +=
using namespace boost::assign;
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>

Some files were not shown because too many files have changed in this diff Show More