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: keir@google.com (Keir Mierle)
300ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
310ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ceres/dense_sparse_matrix.h"
320ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
330ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include <algorithm>
340ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ceres/triplet_sparse_matrix.h"
350ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ceres/internal/eigen.h"
360ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ceres/internal/port.h"
371d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling#include "glog/logging.h"
380ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
390ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongnamespace ceres {
400ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongnamespace internal {
410ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
420ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus KongDenseSparseMatrix::DenseSparseMatrix(int num_rows, int num_cols)
430ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    : has_diagonal_appended_(false),
440ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      has_diagonal_reserved_(false) {
450ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  m_.resize(num_rows, num_cols);
460ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  m_.setZero();
470ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
480ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
491d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha HaeberlingDenseSparseMatrix::DenseSparseMatrix(int num_rows,
501d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                                     int num_cols,
511d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                                     bool reserve_diagonal)
520ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    : has_diagonal_appended_(false),
530ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      has_diagonal_reserved_(reserve_diagonal) {
540ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  if (reserve_diagonal) {
551d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    // Allocate enough space for the diagonal.
560ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    m_.resize(num_rows +  num_cols, num_cols);
570ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  } else {
580ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    m_.resize(num_rows, num_cols);
590ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
600ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  m_.setZero();
610ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
620ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
630ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus KongDenseSparseMatrix::DenseSparseMatrix(const TripletSparseMatrix& m)
640ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    : m_(Eigen::MatrixXd::Zero(m.num_rows(), m.num_cols())),
650ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      has_diagonal_appended_(false),
660ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      has_diagonal_reserved_(false) {
670ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  const double *values = m.values();
680ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  const int *rows = m.rows();
690ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  const int *cols = m.cols();
700ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  int num_nonzeros = m.num_nonzeros();
710ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
720ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  for (int i = 0; i < num_nonzeros; ++i) {
730ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    m_(rows[i], cols[i]) += values[i];
740ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
750ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
760ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
771d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha HaeberlingDenseSparseMatrix::DenseSparseMatrix(const ColMajorMatrix& m)
780ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    : m_(m),
790ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      has_diagonal_appended_(false),
800ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      has_diagonal_reserved_(false) {
810ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
820ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
830ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongvoid DenseSparseMatrix::SetZero() {
840ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  m_.setZero();
850ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
860ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
870ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongvoid DenseSparseMatrix::RightMultiply(const double* x, double* y) const {
880ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  VectorRef(y, num_rows()) += matrix() * ConstVectorRef(x, num_cols());
890ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
900ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
910ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongvoid DenseSparseMatrix::LeftMultiply(const double* x, double* y) const {
920ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  VectorRef(y, num_cols()) +=
930ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      matrix().transpose() * ConstVectorRef(x, num_rows());
940ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
950ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
960ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongvoid DenseSparseMatrix::SquaredColumnNorm(double* x) const {
970ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  VectorRef(x, num_cols()) = m_.colwise().squaredNorm();
980ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
990ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1000ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongvoid DenseSparseMatrix::ScaleColumns(const double* scale) {
1010ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  m_ *= ConstVectorRef(scale, num_cols()).asDiagonal();
1020ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1030ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1040ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongvoid DenseSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const {
1051d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  *dense_matrix = m_.block(0, 0, num_rows(), num_cols());
1060ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1070ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1080ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongvoid DenseSparseMatrix::AppendDiagonal(double *d) {
1090ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  CHECK(!has_diagonal_appended_);
1100ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  if (!has_diagonal_reserved_) {
1111d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    ColMajorMatrix tmp = m_;
1120ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    m_.resize(m_.rows() + m_.cols(), m_.cols());
1130ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    m_.setZero();
1140ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    m_.block(0, 0, tmp.rows(), tmp.cols()) = tmp;
1150ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    has_diagonal_reserved_ = true;
1160ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
1170ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1180ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  m_.bottomLeftCorner(m_.cols(), m_.cols()) =
1190ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      ConstVectorRef(d, m_.cols()).asDiagonal();
1200ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  has_diagonal_appended_ = true;
1210ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1220ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1230ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongvoid DenseSparseMatrix::RemoveDiagonal() {
1240ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  CHECK(has_diagonal_appended_);
1250ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  has_diagonal_appended_ = false;
1260ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Leave the diagonal reserved.
1270ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1280ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1290ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongint DenseSparseMatrix::num_rows() const {
1300ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  if (has_diagonal_reserved_ && !has_diagonal_appended_) {
1310ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    return m_.rows() - m_.cols();
1320ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
1330ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  return m_.rows();
1340ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1350ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1360ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongint DenseSparseMatrix::num_cols() const {
1370ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  return m_.cols();
1380ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1390ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1400ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongint DenseSparseMatrix::num_nonzeros() const {
1410ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  if (has_diagonal_reserved_ && !has_diagonal_appended_) {
1420ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    return (m_.rows() - m_.cols()) * m_.cols();
1430ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
1440ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  return m_.rows() * m_.cols();
1450ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1460ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1471d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha HaeberlingConstColMajorMatrixRef DenseSparseMatrix::matrix() const {
1481d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  return ConstColMajorMatrixRef(
1491d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      m_.data(),
1501d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      ((has_diagonal_reserved_ && !has_diagonal_appended_)
1511d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling       ? m_.rows() - m_.cols()
1521d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling       : m_.rows()),
1531d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      m_.cols(),
1541d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      Eigen::Stride<Eigen::Dynamic, 1>(m_.rows(), 1));
1550ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1560ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1571d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha HaeberlingColMajorMatrixRef DenseSparseMatrix::mutable_matrix() {
1581d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  return ColMajorMatrixRef(
1591d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      m_.data(),
1601d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      ((has_diagonal_reserved_ && !has_diagonal_appended_)
1611d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling       ? m_.rows() - m_.cols()
1621d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling       : m_.rows()),
1631d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      m_.cols(),
1641d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      Eigen::Stride<Eigen::Dynamic, 1>(m_.rows(), 1));
1650ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1660ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1671d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
1680ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongvoid DenseSparseMatrix::ToTextFile(FILE* file) const {
1690ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  CHECK_NOTNULL(file);
1700ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  const int active_rows =
1710ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      (has_diagonal_reserved_ && !has_diagonal_appended_)
1720ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      ? (m_.rows() - m_.cols())
1730ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      : m_.rows();
1740ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1750ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  for (int r = 0; r < active_rows; ++r) {
1760ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    for (int c = 0; c < m_.cols(); ++c) {
1770ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      fprintf(file,  "% 10d % 10d %17f\n", r, c, m_(r, c));
1780ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
1790ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
1800ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1810ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1820ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}  // namespace internal
1830ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}  // namespace ceres
184