10ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Ceres Solver - A fast non-linear least squares minimizer
20ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
30ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// http://code.google.com/p/ceres-solver/
40ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//
50ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Redistribution and use in source and binary forms, with or without
60ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// modification, are permitted provided that the following conditions are met:
70ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//
80ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// * Redistributions of source code must retain the above copyright notice,
90ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//   this list of conditions and the following disclaimer.
100ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// * Redistributions in binary form must reproduce the above copyright notice,
110ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//   this list of conditions and the following disclaimer in the documentation
120ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//   and/or other materials provided with the distribution.
130ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// * Neither the name of Google Inc. nor the names of its contributors may be
140ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//   used to endorse or promote products derived from this software without
150ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//   specific prior written permission.
160ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//
170ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
180ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
190ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
200ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
210ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
220ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
230ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
240ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
250ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
260ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
270ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// POSSIBILITY OF SUCH DAMAGE.
280ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//
290ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Author: fredp@google.com (Fred Pighin)
300ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//
310ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Tests for linear solvers that solve symmetric linear systems. Some
320ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// of this code is inhertited from Fred Pighin's code for testing the
330ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// old Conjugate Gradients solver.
340ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//
350ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// TODO(sameeragarwal): More comprehensive testing with larger and
360ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// more badly conditioned problem.
370ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
380ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "gtest/gtest.h"
390ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ceres/conjugate_gradients_solver.h"
400ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ceres/linear_solver.h"
410ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ceres/triplet_sparse_matrix.h"
420ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ceres/internal/eigen.h"
430ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ceres/internal/scoped_ptr.h"
440ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ceres/types.h"
450ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
460ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongnamespace ceres {
470ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongnamespace internal {
480ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
490ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus KongTEST(ConjugateGradientTest, Solves3x3IdentitySystem) {
500ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double diagonal[] = { 1.0, 1.0, 1.0 };
510ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  scoped_ptr<TripletSparseMatrix>
520ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      A(TripletSparseMatrix::CreateSparseDiagonalMatrix(diagonal, 3));
530ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  Vector b(3);
540ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  Vector x(3);
550ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
560ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  b(0) = 1.0;
570ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  b(1) = 2.0;
580ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  b(2) = 3.0;
590ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
600ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  x(0) = 1;
610ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  x(1) = 1;
620ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  x(2) = 1;
630ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
640ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  LinearSolver::Options options;
650ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  options.max_num_iterations = 10;
660ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
670ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  LinearSolver::PerSolveOptions per_solve_options;
680ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  per_solve_options.r_tolerance = 1e-9;
690ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
700ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  ConjugateGradientsSolver solver(options);
710ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  LinearSolver::Summary summary =
720ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      solver.Solve(A.get(), b.data(), per_solve_options, x.data());
730ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
7479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  EXPECT_EQ(summary.termination_type, LINEAR_SOLVER_SUCCESS);
750ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  ASSERT_EQ(summary.num_iterations, 1);
760ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
770ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  ASSERT_DOUBLE_EQ(1, x(0));
780ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  ASSERT_DOUBLE_EQ(2, x(1));
790ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  ASSERT_DOUBLE_EQ(3, x(2));
800ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
810ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
820ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
830ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus KongTEST(ConjuateGradientTest, Solves3x3SymmetricSystem) {
840ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  scoped_ptr<TripletSparseMatrix> A(new TripletSparseMatrix(3, 3, 9));
850ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  Vector b(3);
860ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  Vector x(3);
870ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
880ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  //      | 2  -1  0|
890ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  //  A = |-1   2 -1| is symmetric positive definite.
900ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  //      | 0  -1  2|
910ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  int* Ai = A->mutable_rows();
920ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  int* Aj = A->mutable_cols();
930ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double* Ax = A->mutable_values();
940ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  int counter = 0;
950ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  for (int i = 0; i < 3; ++i) {
960ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    for (int j = 0; j < 3; ++j) {
970ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      Ai[counter] = i;
980ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      Aj[counter] = j;
990ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      ++counter;
1000ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
1010ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
1020ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  Ax[0] = 2.;
1030ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  Ax[1] = -1.;
1040ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  Ax[2] = 0;
1050ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  Ax[3] = -1.;
1060ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  Ax[4] = 2;
1070ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  Ax[5] = -1;
1080ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  Ax[6] = 0;
1090ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  Ax[7] = -1;
1100ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  Ax[8] = 2;
1110ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  A->set_num_nonzeros(9);
1120ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1130ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  b(0) = -1;
1140ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  b(1) = 0;
1150ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  b(2) = 3;
1160ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1170ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  x(0) = 1;
1180ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  x(1) = 1;
1190ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  x(2) = 1;
1200ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1210ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  LinearSolver::Options options;
1220ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  options.max_num_iterations = 10;
1230ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1240ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  LinearSolver::PerSolveOptions per_solve_options;
1250ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  per_solve_options.r_tolerance = 1e-9;
1260ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1270ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  ConjugateGradientsSolver solver(options);
1280ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  LinearSolver::Summary summary =
1290ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      solver.Solve(A.get(), b.data(), per_solve_options, x.data());
1300ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
13179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  EXPECT_EQ(summary.termination_type, LINEAR_SOLVER_SUCCESS);
1320ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1330ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  ASSERT_DOUBLE_EQ(0, x(0));
1340ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  ASSERT_DOUBLE_EQ(1, x(1));
1350ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  ASSERT_DOUBLE_EQ(2, x(2));
1360ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1370ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1380ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}  // namespace internal
1390ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}  // namespace ceres
140