linear_solver.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. // Ceres Solver - A fast non-linear least squares minimizer
  2. // Copyright 2015 Google Inc. All rights reserved.
  3. // http://ceres-solver.org/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are met:
  7. //
  8. // * Redistributions of source code must retain the above copyright notice,
  9. // this list of conditions and the following disclaimer.
  10. // * Redistributions in binary form must reproduce the above copyright notice,
  11. // this list of conditions and the following disclaimer in the documentation
  12. // and/or other materials provided with the distribution.
  13. // * Neither the name of Google Inc. nor the names of its contributors may be
  14. // used to endorse or promote products derived from this software without
  15. // specific prior written permission.
  16. //
  17. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  18. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  21. // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  22. // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  23. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  24. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  25. // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  26. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  27. // POSSIBILITY OF SUCH DAMAGE.
  28. //
  29. // Author: sameeragarwal@google.com (Sameer Agarwal)
  30. //
  31. // Abstract interface for objects solving linear systems of various
  32. // kinds.
  33. #ifndef CERES_INTERNAL_LINEAR_SOLVER_H_
  34. #define CERES_INTERNAL_LINEAR_SOLVER_H_
  35. #include <cstddef>
  36. #include <map>
  37. #include <memory>
  38. #include <string>
  39. #include <vector>
  40. #include "ceres/block_sparse_matrix.h"
  41. #include "ceres/casts.h"
  42. #include "ceres/compressed_row_sparse_matrix.h"
  43. #include "ceres/context_impl.h"
  44. #include "ceres/dense_sparse_matrix.h"
  45. #include "ceres/execution_summary.h"
  46. #include "ceres/internal/disable_warnings.h"
  47. #include "ceres/internal/export.h"
  48. #include "ceres/triplet_sparse_matrix.h"
  49. #include "ceres/types.h"
  50. #include "glog/logging.h"
  51. namespace ceres::internal {
  52. enum class LinearSolverTerminationType {
  53. // Termination criterion was met.
  54. SUCCESS,
  55. // Solver ran for max_num_iterations and terminated before the
  56. // termination tolerance could be satisfied.
  57. NO_CONVERGENCE,
  58. // Solver was terminated due to numerical problems, generally due to
  59. // the linear system being poorly conditioned.
  60. FAILURE,
  61. // Solver failed with a fatal error that cannot be recovered from,
  62. // e.g. CHOLMOD ran out of memory when computing the symbolic or
  63. // numeric factorization or an underlying library was called with
  64. // the wrong arguments.
  65. FATAL_ERROR
  66. };
  67. inline std::ostream& operator<<(std::ostream& s,
  68. LinearSolverTerminationType type) {
  69. switch (type) {
  70. case LinearSolverTerminationType::SUCCESS:
  71. s << "LINEAR_SOLVER_SUCCESS";
  72. break;
  73. case LinearSolverTerminationType::NO_CONVERGENCE:
  74. s << "LINEAR_SOLVER_NO_CONVERGENCE";
  75. break;
  76. case LinearSolverTerminationType::FAILURE:
  77. s << "LINEAR_SOLVER_FAILURE";
  78. break;
  79. case LinearSolverTerminationType::FATAL_ERROR:
  80. s << "LINEAR_SOLVER_FATAL_ERROR";
  81. break;
  82. default:
  83. s << "UNKNOWN LinearSolverTerminationType";
  84. }
  85. return s;
  86. }
  87. // This enum controls the fill-reducing ordering a sparse linear
  88. // algebra library should use before computing a sparse factorization
  89. // (usually Cholesky).
  90. //
  91. // TODO(sameeragarwal): Add support for nested dissection
  92. enum class OrderingType {
  93. NATURAL, // Do not re-order the matrix. This is useful when the
  94. // matrix has been ordered using a fill-reducing ordering
  95. // already.
  96. AMD, // Use the Approximate Minimum Degree algorithm to re-order
  97. // the matrix.
  98. NESDIS, // Use the Nested Dissection algorithm to re-order the matrix.
  99. };
  100. inline std::ostream& operator<<(std::ostream& s, OrderingType type) {
  101. switch (type) {
  102. case OrderingType::NATURAL:
  103. s << "NATURAL";
  104. break;
  105. case OrderingType::AMD:
  106. s << "AMD";
  107. break;
  108. case OrderingType::NESDIS:
  109. s << "NESDIS";
  110. break;
  111. default:
  112. s << "UNKNOWN OrderingType";
  113. }
  114. return s;
  115. }
  116. class LinearOperator;
  117. // Abstract base class for objects that implement algorithms for
  118. // solving linear systems
  119. //
  120. // Ax = b
  121. //
  122. // It is expected that a single instance of a LinearSolver object
  123. // maybe used multiple times for solving multiple linear systems with
  124. // the same sparsity structure. This allows them to cache and reuse
  125. // information across solves. This means that calling Solve on the
  126. // same LinearSolver instance with two different linear systems will
  127. // result in undefined behaviour.
  128. //
  129. // Subclasses of LinearSolver use two structs to configure themselves.
  130. // The Options struct configures the LinearSolver object for its
  131. // lifetime. The PerSolveOptions struct is used to specify options for
  132. // a particular Solve call.
  133. class CERES_NO_EXPORT LinearSolver {
  134. public:
  135. struct Options {
  136. LinearSolverType type = SPARSE_NORMAL_CHOLESKY;
  137. PreconditionerType preconditioner_type = JACOBI;
  138. VisibilityClusteringType visibility_clustering_type = CANONICAL_VIEWS;
  139. DenseLinearAlgebraLibraryType dense_linear_algebra_library_type = EIGEN;
  140. SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type =
  141. SUITE_SPARSE;
  142. OrderingType ordering_type = OrderingType::NATURAL;
  143. // See solver.h for information about these flags.
  144. bool dynamic_sparsity = false;
  145. bool use_explicit_schur_complement = false;
  146. // Number of internal iterations that the solver uses. This
  147. // parameter only makes sense for iterative solvers like CG.
  148. int min_num_iterations = 1;
  149. int max_num_iterations = 1;
  150. // Maximum number of iterations performed by SCHUR_POWER_SERIES_EXPANSION.
  151. // This value controls the maximum number of iterations whether it is used
  152. // as a preconditioner or just to initialize the solution for
  153. // ITERATIVE_SCHUR.
  154. int max_num_spse_iterations = 5;
  155. // Use SCHUR_POWER_SERIES_EXPANSION to initialize the solution for
  156. // ITERATIVE_SCHUR. This option can be set true regardless of what
  157. // preconditioner is being used.
  158. bool use_spse_initialization = false;
  159. // When use_spse_initialization is true, this parameter along with
  160. // max_num_spse_iterations controls the number of
  161. // SCHUR_POWER_SERIES_EXPANSION iterations performed for initialization. It
  162. // is not used to control the preconditioner.
  163. double spse_tolerance = 0.1;
  164. // If possible, how many threads can the solver use.
  165. int num_threads = 1;
  166. // Hints about the order in which the parameter blocks should be
  167. // eliminated by the linear solver.
  168. //
  169. // For example if elimination_groups is a vector of size k, then
  170. // the linear solver is informed that it should eliminate the
  171. // parameter blocks 0 ... elimination_groups[0] - 1 first, and
  172. // then elimination_groups[0] ... elimination_groups[1] - 1 and so
  173. // on. Within each elimination group, the linear solver is free to
  174. // choose how the parameter blocks are ordered. Different linear
  175. // solvers have differing requirements on elimination_groups.
  176. //
  177. // The most common use is for Schur type solvers, where there
  178. // should be at least two elimination groups and the first
  179. // elimination group must form an independent set in the normal
  180. // equations. The first elimination group corresponds to the
  181. // num_eliminate_blocks in the Schur type solvers.
  182. std::vector<int> elimination_groups;
  183. // Iterative solvers, e.g. Preconditioned Conjugate Gradients
  184. // maintain a cheap estimate of the residual which may become
  185. // inaccurate over time. Thus for non-zero values of this
  186. // parameter, the solver can be told to recalculate the value of
  187. // the residual using a |b - Ax| evaluation.
  188. int residual_reset_period = 10;
  189. // If the block sizes in a BlockSparseMatrix are fixed, then in
  190. // some cases the Schur complement based solvers can detect and
  191. // specialize on them.
  192. //
  193. // It is expected that these parameters are set programmatically
  194. // rather than manually.
  195. //
  196. // Please see schur_complement_solver.h and schur_eliminator.h for
  197. // more details.
  198. int row_block_size = Eigen::Dynamic;
  199. int e_block_size = Eigen::Dynamic;
  200. int f_block_size = Eigen::Dynamic;
  201. bool use_mixed_precision_solves = false;
  202. int max_num_refinement_iterations = 0;
  203. int subset_preconditioner_start_row_block = -1;
  204. ContextImpl* context = nullptr;
  205. };
  206. // Options for the Solve method.
  207. struct PerSolveOptions {
  208. // This option only makes sense for unsymmetric linear solvers
  209. // that can solve rectangular linear systems.
  210. //
  211. // Given a matrix A, an optional diagonal matrix D as a vector,
  212. // and a vector b, the linear solver will solve for
  213. //
  214. // | A | x = | b |
  215. // | D | | 0 |
  216. //
  217. // If D is null, then it is treated as zero, and the solver returns
  218. // the solution to
  219. //
  220. // A x = b
  221. //
  222. // In either case, x is the vector that solves the following
  223. // optimization problem.
  224. //
  225. // arg min_x ||Ax - b||^2 + ||Dx||^2
  226. //
  227. // Here A is a matrix of size m x n, with full column rank. If A
  228. // does not have full column rank, the results returned by the
  229. // solver cannot be relied on. D, if it is not null is an array of
  230. // size n. b is an array of size m and x is an array of size n.
  231. double* D = nullptr;
  232. // This option only makes sense for iterative solvers.
  233. //
  234. // In general the performance of an iterative linear solver
  235. // depends on the condition number of the matrix A. For example
  236. // the convergence rate of the conjugate gradients algorithm
  237. // is proportional to the square root of the condition number.
  238. //
  239. // One particularly useful technique for improving the
  240. // conditioning of a linear system is to precondition it. In its
  241. // simplest form a preconditioner is a matrix M such that instead
  242. // of solving Ax = b, we solve the linear system AM^{-1} y = b
  243. // instead, where M is such that the condition number k(AM^{-1})
  244. // is smaller than the conditioner k(A). Given the solution to
  245. // this system, x = M^{-1} y. The iterative solver takes care of
  246. // the mechanics of solving the preconditioned system and
  247. // returning the corrected solution x. The user only needs to
  248. // supply a linear operator.
  249. //
  250. // A null preconditioner is equivalent to an identity matrix being
  251. // used a preconditioner.
  252. LinearOperator* preconditioner = nullptr;
  253. // The following tolerance related options only makes sense for
  254. // iterative solvers. Direct solvers ignore them.
  255. // Solver terminates when
  256. //
  257. // |Ax - b| <= r_tolerance * |b|.
  258. //
  259. // This is the most commonly used termination criterion for
  260. // iterative solvers.
  261. double r_tolerance = 0.0;
  262. // For PSD matrices A, let
  263. //
  264. // Q(x) = x'Ax - 2b'x
  265. //
  266. // be the cost of the quadratic function defined by A and b. Then,
  267. // the solver terminates at iteration i if
  268. //
  269. // i * (Q(x_i) - Q(x_i-1)) / Q(x_i) < q_tolerance.
  270. //
  271. // This termination criterion is more useful when using CG to
  272. // solve the Newton step. This particular convergence test comes
  273. // from Stephen Nash's work on truncated Newton
  274. // methods. References:
  275. //
  276. // 1. Stephen G. Nash & Ariela Sofer, Assessing A Search
  277. // Direction Within A Truncated Newton Method, Operation
  278. // Research Letters 9(1990) 219-221.
  279. //
  280. // 2. Stephen G. Nash, A Survey of Truncated Newton Methods,
  281. // Journal of Computational and Applied Mathematics,
  282. // 124(1-2), 45-59, 2000.
  283. //
  284. double q_tolerance = 0.0;
  285. };
  286. // Summary of a call to the Solve method. We should move away from
  287. // the true/false method for determining solver success. We should
  288. // let the summary object do the talking.
  289. struct Summary {
  290. double residual_norm = -1.0;
  291. int num_iterations = -1;
  292. LinearSolverTerminationType termination_type =
  293. LinearSolverTerminationType::FAILURE;
  294. std::string message;
  295. };
  296. // If the optimization problem is such that there are no remaining
  297. // e-blocks, a Schur type linear solver cannot be used. If the
  298. // linear solver is of Schur type, this function implements a policy
  299. // to select an alternate nearest linear solver to the one selected
  300. // by the user. The input linear_solver_type is returned otherwise.
  301. static LinearSolverType LinearSolverForZeroEBlocks(
  302. LinearSolverType linear_solver_type);
  303. virtual ~LinearSolver();
  304. // Solve Ax = b.
  305. virtual Summary Solve(LinearOperator* A,
  306. const double* b,
  307. const PerSolveOptions& per_solve_options,
  308. double* x) = 0;
  309. // This method returns copies instead of references so that the base
  310. // class implementation does not have to worry about life time
  311. // issues. Further, this calls are not expected to be frequent or
  312. // performance sensitive.
  313. virtual std::map<std::string, CallStatistics> Statistics() const {
  314. return {};
  315. }
  316. // Factory
  317. static std::unique_ptr<LinearSolver> Create(const Options& options);
  318. };
  319. // This templated subclass of LinearSolver serves as a base class for
  320. // other linear solvers that depend on the particular matrix layout of
  321. // the underlying linear operator. For example some linear solvers
  322. // need low level access to the TripletSparseMatrix implementing the
  323. // LinearOperator interface. This class hides those implementation
  324. // details behind a private virtual method, and has the Solve method
  325. // perform the necessary upcasting.
  326. template <typename MatrixType>
  327. class TypedLinearSolver : public LinearSolver {
  328. public:
  329. LinearSolver::Summary Solve(
  330. LinearOperator* A,
  331. const double* b,
  332. const LinearSolver::PerSolveOptions& per_solve_options,
  333. double* x) override {
  334. ScopedExecutionTimer total_time("LinearSolver::Solve", &execution_summary_);
  335. CHECK(A != nullptr);
  336. CHECK(b != nullptr);
  337. CHECK(x != nullptr);
  338. return SolveImpl(down_cast<MatrixType*>(A), b, per_solve_options, x);
  339. }
  340. std::map<std::string, CallStatistics> Statistics() const override {
  341. return execution_summary_.statistics();
  342. }
  343. private:
  344. virtual LinearSolver::Summary SolveImpl(
  345. MatrixType* A,
  346. const double* b,
  347. const LinearSolver::PerSolveOptions& per_solve_options,
  348. double* x) = 0;
  349. ExecutionSummary execution_summary_;
  350. };
  351. // Linear solvers that depend on access to the low level structure of
  352. // a SparseMatrix.
  353. // clang-format off
  354. using BlockSparseMatrixSolver = TypedLinearSolver<BlockSparseMatrix>; // NOLINT
  355. using CompressedRowSparseMatrixSolver = TypedLinearSolver<CompressedRowSparseMatrix>; // NOLINT
  356. using DenseSparseMatrixSolver = TypedLinearSolver<DenseSparseMatrix>; // NOLINT
  357. using TripletSparseMatrixSolver = TypedLinearSolver<TripletSparseMatrix>; // NOLINT
  358. // clang-format on
  359. } // namespace ceres::internal
  360. #include "ceres/internal/reenable_warnings.h"
  361. #endif // CERES_INTERNAL_LINEAR_SOLVER_H_