blob: a670f006516081de10688d5ba8fe520100268bf7 [file] [log] [blame]
Keir Mierle8ebb0732012-04-30 23:09:08 -07001// Ceres Solver - A fast non-linear least squares minimizer
Keir Mierle7492b0d2015-03-17 22:30:16 -07002// Copyright 2015 Google Inc. All rights reserved.
3// http://ceres-solver.org/
Keir Mierle8ebb0732012-04-30 23:09:08 -07004//
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
Keir Mierle8ebb0732012-04-30 23:09:08 -070031#include "ceres/casts.h"
32#include "ceres/compressed_row_sparse_matrix.h"
Sameer Agarwal0beab862012-08-13 15:12:01 -070033#include "ceres/internal/scoped_ptr.h"
Keir Mierle8ebb0732012-04-30 23:09:08 -070034#include "ceres/linear_least_squares_problems.h"
35#include "ceres/linear_solver.h"
36#include "ceres/triplet_sparse_matrix.h"
Keir Mierle8ebb0732012-04-30 23:09:08 -070037#include "ceres/types.h"
Sameer Agarwal0beab862012-08-13 15:12:01 -070038#include "glog/logging.h"
39#include "gtest/gtest.h"
Keir Mierle8ebb0732012-04-30 23:09:08 -070040
41
42namespace ceres {
43namespace internal {
44
45class UnsymmetricLinearSolverTest : public ::testing::Test {
46 protected :
47 virtual void SetUp() {
48 scoped_ptr<LinearLeastSquaresProblem> problem(
49 CreateLinearLeastSquaresProblemFromId(0));
50
51 CHECK_NOTNULL(problem.get());
52 A_.reset(down_cast<TripletSparseMatrix*>(problem->A.release()));
53 b_.reset(problem->b.release());
54 D_.reset(problem->D.release());
Sameer Agarwalb0518732012-05-29 00:27:57 -070055 sol_unregularized_.reset(problem->x.release());
56 sol_regularized_.reset(problem->x_D.release());
Keir Mierle8ebb0732012-04-30 23:09:08 -070057 }
58
Sameer Agarwald5b93bf2013-04-26 21:17:49 -070059 void TestSolver(const LinearSolver::Options& options) {
Keir Mierle8ebb0732012-04-30 23:09:08 -070060 LinearSolver::PerSolveOptions per_solve_options;
Sameer Agarwalb0518732012-05-29 00:27:57 -070061 LinearSolver::Summary unregularized_solve_summary;
62 LinearSolver::Summary regularized_solve_summary;
63 Vector x_unregularized(A_->num_cols());
64 Vector x_regularized(A_->num_cols());
Keir Mierle8ebb0732012-04-30 23:09:08 -070065
Sameer Agarwalb0518732012-05-29 00:27:57 -070066 scoped_ptr<SparseMatrix> transformed_A;
Keir Mierle8ebb0732012-04-30 23:09:08 -070067
Sameer Agarwald5b93bf2013-04-26 21:17:49 -070068 if (options.type == DENSE_QR ||
69 options.type == DENSE_NORMAL_CHOLESKY) {
Sameer Agarwalb0518732012-05-29 00:27:57 -070070 transformed_A.reset(new DenseSparseMatrix(*A_));
Sameer Agarwald5b93bf2013-04-26 21:17:49 -070071 } else if (options.type == SPARSE_NORMAL_CHOLESKY) {
Sameer Agarwal086ff012017-05-01 17:24:22 -070072 CompressedRowSparseMatrix* crsm =
73 CompressedRowSparseMatrix::FromTripletSparseMatrix(*A_);
Sameer Agarwald5b93bf2013-04-26 21:17:49 -070074 // Add row/column blocks structure.
75 for (int i = 0; i < A_->num_rows(); ++i) {
76 crsm->mutable_row_blocks()->push_back(1);
77 }
78
79 for (int i = 0; i < A_->num_cols(); ++i) {
80 crsm->mutable_col_blocks()->push_back(1);
81 }
Cheng Wang07dbf312017-03-07 14:57:23 -080082
83 // With all blocks of size 1, crsb_rows and crsb_cols are equivalent to
84 // rows and cols.
85 std::copy(crsm->rows(), crsm->rows() + crsm->num_rows() + 1,
86 std::back_inserter(*crsm->mutable_crsb_rows()));
87
88 std::copy(crsm->cols(), crsm->cols() + crsm->num_nonzeros(),
89 std::back_inserter(*crsm->mutable_crsb_cols()));
90
Sameer Agarwald5b93bf2013-04-26 21:17:49 -070091 transformed_A.reset(crsm);
Sameer Agarwalb0518732012-05-29 00:27:57 -070092 } else {
Sameer Agarwald5b93bf2013-04-26 21:17:49 -070093 LOG(FATAL) << "Unknown linear solver : " << options.type;
Keir Mierle8ebb0732012-04-30 23:09:08 -070094 }
Sameer Agarwalf14f6bf2013-12-26 09:50:45 -080095
Sameer Agarwalb0518732012-05-29 00:27:57 -070096 // Unregularized
Sameer Agarwalf14f6bf2013-12-26 09:50:45 -080097 scoped_ptr<LinearSolver> solver(LinearSolver::Create(options));
Sameer Agarwalb0518732012-05-29 00:27:57 -070098 unregularized_solve_summary =
99 solver->Solve(transformed_A.get(),
100 b_.get(),
101 per_solve_options,
102 x_unregularized.data());
Keir Mierle8ebb0732012-04-30 23:09:08 -0700103
Sameer Agarwalf14f6bf2013-12-26 09:50:45 -0800104 // Sparsity structure is changing, reset the solver.
105 solver.reset(LinearSolver::Create(options));
Keir Mierle8ebb0732012-04-30 23:09:08 -0700106 // Regularized solution
107 per_solve_options.D = D_.get();
Sameer Agarwalb0518732012-05-29 00:27:57 -0700108 regularized_solve_summary =
109 solver->Solve(transformed_A.get(),
110 b_.get(),
111 per_solve_options,
112 x_regularized.data());
Keir Mierle8ebb0732012-04-30 23:09:08 -0700113
Sameer Agarwald73acd02013-12-02 12:02:03 -0800114 EXPECT_EQ(unregularized_solve_summary.termination_type,
115 LINEAR_SOLVER_SUCCESS);
Keir Mierle8ebb0732012-04-30 23:09:08 -0700116
117 for (int i = 0; i < A_->num_cols(); ++i) {
Sameer Agarwal03159822014-07-17 14:35:18 -0700118 EXPECT_NEAR(sol_unregularized_[i], x_unregularized[i], 1e-8)
119 << "\nExpected: "
Sameer Agarwalbcc865f2014-12-17 07:35:09 -0800120 << ConstVectorRef(sol_unregularized_.get(),
121 A_->num_cols()).transpose()
Sameer Agarwal03159822014-07-17 14:35:18 -0700122 << "\nActual: " << x_unregularized.transpose();
Sameer Agarwalb0518732012-05-29 00:27:57 -0700123 }
124
Sameer Agarwald73acd02013-12-02 12:02:03 -0800125 EXPECT_EQ(regularized_solve_summary.termination_type,
126 LINEAR_SOLVER_SUCCESS);
Sameer Agarwalb0518732012-05-29 00:27:57 -0700127 for (int i = 0; i < A_->num_cols(); ++i) {
Sameer Agarwal03159822014-07-17 14:35:18 -0700128 EXPECT_NEAR(sol_regularized_[i], x_regularized[i], 1e-8)
129 << "\nExpected: "
130 << ConstVectorRef(sol_regularized_.get(), A_->num_cols()).transpose()
131 << "\nActual: " << x_regularized.transpose();
Keir Mierle8ebb0732012-04-30 23:09:08 -0700132 }
133 }
134
135 scoped_ptr<TripletSparseMatrix> A_;
136 scoped_array<double> b_;
137 scoped_array<double> D_;
Sameer Agarwalb0518732012-05-29 00:27:57 -0700138 scoped_array<double> sol_unregularized_;
139 scoped_array<double> sol_regularized_;
Keir Mierle8ebb0732012-04-30 23:09:08 -0700140};
141
Sameer Agarwal367b65e2013-08-09 10:35:37 -0700142TEST_F(UnsymmetricLinearSolverTest, EigenDenseQR) {
Sameer Agarwald5b93bf2013-04-26 21:17:49 -0700143 LinearSolver::Options options;
144 options.type = DENSE_QR;
Sameer Agarwal367b65e2013-08-09 10:35:37 -0700145 options.dense_linear_algebra_library_type = EIGEN;
Sameer Agarwald5b93bf2013-04-26 21:17:49 -0700146 TestSolver(options);
Keir Mierle8ebb0732012-04-30 23:09:08 -0700147}
148
Sameer Agarwal367b65e2013-08-09 10:35:37 -0700149TEST_F(UnsymmetricLinearSolverTest, EigenDenseNormalCholesky) {
Sameer Agarwald5b93bf2013-04-26 21:17:49 -0700150 LinearSolver::Options options;
Sameer Agarwal367b65e2013-08-09 10:35:37 -0700151 options.dense_linear_algebra_library_type = EIGEN;
Sameer Agarwald5b93bf2013-04-26 21:17:49 -0700152 options.type = DENSE_NORMAL_CHOLESKY;
153 TestSolver(options);
Sameer Agarwalb9f15a52012-08-18 13:06:19 -0700154}
155
Sameer Agarwal367b65e2013-08-09 10:35:37 -0700156#ifndef CERES_NO_LAPACK
157TEST_F(UnsymmetricLinearSolverTest, LAPACKDenseQR) {
158 LinearSolver::Options options;
159 options.type = DENSE_QR;
160 options.dense_linear_algebra_library_type = LAPACK;
161 TestSolver(options);
162}
163
164TEST_F(UnsymmetricLinearSolverTest, LAPACKDenseNormalCholesky) {
165 LinearSolver::Options options;
166 options.dense_linear_algebra_library_type = LAPACK;
167 options.type = DENSE_NORMAL_CHOLESKY;
168 TestSolver(options);
169}
170#endif
171
Keir Mierle8ebb0732012-04-30 23:09:08 -0700172#ifndef CERES_NO_SUITESPARSE
Sameer Agarwalac626962013-05-06 07:04:26 -0700173TEST_F(UnsymmetricLinearSolverTest,
174 SparseNormalCholeskyUsingSuiteSparsePreOrdering) {
Sameer Agarwald5b93bf2013-04-26 21:17:49 -0700175 LinearSolver::Options options;
Sameer Agarwal367b65e2013-08-09 10:35:37 -0700176 options.sparse_linear_algebra_library_type = SUITE_SPARSE;
Sameer Agarwald5b93bf2013-04-26 21:17:49 -0700177 options.type = SPARSE_NORMAL_CHOLESKY;
178 options.use_postordering = false;
179 TestSolver(options);
180}
181
Sameer Agarwalac626962013-05-06 07:04:26 -0700182TEST_F(UnsymmetricLinearSolverTest,
183 SparseNormalCholeskyUsingSuiteSparsePostOrdering) {
Sameer Agarwald5b93bf2013-04-26 21:17:49 -0700184 LinearSolver::Options options;
Sameer Agarwal367b65e2013-08-09 10:35:37 -0700185 options.sparse_linear_algebra_library_type = SUITE_SPARSE;
Sameer Agarwald5b93bf2013-04-26 21:17:49 -0700186 options.type = SPARSE_NORMAL_CHOLESKY;
187 options.use_postordering = true;
188 TestSolver(options);
Keir Mierle8ebb0732012-04-30 23:09:08 -0700189}
Richard Stebbing32530782014-04-26 07:42:23 +0100190
191TEST_F(UnsymmetricLinearSolverTest,
192 SparseNormalCholeskyUsingSuiteSparseDynamicSparsity) {
193 LinearSolver::Options options;
194 options.sparse_linear_algebra_library_type = SUITE_SPARSE;
195 options.type = SPARSE_NORMAL_CHOLESKY;
196 options.dynamic_sparsity = true;
197 TestSolver(options);
198}
Sameer Agarwalb0518732012-05-29 00:27:57 -0700199#endif
200
201#ifndef CERES_NO_CXSPARSE
Sameer Agarwalac626962013-05-06 07:04:26 -0700202TEST_F(UnsymmetricLinearSolverTest,
203 SparseNormalCholeskyUsingCXSparsePreOrdering) {
Sameer Agarwald5b93bf2013-04-26 21:17:49 -0700204 LinearSolver::Options options;
Sameer Agarwal367b65e2013-08-09 10:35:37 -0700205 options.sparse_linear_algebra_library_type = CX_SPARSE;
Sameer Agarwald5b93bf2013-04-26 21:17:49 -0700206 options.type = SPARSE_NORMAL_CHOLESKY;
207 options.use_postordering = false;
208 TestSolver(options);
209}
210
Sameer Agarwalac626962013-05-06 07:04:26 -0700211TEST_F(UnsymmetricLinearSolverTest,
212 SparseNormalCholeskyUsingCXSparsePostOrdering) {
Sameer Agarwald5b93bf2013-04-26 21:17:49 -0700213 LinearSolver::Options options;
Sameer Agarwal367b65e2013-08-09 10:35:37 -0700214 options.sparse_linear_algebra_library_type = CX_SPARSE;
Sameer Agarwald5b93bf2013-04-26 21:17:49 -0700215 options.type = SPARSE_NORMAL_CHOLESKY;
216 options.use_postordering = true;
217 TestSolver(options);
Sameer Agarwalb0518732012-05-29 00:27:57 -0700218}
Richard Stebbing32530782014-04-26 07:42:23 +0100219
220TEST_F(UnsymmetricLinearSolverTest,
221 SparseNormalCholeskyUsingCXSparseDynamicSparsity) {
222 LinearSolver::Options options;
223 options.sparse_linear_algebra_library_type = CX_SPARSE;
224 options.type = SPARSE_NORMAL_CHOLESKY;
225 options.dynamic_sparsity = true;
226 TestSolver(options);
227}
Sameer Agarwalb0518732012-05-29 00:27:57 -0700228#endif
Keir Mierle8ebb0732012-04-30 23:09:08 -0700229
Sameer Agarwal03159822014-07-17 14:35:18 -0700230#ifdef CERES_USE_EIGEN_SPARSE
231TEST_F(UnsymmetricLinearSolverTest,
232 SparseNormalCholeskyUsingEigenPreOrdering) {
233 LinearSolver::Options options;
234 options.sparse_linear_algebra_library_type = EIGEN_SPARSE;
235 options.type = SPARSE_NORMAL_CHOLESKY;
236 options.use_postordering = false;
237 TestSolver(options);
238}
239
240TEST_F(UnsymmetricLinearSolverTest,
241 SparseNormalCholeskyUsingEigenPostOrdering) {
242 LinearSolver::Options options;
243 options.sparse_linear_algebra_library_type = EIGEN_SPARSE;
244 options.type = SPARSE_NORMAL_CHOLESKY;
245 options.use_postordering = true;
246 TestSolver(options);
247}
248
249TEST_F(UnsymmetricLinearSolverTest,
250 SparseNormalCholeskyUsingEigenDynamicSparsity) {
251 LinearSolver::Options options;
252 options.sparse_linear_algebra_library_type = EIGEN_SPARSE;
253 options.type = SPARSE_NORMAL_CHOLESKY;
254 options.dynamic_sparsity = true;
255 TestSolver(options);
256}
257
258#endif // CERES_USE_EIGEN_SPARSE
259
Keir Mierle8ebb0732012-04-30 23:09:08 -0700260} // namespace internal
261} // namespace ceres