Modularize the build. 1. Add -DLINE_SEARCH_MINIMIZER to CMake to make the line search minimizer optional. 2. Better handling of -DSUITESPARSE/-DCXSPARSE in top level cmake file. 3. Disable code which will never be used if SuiteSparse and/or CXSparse is not available. 4. Update build docs. 5. Update jni/Android.mk 6. Minor lint cleanup from William Rucklidge. Change-Id: If60460a858000df82faed7a6bb056dd2bfdde562
diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d33b1e..b6c7359 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -122,6 +122,7 @@ SET(CXSPARSE_SEARCH_HEADERS ${SEARCH_HEADERS}) LIST(APPEND CXSPARSE_SEARCH_HEADERS /usr/include/suitesparse) # Ubuntu +IF ((NOT DEFINED SUITESPARSE) OR (DEFINED SUITESPARSE AND SUITESPARSE)) # Check for SuiteSparse dependencies MESSAGE("-- Check for AMD") SET(AMD_FOUND TRUE) @@ -300,6 +301,7 @@ (${SUITESPARSE_CONFIG_FOUND} OR ${UFCONFIG_FOUND}) AND ${BLAS_AND_LAPACK_FOUND}) +ENDIF ((NOT DEFINED SUITESPARSE) OR (DEFINED SUITESPARSE AND SUITESPARSE)) # By default, if all of SuiteSparse's dependencies are found, Ceres is # built with SuiteSparse support. -DSUITESPARSE=ON/OFF can be used to # enable/disable SuiteSparse explicitly. @@ -325,6 +327,7 @@ # By default, if all of CXSparse's dependencies are found, Ceres is # built with CXSparse support. -DCXSPARSE=ON/OFF can be used to # enable/disable CXSparse explicitly. +IF ((NOT DEFINED CXSPARSE) OR (DEFINED CXSPARSE AND CXSPARSE)) MESSAGE("-- Check for CXSparse") SET(CXSPARSE_FOUND ON) @@ -343,6 +346,7 @@ MESSAGE("-- Did not find CXSparse header") SET(CXSPARSE_FOUND FALSE) ENDIF (EXISTS ${CXSPARSE_INCLUDE}) +ENDIF ((NOT DEFINED CXSPARSE) OR (DEFINED CXSPARSE AND CXSPARSE)) IF (DEFINED CXSPARSE) IF (${CXSPARSE}) @@ -434,6 +438,19 @@ MESSAGE("-- Disabling Schur specializations (faster compiles)") ENDIF (NOT ${SCHUR_SPECIALIZATIONS}) +# Line search minimizer is useful for large scale problems or when +# sparse linear algebra libraries are not available. If compile time, +# binary size or compiler performance is an issue, consider disabling +# this. +OPTION(LINE_SEARCH_MINIMIZER + "Enable the line search minimizer." + ON) + +IF (NOT ${LINE_SEARCH_MINIMIZER}) + ADD_DEFINITIONS(-DCERES_NO_LINE_SEARCH_MINIMIZER) + MESSAGE("-- Disabling line search minimizer") +ENDIF (NOT ${LINE_SEARCH_MINIMIZER}) + # Multithreading using OpenMP OPTION(OPENMP "Enable threaded solving in Ceres (requires OpenMP)"
diff --git a/docs/source/building.rst b/docs/source/building.rst index fa81975..c2d7e24 100644 --- a/docs/source/building.rst +++ b/docs/source/building.rst
@@ -320,6 +320,11 @@ the ``SPARSE_SCHUR`` solver, you can disable some of the template specializations by using this flag. +#. ``-DLINE_SEARCH_MINIMIZER=OFF``: The line search based minimizer is + mostly suitable for large scale optimization problems, or when sparse + linear algebra libraries are not available. You can further save on + some compile time and binary size by using this flag. + #. ``-DOPENMP=OFF``: On certain platforms like Android, multi-threading with ``OpenMP`` is not supported. Use this flag to disable multithreading.
diff --git a/internal/ceres/canonical_views_clustering.cc b/internal/ceres/canonical_views_clustering.cc index d0dc1e6..6531945 100644 --- a/internal/ceres/canonical_views_clustering.cc +++ b/internal/ceres/canonical_views_clustering.cc
@@ -29,6 +29,8 @@ // Author: David Gallup (dgallup@google.com) // Sameer Agarwal (sameeragarwal@google.com) +#ifndef CERES_NO_SUITESPARSE + #include "ceres/canonical_views_clustering.h" #include "ceres/collections_port.h" @@ -236,3 +238,5 @@ } // namespace internal } // namespace ceres + +#endif // CERES_NO_SUITESPARSE
diff --git a/internal/ceres/canonical_views_clustering.h b/internal/ceres/canonical_views_clustering.h index 5f8e4e3..48d1ed2 100644 --- a/internal/ceres/canonical_views_clustering.h +++ b/internal/ceres/canonical_views_clustering.h
@@ -41,6 +41,8 @@ #ifndef CERES_INTERNAL_CANONICAL_VIEWS_CLUSTERING_H_ #define CERES_INTERNAL_CANONICAL_VIEWS_CLUSTERING_H_ +#ifndef CERES_NO_SUITESPARSE + #include <vector> #include "ceres/collections_port.h" @@ -130,4 +132,5 @@ } // namespace internal } // namespace ceres +#endif // CERES_NO_SUITESPARSE #endif // CERES_INTERNAL_CANONICAL_VIEWS_CLUSTERING_H_
diff --git a/internal/ceres/canonical_views_clustering_test.cc b/internal/ceres/canonical_views_clustering_test.cc index 29bac3c..78d5635 100644 --- a/internal/ceres/canonical_views_clustering_test.cc +++ b/internal/ceres/canonical_views_clustering_test.cc
@@ -29,6 +29,8 @@ // Author: Sameer Agarwal (sameeragarwal@google.com) // David Gallup (dgallup@google.com) +#ifndef CERES_NO_SUITESPARSE + #include "ceres/canonical_views_clustering.h" #include "ceres/collections_port.h" @@ -141,3 +143,5 @@ } // namespace internal } // namespace ceres + +#endif // CERES_NO_SUITESPARSE
diff --git a/internal/ceres/generate_eliminator_specialization.py b/internal/ceres/generate_eliminator_specialization.py index b14b145..caeca69 100644 --- a/internal/ceres/generate_eliminator_specialization.py +++ b/internal/ceres/generate_eliminator_specialization.py
@@ -104,7 +104,7 @@ // THIS FILE IS AUTOGENERATED. DO NOT EDIT. //========================================= // -// This file is generated using generate_eliminator_specializations.py. +// This file is generated using generate_eliminator_specialization.py. // Editing it manually is not recommended. """ @@ -204,10 +204,10 @@ template = SPECIALIZATION_FILE if (row_block_size == "Eigen::Dynamic" and e_block_size == "Eigen::Dynamic" and - f_block_size == "Eigen::Dynamic") : + f_block_size == "Eigen::Dynamic"): template = DYNAMIC_FILE - fptr.write(template % (row_block_size, e_block_size, f_block_size)); + fptr.write(template % (row_block_size, e_block_size, f_block_size)) fptr.close() f.write(FACTORY_CONDITIONAL % (row_block_size,
diff --git a/internal/ceres/line_search.cc b/internal/ceres/line_search.cc index e7508ca..437f742 100644 --- a/internal/ceres/line_search.cc +++ b/internal/ceres/line_search.cc
@@ -28,6 +28,7 @@ // // Author: sameeragarwal@google.com (Sameer Agarwal) +#ifndef CERES_NO_LINE_SEARCH_MINIMIZER #include "ceres/line_search.h" #include <glog/logging.h> @@ -209,3 +210,5 @@ } // namespace internal } // namespace ceres + +#endif // CERES_NO_LINE_SEARCH_MINIMIZER
diff --git a/internal/ceres/line_search.h b/internal/ceres/line_search.h index fccf63b..95bf56e 100644 --- a/internal/ceres/line_search.h +++ b/internal/ceres/line_search.h
@@ -33,6 +33,8 @@ #ifndef CERES_INTERNAL_LINE_SEARCH_H_ #define CERES_INTERNAL_LINE_SEARCH_H_ +#ifndef CERES_NO_LINE_SEARCH_MINIMIZER + #include <glog/logging.h> #include <vector> #include "ceres/internal/eigen.h" @@ -209,4 +211,5 @@ } // namespace internal } // namespace ceres +#endif // CERES_NO_LINE_SEARCH_MINIMIZER #endif // CERES_INTERNAL_LINE_SEARCH_H_
diff --git a/internal/ceres/line_search_direction.cc b/internal/ceres/line_search_direction.cc index 1fc4de5..b8b582c 100644 --- a/internal/ceres/line_search_direction.cc +++ b/internal/ceres/line_search_direction.cc
@@ -28,6 +28,8 @@ // // Author: sameeragarwal@google.com (Sameer Agarwal) +#ifndef CERES_NO_LINE_SEARCH_MINIMIZER + #include "ceres/line_search_direction.h" #include "ceres/line_search_minimizer.h" #include "ceres/low_rank_inverse_hessian.h" @@ -143,3 +145,5 @@ } // namespace internal } // namespace ceres + +#endif // CERES_NO_LINE_SEARCH_MINIMIZER
diff --git a/internal/ceres/line_search_direction.h b/internal/ceres/line_search_direction.h index 71063ab..0874754 100644 --- a/internal/ceres/line_search_direction.h +++ b/internal/ceres/line_search_direction.h
@@ -31,6 +31,8 @@ #ifndef CERES_INTERNAL_LINE_SEARCH_DIRECTION_H_ #define CERES_INTERNAL_LINE_SEARCH_DIRECTION_H_ +#ifndef CERES_NO_LINE_SEARCH_MINIMIZER + #include "ceres/internal/eigen.h" #include "ceres/line_search_minimizer.h" #include "ceres/types.h" @@ -67,4 +69,5 @@ } // namespace internal } // namespace ceres +#endif // CERES_NO_LINE_SEARCH_MINIMIZER #endif // CERES_INTERNAL_LINE_SEARCH_DIRECTION_H_
diff --git a/internal/ceres/line_search_minimizer.cc b/internal/ceres/line_search_minimizer.cc index ca7d639..f43278c 100644 --- a/internal/ceres/line_search_minimizer.cc +++ b/internal/ceres/line_search_minimizer.cc
@@ -38,6 +38,8 @@ // For details on the theory and implementation see "Numerical // Optimization" by Nocedal & Wright. +#ifndef CERES_NO_LINE_SEARCH_MINIMIZER + #include "ceres/line_search_minimizer.h" #include <algorithm> @@ -281,3 +283,5 @@ } // namespace internal } // namespace ceres + +#endif // CERES_NO_LINE_SEARCH_MINIMIZER
diff --git a/internal/ceres/line_search_minimizer.h b/internal/ceres/line_search_minimizer.h index f82f139..59f5c3f 100644 --- a/internal/ceres/line_search_minimizer.h +++ b/internal/ceres/line_search_minimizer.h
@@ -31,6 +31,8 @@ #ifndef CERES_INTERNAL_LINE_SEARCH_MINIMIZER_H_ #define CERES_INTERNAL_LINE_SEARCH_MINIMIZER_H_ +#ifndef CERES_NO_LINE_SEARCH_MINIMIZER + #include "ceres/minimizer.h" #include "ceres/solver.h" #include "ceres/types.h" @@ -74,4 +76,5 @@ } // namespace internal } // namespace ceres +#endif // CERES_NO_LINE_SEARCH_MINIMIZER #endif // CERES_INTERNAL_LINE_SEARCH_MINIMIZER_H_
diff --git a/internal/ceres/schur_complement_solver.cc b/internal/ceres/schur_complement_solver.cc index 1753759..bd68c45 100644 --- a/internal/ceres/schur_complement_solver.cc +++ b/internal/ceres/schur_complement_solver.cc
@@ -141,6 +141,7 @@ return true; } +#if !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARE) SparseSchurComplementSolver::SparseSchurComplementSolver( const LinearSolver::Options& options) @@ -365,5 +366,6 @@ } #endif // CERES_NO_CXPARSE +#endif // !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARE) } // namespace internal } // namespace ceres
diff --git a/internal/ceres/schur_complement_solver.h b/internal/ceres/schur_complement_solver.h index 7e98f31..7c8d2e7 100644 --- a/internal/ceres/schur_complement_solver.h +++ b/internal/ceres/schur_complement_solver.h
@@ -151,7 +151,7 @@ CERES_DISALLOW_COPY_AND_ASSIGN(DenseSchurComplementSolver); }; - +#if !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARE) // Sparse Cholesky factorization based solver. class SparseSchurComplementSolver : public SchurComplementSolver { public: @@ -182,6 +182,7 @@ CERES_DISALLOW_COPY_AND_ASSIGN(SparseSchurComplementSolver); }; +#endif // !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARE) } // namespace internal } // namespace ceres
diff --git a/internal/ceres/solver_impl.cc b/internal/ceres/solver_impl.cc index e18d3b9..7ea6d1f 100644 --- a/internal/ceres/solver_impl.cc +++ b/internal/ceres/solver_impl.cc
@@ -268,7 +268,7 @@ WallTimeInSeconds() - minimizer_start_time; } - +#ifndef CERES_NO_LINE_SEARCH_MINIMIZER void SolverImpl::LineSearchMinimize( const Solver::Options& options, Program* program, @@ -309,6 +309,7 @@ summary->minimizer_time_in_seconds = WallTimeInSeconds() - minimizer_start_time; } +#endif // CERES_NO_LINE_SEARCH_MINIMIZER void SolverImpl::Solve(const Solver::Options& options, ProblemImpl* problem_impl, @@ -316,7 +317,11 @@ if (options.minimizer_type == TRUST_REGION) { TrustRegionSolve(options, problem_impl, summary); } else { +#ifndef CERES_NO_LINE_SEARCH_MINIMIZER LineSearchSolve(options, problem_impl, summary); +#else + LOG(FATAL) << "Ceres Solver was compiled with -DLINE_SEARCH_MINIMIZER=OFF"; +#endif } } @@ -608,6 +613,8 @@ event_logger.AddEvent("PostProcess"); } + +#ifndef CERES_NO_LINE_SEARCH_MINIMIZER void SolverImpl::LineSearchSolve(const Solver::Options& original_options, ProblemImpl* original_problem_impl, Solver::Summary* summary) { @@ -661,7 +668,7 @@ << "to single threaded mode."; options.num_threads = 1; } -#endif +#endif // CERES_USE_OPENMP summary->num_threads_given = original_options.num_threads; summary->num_threads_used = options.num_threads; @@ -800,7 +807,7 @@ summary->postprocessor_time_in_seconds = WallTimeInSeconds() - post_process_start_time; } - +#endif // CERES_NO_LINE_SEARCH_MINIMIZER bool SolverImpl::IsOrderingValid(const Solver::Options& options, const ProblemImpl* problem_impl,
diff --git a/internal/ceres/solver_impl.h b/internal/ceres/solver_impl.h index c5f5efa..d2a2dd1 100644 --- a/internal/ceres/solver_impl.h +++ b/internal/ceres/solver_impl.h
@@ -59,10 +59,29 @@ ProblemImpl* problem_impl, Solver::Summary* summary); + // Run the TrustRegionMinimizer for the given evaluator and configuration. + static void TrustRegionMinimize( + const Solver::Options &options, + Program* program, + CoordinateDescentMinimizer* inner_iteration_minimizer, + Evaluator* evaluator, + LinearSolver* linear_solver, + double* parameters, + Solver::Summary* summary); + +#ifndef CERES_NO_LINE_SEARCH_MINIMIZER static void LineSearchSolve(const Solver::Options& options, ProblemImpl* problem_impl, Solver::Summary* summary); + // Run the LineSearchMinimizer for the given evaluator and configuration. + static void LineSearchMinimize(const Solver::Options &options, + Program* program, + Evaluator* evaluator, + double* parameters, + Solver::Summary* summary); +#endif // CERES_NO_LINE_SEARCH_MINIMIZER + // Create the transformed Program, which has all the fixed blocks // and residuals eliminated, and in the case of automatic schur // ordering, has the E blocks first in the resulting program, with @@ -108,24 +127,6 @@ Program* program, string* error); - // Run the TrustRegionMinimizer for the given evaluator and configuration. - static void TrustRegionMinimize( - const Solver::Options &options, - Program* program, - CoordinateDescentMinimizer* inner_iteration_minimizer, - Evaluator* evaluator, - LinearSolver* linear_solver, - double* parameters, - Solver::Summary* summary); - - // Run the LineSearchMinimizer for the given evaluator and configuration. - static void LineSearchMinimize( - const Solver::Options &options, - Program* program, - Evaluator* evaluator, - double* parameters, - Solver::Summary* summary); - // Remove the fixed or unused parameter blocks and residuals // depending only on fixed parameters from the problem. Also updates // num_eliminate_blocks, since removed parameters changes the point
diff --git a/internal/ceres/sparse_normal_cholesky_solver.cc b/internal/ceres/sparse_normal_cholesky_solver.cc index dd05f0c..7946665 100644 --- a/internal/ceres/sparse_normal_cholesky_solver.cc +++ b/internal/ceres/sparse_normal_cholesky_solver.cc
@@ -28,6 +28,8 @@ // // Author: sameeragarwal@google.com (Sameer Agarwal) +#if !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARSE) + #include "ceres/sparse_normal_cholesky_solver.h" #include <algorithm> @@ -257,3 +259,5 @@ } // namespace internal } // namespace ceres + +#endif // !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARSE)
diff --git a/internal/ceres/sparse_normal_cholesky_solver.h b/internal/ceres/sparse_normal_cholesky_solver.h index 8d48096..ebb32e6 100644 --- a/internal/ceres/sparse_normal_cholesky_solver.h +++ b/internal/ceres/sparse_normal_cholesky_solver.h
@@ -34,6 +34,8 @@ #ifndef CERES_INTERNAL_SPARSE_NORMAL_CHOLESKY_SOLVER_H_ #define CERES_INTERNAL_SPARSE_NORMAL_CHOLESKY_SOLVER_H_ +#if !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARSE) + #include "ceres/cxsparse.h" #include "ceres/internal/macros.h" #include "ceres/linear_solver.h" @@ -90,4 +92,5 @@ } // namespace internal } // namespace ceres +#endif // !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARSE) #endif // CERES_INTERNAL_SPARSE_NORMAL_CHOLESKY_SOLVER_H_
diff --git a/internal/ceres/visibility.cc b/internal/ceres/visibility.cc index 371bdfa..fcd793c 100644 --- a/internal/ceres/visibility.cc +++ b/internal/ceres/visibility.cc
@@ -28,6 +28,8 @@ // // Author: kushalav@google.com (Avanish Kushal) +#ifndef CERES_NO_SUITESPARSE + #include "ceres/visibility.h" #include <cmath> @@ -150,3 +152,5 @@ } // namespace internal } // namespace ceres + +#endif
diff --git a/internal/ceres/visibility.h b/internal/ceres/visibility.h index f29e3c6..2d1e6f8 100644 --- a/internal/ceres/visibility.h +++ b/internal/ceres/visibility.h
@@ -35,6 +35,8 @@ #ifndef CERES_INTERNAL_VISIBILITY_H_ #define CERES_INTERNAL_VISIBILITY_H_ +#ifndef CERES_NO_SUITESPARSE + #include <set> #include <vector> #include "ceres/graph.h" @@ -74,4 +76,5 @@ } // namespace internal } // namespace ceres +#endif // CERES_NO_SUITESPARSE #endif // CERES_INTERNAL_VISIBILITY_H_
diff --git a/internal/ceres/visibility_based_preconditioner.cc b/internal/ceres/visibility_based_preconditioner.cc index a75d6f0..9c92190 100644 --- a/internal/ceres/visibility_based_preconditioner.cc +++ b/internal/ceres/visibility_based_preconditioner.cc
@@ -28,6 +28,8 @@ // // Author: sameeragarwal@google.com (Sameer Agarwal) +#ifndef CERES_NO_SUITESPARSE + #include "ceres/visibility_based_preconditioner.h" #include <algorithm> @@ -62,7 +64,6 @@ static const double kSizePenaltyWeight = 3.0; static const double kSimilarityPenaltyWeight = 0.0; -#ifndef CERES_NO_SUITESPARSE VisibilityBasedPreconditioner::VisibilityBasedPreconditioner( const CompressedRowBlockStructure& bs, const Preconditioner::Options& options) @@ -584,7 +585,7 @@ } } -#endif // CERES_NO_SUITESPARSE - } // namespace internal } // namespace ceres + +#endif // CERES_NO_SUITESPARSE
diff --git a/internal/ceres/visibility_test.cc b/internal/ceres/visibility_test.cc index 793a19d..3cfb232 100644 --- a/internal/ceres/visibility_test.cc +++ b/internal/ceres/visibility_test.cc
@@ -29,6 +29,8 @@ // Author: kushalav@google.com (Avanish Kushal) // sameeragarwal@google.com (Sameer Agarwal) +#ifndef CERES_NO_SUITESPARSE + #include "ceres/visibility.h" #include <set> @@ -201,3 +203,5 @@ } // namespace internal } // namespace ceres + +#endif // CERES_NO_SUITESPARSE
diff --git a/jni/Android.mk b/jni/Android.mk index fddb81f..345b3d6 100644 --- a/jni/Android.mk +++ b/jni/Android.mk
@@ -65,6 +65,10 @@ # # to the LOCAL_CFLAGS variable below, and commenting out all the # generated/schur_eliminator_2_2_2.cc-alike files, leaving only the _d_d_d one. +# +# Similarly if you do not need the line search minimizer, consider adding +# +# -DCERES_NO_LINE_SEARCH_MINIMIZER LOCAL_PATH := $(call my-dir)