diff --git a/.cproject b/.cproject
index 061eab2d5..9e76907be 100644
--- a/.cproject
+++ b/.cproject
@@ -692,14 +692,6 @@
true
true
-
- make
- -j2
- tests/testPose2SLAMwSPCG.run
- true
- true
- true
-
make
-j2
@@ -876,6 +868,46 @@
true
true
+
+ make
+ -j2
+ testPose2SLAMwSPCG.run
+ true
+ true
+ true
+
+
+ make
+ -j2
+ testNonlinearOptimizer.run
+ true
+ true
+ true
+
+
+ make
+ -j2
+ testGaussianBayesNet.run
+ true
+ true
+ true
+
+
+ make
+ -j2
+ testNonlinearISAM.run
+ true
+ true
+ true
+
+
+ make
+ -j2
+ testBoundingConstraint.run
+ true
+ true
+ true
+
make
-j2
@@ -2487,14 +2519,6 @@
true
true
-
- make
- -j2
- tests/testPose2SLAMwSPCG.run
- true
- true
- true
-
make
-j2
@@ -2671,6 +2695,46 @@
true
true
+
+ make
+ -j2
+ testPose2SLAMwSPCG.run
+ true
+ true
+ true
+
+
+ make
+ -j2
+ testNonlinearOptimizer.run
+ true
+ true
+ true
+
+
+ make
+ -j2
+ testGaussianBayesNet.run
+ true
+ true
+ true
+
+
+ make
+ -j2
+ testNonlinearISAM.run
+ true
+ true
+ true
+
+
+ make
+ -j2
+ testBoundingConstraint.run
+ true
+ true
+ true
+
make
-j2
diff --git a/CppUnitLite/TestRegistry.cpp b/CppUnitLite/TestRegistry.cpp
index 432faf990..fa5295229 100644
--- a/CppUnitLite/TestRegistry.cpp
+++ b/CppUnitLite/TestRegistry.cpp
@@ -19,9 +19,6 @@
#include "TestRegistry.h"
#include "SimpleString.h"
-//#include
-//using namespace std;
-
void TestRegistry::addTest (Test *test)
{
instance ().add (test);
@@ -63,7 +60,6 @@ int TestRegistry::run (TestResult& result)
for (Test *test = tests; test != 0; test = test->getNext ()) {
if (test->safe()) {
try {
-// cout << test->getName().asCharString() << ", " << test->getFilename().asCharString() << ":" << test->getLineNumber() << endl;
test->run (result);
} catch (std::exception& e) {
// catch standard exceptions and derivatives
diff --git a/examples/PlanarSLAMSelfContained_advanced.cpp b/examples/PlanarSLAMSelfContained_advanced.cpp
index b29871f04..85e8be814 100644
--- a/examples/PlanarSLAMSelfContained_advanced.cpp
+++ b/examples/PlanarSLAMSelfContained_advanced.cpp
@@ -136,11 +136,11 @@ int main(int argc, char** argv) {
resultMF.values()->print("final result (solved with a multifrontal solver)");
// Print marginals covariances for all variables
- print(resultMF.marginalCovariance(x1).second, "x1 covariance");
- print(resultMF.marginalCovariance(x2).second, "x2 covariance");
- print(resultMF.marginalCovariance(x3).second, "x3 covariance");
- print(resultMF.marginalCovariance(l1).second, "l1 covariance");
- print(resultMF.marginalCovariance(l2).second, "l2 covariance");
+ print(resultMF.marginalCovariance(x1), "x1 covariance");
+ print(resultMF.marginalCovariance(x2), "x2 covariance");
+ print(resultMF.marginalCovariance(x3), "x3 covariance");
+ print(resultMF.marginalCovariance(l1), "l1 covariance");
+ print(resultMF.marginalCovariance(l2), "l2 covariance");
return 0;
}
diff --git a/examples/Pose2SLAMExample_advanced.cpp b/examples/Pose2SLAMExample_advanced.cpp
index 697a4b99b..f4e1d3a74 100644
--- a/examples/Pose2SLAMExample_advanced.cpp
+++ b/examples/Pose2SLAMExample_advanced.cpp
@@ -76,8 +76,8 @@ int main(int argc, char** argv) {
result.print("final result");
/* Get covariances */
- Matrix covariance1 = optimizer_result.marginalCovariance(x1).second;
- Matrix covariance2 = optimizer_result.marginalCovariance(x2).second;
+ Matrix covariance1 = optimizer_result.marginalCovariance(x1);
+ Matrix covariance2 = optimizer_result.marginalCovariance(x2);
print(covariance1, "Covariance1");
print(covariance2, "Covariance2");
diff --git a/gtsam/base/FastMap.h b/gtsam/base/FastMap.h
index 936c0664e..ea2468d64 100644
--- a/gtsam/base/FastMap.h
+++ b/gtsam/base/FastMap.h
@@ -57,7 +57,6 @@ public:
friend class boost::serialization::access;
template
void serialize(ARCHIVE & ar, const unsigned int version) {
-
ar & boost::serialization::base_object(*this);
}
};
diff --git a/gtsam/base/FastVector.h b/gtsam/base/FastVector.h
index 00a9bb801..2e87d638a 100644
--- a/gtsam/base/FastVector.h
+++ b/gtsam/base/FastVector.h
@@ -40,6 +40,9 @@ public:
/** Default constructor */
FastVector() {}
+ /** Constructor from size */
+ FastVector(size_t size) : Base(size) {}
+
/** Constructor from a range, passes through to base class */
template
FastVector(INPUTITERATOR first, INPUTITERATOR last) : Base(first, last) {}
diff --git a/gtsam/base/Lie.h b/gtsam/base/Lie.h
index af8092c60..ea3c730bf 100644
--- a/gtsam/base/Lie.h
+++ b/gtsam/base/Lie.h
@@ -56,7 +56,6 @@
#pragma once
#include
-
#include
namespace gtsam {
diff --git a/gtsam/base/Matrix.cpp b/gtsam/base/Matrix.cpp
index 9781f6316..eac671f9e 100644
--- a/gtsam/base/Matrix.cpp
+++ b/gtsam/base/Matrix.cpp
@@ -259,32 +259,13 @@ Vector columnNormSquare(const Matrix &A) {
}
/* ************************************************************************* */
-void solve(Matrix& A, Matrix& B)
-{
+void solve(Matrix& A, Matrix& B) {
// Eigen version - untested
- Eigen::FullPivLU lu;
- lu.compute(A);
- B = lu.solve(B);
- A = lu.matrixLU();
-
-// typedef ublas::permutation_matrix pmatrix;
- // create a working copy of the input
-// Matrix A_(A);
- // create a permutation matrix for the LU-factorization
-// pmatrix pm(A_.rows());
-
- // perform LU-factorization
- // FIXME: add back with Eigen functionality
- // size_t res = lu_factorize(A_,pm);
- // if( res != 0 ) throw runtime_error ("Matrix::solve: lu_factorize failed!");
-
- // backsubstitute to get the inverse
-// lu_substitute(A_, pm, B);
+ B = A.fullPivLu().solve(B);
}
/* ************************************************************************* */
-Matrix inverse(const Matrix& A)
-{
+Matrix inverse(const Matrix& A) {
return A.inverse();
}
@@ -445,31 +426,11 @@ Vector backSubstituteUpper(const Matrix& U, const Vector& b, bool unit) {
/* ************************************************************************* */
Vector backSubstituteUpper(const Vector& b, const Matrix& U, bool unit) {
// @return the solution x of x'*U=b'
- size_t n = U.cols();
-#ifndef NDEBUG
- size_t m = U.rows();
- if (m!=n)
- throw invalid_argument("backSubstituteUpper: U must be square");
-#endif
-
- Vector result(n);
- for (size_t i = 1; i <= n; i++) {
- double zi = b(i-1);
- for (size_t j = 1; j < i; j++)
- zi -= U(j-1,i-1) * result(j-1);
-#ifndef NDEBUG
- if(!unit && fabs(U(i-1,i-1)) <= numeric_limits::epsilon()) {
- stringstream ss;
- ss << "backSubstituteUpper: U is singular,\n";
- print(U, "U: ", ss);
- throw invalid_argument(ss.str());
- }
-#endif
- if (!unit) zi /= U(i-1,i-1);
- result(i-1) = zi;
- }
-
- return result;
+ assert(U.rows() == U.cols());
+ if (unit)
+ return U.triangularView().transpose().solve(b);
+ else
+ return U.triangularView().transpose().solve(b);
}
/* ************************************************************************* */
@@ -578,13 +539,14 @@ Matrix skewSymmetric(double wx, double wy, double wz)
* pointers are subtracted by one to provide base 1 access
*/
/* ************************************************************************* */
-double** createNRC(Matrix& A) {
- const size_t m=A.rows();
- double** a = new double* [m];
- for(size_t i = 0; i < m; i++)
- a[i] = &A(i,0)-1;
- return a;
-}
+// FIXME: assumes row major, rather than column major
+//double** createNRC(Matrix& A) {
+// const size_t m=A.rows();
+// double** a = new double* [m];
+// for(size_t i = 0; i < m; i++)
+// a[i] = &A(i,0)-1;
+// return a;
+//}
/* ******************************************
*
@@ -653,7 +615,6 @@ Matrix inverse_square_root(const Matrix& A) {
Matrix inverse_square_root(const Matrix& A) {
Matrix R = RtR(A);
Matrix inv = eye(A.rows());
-// inplace_solve(R, inv, BNU::upper_tag ());
R.triangularView().solveInPlace(inv);
return inv;
}
diff --git a/gtsam/base/Matrix.h b/gtsam/base/Matrix.h
index 37990be64..9ff6bc4ce 100644
--- a/gtsam/base/Matrix.h
+++ b/gtsam/base/Matrix.h
@@ -22,7 +22,6 @@
#pragma once
-#include
#include
#include
#include
diff --git a/gtsam/base/blockMatrices.h b/gtsam/base/blockMatrices.h
index ad3f97059..fc9d8bd4c 100644
--- a/gtsam/base/blockMatrices.h
+++ b/gtsam/base/blockMatrices.h
@@ -17,9 +17,7 @@
*/
#pragma once
-#include
#include
-#include
#include
namespace gtsam {
diff --git a/gtsam/base/cholesky.cpp b/gtsam/base/cholesky.cpp
index e129a6d30..663418f70 100644
--- a/gtsam/base/cholesky.cpp
+++ b/gtsam/base/cholesky.cpp
@@ -148,4 +148,51 @@ void choleskyPartial(Matrix& ABC, size_t nFrontal) {
toc(3, "compute L");
}
+/* ************************************************************************* */
+Eigen::LDLT::TranspositionType ldlPartial(Matrix& ABC, size_t nFrontal) {
+
+ const bool debug = ISDEBUG("ldlPartial");
+
+ assert(ABC.rows() == ABC.cols());
+ assert(ABC.rows() >= 0 && nFrontal <= size_t(ABC.rows()));
+
+ const size_t n = ABC.rows();
+
+ // Compute Cholesky factorization of A, overwrites A = sqrt(D)*R
+ // tic(1, "ldl");
+ Eigen::LDLT ldlt;
+ ldlt.compute(ABC.block(0,0,nFrontal,nFrontal).selfadjointView());
+
+ Vector sqrtD = ldlt.vectorD().cwiseSqrt();
+ if (debug) cout << "Dsqrt: " << sqrtD << endl;
+
+ // U = sqrtD * L^
+ Matrix U = ldlt.matrixU();
+
+ // we store the permuted upper triangular matrix
+ ABC.block(0,0,nFrontal,nFrontal) = sqrtD.asDiagonal() * U;
+ if(debug) cout << "R:\n" << ABC.topLeftCorner(nFrontal,nFrontal) << endl;
+ // toc(1, "ldl");
+
+ // Compute S = inv(R') * B = inv(P'U')*B = inv(U')*P*B
+ // tic(2, "compute S");
+ if(n - nFrontal > 0) {
+ ABC.topRightCorner(nFrontal, n-nFrontal) = ldlt.transpositionsP() * ABC.topRightCorner(nFrontal, n-nFrontal);
+ ABC.block(0,0,nFrontal,nFrontal).triangularView().transpose().solveInPlace(ABC.topRightCorner(nFrontal, n-nFrontal));
+ }
+ if(debug) cout << "S:\n" << ABC.topRightCorner(nFrontal, n-nFrontal) << endl;
+ // toc(2, "compute S");
+
+ // Compute L = C - S' * S
+ // tic(3, "compute L");
+ if(debug) cout << "C:\n" << Eigen::MatrixXd(ABC.bottomRightCorner(n-nFrontal,n-nFrontal).selfadjointView()) << endl;
+ if(n - nFrontal > 0)
+ ABC.bottomRightCorner(n-nFrontal,n-nFrontal).selfadjointView().rankUpdate(
+ ABC.topRightCorner(nFrontal, n-nFrontal).transpose(), -1.0);
+ if(debug) cout << "L:\n" << Eigen::MatrixXd(ABC.bottomRightCorner(n-nFrontal,n-nFrontal).selfadjointView()) << endl;
+ // toc(3, "compute L");
+
+ return ldlt.transpositionsP();
+}
+
}
diff --git a/gtsam/base/cholesky.h b/gtsam/base/cholesky.h
index 48e1d5314..6bb105356 100644
--- a/gtsam/base/cholesky.h
+++ b/gtsam/base/cholesky.h
@@ -50,5 +50,25 @@ std::pair choleskyCareful(Matrix& ATA, int order = -1);
*/
void choleskyPartial(Matrix& ABC, size_t nFrontal);
+
+/**
+ * Partial LDL computes a factor [R S such that [P'R' 0 [RP S = [A B
+ * 0 F] S' I] 0 F] B' C].
+ * The input to this function is the matrix ABC = [A B], and the parameter
+ * [B' C]
+ * nFrontal determines the split between A, B, and C, with A being of size
+ * nFrontal x nFrontal.
+ * P is a permutation matrix obtained from the pivoting process while doing LDL'.
+ *
+ * Specifically, if A = P'U'DUP is the LDL' factorization of A,
+ * then R = sqrt(D)*U is the permuted upper-triangular matrix.
+ * The permutation is returned so that it can be used in the backsubstitution
+ * process to return the correct order of variables, and in creating the
+ * Jacobian factor by permuting R correctly.
+ *
+ * Note that S and F are not permuted (in correct original ordering).
+ */
+Eigen::LDLT::TranspositionType ldlPartial(Matrix& ABC, size_t nFrontal);
+
}
diff --git a/gtsam/base/numericalDerivative.h b/gtsam/base/numericalDerivative.h
index 3217fe298..21111881e 100644
--- a/gtsam/base/numericalDerivative.h
+++ b/gtsam/base/numericalDerivative.h
@@ -22,7 +22,6 @@
#include
#include
-#include
#include
#include
diff --git a/gtsam/base/tests/testBTree.cpp b/gtsam/base/tests/testBTree.cpp
index 9343f00e7..da6b56015 100644
--- a/gtsam/base/tests/testBTree.cpp
+++ b/gtsam/base/tests/testBTree.cpp
@@ -9,7 +9,7 @@
* -------------------------------------------------------------------------- */
-/*
+/**
* testBTree.cpp
*
* Created on: Feb 3, 2010
diff --git a/gtsam/base/tests/testBlockMatrices.cpp b/gtsam/base/tests/testBlockMatrices.cpp
index 09b04d4ac..06b3f3002 100644
--- a/gtsam/base/tests/testBlockMatrices.cpp
+++ b/gtsam/base/tests/testBlockMatrices.cpp
@@ -1,3 +1,14 @@
+/* ----------------------------------------------------------------------------
+
+ * 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 testBlockMatrices
* @author Alex Cunningham
diff --git a/gtsam/base/tests/testCholesky.cpp b/gtsam/base/tests/testCholesky.cpp
index c6bdc5cfd..cbc45aff6 100644
--- a/gtsam/base/tests/testCholesky.cpp
+++ b/gtsam/base/tests/testCholesky.cpp
@@ -21,6 +21,7 @@
#include
using namespace gtsam;
+using namespace std;
/* ************************************************************************* */
TEST(cholesky, choleskyPartial) {
@@ -53,6 +54,41 @@ TEST(cholesky, choleskyPartial) {
EXPECT(assert_equal(expected, actual, 1e-9));
}
+/* ************************************************************************* */
+TEST(cholesky, ldlPartial) {
+
+ // choleskyPartial should only use the upper triangle, so this represents a
+ // symmetric matrix.
+ Matrix ABC = Matrix_(7,7,
+ 4.0375, 3.4584, 3.5735, 2.4815, 2.1471, 2.7400, 2.2063,
+ 0., 4.7267, 3.8423, 2.3624, 2.8091, 2.9579, 2.5914,
+ 0., 0., 5.1600, 2.0797, 3.4690, 3.2419, 2.9992,
+ 0., 0., 0., 1.8786, 1.0535, 1.4250, 1.3347,
+ 0., 0., 0., 0., 3.0788, 2.6283, 2.3791,
+ 0., 0., 0., 0., 0., 2.9227, 2.4056,
+ 0., 0., 0., 0., 0., 0., 2.5776);
+
+ // Do partial Cholesky on 3 frontal scalar variables
+ Matrix RSL(ABC);
+ Eigen::LDLT::TranspositionType permutation = ldlPartial(RSL, 3);
+
+ // See the function comment for choleskyPartial, this decomposition should hold.
+ Matrix R1 = RSL.transpose();
+ Matrix R2 = RSL;
+ R1.block(3, 3, 4, 4).setIdentity();
+
+ R2.block(3, 3, 4, 4) = R2.block(3, 3, 4, 4).selfadjointView();
+
+ // un-permute the permuted upper triangular part
+ R1.topLeftCorner(3,3) = permutation.transpose() * R1.topLeftCorner(3,3);
+ R2.topLeftCorner(3,3) = R2.topLeftCorner(3,3)*permutation;
+
+ Matrix actual = R1 * R2;
+
+ Matrix expected = ABC.selfadjointView();
+ EXPECT(assert_equal(expected, actual, 1e-9));
+}
+
/* ************************************************************************* */
int main() {
TestResult tr;
diff --git a/gtsam/base/tests/timeMatrixOps.cpp b/gtsam/base/tests/timeMatrixOps.cpp
index 114968381..ab9488d32 100644
--- a/gtsam/base/tests/timeMatrixOps.cpp
+++ b/gtsam/base/tests/timeMatrixOps.cpp
@@ -16,10 +16,6 @@
* @created Sep 18, 2010
*/
-//#include
-//#include
-//#include
-//#include
#include
#include
#include
diff --git a/gtsam/geometry/Cal3Bundler.h b/gtsam/geometry/Cal3Bundler.h
index 466f888f3..1883d28a5 100644
--- a/gtsam/geometry/Cal3Bundler.h
+++ b/gtsam/geometry/Cal3Bundler.h
@@ -18,8 +18,6 @@
#pragma once
-#include
-#include
#include
namespace gtsam {
diff --git a/gtsam/geometry/Cal3DS2.h b/gtsam/geometry/Cal3DS2.h
index c3578c21e..a834bd3bf 100644
--- a/gtsam/geometry/Cal3DS2.h
+++ b/gtsam/geometry/Cal3DS2.h
@@ -19,8 +19,6 @@
#pragma once
-#include
-#include
#include
namespace gtsam {
diff --git a/gtsam/geometry/Cal3_S2.cpp b/gtsam/geometry/Cal3_S2.cpp
index a2807587f..709e03493 100644
--- a/gtsam/geometry/Cal3_S2.cpp
+++ b/gtsam/geometry/Cal3_S2.cpp
@@ -28,7 +28,7 @@ namespace gtsam {
Cal3_S2::Cal3_S2(double fov, int w, int h) :
s_(0), u0_((double) w / 2.0), v0_((double) h / 2.0) {
double a = fov * M_PI / 360.0; // fov/2 in radians
- fx_ = (double) w * tan(a);
+ fx_ = (double)w / (2.0*tan(a)); // old formula: fx_ = (double) w * tan(a);
fy_ = fx_;
}
diff --git a/gtsam/geometry/Cal3_S2.h b/gtsam/geometry/Cal3_S2.h
index 66d2fb514..43a88d88b 100644
--- a/gtsam/geometry/Cal3_S2.h
+++ b/gtsam/geometry/Cal3_S2.h
@@ -17,7 +17,6 @@
#pragma once
-#include
#include
namespace gtsam {
diff --git a/gtsam/geometry/Cal3_S2Stereo.h b/gtsam/geometry/Cal3_S2Stereo.h
index b22416c37..1b69468e7 100644
--- a/gtsam/geometry/Cal3_S2Stereo.h
+++ b/gtsam/geometry/Cal3_S2Stereo.h
@@ -17,8 +17,6 @@
#pragma once
-#include
-#include
#include
namespace gtsam {
diff --git a/gtsam/geometry/CalibratedCameraT.h b/gtsam/geometry/CalibratedCameraT.h
index 469a89aa7..3ecdfc01a 100644
--- a/gtsam/geometry/CalibratedCameraT.h
+++ b/gtsam/geometry/CalibratedCameraT.h
@@ -8,7 +8,6 @@
#pragma once
#include
-#include
#include
#include
diff --git a/gtsam/geometry/GeneralCameraT.h b/gtsam/geometry/GeneralCameraT.h
index 2d6a746e6..ae2235e5b 100644
--- a/gtsam/geometry/GeneralCameraT.h
+++ b/gtsam/geometry/GeneralCameraT.h
@@ -18,16 +18,8 @@
#pragma once
-#include
-#include
-#include
-#include
-#include
-#include
#include
#include
-
-
#include
#include
diff --git a/gtsam/geometry/Point2.h b/gtsam/geometry/Point2.h
index 025d0c1f5..4a77e039b 100644
--- a/gtsam/geometry/Point2.h
+++ b/gtsam/geometry/Point2.h
@@ -18,7 +18,6 @@
#pragma once
#include
-#include
#include
#include
#include
diff --git a/gtsam/geometry/Pose2.h b/gtsam/geometry/Pose2.h
index 77b78eb79..93fdaad69 100644
--- a/gtsam/geometry/Pose2.h
+++ b/gtsam/geometry/Pose2.h
@@ -22,8 +22,6 @@
#include
#include
-#include
-#include
#include
#include
diff --git a/gtsam/geometry/Pose3.h b/gtsam/geometry/Pose3.h
index df0bfcbc2..9c4d46847 100644
--- a/gtsam/geometry/Pose3.h
+++ b/gtsam/geometry/Pose3.h
@@ -20,8 +20,6 @@
#include
#include
-#include
-#include
namespace gtsam {
diff --git a/gtsam/geometry/Rot2.h b/gtsam/geometry/Rot2.h
index 40f77d414..23af69529 100644
--- a/gtsam/geometry/Rot2.h
+++ b/gtsam/geometry/Rot2.h
@@ -16,14 +16,10 @@
* Author: Frank Dellaert
*/
-#ifndef ROT2_H_
-#define ROT2_H_
+#pragma once
#include
-#include
#include
-#include
-#include
namespace gtsam {
@@ -175,5 +171,3 @@ namespace gtsam {
}; // Rot2
} // gtsam
-
-#endif /* ROT2_H_ */
diff --git a/gtsam/geometry/Rot3.cpp b/gtsam/geometry/Rot3.cpp
index 4ea4de6c8..cb31a5c0a 100644
--- a/gtsam/geometry/Rot3.cpp
+++ b/gtsam/geometry/Rot3.cpp
@@ -161,8 +161,15 @@ namespace gtsam {
// Log map at identity - return the canonical coordinates of this rotation
Vector Rot3::Logmap(const Rot3& R) {
double tr = R.r1().x()+R.r2().y()+R.r3().z();
- if (tr > 3.0 - 1e-10) { // when theta = 0, +-2pi, +-4pi, etc. (or tr > 3 + 1E-10)
- return zero(3);
+ if (tr > 3.0 - 1e-17) { // when theta = 0, +-2pi, +-4pi, etc. (or tr > 3 + 1E-10)
+ return zero(3);
+ } else if (tr > 3.0 - 1e-10) { // when theta near 0, +-2pi, +-4pi, etc. (or tr > 3 + 1E-3)
+ double theta = acos((tr-1.0)/2.0);
+ // Using Taylor expansion: theta/(2*sin(theta)) \approx 1/2+theta^2/12 + O(theta^4)
+ return (0.5 + theta*theta/12)*Vector_(3,
+ R.r2().z()-R.r3().y(),
+ R.r3().x()-R.r1().z(),
+ R.r1().y()-R.r2().x());
} else if (fabs(tr - -1.0) < 1e-10) { // when theta = +-pi, +-3pi, +-5pi, etc.
if(fabs(R.r3().z() - -1.0) > 1e-10)
return (boost::math::constants::pi() / sqrt(2.0+2.0*R.r3().z())) *
diff --git a/gtsam/geometry/Rot3.h b/gtsam/geometry/Rot3.h
index 33cf2b242..9f955829b 100644
--- a/gtsam/geometry/Rot3.h
+++ b/gtsam/geometry/Rot3.h
@@ -22,8 +22,6 @@
#pragma once
#include
-#include
-#include
namespace gtsam {
diff --git a/gtsam/geometry/StereoCamera.h b/gtsam/geometry/StereoCamera.h
index 5dab53d5a..f06e45cfb 100644
--- a/gtsam/geometry/StereoCamera.h
+++ b/gtsam/geometry/StereoCamera.h
@@ -17,8 +17,7 @@
#pragma once
-#include
-#include "boost/tuple/tuple.hpp"
+#include
#include
#include
#include
diff --git a/gtsam/geometry/StereoPoint2.h b/gtsam/geometry/StereoPoint2.h
index cd7d6166b..225e342cf 100644
--- a/gtsam/geometry/StereoPoint2.h
+++ b/gtsam/geometry/StereoPoint2.h
@@ -9,20 +9,16 @@
* -------------------------------------------------------------------------- */
-/*
+/**
* StereoPoint2.h
*
* Created on: Jan 26, 2010
* Author: dellaert
*/
-#ifndef STEREOPOINT2_H_
-#define STEREOPOINT2_H_
+#pragma once
#include
-#include
-#include
-#include
#include
namespace gtsam {
@@ -133,5 +129,3 @@ namespace gtsam {
};
}
-
-#endif /* STEREOPOINT2_H_ */
diff --git a/gtsam/geometry/tests/testCal3_S2.cpp b/gtsam/geometry/tests/testCal3_S2.cpp
index d8a3ab33c..99525ec1f 100644
--- a/gtsam/geometry/tests/testCal3_S2.cpp
+++ b/gtsam/geometry/tests/testCal3_S2.cpp
@@ -26,7 +26,7 @@ Point2 p(1, -2);
/* ************************************************************************* */
TEST( Cal3_S2, easy_constructor)
{
- Cal3_S2 expected(369.504, 369.504, 0, 640 / 2, 480 / 2);
+ Cal3_S2 expected(554.256, 554.256, 0, 640 / 2, 480 / 2);
double fov = 60; // degrees
size_t w=640,h=480;
diff --git a/gtsam/geometry/tests/testRot3.cpp b/gtsam/geometry/tests/testRot3.cpp
index 2a747e0e8..5421351c0 100644
--- a/gtsam/geometry/tests/testRot3.cpp
+++ b/gtsam/geometry/tests/testRot3.cpp
@@ -402,6 +402,35 @@ TEST( Rot3, RQ)
CHECK(assert_equal(expected,actual,1e-6));
}
+/* ************************************************************************* */
+TEST( Rot3, expmapStability ) {
+ Vector w = Vector_(3, 78e-9, 5e-8, 97e-7);
+ double theta = w.norm();
+ double theta2 = theta*theta;
+ Rot3 actualR = Rot3::Expmap(w);
+ Matrix W = Matrix_(3,3, 0.0, -w(2), w(1),
+ w(2), 0.0, -w(0),
+ -w(1), w(0), 0.0 );
+ Matrix W2 = W*W;
+ Matrix Rmat = eye(3) + (1.0-theta2/6.0 + theta2*theta2/120.0
+ - theta2*theta2*theta2/5040.0)*W + (0.5 - theta2/24.0 + theta2*theta2/720.0)*W2 ;
+ Rot3 expectedR( Rmat );
+ CHECK(assert_equal(expectedR, actualR, 1e-10));
+}
+
+/* ************************************************************************* */
+TEST( Rot3, logmapStability ) {
+ Vector w = Vector_(3, 1e-8, 0.0, 0.0);
+ Rot3 R = Rot3::Expmap(w);
+// double tr = R.r1().x()+R.r2().y()+R.r3().z();
+// std::cout.precision(5000);
+// std::cout << "theta: " << w.norm() << std::endl;
+// std::cout << "trace: " << tr << std::endl;
+// R.print("R = ");
+ Vector actualw = Rot3::Logmap(R);
+ CHECK(assert_equal(w, actualw, 1e-15));
+}
+
/* ************************************************************************* */
int main() {
TestResult tr;
diff --git a/gtsam/inference/BayesNet-inl.h b/gtsam/inference/BayesNet-inl.h
index 8e26affb6..ac1349f25 100644
--- a/gtsam/inference/BayesNet-inl.h
+++ b/gtsam/inference/BayesNet-inl.h
@@ -39,7 +39,7 @@ namespace gtsam {
void BayesNet::print(const string& s) const {
cout << s << ":\n";
BOOST_REVERSE_FOREACH(sharedConditional conditional,conditionals_)
- conditional->print((boost::format("Node[%1%]") % conditional->key()).str());
+ conditional->print();
}
/* ************************************************************************* */
@@ -82,39 +82,43 @@ namespace gtsam {
push_front(conditional);
}
- /* ************************************************************************* */
- template
- FastList BayesNet::ordering() const {
- FastList ord;
- BOOST_FOREACH(sharedConditional conditional,conditionals_)
- ord.push_back(conditional->key());
- return ord;
- }
-
- /* ************************************************************************* */
- template
- void BayesNet::saveGraph(const std::string &s) const {
- ofstream of(s.c_str());
- of<< "digraph G{\n";
- BOOST_FOREACH(const_sharedConditional conditional,conditionals_) {
- Index child = conditional->key();
- BOOST_FOREACH(Index parent, conditional->parents()) {
- of << parent << "->" << child << endl;
- }
- }
- of<<"}";
- of.close();
- }
-
+// /* ************************************************************************* */
+// template
+// FastList BayesNet::ordering() const {
+// FastList ord;
+// BOOST_FOREACH(sharedConditional conditional,conditionals_)
+// ord.push_back(conditional->key());
+// return ord;
+// }
+//
+// /* ************************************************************************* */
+// template
+// void BayesNet::saveGraph(const std::string &s) const {
+// ofstream of(s.c_str());
+// of<< "digraph G{\n";
+// BOOST_FOREACH(const_sharedConditional conditional,conditionals_) {
+// Index child = conditional->key();
+// BOOST_FOREACH(Index parent, conditional->parents()) {
+// of << parent << "->" << child << endl;
+// }
+// }
+// of<<"}";
+// of.close();
+// }
+//
/* ************************************************************************* */
template
typename BayesNet::sharedConditional
BayesNet::operator[](Index key) const {
- const_iterator it = find_if(conditionals_.begin(), conditionals_.end(), boost::lambda::bind(&CONDITIONAL::key, *boost::lambda::_1) == key);
- if (it == conditionals_.end()) throw(invalid_argument((boost::format(
+ BOOST_FOREACH(typename CONDITIONAL::shared_ptr conditional, conditionals_) {
+ typename CONDITIONAL::const_iterator it = std::find(conditional->beginFrontals(), conditional->endFrontals(), key);
+ if (it!=conditional->endFrontals()) {
+ return conditional;
+ }
+ }
+ throw(invalid_argument((boost::format(
"BayesNet::operator['%1%']: not found") % key).str()));
- return *it;
}
/* ************************************************************************* */
diff --git a/gtsam/inference/BayesNet.h b/gtsam/inference/BayesNet.h
index 2d70d8589..d43526a46 100644
--- a/gtsam/inference/BayesNet.h
+++ b/gtsam/inference/BayesNet.h
@@ -19,15 +19,15 @@
#pragma once
+#include
+#include
+#include
+
#include
#include
#include
#include
-#include
-#include
-#include
-
namespace gtsam {
/**
@@ -67,6 +67,12 @@ namespace gtsam {
public:
+ /** Default constructor as an empty BayesNet */
+ BayesNet() {};
+
+ /** BayesNet with 1 conditional */
+ BayesNet(const sharedConditional& conditional) { push_back(conditional); }
+
/** print */
void print(const std::string& s = "") const;
@@ -110,10 +116,10 @@ namespace gtsam {
return conditionals_.size();
}
- /** return keys in reverse topological sort order, i.e., elimination order */
- FastList ordering() const;
-
- /** SLOW O(n) random access to Conditional by key */
+// /** return keys in reverse topological sort order, i.e., elimination order */
+// FastList ordering() const;
+//
+// /** SLOW O(n) random access to Conditional by key */
sharedConditional operator[](Index key) const;
/** return last node in ordering */
@@ -135,7 +141,7 @@ namespace gtsam {
inline const_reverse_iterator const rend() const {return conditionals_.rend();}
/** saves the bayes to a text file in GraphViz format */
- void saveGraph(const std::string& s) const;
+// void saveGraph(const std::string& s) const;
private:
/** Serialization function */
diff --git a/gtsam/inference/BayesTree-inl.h b/gtsam/inference/BayesTree-inl.h
index 9f950096e..9efdfad5d 100644
--- a/gtsam/inference/BayesTree-inl.h
+++ b/gtsam/inference/BayesTree-inl.h
@@ -15,11 +15,13 @@
* @author Frank Dellaert
* @author Michael Kaess
* @author Viorela Ila
+ * @author Richard Roberts
*/
#pragma once
#include
+#include
#include
#include
#include
@@ -45,87 +47,24 @@ namespace gtsam {
void BayesTree::Clique::assertInvariants() const {
#ifndef NDEBUG
// We rely on the keys being sorted
- typename BayesNet::const_iterator cond = this->begin();
- if(cond != this->end()) {
- Index lastKey = (*cond)->key();
- ++cond;
- for(; cond != this->end(); ++cond)
- assert(lastKey < (*cond)->key());
- }
+ FastVector sortedUniqueKeys(conditional_->begin(), conditional_->end());
+ std::sort(sortedUniqueKeys.begin(), sortedUniqueKeys.end());
+ std::unique(sortedUniqueKeys.begin(), sortedUniqueKeys.end());
+ assert(sortedUniqueKeys.size() == conditional_->size() &&
+ std::equal(sortedUniqueKeys.begin(), sortedUniqueKeys.end(), conditional_->begin()));
#endif
}
/* ************************************************************************* */
template
- BayesTree::Clique::Clique() { assertInvariants(); }
-
- /* ************************************************************************* */
- template
- BayesTree::Clique::Clique(const sharedConditional& conditional) {
- separator_.assign(conditional->parents().begin(), conditional->parents().end());
- this->push_back(conditional);
+ BayesTree::Clique::Clique(const sharedConditional& conditional) : conditional_(conditional) {
assertInvariants();
}
- /* ************************************************************************* */
- template
- BayesTree::Clique::Clique(const BayesNet& bayesNet)
- : BayesNet(bayesNet) {
- if(bayesNet.size() > 0) {
-#ifndef NDEBUG
- // Debug check that each parent variable is either a frontal variable in
- // a later conditional in the Bayes net fragment, or that the parent is
- // also a parent of the last conditional. This checks that the fragment
- // is "enough like a clique". todo: this should really check that the
- // fragment *is* a clique.
- if(bayesNet.size() > 1) {
- typename BayesNet::const_reverse_iterator cond = bayesNet.rbegin();
- ++ cond;
- typename CONDITIONAL::shared_ptr lastConditional = *cond;
- for( ; cond != bayesNet.rend(); ++cond)
- for(typename CONDITIONAL::const_iterator parent=(*cond)->beginParents(); parent!=(*cond)->endParents(); ++parent) {
- bool infragment = false;
- typename BayesNet::const_reverse_iterator parentCond = cond;
- do {
- if(*parent == (*parentCond)->key())
- infragment = true;
- --parentCond;
- } while(parentCond != bayesNet.rbegin());
- assert(infragment || find(lastConditional->beginParents(), lastConditional->endParents(), *parent) != lastConditional->endParents());
- }
- }
-#endif
-
-// separator_.assign((*bayesNet.rbegin())->parents().begin(), (*bayesNet.rbegin())->parents().end());
- separator_.assign((*bayesNet.rbegin())->beginParents(), (*bayesNet.rbegin())->endParents());
- }
- assertInvariants();
- }
-
- /* ************************************************************************* */
- template
- vector BayesTree::Clique::keys() const {
- vector keys;
- keys.reserve(this->size() + separator_.size());
- BOOST_FOREACH(const sharedConditional conditional, *this) {
- keys.push_back(conditional->key());
- }
- keys.insert(keys.end(), separator_.begin(), separator_.end());
- return keys;
- }
-
/* ************************************************************************* */
template
void BayesTree::Clique::print(const string& s) const {
- cout << s << "Clique ";
- BOOST_FOREACH(const sharedConditional& conditional, this->conditionals_)
- cout << conditional->key() << " ";
- cout << "| ";
- BOOST_FOREACH(const Index sep, separator_)
- cout << sep << " ";
- cout << "\n";
- BOOST_FOREACH(const sharedConditional& conditional, this->conditionals_)
- conditional->print(" " + s + "conditional");
+ conditional_->print(s);
}
/* ************************************************************************* */
@@ -148,8 +87,7 @@ namespace gtsam {
/* ************************************************************************* */
template
void BayesTree::Clique::permuteWithInverse(const Permutation& inversePermutation) {
- BayesNet::permuteWithInverse(inversePermutation);
- BOOST_FOREACH(Index& separatorKey, separator_) { separatorKey = inversePermutation[separatorKey]; }
+ conditional_->permuteWithInverse(inversePermutation);
if(cachedFactor_) cachedFactor_->permuteWithInverse(inversePermutation);
BOOST_FOREACH(const shared_ptr& child, children_) {
child->permuteWithInverse(inversePermutation);
@@ -160,17 +98,16 @@ namespace gtsam {
/* ************************************************************************* */
template
bool BayesTree::Clique::permuteSeparatorWithInverse(const Permutation& inversePermutation) {
- bool changed = BayesNet::permuteSeparatorWithInverse(inversePermutation);
+ bool changed = conditional_->permuteSeparatorWithInverse(inversePermutation);
#ifndef NDEBUG
if(!changed) {
- BOOST_FOREACH(Index& separatorKey, separator_) { assert(separatorKey == inversePermutation[separatorKey]); }
+ BOOST_FOREACH(Index& separatorKey, conditional_->parents()) { assert(separatorKey == inversePermutation[separatorKey]); }
BOOST_FOREACH(const shared_ptr& child, children_) {
assert(child->permuteSeparatorWithInverse(inversePermutation) == false);
}
}
#endif
if(changed) {
- BOOST_FOREACH(Index& separatorKey, separator_) { separatorKey = inversePermutation[separatorKey]; }
if(cachedFactor_) cachedFactor_->permuteWithInverse(inversePermutation);
BOOST_FOREACH(const shared_ptr& child, children_) {
(void)child->permuteSeparatorWithInverse(inversePermutation);
@@ -192,8 +129,8 @@ namespace gtsam {
template
void BayesTree::getCliqueData(CliqueData& data,
BayesTree::sharedClique clique) const {
- data.conditionalSizes.push_back(clique->conditionals_.size());
- data.separatorSizes.push_back(clique->separator_.size());
+ data.conditionalSizes.push_back((*clique)->nrFrontals());
+ data.separatorSizes.push_back((*clique)->nrParents());
BOOST_FOREACH(sharedClique c, clique->children_) {
getCliqueData(data, c);
}
@@ -277,7 +214,6 @@ namespace gtsam {
// The shortcut density is a conditional P(S|R) of the separator of this
// clique on the root. We can compute it recursively from the parent shortcut
// P(Sp|R) as \int P(Fp|Sp) P(Sp|R), where Fp are the frontal nodes in p
- // TODO, why do we actually return a shared pointer, why does eliminate?
/* ************************************************************************* */
template
BayesNet BayesTree::Clique::shortcut(shared_ptr R,
@@ -296,11 +232,11 @@ namespace gtsam {
}
// The root conditional
- FactorGraph p_R(*R);
+ FactorGraph p_R(BayesNet(R->conditional()));
// The parent clique has a CONDITIONAL for each frontal node in Fp
// so we can obtain P(Fp|Sp) in factor graph form
- FactorGraph p_Fp_Sp(*parent);
+ FactorGraph p_Fp_Sp(BayesNet(parent->conditional()));
// If not the base case, obtain the parent shortcut P(Sp|R) as factors
FactorGraph p_Sp_R(parent->shortcut(R, function));
@@ -330,20 +266,20 @@ namespace gtsam {
FastSet variablesAtBack;
FastSet separator;
size_t uniqueRootVariables = 0;
- BOOST_FOREACH(const Index separatorIndex, this->separator_) {
+ BOOST_FOREACH(const Index separatorIndex, this->conditional()->parents()) {
variablesAtBack.insert(separatorIndex);
separator.insert(separatorIndex);
if(debug) cout << "At back (this): " << separatorIndex << endl;
}
- BOOST_FOREACH(const sharedConditional& conditional, *R) {
- if(variablesAtBack.insert(conditional->key()).second)
+ BOOST_FOREACH(const Index key, R->conditional()->keys()) {
+ if(variablesAtBack.insert(key).second)
++ uniqueRootVariables;
- if(debug) cout << "At back (root): " << conditional->key() << endl;
+ if(debug) cout << "At back (root): " << key << endl;
}
Permutation toBack = Permutation::PushToBack(
vector(variablesAtBack.begin(), variablesAtBack.end()),
- R->back()->key() + 1);
+ R->conditional()->lastFrontalKey() + 1);
Permutation::shared_ptr toBackInverse(toBack.inverse());
BOOST_FOREACH(const typename FactorType::shared_ptr& factor, p_Cp_R) {
factor->permuteWithInverse(*toBackInverse); }
@@ -356,7 +292,8 @@ namespace gtsam {
// want to include those variables in the conditional.
BayesNet p_S_R;
BOOST_REVERSE_FOREACH(typename CONDITIONAL::shared_ptr conditional, *eliminated) {
- if(separator.find(toBack[conditional->key()]) != separator.end()) {
+ // TODO: CHECK!!! is it firstFrontalKey() or lastFrontalKey() or something else???
+ if(separator.find(toBack[conditional->firstFrontalKey()]) != separator.end()) {
if(debug)
conditional->print("Taking C|R conditional: ");
p_S_R.push_front(conditional);
@@ -385,16 +322,17 @@ namespace gtsam {
shared_ptr R, Eliminate function) {
// If we are the root, just return this root
// NOTE: immediately cast to a factor graph
- if (R.get()==this) return *R;
+ BayesNet bn(R->conditional());
+ if (R.get()==this) return bn;
// Combine P(F|S), P(S|R), and P(R)
BayesNet p_FSR = this->shortcut(R, function);
- p_FSR.push_front(*this);
- p_FSR.push_back(*R);
+ p_FSR.push_front(this->conditional());
+ p_FSR.push_back(R->conditional());
assertInvariants();
GenericSequentialSolver solver(p_FSR);
- return *solver.jointFactorGraph(keys(), function);
+ return *solver.jointFactorGraph(conditional_->keys(), function);
}
/* ************************************************************************* */
@@ -407,15 +345,15 @@ namespace gtsam {
// Combine P(F1|S1), P(S1|R), P(F2|S2), P(S2|R), and P(R)
FactorGraph joint;
- if (!isRoot()) joint.push_back(*this); // P(F1|S1)
+ if (!isRoot()) joint.push_back(this->conditional()->toFactor()); // P(F1|S1)
if (!isRoot()) joint.push_back(shortcut(R, function)); // P(S1|R)
- if (!C2->isRoot()) joint.push_back(*C2); // P(F2|S2)
+ if (!C2->isRoot()) joint.push_back(C2->conditional()->toFactor()); // P(F2|S2)
if (!C2->isRoot()) joint.push_back(C2->shortcut(R, function)); // P(S2|R)
- joint.push_back(*R); // P(R)
+ joint.push_back(R->conditional()->toFactor()); // P(R)
// Find the keys of both C1 and C2
- vector keys1(keys());
- vector keys2(C2->keys());
+ vector keys1(conditional_->keys());
+ vector keys2(C2->conditional_->keys());
FastSet keys12;
keys12.insert(keys1.begin(), keys1.end());
keys12.insert(keys2.begin(), keys2.end());
@@ -447,9 +385,9 @@ namespace gtsam {
typename BayesTree::sharedClique BayesTree::addClique(
const sharedConditional& conditional, sharedClique parent_clique) {
sharedClique new_clique(new Clique(conditional));
- Index key = conditional->key();
- nodes_.resize(std::max(key+1, nodes_.size()));
- nodes_[key] = new_clique;
+ nodes_.resize(std::max(conditional->lastFrontalKey()+1, nodes_.size()));
+ BOOST_FOREACH(Index key, conditional->frontals())
+ nodes_[key] = new_clique;
if (parent_clique != NULL) {
new_clique->parent_ = parent_clique;
parent_clique->children_.push_back(new_clique);
@@ -463,9 +401,9 @@ namespace gtsam {
typename BayesTree::sharedClique BayesTree::addClique(
const sharedConditional& conditional, list& child_cliques) {
sharedClique new_clique(new Clique(conditional));
- Index key = conditional->key();
- nodes_.resize(max(key+1, nodes_.size()));
- nodes_[key] = new_clique;
+ nodes_.resize(std::max(conditional->lastFrontalKey()+1, nodes_.size()));
+ BOOST_FOREACH(Index key, conditional->frontals())
+ nodes_[key] = new_clique;
new_clique->children_ = child_cliques;
BOOST_FOREACH(sharedClique& child, child_cliques)
child->parent_ = new_clique;
@@ -475,34 +413,28 @@ namespace gtsam {
/* ************************************************************************* */
template
- inline void BayesTree::addToCliqueFront(const sharedConditional& conditional, const sharedClique& clique) {
+ inline void BayesTree::addToCliqueFront(BayesTree& bayesTree, const sharedConditional& conditional, const sharedClique& clique) {
static const bool debug = false;
#ifndef NDEBUG
// Debug check to make sure the conditional variable is ordered lower than
// its parents and that all of its parents are present either in this
// clique or its separator.
BOOST_FOREACH(Index parent, conditional->parents()) {
- assert(parent > conditional->key());
- bool hasParent = false;
+ assert(parent > conditional->lastFrontalKey());
const Clique& cliquer(*clique);
- BOOST_FOREACH(const sharedConditional& child, cliquer) {
- if(child->key() == parent) {
- hasParent = true;
- break;
- }
- }
- if(!hasParent)
- if(find(clique->separator_.begin(), clique->separator_.end(), parent) != clique->separator_.end())
- hasParent = true;
- assert(hasParent);
+ assert(find(cliquer->begin(), cliquer->end(), parent) != cliquer->end());
}
#endif
if(debug) conditional->print("Adding conditional ");
if(debug) clique->print("To clique ");
- Index key = conditional->key();
- nodes_.resize(std::max(key+1, nodes_.size()));
- nodes_[key] = clique;
- clique->push_front(conditional);
+ Index key = conditional->lastFrontalKey();
+ bayesTree.nodes_.resize(std::max(key+1, bayesTree.nodes_.size()));
+ bayesTree.nodes_[key] = clique;
+ FastVector newKeys((*clique)->size() + 1);
+ newKeys[0] = key;
+ std::copy((*clique)->begin(), (*clique)->end(), newKeys.begin()+1);
+ clique->conditional_ = CONDITIONAL::FromKeys(newKeys, (*clique)->nrFrontals() + 1);
+// clique->conditional_->addFrontal(conditional);
if(debug) clique->print("Expanded clique is ");
clique->assertInvariants();
}
@@ -520,13 +452,9 @@ namespace gtsam {
BOOST_FOREACH(sharedClique child, clique->children_)
child->parent_ = typename BayesTree::Clique::weak_ptr();
- BOOST_FOREACH(Index key, clique->separator_) {
+ BOOST_FOREACH(Index key, (*clique->conditional())) {
nodes_[key].reset();
}
- const Clique& cliquer(*clique);
- BOOST_FOREACH(const sharedConditional& conditional, cliquer) {
- nodes_[conditional->key()].reset();
- }
}
/* ************************************************************************* */
@@ -539,7 +467,7 @@ namespace gtsam {
BayesTree::BayesTree(const BayesNet& bayesNet) {
typename BayesNet::const_reverse_iterator rit;
for ( rit=bayesNet.rbegin(); rit != bayesNet.rend(); ++rit )
- insert(*rit);
+ insert(*this, *rit);
}
/* ************************************************************************* */
@@ -562,7 +490,7 @@ namespace gtsam {
if (!new_clique.get())
new_clique = addClique(conditional,childRoots);
else
- addToCliqueFront(conditional, new_clique);
+ addToCliqueFront(*this, conditional, new_clique);
}
root_ = new_clique;
@@ -622,31 +550,31 @@ namespace gtsam {
/* ************************************************************************* */
template
- void BayesTree::insert(const sharedConditional& conditional)
+ void BayesTree::insert(BayesTree& bayesTree, const sharedConditional& conditional)
{
static const bool debug = false;
// get key and parents
- typename CONDITIONAL::Parents parents = conditional->parents(); // todo: const reference?
+ const typename CONDITIONAL::Parents& parents = conditional->parents();
if(debug) conditional->print("Adding conditional ");
// if no parents, start a new root clique
if (parents.empty()) {
if(debug) cout << "No parents so making root" << endl;
- root_ = addClique(conditional);
+ bayesTree.root_ = bayesTree.addClique(conditional);
return;
}
// otherwise, find the parent clique by using the index data structure
// to find the lowest-ordered parent
- Index parentRepresentative = findParentClique(parents);
- if(debug) cout << "First-eliminated parent is " << parentRepresentative << ", have " << nodes_.size() << " nodes." << endl;
- sharedClique parent_clique = (*this)[parentRepresentative];
+ Index parentRepresentative = bayesTree.findParentClique(parents);
+ if(debug) cout << "First-eliminated parent is " << parentRepresentative << ", have " << bayesTree.nodes_.size() << " nodes." << endl;
+ sharedClique parent_clique = bayesTree[parentRepresentative];
if(debug) parent_clique->print("Parent clique is ");
// if the parents and parent clique have the same size, add to parent clique
- if (parent_clique->size() == size_t(parents.size())) {
+ if ((*parent_clique)->size() == size_t(parents.size())) {
if(debug) cout << "Adding to parent clique" << endl;
#ifndef NDEBUG
// Debug check that the parent keys of the new conditional match the keys
@@ -660,11 +588,11 @@ namespace gtsam {
// ++ cond;
// }
#endif
- addToCliqueFront(conditional, parent_clique);
+ addToCliqueFront(bayesTree, conditional, parent_clique);
} else {
if(debug) cout << "Starting new clique" << endl;
// otherwise, start a new clique and add it to the tree
- addClique(conditional,parent_clique);
+ bayesTree.addClique(conditional,parent_clique);
}
}
@@ -672,24 +600,14 @@ namespace gtsam {
//TODO: remove this function after removing TSAM.cpp
template
typename BayesTree::sharedClique BayesTree::insert(
- const BayesNet& bayesNet, list& children, bool isRootClique)
- {
+ const sharedConditional& clique, list& children, bool isRootClique) {
static const bool debug = false;
- if (bayesNet.size() == 0)
- throw invalid_argument("BayesTree::insert: empty bayes net!");
+ if (clique->nrFrontals() == 0)
+ throw invalid_argument("BayesTree::insert: empty clique!");
// create a new clique and add all the conditionals to the clique
- sharedClique new_clique;
- typename BayesNet::sharedConditional conditional;
- BOOST_REVERSE_FOREACH(conditional, bayesNet) {
- if(debug) conditional->print("Inserting conditional: ");
- if (!new_clique.get())
- new_clique = addClique(conditional,children);
- else
- addToCliqueFront(conditional, new_clique);
- }
-
+ sharedClique new_clique = addClique(clique, children);
if (isRootClique) root_ = new_clique;
return new_clique;
@@ -699,7 +617,7 @@ namespace gtsam {
template
void BayesTree::fillNodesIndex(const sharedClique& subtree) {
// Add each frontal variable of this root node
- BOOST_FOREACH(const typename CONDITIONAL::shared_ptr& cond, *subtree) { nodes_[cond->key()] = subtree; }
+ BOOST_FOREACH(const Index& key, subtree->conditional()->frontals()) { nodes_[key] = subtree; }
// Fill index for each child
BOOST_FOREACH(const typename BayesTree::sharedClique& child, subtree->children_) {
fillNodesIndex(child); }
@@ -713,19 +631,20 @@ namespace gtsam {
// property, those separator variables in the subtree that are ordered
// lower than the highest frontal variable of the subtree root will all
// appear in the separator of the subtree root.
- if(subtree->separator_.empty()) {
+ if(subtree->conditional()->parents().empty()) {
assert(!root_);
root_ = subtree;
} else {
- Index parentRepresentative = findParentClique(subtree->separator_);
+ Index parentRepresentative = findParentClique(subtree->conditional()->parents());
sharedClique parent = (*this)[parentRepresentative];
parent->children_ += subtree;
subtree->parent_ = parent; // set new parent!
}
// Now fill in the nodes index
- if(nodes_.size() == 0 || subtree->back()->key() > (nodes_.size() - 1))
- nodes_.resize(subtree->back()->key() + 1);
+ if(nodes_.size() == 0 || (subtree->conditional()->lastFrontalKey()) > (nodes_.size() - 1)) {
+ nodes_.resize(subtree->conditional()->lastFrontalKey() + 1);
+ }
fillNodesIndex(subtree);
}
}
@@ -743,7 +662,7 @@ namespace gtsam {
// calculate or retrieve its marginal
FactorGraph cliqueMarginal = clique->marginal(root_,function);
- return GenericSequentialSolver (cliqueMarginal).marginalFactor(
+ return GenericSequentialSolver(cliqueMarginal).marginalFactor(
key, function);
}
@@ -817,7 +736,7 @@ namespace gtsam {
// add children to list of orphans (splice also removed them from clique->children_)
orphans.splice (orphans.begin(), clique->children_);
- bn.push_back(*clique);
+ bn.push_back(clique->conditional());
}
}
diff --git a/gtsam/inference/BayesTree.h b/gtsam/inference/BayesTree.h
index 5de62342f..fafeba94b 100644
--- a/gtsam/inference/BayesTree.h
+++ b/gtsam/inference/BayesTree.h
@@ -19,13 +19,11 @@
#pragma once
-#include
#include
#include
#include
#include
-#include
#include
#include
@@ -51,43 +49,45 @@ namespace gtsam {
* A Clique in the tree is an incomplete Bayes net: the variables
* in the Bayes net are the frontal nodes, and the variables conditioned
* on are the separator. We also have pointers up and down the tree.
+ *
+ * Since our Conditional class already handles multiple frontal variables,
+ * this Clique contains exactly 1 conditional.
*/
- struct Clique: public BayesNet {
+ struct Clique {
protected:
void assertInvariants() const;
public:
- typedef BayesNet Base;
+ typedef CONDITIONAL Base;
typedef typename boost::shared_ptr shared_ptr;
typedef typename boost::weak_ptr weak_ptr;
+ sharedConditional conditional_;
weak_ptr parent_;
std::list children_;
- std::list separator_; /** separator keys */
typename FactorType::shared_ptr cachedFactor_;
friend class BayesTree;
//* Constructor */
- Clique();
+ Clique() {}
Clique(const sharedConditional& conditional);
- Clique(const BayesNet& bayesNet);
-
- /** return keys in frontal:separator order */
- std::vector keys() const;
-
/** print this node */
void print(const std::string& s = "") const;
- /** The size *includes* the separator */
- size_t size() const {
- return this->conditionals_.size() + separator_.size();
- }
+ /** The arrow operator accesses the conditional */
+ const CONDITIONAL* operator->() const { return conditional_.get(); }
+
+ /** The arrow operator accesses the conditional */
+ CONDITIONAL* operator->() { return conditional_.get(); }
+
+ /** Access the conditional */
+ const sharedConditional& conditional() const { return conditional_; }
/** is this the root of a Bayes tree ? */
- inline bool isRoot() const { return parent_.expired();}
+ inline bool isRoot() const { return parent_.expired(); }
/** return the const reference of children */
std::list& children() { return children_; }
@@ -122,15 +122,19 @@ namespace gtsam {
/** return the joint P(C1,C2), where C1==this. TODO: not a method? */
FactorGraph joint(shared_ptr C2, shared_ptr root, Eliminate function);
+ bool equals(const Clique& other, double tol=1e-9) const {
+ return (!conditional_ && !other.conditional()) ||
+ conditional_->equals(*(other.conditional()), tol);
+ }
+
private:
/** Serialization function */
friend class boost::serialization::access;
template
void serialize(ARCHIVE & ar, const unsigned int version) {
- ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base);
+ ar & BOOST_SERIALIZATION_NVP(conditional_);
ar & BOOST_SERIALIZATION_NVP(parent_);
ar & BOOST_SERIALIZATION_NVP(children_);
- ar & BOOST_SERIALIZATION_NVP(separator_);
ar & BOOST_SERIALIZATION_NVP(cachedFactor_);
}
@@ -194,7 +198,8 @@ namespace gtsam {
* parents are already in the clique or its separators. This function does
* not check for this condition, it just updates the data structures.
*/
- void addToCliqueFront(const sharedConditional& conditional, const sharedClique& clique);
+ static void addToCliqueFront(BayesTree& bayesTree,
+ const sharedConditional& conditional, const sharedClique& clique);
/** Fill the nodes index for a subtree */
void fillNodesIndex(const sharedClique& subtree);
@@ -220,15 +225,18 @@ namespace gtsam {
* Constructing Bayes trees
*/
- /** Insert a new conditional */
- void insert(const sharedConditional& conditional);
+ /** Insert a new conditional
+ * This function only applies for Symbolic case with IndexCondtional,
+ * We make it static so that it won't be compiled in GaussianConditional case.
+ * */
+ static void insert(BayesTree& bayesTree, const sharedConditional& conditional);
/**
* Insert a new clique corresponding to the given Bayes net.
* It is the caller's responsibility to decide whether the given Bayes net is a valid clique,
* i.e. all the variables (frontal and separator) are connected
*/
- sharedClique insert(const BayesNet& bayesNet,
+ sharedClique insert(const sharedConditional& clique,
std::list& children, bool isRootClique = false);
/**
@@ -262,6 +270,9 @@ namespace gtsam {
return 0;
}
+ /** return nodes */
+ Nodes nodes() const { return nodes_; }
+
/** return root clique */
const sharedClique& root() const { return root_; }
sharedClique& root() { return root_; }
@@ -275,7 +286,7 @@ namespace gtsam {
CliqueData getCliqueData() const;
/** return marginal on any variable */
- typename CONDITIONAL::FactorType::shared_ptr marginalFactor(Index key,
+ typename FactorType::shared_ptr marginalFactor(Index key,
Eliminate function) const;
/**
diff --git a/gtsam/inference/ClusterTree.h b/gtsam/inference/ClusterTree.h
index 77f46a924..18d1202d7 100644
--- a/gtsam/inference/ClusterTree.h
+++ b/gtsam/inference/ClusterTree.h
@@ -19,15 +19,15 @@
#pragma once
-#include
-#include
+#include
+#include
+#include
#include
#include
-#include