conjugate_gradients_solver_test.cc 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // Ceres Solver - A fast non-linear least squares minimizer
  2. // Copyright 2017 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: fredp@google.com (Fred Pighin)
  30. //
  31. // TODO(sameeragarwal): More comprehensive testing with larger and
  32. // more badly conditioned problem.
  33. #include "ceres/conjugate_gradients_solver.h"
  34. #include <memory>
  35. #include "ceres/internal/eigen.h"
  36. #include "ceres/linear_solver.h"
  37. #include "ceres/preconditioner.h"
  38. #include "ceres/triplet_sparse_matrix.h"
  39. #include "ceres/types.h"
  40. #include "gtest/gtest.h"
  41. namespace ceres::internal {
  42. TEST(ConjugateGradientTest, Solves3x3IdentitySystem) {
  43. double diagonal[] = {1.0, 1.0, 1.0};
  44. std::unique_ptr<TripletSparseMatrix> A(
  45. TripletSparseMatrix::CreateSparseDiagonalMatrix(diagonal, 3));
  46. Vector b(3);
  47. Vector x(3);
  48. b(0) = 1.0;
  49. b(1) = 2.0;
  50. b(2) = 3.0;
  51. x(0) = 1;
  52. x(1) = 1;
  53. x(2) = 1;
  54. ConjugateGradientsSolverOptions cg_options;
  55. cg_options.min_num_iterations = 1;
  56. cg_options.max_num_iterations = 10;
  57. cg_options.residual_reset_period = 20;
  58. cg_options.q_tolerance = 0.0;
  59. cg_options.r_tolerance = 1e-9;
  60. Vector scratch[4];
  61. for (int i = 0; i < 4; ++i) {
  62. scratch[i] = Vector::Zero(A->num_cols());
  63. }
  64. IdentityPreconditioner identity(A->num_cols());
  65. LinearOperatorAdapter lhs(*A);
  66. LinearOperatorAdapter preconditioner(identity);
  67. Vector* scratch_array[4] = {
  68. &scratch[0], &scratch[1], &scratch[2], &scratch[3]};
  69. auto summary = ConjugateGradientsSolver(
  70. cg_options, lhs, b, preconditioner, scratch_array, x);
  71. EXPECT_EQ(summary.termination_type, LinearSolverTerminationType::SUCCESS);
  72. ASSERT_EQ(summary.num_iterations, 1);
  73. ASSERT_DOUBLE_EQ(1, x(0));
  74. ASSERT_DOUBLE_EQ(2, x(1));
  75. ASSERT_DOUBLE_EQ(3, x(2));
  76. }
  77. TEST(ConjuateGradientTest, Solves3x3SymmetricSystem) {
  78. std::unique_ptr<TripletSparseMatrix> A(new TripletSparseMatrix(3, 3, 9));
  79. Vector b(3);
  80. Vector x(3);
  81. // | 2 -1 0|
  82. // A = |-1 2 -1| is symmetric positive definite.
  83. // | 0 -1 2|
  84. int* Ai = A->mutable_rows();
  85. int* Aj = A->mutable_cols();
  86. double* Ax = A->mutable_values();
  87. int counter = 0;
  88. for (int i = 0; i < 3; ++i) {
  89. for (int j = 0; j < 3; ++j) {
  90. Ai[counter] = i;
  91. Aj[counter] = j;
  92. ++counter;
  93. }
  94. }
  95. Ax[0] = 2.;
  96. Ax[1] = -1.;
  97. Ax[2] = 0;
  98. Ax[3] = -1.;
  99. Ax[4] = 2;
  100. Ax[5] = -1;
  101. Ax[6] = 0;
  102. Ax[7] = -1;
  103. Ax[8] = 2;
  104. A->set_num_nonzeros(9);
  105. b(0) = -1;
  106. b(1) = 0;
  107. b(2) = 3;
  108. x(0) = 1;
  109. x(1) = 1;
  110. x(2) = 1;
  111. ConjugateGradientsSolverOptions cg_options;
  112. cg_options.min_num_iterations = 1;
  113. cg_options.max_num_iterations = 10;
  114. cg_options.residual_reset_period = 20;
  115. cg_options.q_tolerance = 0.0;
  116. cg_options.r_tolerance = 1e-9;
  117. Vector scratch[4];
  118. for (int i = 0; i < 4; ++i) {
  119. scratch[i] = Vector::Zero(A->num_cols());
  120. }
  121. Vector* scratch_array[4] = {
  122. &scratch[0], &scratch[1], &scratch[2], &scratch[3]};
  123. IdentityPreconditioner identity(A->num_cols());
  124. LinearOperatorAdapter lhs(*A);
  125. LinearOperatorAdapter preconditioner(identity);
  126. auto summary = ConjugateGradientsSolver(
  127. cg_options, lhs, b, preconditioner, scratch_array, x);
  128. EXPECT_EQ(summary.termination_type, LinearSolverTerminationType::SUCCESS);
  129. ASSERT_DOUBLE_EQ(0, x(0));
  130. ASSERT_DOUBLE_EQ(1, x(1));
  131. ASSERT_DOUBLE_EQ(2, x(2));
  132. }
  133. } // namespace ceres::internal