Multiple sparse linear algebra backends.
1. Added support for CXSparse - SparseNormalCholesky and
SchurComplementSolver support SuiteSparse and CXSparse now.
I am not sure I will add suport for visibility based
preconditioning using CXSparse. Its not a high priority.
2. New enum SparseLinearAlgebraLibraryType which allows the user
to indicate which sparse linear algebra library should be used.
3. Updated tests for SolverImpl and system_test.
4. Build system changes to automatically detect CXSparse and
link to it by default -- just like SuiteSparse.
5. Minor bug fixes dealing in the cmake files and VBP.
6. Changed the order of the system test.
7. Deduped the unsymmetric linear solver test.
Change-Id: I33252a103c87b722ecb7ed7b5f0ae7fd91249244
diff --git a/internal/ceres/system_test.cc b/internal/ceres/system_test.cc
index a9a6747..8e2f5eb 100644
--- a/internal/ceres/system_test.cc
+++ b/internal/ceres/system_test.cc
@@ -62,32 +62,39 @@
// Struct used for configuring the solver.
struct SolverConfig {
SolverConfig(LinearSolverType linear_solver_type,
+ SparseLinearAlgebraLibraryType sparse_linear_algebra_library,
OrderingType ordering_type)
: linear_solver_type(linear_solver_type),
+ sparse_linear_algebra_library(sparse_linear_algebra_library),
ordering_type(ordering_type),
preconditioner_type(IDENTITY),
num_threads(1) {
}
SolverConfig(LinearSolverType linear_solver_type,
+ SparseLinearAlgebraLibraryType sparse_linear_algebra_library,
OrderingType ordering_type,
PreconditionerType preconditioner_type,
int num_threads)
: linear_solver_type(linear_solver_type),
+ sparse_linear_algebra_library(sparse_linear_algebra_library),
ordering_type(ordering_type),
preconditioner_type(preconditioner_type),
num_threads(num_threads) {
}
string ToString() const {
- return StringPrintf("(%s, %s, %s, %d)",
- LinearSolverTypeToString(linear_solver_type),
- OrderingTypeToString(ordering_type),
- PreconditionerTypeToString(preconditioner_type),
- num_threads);
+ return StringPrintf(
+ "(%s, %s, %s, %s, %d)",
+ LinearSolverTypeToString(linear_solver_type),
+ SparseLinearAlgebraLibraryTypeToString(sparse_linear_algebra_library),
+ OrderingTypeToString(ordering_type),
+ PreconditionerTypeToString(preconditioner_type),
+ num_threads);
}
LinearSolverType linear_solver_type;
+ SparseLinearAlgebraLibraryType sparse_linear_algebra_library;
OrderingType ordering_type;
PreconditionerType preconditioner_type;
int num_threads;
@@ -122,6 +129,8 @@
Solver::Options& options = *(system_test_problem->mutable_solver_options());
options.linear_solver_type = config.linear_solver_type;
+ options.sparse_linear_algebra_library =
+ config.sparse_linear_algebra_library;
options.ordering_type = config.ordering_type;
options.preconditioner_type = config.preconditioner_type;
options.num_threads = config.num_threads;
@@ -266,19 +275,31 @@
};
TEST(SystemTest, PowellsFunction) {
- vector<SolverConfig> configurations;
- configurations.push_back(SolverConfig(DENSE_QR, NATURAL));
- configurations.push_back(SolverConfig(DENSE_SCHUR, SCHUR));
+ vector<SolverConfig> configs;
+#define CONFIGURE(linear_solver, sparse_linear_algebra_library, ordering) \
+ configs.push_back(SolverConfig(linear_solver, \
+ sparse_linear_algebra_library, \
+ ordering))
+
+ CONFIGURE(DENSE_QR, SUITE_SPARSE, NATURAL);
+ CONFIGURE(DENSE_SCHUR, SUITE_SPARSE, SCHUR);
#ifndef CERES_NO_SUITESPARSE
- configurations.push_back(SolverConfig(SPARSE_NORMAL_CHOLESKY, NATURAL));
- configurations.push_back(SolverConfig(SPARSE_SCHUR, SCHUR));
+ CONFIGURE(SPARSE_NORMAL_CHOLESKY, SUITE_SPARSE, NATURAL);
+ CONFIGURE(SPARSE_NORMAL_CHOLESKY, SUITE_SPARSE, SCHUR);
#endif // CERES_NO_SUITESPARSE
- configurations.push_back(SolverConfig(ITERATIVE_SCHUR, SCHUR));
+#ifndef CERES_NO_CXSPARSE
+ CONFIGURE(SPARSE_NORMAL_CHOLESKY, CX_SPARSE, NATURAL);
+ CONFIGURE(SPARSE_NORMAL_CHOLESKY, CX_SPARSE, SCHUR);
+#endif // CERES_NO_CXSPARSE
+
+ CONFIGURE(ITERATIVE_SCHUR, SUITE_SPARSE, SCHUR);
+
+#undef CONFIGURE
+
const double kMaxAbsoluteDifference = 1e-8;
- RunSolversAndCheckTheyMatch<PowellsFunction>(configurations,
- kMaxAbsoluteDifference);
+ RunSolversAndCheckTheyMatch<PowellsFunction>(configs, kMaxAbsoluteDifference);
}
// This class implements the SystemTestProblem interface and provides
@@ -462,36 +483,50 @@
TEST(SystemTest, BundleAdjustmentProblem) {
vector<SolverConfig> configs;
-#define CONFIGURE(a, b, c, d) configs.push_back(SolverConfig(a, b, c, d))
+#define CONFIGURE(linear_solver, sparse_linear_algebra_library, ordering, preconditioner, threads) \
+ configs.push_back(SolverConfig(linear_solver, \
+ sparse_linear_algebra_library, \
+ ordering, \
+ preconditioner, \
+ threads))
#ifndef CERES_NO_SUITESPARSE
- CONFIGURE(SPARSE_NORMAL_CHOLESKY, NATURAL, IDENTITY, 1);
- CONFIGURE(SPARSE_NORMAL_CHOLESKY, USER, IDENTITY, 1);
- CONFIGURE(SPARSE_NORMAL_CHOLESKY, SCHUR, IDENTITY, 1);
+ CONFIGURE(SPARSE_NORMAL_CHOLESKY, SUITE_SPARSE, NATURAL, IDENTITY, 1);
+ CONFIGURE(SPARSE_NORMAL_CHOLESKY, SUITE_SPARSE, USER, IDENTITY, 1);
+ CONFIGURE(SPARSE_NORMAL_CHOLESKY, SUITE_SPARSE, SCHUR, IDENTITY, 1);
- CONFIGURE(SPARSE_SCHUR, USER, IDENTITY, 1);
- CONFIGURE(SPARSE_SCHUR, SCHUR, IDENTITY, 1);
+ CONFIGURE(SPARSE_SCHUR, SUITE_SPARSE, USER, IDENTITY, 1);
+ CONFIGURE(SPARSE_SCHUR, SUITE_SPARSE, SCHUR, IDENTITY, 1);
#endif // CERES_NO_SUITESPARSE
- CONFIGURE(DENSE_SCHUR, USER, IDENTITY, 1);
- CONFIGURE(DENSE_SCHUR, SCHUR, IDENTITY, 1);
+#ifndef CERES_NO_CXSPARSE
+ CONFIGURE(SPARSE_NORMAL_CHOLESKY, CX_SPARSE, NATURAL, IDENTITY, 1);
+ CONFIGURE(SPARSE_NORMAL_CHOLESKY, CX_SPARSE, USER, IDENTITY, 1);
+ CONFIGURE(SPARSE_NORMAL_CHOLESKY, CX_SPARSE, SCHUR, IDENTITY, 1);
- CONFIGURE(CGNR, USER, JACOBI, 1);
+ CONFIGURE(SPARSE_SCHUR, CX_SPARSE, USER, IDENTITY, 1);
+ CONFIGURE(SPARSE_SCHUR, CX_SPARSE, SCHUR, IDENTITY, 1);
+#endif // CERES_NO_CXSPARSE
- CONFIGURE(ITERATIVE_SCHUR, USER, JACOBI, 1);
+ CONFIGURE(DENSE_SCHUR, SUITE_SPARSE, USER, IDENTITY, 1);
+ CONFIGURE(DENSE_SCHUR, SUITE_SPARSE, SCHUR, IDENTITY, 1);
+
+ CONFIGURE(CGNR, SUITE_SPARSE, USER, JACOBI, 1);
+
+ CONFIGURE(ITERATIVE_SCHUR, SUITE_SPARSE, USER, JACOBI, 1);
#ifndef CERES_NO_SUITESPARSE
- CONFIGURE(ITERATIVE_SCHUR, USER, SCHUR_JACOBI, 1);
- CONFIGURE(ITERATIVE_SCHUR, USER, CLUSTER_JACOBI, 1);
- CONFIGURE(ITERATIVE_SCHUR, USER, CLUSTER_TRIDIAGONAL, 1);
+ CONFIGURE(ITERATIVE_SCHUR, SUITE_SPARSE, USER, SCHUR_JACOBI, 1);
+ CONFIGURE(ITERATIVE_SCHUR, SUITE_SPARSE, USER, CLUSTER_JACOBI, 1);
+ CONFIGURE(ITERATIVE_SCHUR, SUITE_SPARSE, USER, CLUSTER_TRIDIAGONAL, 1);
#endif // CERES_NO_SUITESPARSE
- CONFIGURE(ITERATIVE_SCHUR, SCHUR, JACOBI, 1);
+ CONFIGURE(ITERATIVE_SCHUR, SUITE_SPARSE, SCHUR, JACOBI, 1);
#ifndef CERES_NO_SUITESPARSE
- CONFIGURE(ITERATIVE_SCHUR, SCHUR, SCHUR_JACOBI, 1);
- CONFIGURE(ITERATIVE_SCHUR, SCHUR, CLUSTER_JACOBI, 1);
- CONFIGURE(ITERATIVE_SCHUR, SCHUR, CLUSTER_TRIDIAGONAL, 1);
+ CONFIGURE(ITERATIVE_SCHUR, SUITE_SPARSE, SCHUR, SCHUR_JACOBI, 1);
+ CONFIGURE(ITERATIVE_SCHUR, SUITE_SPARSE, SCHUR, CLUSTER_JACOBI, 1);
+ CONFIGURE(ITERATIVE_SCHUR, SUITE_SPARSE, SCHUR, CLUSTER_TRIDIAGONAL, 1);
#endif // CERES_NO_SUITESPARSE
#undef CONFIGURE