355 lines
9.7 KiB
C++
355 lines
9.7 KiB
C++
/* ----------------------------------------------------------------------------
|
|
|
|
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
|
|
* Atlanta, Georgia 30332-0415
|
|
* All Rights Reserved
|
|
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
|
|
|
|
* See LICENSE for the license information
|
|
|
|
* -------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
* @file testGaussianConditional.cpp
|
|
* @brief Unit tests for Conditional gaussian
|
|
* @author Christian Potthast
|
|
**/
|
|
|
|
#include <CppUnitLite/TestHarness.h>
|
|
#include <gtsam/base/TestableAssertions.h>
|
|
|
|
#include <gtsam/base/Matrix.h>
|
|
#include <gtsam/linear/JacobianFactor.h>
|
|
#include <gtsam/linear/GaussianConditional.h>
|
|
#include <gtsam/linear/GaussianBayesNet.h>
|
|
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <vector>
|
|
#include <boost/assign/std/list.hpp>
|
|
#include <boost/assign/std/vector.hpp>
|
|
|
|
using namespace gtsam;
|
|
using namespace std;
|
|
using namespace boost::assign;
|
|
|
|
static const double tol = 1e-5;
|
|
static const Index _x_=0, _x1_=1, _l1_=2;
|
|
|
|
Matrix R = Matrix_(2,2,
|
|
-12.1244, -5.1962,
|
|
0., 4.6904);
|
|
|
|
/* ************************************************************************* */
|
|
TEST(GaussianConditional, constructor)
|
|
{
|
|
Matrix S1 = Matrix_(2,2,
|
|
-5.2786, -8.6603,
|
|
5.0254, 5.5432);
|
|
Matrix S2 = Matrix_(2,2,
|
|
-10.5573, -5.9385,
|
|
5.5737, 3.0153);
|
|
Matrix S3 = Matrix_(2,2,
|
|
-11.3820, -7.2581,
|
|
-3.0153, -3.5635);
|
|
|
|
Vector d = Vector_(2, 1.0, 2.0);
|
|
Vector s = Vector_(2, 3.0, 4.0);
|
|
|
|
list<pair<Index, Matrix> > terms;
|
|
terms +=
|
|
make_pair(3, S1),
|
|
make_pair(5, S2),
|
|
make_pair(7, S3);
|
|
|
|
GaussianConditional actual(1, d, R, terms, s);
|
|
|
|
GaussianConditional::const_iterator it = actual.beginFrontals();
|
|
EXPECT(assert_equal(Index(1), *it));
|
|
EXPECT(assert_equal(R, actual.get_R()));
|
|
++ it;
|
|
EXPECT(it == actual.endFrontals());
|
|
|
|
it = actual.beginParents();
|
|
EXPECT(assert_equal(Index(3), *it));
|
|
EXPECT(assert_equal(S1, actual.get_S(it)));
|
|
|
|
++ it;
|
|
EXPECT(assert_equal(Index(5), *it));
|
|
EXPECT(assert_equal(S2, actual.get_S(it)));
|
|
|
|
++ it;
|
|
EXPECT(assert_equal(Index(7), *it));
|
|
EXPECT(assert_equal(S3, actual.get_S(it)));
|
|
|
|
++it;
|
|
EXPECT(it == actual.endParents());
|
|
|
|
EXPECT(assert_equal(d, actual.get_d()));
|
|
EXPECT(assert_equal(s, actual.get_sigmas()));
|
|
|
|
// test copy constructor
|
|
GaussianConditional copied(actual);
|
|
EXPECT(assert_equal(d, copied.get_d()));
|
|
EXPECT(assert_equal(s, copied.get_sigmas()));
|
|
EXPECT(assert_equal(R, copied.get_R()));
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
|
|
GaussianConditional construct() {
|
|
Vector d = Vector_(2, 1.0, 2.0);
|
|
Vector s = Vector_(2, 3.0, 4.0);
|
|
GaussianConditional::shared_ptr shared(new GaussianConditional(1, d, R, s));
|
|
return *shared;
|
|
}
|
|
|
|
TEST(GaussianConditional, return_value)
|
|
{
|
|
Vector d = Vector_(2, 1.0, 2.0);
|
|
Vector s = Vector_(2, 3.0, 4.0);
|
|
GaussianConditional copied = construct();
|
|
EXPECT(assert_equal(d, copied.get_d()));
|
|
EXPECT(assert_equal(s, copied.get_sigmas()));
|
|
EXPECT(assert_equal(R, copied.get_R()));
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
TEST( GaussianConditional, equals )
|
|
{
|
|
// create a conditional gaussian node
|
|
Matrix A1(2,2);
|
|
A1(0,0) = 1 ; A1(1,0) = 2;
|
|
A1(0,1) = 3 ; A1(1,1) = 4;
|
|
|
|
Matrix A2(2,2);
|
|
A2(0,0) = 6 ; A2(1,0) = 0.2;
|
|
A2(0,1) = 8 ; A2(1,1) = 0.4;
|
|
|
|
Matrix R(2,2);
|
|
R(0,0) = 0.1 ; R(1,0) = 0.3;
|
|
R(0,1) = 0.0 ; R(1,1) = 0.34;
|
|
|
|
Vector tau(2);
|
|
tau(0) = 1.0;
|
|
tau(1) = 0.34;
|
|
|
|
Vector d(2);
|
|
d(0) = 0.2; d(1) = 0.5;
|
|
|
|
GaussianConditional
|
|
expected(_x_,d, R, _x1_, A1, _l1_, A2, tau),
|
|
actual(_x_,d, R, _x1_, A1, _l1_, A2, tau);
|
|
|
|
EXPECT( expected.equals(actual) );
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
TEST( GaussianConditional, solve )
|
|
{
|
|
//expected solution
|
|
Vector expectedX(2);
|
|
expectedX(0) = 20-3-11 ; expectedX(1) = 40-7-15;
|
|
|
|
// create a conditional Gaussian node
|
|
Matrix R = Matrix_(2,2, 1., 0.,
|
|
0., 1.);
|
|
|
|
Matrix A1 = Matrix_(2,2, 1., 2.,
|
|
3., 4.);
|
|
|
|
Matrix A2 = Matrix_(2,2, 5., 6.,
|
|
7., 8.);
|
|
|
|
Vector d(2);
|
|
d(0) = 20.0; d(1) = 40.0;
|
|
|
|
Vector tau = ones(2);
|
|
|
|
GaussianConditional cg(_x_, d, R, _x1_, A1, _l1_, A2, tau);
|
|
|
|
Vector sx1(2);
|
|
sx1(0) = 1.0; sx1(1) = 1.0;
|
|
|
|
Vector sl1(2);
|
|
sl1(0) = 1.0; sl1(1) = 1.0;
|
|
|
|
VectorValues solution(vector<size_t>(3, 2));
|
|
solution[_x_] = d;
|
|
solution[_x1_] = sx1; // parents
|
|
solution[_l1_] = sl1;
|
|
|
|
VectorValues expected(vector<size_t>(3, 2));
|
|
expected[_x_] = expectedX;
|
|
expected[_x1_] = sx1;
|
|
expected[_l1_] = sl1;
|
|
cg.solveInPlace(solution);
|
|
|
|
EXPECT(assert_equal(expected, solution, 0.0001));
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
TEST( GaussianConditional, solve_simple )
|
|
{
|
|
Matrix full_matrix = Matrix_(4, 7,
|
|
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);
|
|
|
|
// solve system as a non-multifrontal version first
|
|
// 2 variables, frontal has dim=4
|
|
vector<size_t> dims; dims += 4, 2, 1;
|
|
GaussianConditional::rsd_type matrices(full_matrix, dims.begin(), dims.end());
|
|
Vector sigmas = ones(4);
|
|
vector<size_t> cgdims; cgdims += _x_, _x1_;
|
|
GaussianConditional cg(cgdims.begin(), cgdims.end(), 1, matrices, sigmas);
|
|
|
|
// partial solution
|
|
Vector sx1 = Vector_(2, 9.0, 10.0);
|
|
|
|
// elimination order; _x_, _x1_
|
|
vector<size_t> vdim; vdim += 4, 2;
|
|
VectorValues actual(vdim);
|
|
actual[_x1_] = sx1; // parent
|
|
|
|
VectorValues expected(vdim);
|
|
expected[_x1_] = sx1;
|
|
expected[_x_] = Vector_(4, -3.1,-3.4,-11.9,-13.2);
|
|
|
|
// verify indices/size
|
|
EXPECT_LONGS_EQUAL(2, cg.size());
|
|
EXPECT_LONGS_EQUAL(4, cg.dim());
|
|
|
|
// solve and verify
|
|
cg.solveInPlace(actual);
|
|
EXPECT(assert_equal(expected, actual, tol));
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
TEST( GaussianConditional, solve_multifrontal )
|
|
{
|
|
// create full system, 3 variables, 2 frontals, all 2 dim
|
|
Matrix full_matrix = Matrix_(4, 7,
|
|
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);
|
|
|
|
// 3 variables, all dim=2
|
|
vector<size_t> dims; dims += 2, 2, 2, 1;
|
|
GaussianConditional::rsd_type matrices(full_matrix, dims.begin(), dims.end());
|
|
Vector sigmas = ones(4);
|
|
vector<size_t> cgdims; cgdims += _x_, _x1_, _l1_;
|
|
GaussianConditional cg(cgdims.begin(), cgdims.end(), 2, matrices, sigmas);
|
|
|
|
EXPECT(assert_equal(Vector_(4, 0.1, 0.2, 0.3, 0.4), cg.get_d()));
|
|
|
|
// partial solution
|
|
Vector sl1 = Vector_(2, 9.0, 10.0);
|
|
|
|
// elimination order; _x_, _x1_, _l1_
|
|
VectorValues actual(vector<size_t>(3, 2));
|
|
actual[_l1_] = sl1; // parent
|
|
|
|
VectorValues expected(vector<size_t>(3, 2));
|
|
expected[_x_] = Vector_(2, -3.1,-3.4);
|
|
expected[_x1_] = Vector_(2, -11.9,-13.2);
|
|
expected[_l1_] = sl1;
|
|
|
|
// verify indices/size
|
|
EXPECT_LONGS_EQUAL(3, cg.size());
|
|
EXPECT_LONGS_EQUAL(4, cg.dim());
|
|
|
|
// solve and verify
|
|
cg.solveInPlace(actual);
|
|
EXPECT(assert_equal(expected, actual, tol));
|
|
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
TEST( GaussianConditional, solveTranspose ) {
|
|
static const Index _y_=1;
|
|
/** create small Chordal Bayes Net x <- y
|
|
* x y d
|
|
* 1 1 9
|
|
* 1 5
|
|
*/
|
|
Matrix R11 = Matrix_(1, 1, 1.0), S12 = Matrix_(1, 1, 1.0);
|
|
Matrix R22 = Matrix_(1, 1, 1.0);
|
|
Vector d1(1), d2(1);
|
|
d1(0) = 9;
|
|
d2(0) = 5;
|
|
Vector tau(1);
|
|
tau(0) = 1.0;
|
|
|
|
// define nodes and specify in reverse topological sort (i.e. parents last)
|
|
GaussianConditional::shared_ptr Px_y(new GaussianConditional(_x_, d1, R11, _y_, S12, tau));
|
|
GaussianConditional::shared_ptr Py(new GaussianConditional(_y_, d2, R22, tau));
|
|
GaussianBayesNet cbn;
|
|
cbn.push_back(Px_y);
|
|
cbn.push_back(Py);
|
|
|
|
// x=R'*y, y=inv(R')*x
|
|
// 2 = 1 2
|
|
// 5 1 1 3
|
|
|
|
VectorValues y(vector<size_t>(2,1)), x(vector<size_t>(2,1));
|
|
x[_x_] = Vector_(1,2.);
|
|
x[_y_] = Vector_(1,5.);
|
|
y[_x_] = Vector_(1,2.);
|
|
y[_y_] = Vector_(1,3.);
|
|
|
|
// test functional version
|
|
VectorValues actual = backSubstituteTranspose(cbn,x);
|
|
CHECK(assert_equal(y,actual));
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
TEST( GaussianConditional, information ) {
|
|
|
|
// Create R matrix
|
|
Matrix R = (Matrix(4,4) <<
|
|
1, 2, 3, 4,
|
|
0, 5, 6, 7,
|
|
0, 0, 8, 9,
|
|
0, 0, 0, 10).finished();
|
|
|
|
// Create conditional
|
|
GaussianConditional conditional(0, Vector::Zero(4), R, Vector::Constant(4, 1.0));
|
|
|
|
// Expected information matrix (using permuted R)
|
|
Matrix IExpected = R.transpose() * R;
|
|
|
|
// Actual information matrix (conditional should permute R)
|
|
Matrix IActual = conditional.information();
|
|
EXPECT(assert_equal(IExpected, IActual));
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
TEST( GaussianConditional, isGaussianFactor ) {
|
|
|
|
// Create R matrix
|
|
Matrix R = (Matrix(4,4) <<
|
|
1, 2, 3, 4,
|
|
0, 5, 6, 7,
|
|
0, 0, 8, 9,
|
|
0, 0, 0, 10).finished();
|
|
|
|
// Create a conditional
|
|
GaussianConditional conditional(0, Vector::Zero(4), R, Vector::Constant(4, 1.0));
|
|
|
|
// Expected information matrix computed by conditional
|
|
Matrix IExpected = conditional.information();
|
|
|
|
// Expected information matrix computed by a factor
|
|
JacobianFactor jf = *conditional.toFactor();
|
|
Matrix IActual = jf.getA(jf.begin()).transpose() * jf.getA(jf.begin());
|
|
|
|
EXPECT(assert_equal(IExpected, IActual));
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
int main() { TestResult tr; return TestRegistry::runAllTests(tr);}
|
|
/* ************************************************************************* */
|