mirror of
https://github.com/ceres-solver/ceres-solver.git
synced 2026-08-29 08:34:37 +08:00
Remove Protocol Buffers support.
Change-Id: I451c543c82cdfb566736aab94d836abcfb5c689d
This commit is contained in:
@@ -514,23 +514,6 @@ IF (BUILD_ANDROID)
|
||||
ADD_DEFINITIONS(-DCERES_WORK_AROUND_ANDROID_NDK_COMPILER_BUG)
|
||||
ENDIF (BUILD_ANDROID)
|
||||
|
||||
# Protocol buffers
|
||||
OPTION(PROTOBUF
|
||||
"Enable protocol buffers support."
|
||||
ON)
|
||||
|
||||
IF (PROTOBUF)
|
||||
FIND_PACKAGE(Protobuf)
|
||||
IF (PROTOBUF_FOUND)
|
||||
INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIRS})
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/internal)
|
||||
ELSE (PROTOBUF_FOUND)
|
||||
ADD_DEFINITIONS(-DCERES_NO_PROTOCOL_BUFFERS)
|
||||
ENDIF (PROTOBUF_FOUND)
|
||||
ELSE (PROTOBUF)
|
||||
ADD_DEFINITIONS(-DCERES_NO_PROTOCOL_BUFFERS)
|
||||
ENDIF (PROTOBUF)
|
||||
|
||||
OPTION(DISABLE_TR1
|
||||
"Don't use TR1. This replaces some hash tables with sets. Slower."
|
||||
OFF)
|
||||
|
||||
@@ -151,5 +151,4 @@ cmake $CERES_SOURCE_ROOT \
|
||||
-DBUILD_ANDROID=ON \
|
||||
-DSUITESPARSE=OFF \
|
||||
-DGFLAGS=OFF \
|
||||
-DCXSPARSE=OFF \
|
||||
-DPROTOBUF=OFF
|
||||
-DCXSPARSE=OFF
|
||||
|
||||
Binary file not shown.
@@ -57,11 +57,6 @@ SuiteSparse. We recommend either `OpenBLAS
|
||||
atlas.sourceforge.net/>`_, both of which ship with BLAS and LAPACK
|
||||
routines.
|
||||
|
||||
8. `protobuf <http://code.google.com/p/protobuf/>`_ is used for
|
||||
serializing and deserializing linear least squares problems to
|
||||
disk. This is useful for debugging and testing. It is an optional
|
||||
dependency and without it some of the tests will be disabled.
|
||||
|
||||
.. _section-linux:
|
||||
|
||||
Building on Linux
|
||||
@@ -91,8 +86,6 @@ platform. Start by installing all the dependencies.
|
||||
sudo apt-get install libeigen3-dev
|
||||
# SuiteSparse and CXSparse
|
||||
sudo apt-get install libsuitesparse-dev
|
||||
# protobuf
|
||||
sudo apt-get install libprotobuf-dev
|
||||
|
||||
We are now ready to build and test Ceres.
|
||||
|
||||
@@ -189,8 +182,6 @@ framework.
|
||||
brew install eigen
|
||||
# SuiteSparse and CXSparse
|
||||
brew install suite-sparse
|
||||
# protobuf
|
||||
brew install protobuf
|
||||
|
||||
|
||||
We are now ready to build and test Ceres.
|
||||
@@ -296,11 +287,6 @@ It is possible to reduce the libraries needed to build Ceres and
|
||||
customize the build process by passing appropriate flags to
|
||||
``CMake``. Use these flags only if you really know what you are doing.
|
||||
|
||||
#. ``-DPROTOBUF=OFF``: ``protobuf`` is a large and complicated
|
||||
dependency. If you do not care for the tests that depend on it and
|
||||
the logging support it enables, you can use this flag to turn it
|
||||
off.
|
||||
|
||||
#. ``-DSUITESPARSE=OFF``: By default, Ceres will link to
|
||||
``SuiteSparse`` if all its dependencies are present. Use this flag
|
||||
to build Ceres without ``SuiteSparse``. This will also disable
|
||||
|
||||
@@ -1205,15 +1205,6 @@ elimination group [LiSaad]_.
|
||||
printed as dense vectors. This should only be used for small
|
||||
problems.
|
||||
|
||||
* ``PROTOBUF`` Write out the linear least squares problem to the
|
||||
directory pointed to by
|
||||
:member:`Solver::Options::trust_region_problem_dump_directory` as
|
||||
a protocol buffer. ``linear_least_squares_problems.h/cc``
|
||||
contains routines for loading these problems. For details on the
|
||||
on disk format used, see ``matrix.proto``. The files are named
|
||||
``ceres_solver_iteration_???.bin``. This requires that ``protobuf`` be
|
||||
linked into Ceres Solver.
|
||||
|
||||
* ``TEXTFILE`` Write out the linear least squares problem to the
|
||||
directory pointed to by
|
||||
:member:`Solver::Options::trust_region_problem_dump_directory` as
|
||||
|
||||
@@ -309,13 +309,6 @@ enum DumpFormatType {
|
||||
// for small problems.
|
||||
CONSOLE,
|
||||
|
||||
// Write out the linear least squares problem to the directory
|
||||
// pointed to by Solver::Options::lsqp_dump_directory as a protocol
|
||||
// buffer. linear_least_squares_problems.h/cc contains routines for
|
||||
// loading these problems. For details on the on disk format used,
|
||||
// see matrix.proto. The files are named lm_iteration_???.lsqp.
|
||||
PROTOBUF,
|
||||
|
||||
// Write out the linear least squares problem to the directory
|
||||
// pointed to by Solver::Options::lsqp_dump_directory as text files
|
||||
// which can be read into MATLAB/Octave. The Jacobian is dumped as a
|
||||
|
||||
@@ -118,10 +118,6 @@ IF (CMAKE_SYSTEM_NAME MATCHES "Linux" AND
|
||||
SET(LIB_SUFFIX "64")
|
||||
ENDIF ()
|
||||
|
||||
If (PROTOBUF_FOUND)
|
||||
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS matrix.proto)
|
||||
ENDIF (PROTOBUF_FOUND)
|
||||
|
||||
# Also depend on the header files so that they appear in IDEs.
|
||||
FILE(GLOB CERES_INTERNAL_HDRS *.h)
|
||||
|
||||
@@ -186,13 +182,7 @@ IF (OPENMP_FOUND)
|
||||
ENDIF (NOT MSVC)
|
||||
ENDIF (OPENMP_FOUND)
|
||||
|
||||
IF (PROTOBUF_FOUND)
|
||||
LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${PROTOBUF_LIBRARY})
|
||||
ENDIF (PROTOBUF_FOUND)
|
||||
|
||||
SET(CERES_LIBRARY_SOURCE
|
||||
${PROTO_SRCS}
|
||||
${PROTO_HDRS}
|
||||
${CERES_INTERNAL_SRC}
|
||||
${CERES_INTERNAL_HDRS}
|
||||
${CERES_INTERNAL_SCHUR_FILES})
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#include "ceres/blas.h"
|
||||
#include "ceres/block_structure.h"
|
||||
#include "ceres/internal/eigen.h"
|
||||
#include "ceres/matrix_proto.h"
|
||||
#include "ceres/triplet_sparse_matrix.h"
|
||||
#include "glog/logging.h"
|
||||
|
||||
@@ -82,31 +81,6 @@ BlockSparseMatrix::BlockSparseMatrix(
|
||||
CHECK_NOTNULL(values_.get());
|
||||
}
|
||||
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
BlockSparseMatrix::BlockSparseMatrix(const SparseMatrixProto& outer_proto) {
|
||||
CHECK(outer_proto.has_block_matrix());
|
||||
|
||||
const BlockSparseMatrixProto& proto = outer_proto.block_matrix();
|
||||
CHECK(proto.has_num_rows());
|
||||
CHECK(proto.has_num_cols());
|
||||
CHECK_EQ(proto.num_nonzeros(), proto.values_size());
|
||||
|
||||
num_rows_ = proto.num_rows();
|
||||
num_cols_ = proto.num_cols();
|
||||
num_nonzeros_ = proto.num_nonzeros();
|
||||
|
||||
// Copy out the values into *this.
|
||||
values_.reset(new double[num_nonzeros_]);
|
||||
for (int i = 0; i < proto.num_nonzeros(); ++i) {
|
||||
values_[i] = proto.values(i);
|
||||
}
|
||||
|
||||
// Create the block structure according to the proto.
|
||||
block_structure_.reset(new CompressedRowBlockStructure);
|
||||
ProtoToBlockStructure(proto.block_structure(), block_structure_.get());
|
||||
}
|
||||
#endif
|
||||
|
||||
void BlockSparseMatrix::SetZero() {
|
||||
fill(values_.get(), values_.get() + num_nonzeros_, 0.0);
|
||||
}
|
||||
@@ -243,21 +217,6 @@ const CompressedRowBlockStructure* BlockSparseMatrix::block_structure()
|
||||
return block_structure_.get();
|
||||
}
|
||||
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
void BlockSparseMatrix::ToProto(SparseMatrixProto* outer_proto) const {
|
||||
outer_proto->Clear();
|
||||
|
||||
BlockSparseMatrixProto* proto = outer_proto->mutable_block_matrix();
|
||||
proto->set_num_rows(num_rows_);
|
||||
proto->set_num_cols(num_cols_);
|
||||
proto->set_num_nonzeros(num_nonzeros_);
|
||||
for (int i = 0; i < num_nonzeros_; ++i) {
|
||||
proto->add_values(values_[i]);
|
||||
}
|
||||
BlockStructureToProto(*block_structure_, proto->mutable_block_structure());
|
||||
}
|
||||
#endif
|
||||
|
||||
void BlockSparseMatrix::ToTextFile(FILE* file) const {
|
||||
CHECK_NOTNULL(file);
|
||||
for (int i = 0; i < block_structure_->rows.size(); ++i) {
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
namespace ceres {
|
||||
namespace internal {
|
||||
|
||||
class SparseMatrixProto;
|
||||
class TripletSparseMatrix;
|
||||
|
||||
// This class implements the SparseMatrix interface for storing and
|
||||
@@ -64,11 +63,6 @@ class BlockSparseMatrix : public SparseMatrix {
|
||||
// CompressedRowBlockStructure objects.
|
||||
explicit BlockSparseMatrix(CompressedRowBlockStructure* block_structure);
|
||||
|
||||
// Construct a block sparse matrix from a protocol buffer.
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
explicit BlockSparseMatrix(const SparseMatrixProto& proto);
|
||||
#endif
|
||||
|
||||
BlockSparseMatrix();
|
||||
virtual ~BlockSparseMatrix();
|
||||
|
||||
@@ -79,9 +73,6 @@ class BlockSparseMatrix : public SparseMatrix {
|
||||
virtual void SquaredColumnNorm(double* x) const;
|
||||
virtual void ScaleColumns(const double* scale);
|
||||
virtual void ToDenseMatrix(Matrix* dense_matrix) const;
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
virtual void ToProto(SparseMatrixProto* proto) const;
|
||||
#endif
|
||||
virtual void ToTextFile(FILE* file) const;
|
||||
|
||||
virtual int num_rows() const { return num_rows_; }
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
#include "ceres/internal/eigen.h"
|
||||
#include "ceres/internal/scoped_ptr.h"
|
||||
#include "ceres/linear_least_squares_problems.h"
|
||||
#include "ceres/matrix_proto.h"
|
||||
#include "ceres/triplet_sparse_matrix.h"
|
||||
#include "glog/logging.h"
|
||||
#include "gtest/gtest.h"
|
||||
@@ -109,27 +108,5 @@ TEST_F(BlockSparseMatrixTest, ToDenseMatrixTest) {
|
||||
EXPECT_LT((m_a - m_b).norm(), 1e-12);
|
||||
}
|
||||
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
TEST_F(BlockSparseMatrixTest, Serialization) {
|
||||
// Roundtrip through serialization and check for equality.
|
||||
SparseMatrixProto proto;
|
||||
A_->ToProto(&proto);
|
||||
|
||||
LOG(INFO) << proto.DebugString();
|
||||
|
||||
BlockSparseMatrix A2(proto);
|
||||
|
||||
Matrix m_a;
|
||||
Matrix m_b;
|
||||
A_->ToDenseMatrix(&m_a);
|
||||
A2.ToDenseMatrix(&m_b);
|
||||
|
||||
LOG(INFO) << "\n" << m_a;
|
||||
LOG(INFO) << "\n" << m_b;
|
||||
|
||||
EXPECT_LT((m_a - m_b).norm(), 1e-12);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace internal
|
||||
} // namespace ceres
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
// Author: sameeragarwal@google.com (Sameer Agarwal)
|
||||
|
||||
#include "ceres/block_structure.h"
|
||||
#include "ceres/matrix_proto.h"
|
||||
|
||||
namespace ceres {
|
||||
namespace internal {
|
||||
@@ -38,55 +37,5 @@ bool CellLessThan(const Cell& lhs, const Cell& rhs) {
|
||||
return (lhs.block_id < rhs.block_id);
|
||||
}
|
||||
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
void ProtoToBlockStructure(const BlockStructureProto &proto,
|
||||
CompressedRowBlockStructure *block_structure) {
|
||||
// Decode the column blocks.
|
||||
block_structure->cols.resize(proto.cols_size());
|
||||
for (int i = 0; i < proto.cols_size(); ++i) {
|
||||
block_structure->cols[i].size = proto.cols(i).size();
|
||||
block_structure->cols[i].position =
|
||||
proto.cols(i).position();
|
||||
}
|
||||
// Decode the row structure.
|
||||
block_structure->rows.resize(proto.rows_size());
|
||||
for (int i = 0; i < proto.rows_size(); ++i) {
|
||||
const CompressedRowProto &row = proto.rows(i);
|
||||
block_structure->rows[i].block.size = row.block().size();
|
||||
block_structure->rows[i].block.position = row.block().position();
|
||||
|
||||
// Copy the cells within the row.
|
||||
block_structure->rows[i].cells.resize(row.cells_size());
|
||||
for (int j = 0; j < row.cells_size(); ++j) {
|
||||
const CellProto &cell = row.cells(j);
|
||||
block_structure->rows[i].cells[j].block_id = cell.block_id();
|
||||
block_structure->rows[i].cells[j].position = cell.position();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BlockStructureToProto(const CompressedRowBlockStructure &block_structure,
|
||||
BlockStructureProto *proto) {
|
||||
// Encode the column blocks.
|
||||
for (int i = 0; i < block_structure.cols.size(); ++i) {
|
||||
BlockProto *block = proto->add_cols();
|
||||
block->set_size(block_structure.cols[i].size);
|
||||
block->set_position(block_structure.cols[i].position);
|
||||
}
|
||||
// Encode the row structure.
|
||||
for (int i = 0; i < block_structure.rows.size(); ++i) {
|
||||
CompressedRowProto *row = proto->add_rows();
|
||||
BlockProto *block = row->mutable_block();
|
||||
block->set_size(block_structure.rows[i].block.size);
|
||||
block->set_position(block_structure.rows[i].block.position);
|
||||
for (int j = 0; j < block_structure.rows[i].cells.size(); ++j) {
|
||||
CellProto *cell = row->add_cells();
|
||||
cell->set_block_id(block_structure.rows[i].cells[j].block_id);
|
||||
cell->set_position(block_structure.rows[i].cells[j].position);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace internal
|
||||
} // namespace ceres
|
||||
|
||||
@@ -92,13 +92,6 @@ class CompressedRowSparseMatrix : public SparseMatrix {
|
||||
virtual const double* values() const { return &values_[0]; }
|
||||
virtual double* mutable_values() { return &values_[0]; }
|
||||
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
// Dump the sparse matrix to a proto. Destroys the contents of proto.
|
||||
virtual void ToProto(SparseMatrixProto* proto) const {
|
||||
LOG(FATAL) << "Broken.;";
|
||||
}
|
||||
#endif
|
||||
|
||||
// Delete the bottom delta_rows.
|
||||
// num_rows -= delta_rows
|
||||
void DeleteRows(int delta_rows);
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include "ceres/dense_sparse_matrix.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include "ceres/matrix_proto.h"
|
||||
#include "ceres/triplet_sparse_matrix.h"
|
||||
#include "ceres/internal/eigen.h"
|
||||
#include "ceres/internal/port.h"
|
||||
@@ -81,22 +80,6 @@ DenseSparseMatrix::DenseSparseMatrix(const ColMajorMatrix& m)
|
||||
has_diagonal_reserved_(false) {
|
||||
}
|
||||
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
DenseSparseMatrix::DenseSparseMatrix(const SparseMatrixProto& outer_proto)
|
||||
: m_(Eigen::MatrixXd::Zero(
|
||||
outer_proto.dense_matrix().num_rows(),
|
||||
outer_proto.dense_matrix().num_cols())),
|
||||
has_diagonal_appended_(false),
|
||||
has_diagonal_reserved_(false) {
|
||||
const DenseSparseMatrixProto& proto = outer_proto.dense_matrix();
|
||||
for (int i = 0; i < m_.rows(); ++i) {
|
||||
for (int j = 0; j < m_.cols(); ++j) {
|
||||
m_(i, j) = proto.values(m_.cols() * i + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void DenseSparseMatrix::SetZero() {
|
||||
m_.setZero();
|
||||
}
|
||||
@@ -122,22 +105,6 @@ void DenseSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const {
|
||||
*dense_matrix = m_.block(0, 0, num_rows(), num_cols());
|
||||
}
|
||||
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
void DenseSparseMatrix::ToProto(SparseMatrixProto* outer_proto) const {
|
||||
CHECK(!has_diagonal_appended_) << "Not supported.";
|
||||
outer_proto->Clear();
|
||||
DenseSparseMatrixProto* proto = outer_proto->mutable_dense_matrix();
|
||||
|
||||
proto->set_num_rows(num_rows());
|
||||
proto->set_num_cols(num_cols());
|
||||
|
||||
int num_nnz = num_nonzeros();
|
||||
for (int i = 0; i < num_nnz; ++i) {
|
||||
proto->add_values(m_.data()[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void DenseSparseMatrix::AppendDiagonal(double *d) {
|
||||
CHECK(!has_diagonal_appended_);
|
||||
if (!has_diagonal_reserved_) {
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
namespace ceres {
|
||||
namespace internal {
|
||||
|
||||
class SparseMatrixProto;
|
||||
class TripletSparseMatrix;
|
||||
|
||||
class DenseSparseMatrix : public SparseMatrix {
|
||||
@@ -51,9 +50,6 @@ class DenseSparseMatrix : public SparseMatrix {
|
||||
// m. This assumes that m does not have any repeated entries.
|
||||
explicit DenseSparseMatrix(const TripletSparseMatrix& m);
|
||||
explicit DenseSparseMatrix(const ColMajorMatrix& m);
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
explicit DenseSparseMatrix(const SparseMatrixProto& proto);
|
||||
#endif
|
||||
|
||||
DenseSparseMatrix(int num_rows, int num_cols);
|
||||
DenseSparseMatrix(int num_rows, int num_cols, bool reserve_diagonal);
|
||||
@@ -67,9 +63,6 @@ class DenseSparseMatrix : public SparseMatrix {
|
||||
virtual void SquaredColumnNorm(double* x) const;
|
||||
virtual void ScaleColumns(const double* scale);
|
||||
virtual void ToDenseMatrix(Matrix* dense_matrix) const;
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
virtual void ToProto(SparseMatrixProto* proto) const;
|
||||
#endif
|
||||
virtual void ToTextFile(FILE* file) const;
|
||||
virtual int num_rows() const;
|
||||
virtual int num_cols() const;
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
|
||||
#include "ceres/casts.h"
|
||||
#include "ceres/linear_least_squares_problems.h"
|
||||
#include "ceres/matrix_proto.h"
|
||||
#include "ceres/triplet_sparse_matrix.h"
|
||||
#include "ceres/internal/eigen.h"
|
||||
#include "ceres/internal/scoped_ptr.h"
|
||||
@@ -156,22 +155,6 @@ TEST_F(DenseSparseMatrixTest, Scale) {
|
||||
CompareMatrices(tsm.get(), dsm.get());
|
||||
}
|
||||
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
TEST_F(DenseSparseMatrixTest, Serialization) {
|
||||
SparseMatrixProto proto;
|
||||
dsm->ToProto(&proto);
|
||||
|
||||
DenseSparseMatrix n(proto);
|
||||
ASSERT_EQ(dsm->num_rows(), n.num_rows());
|
||||
ASSERT_EQ(dsm->num_cols(), n.num_cols());
|
||||
ASSERT_EQ(dsm->num_nonzeros(), n.num_nonzeros());
|
||||
|
||||
for (int i = 0; i < n.num_rows() + 1; ++i) {
|
||||
ASSERT_EQ(dsm->values()[i], proto.dense_matrix().values(i));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_F(DenseSparseMatrixTest, ToDenseMatrix) {
|
||||
Matrix tsm_dense;
|
||||
Matrix dsm_dense;
|
||||
@@ -182,54 +165,5 @@ TEST_F(DenseSparseMatrixTest, ToDenseMatrix) {
|
||||
EXPECT_EQ((tsm_dense - dsm_dense).norm(), 0.0);
|
||||
}
|
||||
|
||||
// TODO(keir): Make this work without protocol buffers.
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
TEST_F(DenseSparseMatrixTest, AppendDiagonal) {
|
||||
DenseSparseMatrixProto proto;
|
||||
proto.set_num_rows(3);
|
||||
proto.set_num_cols(3);
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
proto.add_values(i);
|
||||
}
|
||||
SparseMatrixProto outer_proto;
|
||||
*outer_proto.mutable_dense_matrix() = proto;
|
||||
|
||||
DenseSparseMatrix dsm(outer_proto);
|
||||
|
||||
double diagonal[] = { 10, 11, 12 };
|
||||
dsm.AppendDiagonal(diagonal);
|
||||
|
||||
// Verify the diagonal got added.
|
||||
Matrix m = dsm.matrix();
|
||||
|
||||
EXPECT_EQ(6, m.rows());
|
||||
EXPECT_EQ(3, m.cols());
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
EXPECT_EQ(3 * i + j, m(i, j));
|
||||
if (i == j) {
|
||||
EXPECT_EQ(10 + i, m(i + 3, j));
|
||||
} else {
|
||||
EXPECT_EQ(0, m(i + 3, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify the diagonal gets removed.
|
||||
dsm.RemoveDiagonal();
|
||||
|
||||
m = dsm.matrix();
|
||||
|
||||
EXPECT_EQ(3, m.rows());
|
||||
EXPECT_EQ(3, m.cols());
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
EXPECT_EQ(3 * i + j, m(i, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace internal
|
||||
} // namespace ceres
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
#include "ceres/casts.h"
|
||||
#include "ceres/file.h"
|
||||
#include "ceres/internal/scoped_ptr.h"
|
||||
#include "ceres/matrix_proto.h"
|
||||
#include "ceres/stringprintf.h"
|
||||
#include "ceres/triplet_sparse_matrix.h"
|
||||
#include "ceres/types.h"
|
||||
@@ -63,74 +62,6 @@ LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromId(int id) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromFile(
|
||||
const string& filename) {
|
||||
LinearLeastSquaresProblemProto problem_proto;
|
||||
{
|
||||
string serialized_proto;
|
||||
ReadFileToStringOrDie(filename, &serialized_proto);
|
||||
CHECK(problem_proto.ParseFromString(serialized_proto));
|
||||
}
|
||||
|
||||
LinearLeastSquaresProblem* problem = new LinearLeastSquaresProblem;
|
||||
const SparseMatrixProto& A = problem_proto.a();
|
||||
|
||||
if (A.has_block_matrix()) {
|
||||
problem->A.reset(new BlockSparseMatrix(A));
|
||||
} else if (A.has_triplet_matrix()) {
|
||||
problem->A.reset(new TripletSparseMatrix(A));
|
||||
} else {
|
||||
LOG(FATAL) << "Broken.";
|
||||
}
|
||||
|
||||
if (problem_proto.b_size() > 0) {
|
||||
problem->b.reset(new double[problem_proto.b_size()]);
|
||||
for (int i = 0; i < problem_proto.b_size(); ++i) {
|
||||
problem->b[i] = problem_proto.b(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (problem_proto.d_size() > 0) {
|
||||
problem->D.reset(new double[problem_proto.d_size()]);
|
||||
for (int i = 0; i < problem_proto.d_size(); ++i) {
|
||||
problem->D[i] = problem_proto.d(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (problem_proto.d_size() > 0) {
|
||||
if (problem_proto.x_size() > 0) {
|
||||
problem->x_D.reset(new double[problem_proto.x_size()]);
|
||||
for (int i = 0; i < problem_proto.x_size(); ++i) {
|
||||
problem->x_D[i] = problem_proto.x(i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (problem_proto.x_size() > 0) {
|
||||
problem->x.reset(new double[problem_proto.x_size()]);
|
||||
for (int i = 0; i < problem_proto.x_size(); ++i) {
|
||||
problem->x[i] = problem_proto.x(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
problem->num_eliminate_blocks = 0;
|
||||
if (problem_proto.has_num_eliminate_blocks()) {
|
||||
problem->num_eliminate_blocks = problem_proto.num_eliminate_blocks();
|
||||
}
|
||||
|
||||
return problem;
|
||||
}
|
||||
#else
|
||||
LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromFile(
|
||||
const string& filename) {
|
||||
LOG(FATAL)
|
||||
<< "Loading a least squares problem from disk requires "
|
||||
<< "Ceres to be built with Protocol Buffers support.";
|
||||
return NULL;
|
||||
}
|
||||
#endif // CERES_NO_PROTOCOL_BUFFERS
|
||||
|
||||
/*
|
||||
A = [1 2]
|
||||
[3 4]
|
||||
@@ -598,56 +529,6 @@ bool DumpLinearLeastSquaresProblemToConsole(const SparseMatrix* A,
|
||||
return true;
|
||||
};
|
||||
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& filename_base,
|
||||
const SparseMatrix* A,
|
||||
const double* D,
|
||||
const double* b,
|
||||
const double* x,
|
||||
int num_eliminate_blocks) {
|
||||
CHECK_NOTNULL(A);
|
||||
LinearLeastSquaresProblemProto lsqp;
|
||||
A->ToProto(lsqp.mutable_a());
|
||||
|
||||
if (D != NULL) {
|
||||
for (int i = 0; i < A->num_cols(); ++i) {
|
||||
lsqp.add_d(D[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (b != NULL) {
|
||||
for (int i = 0; i < A->num_rows(); ++i) {
|
||||
lsqp.add_b(b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (x != NULL) {
|
||||
for (int i = 0; i < A->num_cols(); ++i) {
|
||||
lsqp.add_x(x[i]);
|
||||
}
|
||||
}
|
||||
|
||||
lsqp.set_num_eliminate_blocks(num_eliminate_blocks);
|
||||
|
||||
const string filename = filename_base + ".bin";
|
||||
LOG(INFO) << "Dumping least squares problem to disk. File: " << filename;
|
||||
WriteStringToFileOrDie(lsqp.SerializeAsString(), filename);
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& filename_base,
|
||||
const SparseMatrix* A,
|
||||
const double* D,
|
||||
const double* b,
|
||||
const double* x,
|
||||
int num_eliminate_blocks) {
|
||||
LOG(ERROR) << "Dumping least squares problems is only "
|
||||
<< "supported when Ceres is compiled with "
|
||||
<< "protocol buffer support.";
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void WriteArrayToFileOrDie(const string& filename,
|
||||
const double* x,
|
||||
const int size) {
|
||||
@@ -732,12 +613,6 @@ bool DumpLinearLeastSquaresProblem(const string& filename_base,
|
||||
case CONSOLE:
|
||||
return DumpLinearLeastSquaresProblemToConsole(A, D, b, x,
|
||||
num_eliminate_blocks);
|
||||
case PROTOBUF:
|
||||
return DumpLinearLeastSquaresProblemToProtocolBuffer(
|
||||
filename_base,
|
||||
A, D, b, x,
|
||||
num_eliminate_blocks);
|
||||
|
||||
case TEXTFILE:
|
||||
return DumpLinearLeastSquaresProblemToTextFile(filename_base,
|
||||
A, D, b, x,
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/ceres-solver/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Author: keir@google.com (Keir Mierle)
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package ceres.internal;
|
||||
|
||||
message BlockProto {
|
||||
// The span of the block.
|
||||
optional int32 size = 1;
|
||||
|
||||
// Position along the row or column (depending on storage orientation).
|
||||
optional int32 position = 2;
|
||||
}
|
||||
|
||||
message CellProto {
|
||||
// Column or row block id as appropriate.
|
||||
optional int32 block_id = 1;
|
||||
|
||||
// Position in the values array the cell is located. Each cell is stored as a
|
||||
// row-major chunk inside the values array.
|
||||
optional int32 position = 2;
|
||||
}
|
||||
|
||||
// A single row or column, depending on the matrix type.
|
||||
message CompressedRowProto {
|
||||
optional BlockProto block = 2;
|
||||
repeated CellProto cells = 1;
|
||||
}
|
||||
|
||||
message BlockStructureProto {
|
||||
repeated BlockProto cols = 1;
|
||||
repeated CompressedRowProto rows = 2;
|
||||
}
|
||||
|
||||
// A block sparse matrix, either in column major or row major format.
|
||||
message BlockSparseMatrixProto {
|
||||
optional int64 num_rows = 2;
|
||||
optional int64 num_cols = 3;
|
||||
optional int64 num_nonzeros = 4;
|
||||
repeated double values = 1 [packed=true];
|
||||
|
||||
optional BlockStructureProto block_structure = 5;
|
||||
}
|
||||
|
||||
message TripletSparseMatrixProto {
|
||||
optional int64 num_rows = 4;
|
||||
optional int64 num_cols = 5;
|
||||
optional int64 num_nonzeros = 6;
|
||||
|
||||
// The data is stored as three arrays. For each i, values(i) is stored at the
|
||||
// location (rows(i), cols(i)). If the there are multiple entries with the
|
||||
// same (rows(i), cols(i)), the values entries corresponding to them are
|
||||
// summed up.
|
||||
repeated int64 rows = 1 [packed=true];
|
||||
repeated int64 cols = 2 [packed=true];
|
||||
repeated double values = 3 [packed=true];
|
||||
}
|
||||
|
||||
message CompressedRowSparseMatrixProto {
|
||||
optional int64 num_rows = 4;
|
||||
optional int64 num_cols = 5;
|
||||
|
||||
repeated int64 rows = 1 [packed=true];
|
||||
repeated int64 cols = 2 [packed=true];
|
||||
repeated double values = 3 [packed=true];
|
||||
}
|
||||
|
||||
message DenseSparseMatrixProto {
|
||||
optional int64 num_rows = 1;
|
||||
optional int64 num_cols = 2;
|
||||
|
||||
// Entries are stored in row-major order.
|
||||
repeated double values = 3 [packed=true];
|
||||
}
|
||||
|
||||
// A sparse matrix. It is a union; only one field is permitted. If new sparse
|
||||
// implementations are added, update this proto accordingly.
|
||||
message SparseMatrixProto {
|
||||
optional TripletSparseMatrixProto triplet_matrix = 1;
|
||||
optional BlockSparseMatrixProto block_matrix = 2;
|
||||
optional CompressedRowSparseMatrixProto compressed_row_matrix = 3;
|
||||
optional DenseSparseMatrixProto dense_matrix = 4;
|
||||
}
|
||||
|
||||
// A linear least squares problem.
|
||||
//
|
||||
// Given a matrix A, an optional diagonal matrix D as a vector, and a vector b,
|
||||
// the proto represents the following linear least squares problem.
|
||||
//
|
||||
// | A | x = | b |
|
||||
// | D | | 0 |
|
||||
//
|
||||
// If D is empty, then the problem is considered to be
|
||||
//
|
||||
// A x = b
|
||||
//
|
||||
// The desired solution for the problem is the vector x that solves the
|
||||
// following optimization problem:
|
||||
//
|
||||
// arg min_x ||Ax - b||^2 + ||Dx||^2
|
||||
//
|
||||
// If x is present, then it is the expected solution to the
|
||||
// problem. The dimensions of A, b, x, and D should be consistent.
|
||||
message LinearLeastSquaresProblemProto {
|
||||
optional SparseMatrixProto a = 1;
|
||||
repeated double b = 2 [packed=true];
|
||||
repeated double d = 3 [packed=true];
|
||||
repeated double x = 4 [packed=true];
|
||||
// If the problem is of SfM type, i.e it has a generalized
|
||||
// bi-partite structure, then num_eliminate_blocks is the number of
|
||||
// column blocks that are to eliminated in the formation of the
|
||||
// Schur complement. For more details see
|
||||
// explicit_schur_complement_solver.h.
|
||||
optional int32 num_eliminate_blocks = 5;
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/ceres-solver/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Author: keir@google.com (Keir Mierle)
|
||||
//
|
||||
// A portability header to make optional protocol buffer support less intrusive.
|
||||
|
||||
#ifndef CERES_INTERNAL_MATRIX_PROTO_H_
|
||||
#define CERES_INTERNAL_MATRIX_PROTO_H_
|
||||
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
#include "ceres/matrix.pb.h"
|
||||
#endif
|
||||
|
||||
#endif // CERES_INTERNAL_MATRIX_PROTO_H_
|
||||
@@ -214,16 +214,5 @@ TEST_F(SchurEliminatorTest, ScalarProblem) {
|
||||
EliminateSolveAndCompare(VectorRef(D.get(), A->num_cols()), false, 1e-14);
|
||||
}
|
||||
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
TEST_F(SchurEliminatorTest, BlockProblem) {
|
||||
const string input_file = TestFileAbsolutePath("problem-6-1384-000.lsqp");
|
||||
|
||||
SetUpFromFilename(input_file);
|
||||
ComputeReferenceSolution(VectorRef(D.get(), A->num_cols()));
|
||||
EliminateSolveAndCompare(VectorRef(D.get(), A->num_cols()), true, 1e-10);
|
||||
EliminateSolveAndCompare(VectorRef(D.get(), A->num_cols()), false, 1e-10);
|
||||
}
|
||||
#endif // CERES_NO_PROTOCOL_BUFFERS
|
||||
|
||||
} // namespace internal
|
||||
} // namespace ceres
|
||||
|
||||
@@ -41,8 +41,6 @@
|
||||
namespace ceres {
|
||||
namespace internal {
|
||||
|
||||
class SparseMatrixProto;
|
||||
|
||||
// This class defines the interface for storing and manipulating
|
||||
// sparse matrices. The key property that differentiates different
|
||||
// sparse matrices is how they are organized in memory and how the
|
||||
@@ -86,11 +84,6 @@ class SparseMatrix : public LinearOperator {
|
||||
// sparse matrix.
|
||||
virtual void ToDenseMatrix(Matrix* dense_matrix) const = 0;
|
||||
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
// Dump the sparse matrix to a proto. Destroys the contents of proto.
|
||||
virtual void ToProto(SparseMatrixProto* proto) const = 0;
|
||||
#endif
|
||||
|
||||
// Write out the matrix as a sequence of (i,j,s) triplets. This
|
||||
// format is useful for loading the matrix into MATLAB/octave as a
|
||||
// sparse matrix.
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
#include "ceres/internal/eigen.h"
|
||||
#include "ceres/internal/port.h"
|
||||
#include "ceres/internal/scoped_ptr.h"
|
||||
#include "ceres/matrix_proto.h"
|
||||
#include "ceres/types.h"
|
||||
#include "glog/logging.h"
|
||||
|
||||
@@ -83,32 +82,6 @@ TripletSparseMatrix::TripletSparseMatrix(const TripletSparseMatrix& orig)
|
||||
CopyData(orig);
|
||||
}
|
||||
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
TripletSparseMatrix::TripletSparseMatrix(const SparseMatrixProto& outer_proto) {
|
||||
CHECK(outer_proto.has_triplet_matrix());
|
||||
|
||||
const TripletSparseMatrixProto& proto = outer_proto.triplet_matrix();
|
||||
CHECK(proto.has_num_rows());
|
||||
CHECK(proto.has_num_cols());
|
||||
CHECK_EQ(proto.rows_size(), proto.cols_size());
|
||||
CHECK_EQ(proto.cols_size(), proto.values_size());
|
||||
|
||||
// Initialize the matrix with the appropriate size and capacity.
|
||||
max_num_nonzeros_ = 0;
|
||||
set_num_nonzeros(0);
|
||||
Reserve(proto.num_nonzeros());
|
||||
Resize(proto.num_rows(), proto.num_cols());
|
||||
set_num_nonzeros(proto.num_nonzeros());
|
||||
|
||||
// Copy the entries in.
|
||||
for (int i = 0; i < proto.num_nonzeros(); ++i) {
|
||||
rows_[i] = proto.rows(i);
|
||||
cols_[i] = proto.cols(i);
|
||||
values_[i] = proto.values(i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TripletSparseMatrix& TripletSparseMatrix::operator=(
|
||||
const TripletSparseMatrix& rhs) {
|
||||
num_rows_ = rhs.num_rows_;
|
||||
@@ -215,22 +188,6 @@ void TripletSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const {
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
void TripletSparseMatrix::ToProto(SparseMatrixProto *proto) const {
|
||||
proto->Clear();
|
||||
|
||||
TripletSparseMatrixProto* tsm_proto = proto->mutable_triplet_matrix();
|
||||
tsm_proto->set_num_rows(num_rows_);
|
||||
tsm_proto->set_num_cols(num_cols_);
|
||||
tsm_proto->set_num_nonzeros(num_nonzeros_);
|
||||
for (int i = 0; i < num_nonzeros_; ++i) {
|
||||
tsm_proto->add_rows(rows_[i]);
|
||||
tsm_proto->add_cols(cols_[i]);
|
||||
tsm_proto->add_values(values_[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void TripletSparseMatrix::AppendRows(const TripletSparseMatrix& B) {
|
||||
CHECK_EQ(B.num_cols(), num_cols_);
|
||||
Reserve(num_nonzeros_ + B.num_nonzeros_);
|
||||
|
||||
@@ -39,8 +39,6 @@
|
||||
namespace ceres {
|
||||
namespace internal {
|
||||
|
||||
class SparseMatrixProto;
|
||||
|
||||
// An implementation of the SparseMatrix interface to store and
|
||||
// manipulate sparse matrices in triplet (i,j,s) form. This object is
|
||||
// inspired by the design of the cholmod_triplet struct used in the
|
||||
@@ -50,9 +48,6 @@ class TripletSparseMatrix : public SparseMatrix {
|
||||
TripletSparseMatrix();
|
||||
TripletSparseMatrix(int num_rows, int num_cols, int max_num_nonzeros);
|
||||
explicit TripletSparseMatrix(const TripletSparseMatrix& orig);
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
explicit TripletSparseMatrix(const SparseMatrixProto& proto);
|
||||
#endif
|
||||
|
||||
TripletSparseMatrix& operator=(const TripletSparseMatrix& rhs);
|
||||
|
||||
@@ -65,9 +60,6 @@ class TripletSparseMatrix : public SparseMatrix {
|
||||
virtual void SquaredColumnNorm(double* x) const;
|
||||
virtual void ScaleColumns(const double* scale);
|
||||
virtual void ToDenseMatrix(Matrix* dense_matrix) const;
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
virtual void ToProto(SparseMatrixProto *proto) const;
|
||||
#endif
|
||||
virtual void ToTextFile(FILE* file) const;
|
||||
virtual int num_rows() const { return num_rows_; }
|
||||
virtual int num_cols() const { return num_cols_; }
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include "ceres/triplet_sparse_matrix.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "ceres/matrix_proto.h"
|
||||
#include "ceres/internal/scoped_ptr.h"
|
||||
|
||||
namespace ceres {
|
||||
@@ -316,39 +315,5 @@ TEST(TripletSparseMatrix, Resize) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
TEST(TripletSparseMatrix, Serialization) {
|
||||
TripletSparseMatrix m(2, 5, 4);
|
||||
|
||||
m.mutable_rows()[0] = 0;
|
||||
m.mutable_cols()[0] = 1;
|
||||
m.mutable_values()[0] = 2.5;
|
||||
|
||||
m.mutable_rows()[1] = 1;
|
||||
m.mutable_cols()[1] = 4;
|
||||
m.mutable_values()[1] = 5.2;
|
||||
m.set_num_nonzeros(2);
|
||||
|
||||
// Roundtrip through serialization and check for equality.
|
||||
SparseMatrixProto proto;
|
||||
m.ToProto(&proto);
|
||||
|
||||
TripletSparseMatrix n(proto);
|
||||
|
||||
ASSERT_EQ(n.num_rows(), 2);
|
||||
ASSERT_EQ(n.num_cols(), 5);
|
||||
|
||||
// Note that max_num_nonzeros gets truncated; the serialization
|
||||
ASSERT_EQ(n.num_nonzeros(), 2);
|
||||
ASSERT_EQ(n.max_num_nonzeros(), 2);
|
||||
|
||||
for (int i = 0; i < m.num_nonzeros(); ++i) {
|
||||
EXPECT_EQ(m.rows()[i], n.rows()[i]);
|
||||
EXPECT_EQ(m.cols()[i], n.cols()[i]);
|
||||
EXPECT_EQ(m.values()[i], n.values()[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace internal
|
||||
} // namespace ceres
|
||||
|
||||
@@ -52,292 +52,293 @@
|
||||
namespace ceres {
|
||||
namespace internal {
|
||||
|
||||
using testing::AssertionResult;
|
||||
using testing::AssertionSuccess;
|
||||
using testing::AssertionFailure;
|
||||
// TODO(sameeragarwal): Re-enable this test once serialization is
|
||||
// working again.
|
||||
|
||||
static const double kTolerance = 1e-12;
|
||||
// using testing::AssertionResult;
|
||||
// using testing::AssertionSuccess;
|
||||
// using testing::AssertionFailure;
|
||||
|
||||
class VisibilityBasedPreconditionerTest : public ::testing::Test {
|
||||
public:
|
||||
static const int kCameraSize = 9;
|
||||
// static const double kTolerance = 1e-12;
|
||||
|
||||
protected:
|
||||
void SetUp() {
|
||||
string input_file = TestFileAbsolutePath("problem-6-1384-000.lsqp");
|
||||
// class VisibilityBasedPreconditionerTest : public ::testing::Test {
|
||||
// public:
|
||||
// static const int kCameraSize = 9;
|
||||
|
||||
scoped_ptr<LinearLeastSquaresProblem> problem(
|
||||
CHECK_NOTNULL(CreateLinearLeastSquaresProblemFromFile(input_file)));
|
||||
A_.reset(down_cast<BlockSparseMatrix*>(problem->A.release()));
|
||||
b_.reset(problem->b.release());
|
||||
D_.reset(problem->D.release());
|
||||
// protected:
|
||||
// void SetUp() {
|
||||
// string input_file = TestFileAbsolutePath("problem-6-1384-000.lsqp");
|
||||
|
||||
const CompressedRowBlockStructure* bs =
|
||||
CHECK_NOTNULL(A_->block_structure());
|
||||
const int num_col_blocks = bs->cols.size();
|
||||
// scoped_ptr<LinearLeastSquaresProblem> problem(
|
||||
// CHECK_NOTNULL(CreateLinearLeastSquaresProblemFromFile(input_file)));
|
||||
// A_.reset(down_cast<BlockSparseMatrix*>(problem->A.release()));
|
||||
// b_.reset(problem->b.release());
|
||||
// D_.reset(problem->D.release());
|
||||
|
||||
num_cols_ = A_->num_cols();
|
||||
num_rows_ = A_->num_rows();
|
||||
num_eliminate_blocks_ = problem->num_eliminate_blocks;
|
||||
num_camera_blocks_ = num_col_blocks - num_eliminate_blocks_;
|
||||
options_.elimination_groups.push_back(num_eliminate_blocks_);
|
||||
options_.elimination_groups.push_back(
|
||||
A_->block_structure()->cols.size() - num_eliminate_blocks_);
|
||||
// const CompressedRowBlockStructure* bs =
|
||||
// CHECK_NOTNULL(A_->block_structure());
|
||||
// const int num_col_blocks = bs->cols.size();
|
||||
|
||||
vector<int> blocks(num_col_blocks - num_eliminate_blocks_, 0);
|
||||
for (int i = num_eliminate_blocks_; i < num_col_blocks; ++i) {
|
||||
blocks[i - num_eliminate_blocks_] = bs->cols[i].size;
|
||||
}
|
||||
// num_cols_ = A_->num_cols();
|
||||
// num_rows_ = A_->num_rows();
|
||||
// num_eliminate_blocks_ = problem->num_eliminate_blocks;
|
||||
// num_camera_blocks_ = num_col_blocks - num_eliminate_blocks_;
|
||||
// options_.elimination_groups.push_back(num_eliminate_blocks_);
|
||||
// options_.elimination_groups.push_back(
|
||||
// A_->block_structure()->cols.size() - num_eliminate_blocks_);
|
||||
|
||||
// The input matrix is a real jacobian and fairly poorly
|
||||
// conditioned. Setting D to a large constant makes the normal
|
||||
// equations better conditioned and makes the tests below better
|
||||
// conditioned.
|
||||
VectorRef(D_.get(), num_cols_).setConstant(10.0);
|
||||
// vector<int> blocks(num_col_blocks - num_eliminate_blocks_, 0);
|
||||
// for (int i = num_eliminate_blocks_; i < num_col_blocks; ++i) {
|
||||
// blocks[i - num_eliminate_blocks_] = bs->cols[i].size;
|
||||
// }
|
||||
|
||||
schur_complement_.reset(new BlockRandomAccessDenseMatrix(blocks));
|
||||
Vector rhs(schur_complement_->num_rows());
|
||||
// // The input matrix is a real jacobian and fairly poorly
|
||||
// // conditioned. Setting D to a large constant makes the normal
|
||||
// // equations better conditioned and makes the tests below better
|
||||
// // conditioned.
|
||||
// VectorRef(D_.get(), num_cols_).setConstant(10.0);
|
||||
|
||||
scoped_ptr<SchurEliminatorBase> eliminator;
|
||||
LinearSolver::Options eliminator_options;
|
||||
eliminator_options.elimination_groups = options_.elimination_groups;
|
||||
eliminator_options.num_threads = options_.num_threads;
|
||||
// schur_complement_.reset(new BlockRandomAccessDenseMatrix(blocks));
|
||||
// Vector rhs(schur_complement_->num_rows());
|
||||
|
||||
eliminator.reset(SchurEliminatorBase::Create(eliminator_options));
|
||||
eliminator->Init(num_eliminate_blocks_, bs);
|
||||
eliminator->Eliminate(A_.get(), b_.get(), D_.get(),
|
||||
schur_complement_.get(), rhs.data());
|
||||
}
|
||||
// scoped_ptr<SchurEliminatorBase> eliminator;
|
||||
// LinearSolver::Options eliminator_options;
|
||||
// eliminator_options.elimination_groups = options_.elimination_groups;
|
||||
// eliminator_options.num_threads = options_.num_threads;
|
||||
|
||||
// eliminator.reset(SchurEliminatorBase::Create(eliminator_options));
|
||||
// eliminator->Init(num_eliminate_blocks_, bs);
|
||||
// eliminator->Eliminate(A_.get(), b_.get(), D_.get(),
|
||||
// schur_complement_.get(), rhs.data());
|
||||
// }
|
||||
|
||||
|
||||
AssertionResult IsSparsityStructureValid() {
|
||||
preconditioner_->InitStorage(*A_->block_structure());
|
||||
const HashSet<pair<int, int> >& cluster_pairs = get_cluster_pairs();
|
||||
const vector<int>& cluster_membership = get_cluster_membership();
|
||||
// AssertionResult IsSparsityStructureValid() {
|
||||
// preconditioner_->InitStorage(*A_->block_structure());
|
||||
// const HashSet<pair<int, int> >& cluster_pairs = get_cluster_pairs();
|
||||
// const vector<int>& cluster_membership = get_cluster_membership();
|
||||
|
||||
for (int i = 0; i < num_camera_blocks_; ++i) {
|
||||
for (int j = i; j < num_camera_blocks_; ++j) {
|
||||
if (cluster_pairs.count(make_pair(cluster_membership[i],
|
||||
cluster_membership[j]))) {
|
||||
if (!IsBlockPairInPreconditioner(i, j)) {
|
||||
return AssertionFailure()
|
||||
<< "block pair (" << i << "," << j << "missing";
|
||||
}
|
||||
} else {
|
||||
if (IsBlockPairInPreconditioner(i, j)) {
|
||||
return AssertionFailure()
|
||||
<< "block pair (" << i << "," << j << "should not be present";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return AssertionSuccess();
|
||||
}
|
||||
// for (int i = 0; i < num_camera_blocks_; ++i) {
|
||||
// for (int j = i; j < num_camera_blocks_; ++j) {
|
||||
// if (cluster_pairs.count(make_pair(cluster_membership[i],
|
||||
// cluster_membership[j]))) {
|
||||
// if (!IsBlockPairInPreconditioner(i, j)) {
|
||||
// return AssertionFailure()
|
||||
// << "block pair (" << i << "," << j << "missing";
|
||||
// }
|
||||
// } else {
|
||||
// if (IsBlockPairInPreconditioner(i, j)) {
|
||||
// return AssertionFailure()
|
||||
// << "block pair (" << i << "," << j << "should not be present";
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return AssertionSuccess();
|
||||
// }
|
||||
|
||||
AssertionResult PreconditionerValuesMatch() {
|
||||
preconditioner_->Update(*A_, D_.get());
|
||||
const HashSet<pair<int, int> >& cluster_pairs = get_cluster_pairs();
|
||||
const BlockRandomAccessSparseMatrix* m = get_m();
|
||||
Matrix preconditioner_matrix;
|
||||
m->matrix()->ToDenseMatrix(&preconditioner_matrix);
|
||||
ConstMatrixRef full_schur_complement(schur_complement_->values(),
|
||||
m->num_rows(),
|
||||
m->num_rows());
|
||||
const int num_clusters = get_num_clusters();
|
||||
const int kDiagonalBlockSize =
|
||||
kCameraSize * num_camera_blocks_ / num_clusters;
|
||||
// AssertionResult PreconditionerValuesMatch() {
|
||||
// preconditioner_->Update(*A_, D_.get());
|
||||
// const HashSet<pair<int, int> >& cluster_pairs = get_cluster_pairs();
|
||||
// const BlockRandomAccessSparseMatrix* m = get_m();
|
||||
// Matrix preconditioner_matrix;
|
||||
// m->matrix()->ToDenseMatrix(&preconditioner_matrix);
|
||||
// ConstMatrixRef full_schur_complement(schur_complement_->values(),
|
||||
// m->num_rows(),
|
||||
// m->num_rows());
|
||||
// const int num_clusters = get_num_clusters();
|
||||
// const int kDiagonalBlockSize =
|
||||
// kCameraSize * num_camera_blocks_ / num_clusters;
|
||||
|
||||
for (int i = 0; i < num_clusters; ++i) {
|
||||
for (int j = i; j < num_clusters; ++j) {
|
||||
double diff = 0.0;
|
||||
if (cluster_pairs.count(make_pair(i, j))) {
|
||||
diff =
|
||||
(preconditioner_matrix.block(kDiagonalBlockSize * i,
|
||||
kDiagonalBlockSize * j,
|
||||
kDiagonalBlockSize,
|
||||
kDiagonalBlockSize) -
|
||||
full_schur_complement.block(kDiagonalBlockSize * i,
|
||||
kDiagonalBlockSize * j,
|
||||
kDiagonalBlockSize,
|
||||
kDiagonalBlockSize)).norm();
|
||||
} else {
|
||||
diff = preconditioner_matrix.block(kDiagonalBlockSize * i,
|
||||
kDiagonalBlockSize * j,
|
||||
kDiagonalBlockSize,
|
||||
kDiagonalBlockSize).norm();
|
||||
}
|
||||
if (diff > kTolerance) {
|
||||
return AssertionFailure()
|
||||
<< "Preconditioner block " << i << " " << j << " differs "
|
||||
<< "from expected value by " << diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
return AssertionSuccess();
|
||||
}
|
||||
// for (int i = 0; i < num_clusters; ++i) {
|
||||
// for (int j = i; j < num_clusters; ++j) {
|
||||
// double diff = 0.0;
|
||||
// if (cluster_pairs.count(make_pair(i, j))) {
|
||||
// diff =
|
||||
// (preconditioner_matrix.block(kDiagonalBlockSize * i,
|
||||
// kDiagonalBlockSize * j,
|
||||
// kDiagonalBlockSize,
|
||||
// kDiagonalBlockSize) -
|
||||
// full_schur_complement.block(kDiagonalBlockSize * i,
|
||||
// kDiagonalBlockSize * j,
|
||||
// kDiagonalBlockSize,
|
||||
// kDiagonalBlockSize)).norm();
|
||||
// } else {
|
||||
// diff = preconditioner_matrix.block(kDiagonalBlockSize * i,
|
||||
// kDiagonalBlockSize * j,
|
||||
// kDiagonalBlockSize,
|
||||
// kDiagonalBlockSize).norm();
|
||||
// }
|
||||
// if (diff > kTolerance) {
|
||||
// return AssertionFailure()
|
||||
// << "Preconditioner block " << i << " " << j << " differs "
|
||||
// << "from expected value by " << diff;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return AssertionSuccess();
|
||||
// }
|
||||
|
||||
// Accessors
|
||||
int get_num_blocks() { return preconditioner_->num_blocks_; }
|
||||
// // Accessors
|
||||
// int get_num_blocks() { return preconditioner_->num_blocks_; }
|
||||
|
||||
int get_num_clusters() { return preconditioner_->num_clusters_; }
|
||||
int* get_mutable_num_clusters() { return &preconditioner_->num_clusters_; }
|
||||
// int get_num_clusters() { return preconditioner_->num_clusters_; }
|
||||
// int* get_mutable_num_clusters() { return &preconditioner_->num_clusters_; }
|
||||
|
||||
const vector<int>& get_block_size() {
|
||||
return preconditioner_->block_size_; }
|
||||
// const vector<int>& get_block_size() {
|
||||
// return preconditioner_->block_size_; }
|
||||
|
||||
vector<int>* get_mutable_block_size() {
|
||||
return &preconditioner_->block_size_; }
|
||||
// vector<int>* get_mutable_block_size() {
|
||||
// return &preconditioner_->block_size_; }
|
||||
|
||||
const vector<int>& get_cluster_membership() {
|
||||
return preconditioner_->cluster_membership_;
|
||||
}
|
||||
// const vector<int>& get_cluster_membership() {
|
||||
// return preconditioner_->cluster_membership_;
|
||||
// }
|
||||
|
||||
vector<int>* get_mutable_cluster_membership() {
|
||||
return &preconditioner_->cluster_membership_;
|
||||
}
|
||||
// vector<int>* get_mutable_cluster_membership() {
|
||||
// return &preconditioner_->cluster_membership_;
|
||||
// }
|
||||
|
||||
const set<pair<int, int> >& get_block_pairs() {
|
||||
return preconditioner_->block_pairs_;
|
||||
}
|
||||
// const set<pair<int, int> >& get_block_pairs() {
|
||||
// return preconditioner_->block_pairs_;
|
||||
// }
|
||||
|
||||
set<pair<int, int> >* get_mutable_block_pairs() {
|
||||
return &preconditioner_->block_pairs_;
|
||||
}
|
||||
// set<pair<int, int> >* get_mutable_block_pairs() {
|
||||
// return &preconditioner_->block_pairs_;
|
||||
// }
|
||||
|
||||
const HashSet<pair<int, int> >& get_cluster_pairs() {
|
||||
return preconditioner_->cluster_pairs_;
|
||||
}
|
||||
// const HashSet<pair<int, int> >& get_cluster_pairs() {
|
||||
// return preconditioner_->cluster_pairs_;
|
||||
// }
|
||||
|
||||
HashSet<pair<int, int> >* get_mutable_cluster_pairs() {
|
||||
return &preconditioner_->cluster_pairs_;
|
||||
}
|
||||
// HashSet<pair<int, int> >* get_mutable_cluster_pairs() {
|
||||
// return &preconditioner_->cluster_pairs_;
|
||||
// }
|
||||
|
||||
bool IsBlockPairInPreconditioner(const int block1, const int block2) {
|
||||
return preconditioner_->IsBlockPairInPreconditioner(block1, block2);
|
||||
}
|
||||
// bool IsBlockPairInPreconditioner(const int block1, const int block2) {
|
||||
// return preconditioner_->IsBlockPairInPreconditioner(block1, block2);
|
||||
// }
|
||||
|
||||
bool IsBlockPairOffDiagonal(const int block1, const int block2) {
|
||||
return preconditioner_->IsBlockPairOffDiagonal(block1, block2);
|
||||
}
|
||||
// bool IsBlockPairOffDiagonal(const int block1, const int block2) {
|
||||
// return preconditioner_->IsBlockPairOffDiagonal(block1, block2);
|
||||
// }
|
||||
|
||||
const BlockRandomAccessSparseMatrix* get_m() {
|
||||
return preconditioner_->m_.get();
|
||||
}
|
||||
// const BlockRandomAccessSparseMatrix* get_m() {
|
||||
// return preconditioner_->m_.get();
|
||||
// }
|
||||
|
||||
int num_rows_;
|
||||
int num_cols_;
|
||||
int num_eliminate_blocks_;
|
||||
int num_camera_blocks_;
|
||||
// int num_rows_;
|
||||
// int num_cols_;
|
||||
// int num_eliminate_blocks_;
|
||||
// int num_camera_blocks_;
|
||||
|
||||
scoped_ptr<BlockSparseMatrix> A_;
|
||||
scoped_array<double> b_;
|
||||
scoped_array<double> D_;
|
||||
// scoped_ptr<BlockSparseMatrix> A_;
|
||||
// scoped_array<double> b_;
|
||||
// scoped_array<double> D_;
|
||||
|
||||
Preconditioner::Options options_;
|
||||
scoped_ptr<VisibilityBasedPreconditioner> preconditioner_;
|
||||
scoped_ptr<BlockRandomAccessDenseMatrix> schur_complement_;
|
||||
};
|
||||
// Preconditioner::Options options_;
|
||||
// scoped_ptr<VisibilityBasedPreconditioner> preconditioner_;
|
||||
// scoped_ptr<BlockRandomAccessDenseMatrix> schur_complement_;
|
||||
// };
|
||||
|
||||
#ifndef CERES_NO_PROTOCOL_BUFFERS
|
||||
TEST_F(VisibilityBasedPreconditionerTest, OneClusterClusterJacobi) {
|
||||
options_.type = CLUSTER_JACOBI;
|
||||
preconditioner_.reset(
|
||||
new VisibilityBasedPreconditioner(*A_->block_structure(), options_));
|
||||
// TEST_F(VisibilityBasedPreconditionerTest, OneClusterClusterJacobi) {
|
||||
// options_.type = CLUSTER_JACOBI;
|
||||
// preconditioner_.reset(
|
||||
// new VisibilityBasedPreconditioner(*A_->block_structure(), options_));
|
||||
|
||||
// Override the clustering to be a single clustering containing all
|
||||
// the cameras.
|
||||
vector<int>& cluster_membership = *get_mutable_cluster_membership();
|
||||
for (int i = 0; i < num_camera_blocks_; ++i) {
|
||||
cluster_membership[i] = 0;
|
||||
}
|
||||
// // Override the clustering to be a single clustering containing all
|
||||
// // the cameras.
|
||||
// vector<int>& cluster_membership = *get_mutable_cluster_membership();
|
||||
// for (int i = 0; i < num_camera_blocks_; ++i) {
|
||||
// cluster_membership[i] = 0;
|
||||
// }
|
||||
|
||||
*get_mutable_num_clusters() = 1;
|
||||
// *get_mutable_num_clusters() = 1;
|
||||
|
||||
HashSet<pair<int, int> >& cluster_pairs = *get_mutable_cluster_pairs();
|
||||
cluster_pairs.clear();
|
||||
cluster_pairs.insert(make_pair(0, 0));
|
||||
// HashSet<pair<int, int> >& cluster_pairs = *get_mutable_cluster_pairs();
|
||||
// cluster_pairs.clear();
|
||||
// cluster_pairs.insert(make_pair(0, 0));
|
||||
|
||||
EXPECT_TRUE(IsSparsityStructureValid());
|
||||
EXPECT_TRUE(PreconditionerValuesMatch());
|
||||
// EXPECT_TRUE(IsSparsityStructureValid());
|
||||
// EXPECT_TRUE(PreconditionerValuesMatch());
|
||||
|
||||
// Multiplication by the inverse of the preconditioner.
|
||||
const int num_rows = schur_complement_->num_rows();
|
||||
ConstMatrixRef full_schur_complement(schur_complement_->values(),
|
||||
num_rows,
|
||||
num_rows);
|
||||
Vector x(num_rows);
|
||||
Vector y(num_rows);
|
||||
Vector z(num_rows);
|
||||
// // Multiplication by the inverse of the preconditioner.
|
||||
// const int num_rows = schur_complement_->num_rows();
|
||||
// ConstMatrixRef full_schur_complement(schur_complement_->values(),
|
||||
// num_rows,
|
||||
// num_rows);
|
||||
// Vector x(num_rows);
|
||||
// Vector y(num_rows);
|
||||
// Vector z(num_rows);
|
||||
|
||||
for (int i = 0; i < num_rows; ++i) {
|
||||
x.setZero();
|
||||
y.setZero();
|
||||
z.setZero();
|
||||
x[i] = 1.0;
|
||||
preconditioner_->RightMultiply(x.data(), y.data());
|
||||
z = full_schur_complement
|
||||
.selfadjointView<Eigen::Upper>()
|
||||
.ldlt().solve(x);
|
||||
double max_relative_difference =
|
||||
((y - z).array() / z.array()).matrix().lpNorm<Eigen::Infinity>();
|
||||
EXPECT_NEAR(max_relative_difference, 0.0, kTolerance);
|
||||
}
|
||||
}
|
||||
// for (int i = 0; i < num_rows; ++i) {
|
||||
// x.setZero();
|
||||
// y.setZero();
|
||||
// z.setZero();
|
||||
// x[i] = 1.0;
|
||||
// preconditioner_->RightMultiply(x.data(), y.data());
|
||||
// z = full_schur_complement
|
||||
// .selfadjointView<Eigen::Upper>()
|
||||
// .ldlt().solve(x);
|
||||
// double max_relative_difference =
|
||||
// ((y - z).array() / z.array()).matrix().lpNorm<Eigen::Infinity>();
|
||||
// EXPECT_NEAR(max_relative_difference, 0.0, kTolerance);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
TEST_F(VisibilityBasedPreconditionerTest, ClusterJacobi) {
|
||||
options_.type = CLUSTER_JACOBI;
|
||||
preconditioner_.reset(
|
||||
new VisibilityBasedPreconditioner(*A_->block_structure(), options_));
|
||||
// TEST_F(VisibilityBasedPreconditionerTest, ClusterJacobi) {
|
||||
// options_.type = CLUSTER_JACOBI;
|
||||
// preconditioner_.reset(
|
||||
// new VisibilityBasedPreconditioner(*A_->block_structure(), options_));
|
||||
|
||||
// Override the clustering to be equal number of cameras.
|
||||
vector<int>& cluster_membership = *get_mutable_cluster_membership();
|
||||
cluster_membership.resize(num_camera_blocks_);
|
||||
static const int kNumClusters = 3;
|
||||
// // Override the clustering to be equal number of cameras.
|
||||
// vector<int>& cluster_membership = *get_mutable_cluster_membership();
|
||||
// cluster_membership.resize(num_camera_blocks_);
|
||||
// static const int kNumClusters = 3;
|
||||
|
||||
for (int i = 0; i < num_camera_blocks_; ++i) {
|
||||
cluster_membership[i] = (i * kNumClusters) / num_camera_blocks_;
|
||||
}
|
||||
*get_mutable_num_clusters() = kNumClusters;
|
||||
// for (int i = 0; i < num_camera_blocks_; ++i) {
|
||||
// cluster_membership[i] = (i * kNumClusters) / num_camera_blocks_;
|
||||
// }
|
||||
// *get_mutable_num_clusters() = kNumClusters;
|
||||
|
||||
HashSet<pair<int, int> >& cluster_pairs = *get_mutable_cluster_pairs();
|
||||
cluster_pairs.clear();
|
||||
for (int i = 0; i < kNumClusters; ++i) {
|
||||
cluster_pairs.insert(make_pair(i, i));
|
||||
}
|
||||
// HashSet<pair<int, int> >& cluster_pairs = *get_mutable_cluster_pairs();
|
||||
// cluster_pairs.clear();
|
||||
// for (int i = 0; i < kNumClusters; ++i) {
|
||||
// cluster_pairs.insert(make_pair(i, i));
|
||||
// }
|
||||
|
||||
EXPECT_TRUE(IsSparsityStructureValid());
|
||||
EXPECT_TRUE(PreconditionerValuesMatch());
|
||||
}
|
||||
// EXPECT_TRUE(IsSparsityStructureValid());
|
||||
// EXPECT_TRUE(PreconditionerValuesMatch());
|
||||
// }
|
||||
|
||||
|
||||
TEST_F(VisibilityBasedPreconditionerTest, ClusterTridiagonal) {
|
||||
options_.type = CLUSTER_TRIDIAGONAL;
|
||||
preconditioner_.reset(
|
||||
new VisibilityBasedPreconditioner(*A_->block_structure(), options_));
|
||||
static const int kNumClusters = 3;
|
||||
// TEST_F(VisibilityBasedPreconditionerTest, ClusterTridiagonal) {
|
||||
// options_.type = CLUSTER_TRIDIAGONAL;
|
||||
// preconditioner_.reset(
|
||||
// new VisibilityBasedPreconditioner(*A_->block_structure(), options_));
|
||||
// static const int kNumClusters = 3;
|
||||
|
||||
// Override the clustering to be 3 clusters.
|
||||
vector<int>& cluster_membership = *get_mutable_cluster_membership();
|
||||
cluster_membership.resize(num_camera_blocks_);
|
||||
for (int i = 0; i < num_camera_blocks_; ++i) {
|
||||
cluster_membership[i] = (i * kNumClusters) / num_camera_blocks_;
|
||||
}
|
||||
*get_mutable_num_clusters() = kNumClusters;
|
||||
// // Override the clustering to be 3 clusters.
|
||||
// vector<int>& cluster_membership = *get_mutable_cluster_membership();
|
||||
// cluster_membership.resize(num_camera_blocks_);
|
||||
// for (int i = 0; i < num_camera_blocks_; ++i) {
|
||||
// cluster_membership[i] = (i * kNumClusters) / num_camera_blocks_;
|
||||
// }
|
||||
// *get_mutable_num_clusters() = kNumClusters;
|
||||
|
||||
// Spanning forest has structure 0-1 2
|
||||
HashSet<pair<int, int> >& cluster_pairs = *get_mutable_cluster_pairs();
|
||||
cluster_pairs.clear();
|
||||
for (int i = 0; i < kNumClusters; ++i) {
|
||||
cluster_pairs.insert(make_pair(i, i));
|
||||
}
|
||||
cluster_pairs.insert(make_pair(0, 1));
|
||||
// // Spanning forest has structure 0-1 2
|
||||
// HashSet<pair<int, int> >& cluster_pairs = *get_mutable_cluster_pairs();
|
||||
// cluster_pairs.clear();
|
||||
// for (int i = 0; i < kNumClusters; ++i) {
|
||||
// cluster_pairs.insert(make_pair(i, i));
|
||||
// }
|
||||
// cluster_pairs.insert(make_pair(0, 1));
|
||||
|
||||
EXPECT_TRUE(IsSparsityStructureValid());
|
||||
EXPECT_TRUE(PreconditionerValuesMatch());
|
||||
}
|
||||
#endif // CERES_NO_PROTOCOL_BUFFERS
|
||||
// EXPECT_TRUE(IsSparsityStructureValid());
|
||||
// EXPECT_TRUE(PreconditionerValuesMatch());
|
||||
// }
|
||||
|
||||
} // namespace internal
|
||||
} // namespace ceres
|
||||
|
||||
@@ -99,7 +99,6 @@ LOCAL_C_INCLUDES += $(EIGEN_PATH)
|
||||
|
||||
LOCAL_CPP_EXTENSION := .cc
|
||||
LOCAL_CFLAGS := $(CERES_EXTRA_DEFINES) \
|
||||
-DCERES_NO_PROTOCOL_BUFFERS \
|
||||
-DCERES_NO_SUITESPARSE \
|
||||
-DCERES_NO_GFLAGS \
|
||||
-DCERES_NO_THREADS \
|
||||
|
||||
Reference in New Issue
Block a user