Remove Protocol Buffers support.

Change-Id: I451c543c82cdfb566736aab94d836abcfb5c689d
This commit is contained in:
Sameer Agarwal
2013-06-24 13:51:58 -07:00
parent 5d00bf40f5
commit 79d9353036
25 changed files with 237 additions and 944 deletions
-17
View File
@@ -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)
+1 -2
View File
@@ -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.
-14
View File
@@ -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
-9
View File
@@ -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
-7
View File
@@ -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
-10
View File
@@ -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})
-41
View File
@@ -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) {
-9
View File
@@ -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
-51
View File
@@ -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);
-33
View File
@@ -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_) {
-7
View File
@@ -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,
-143
View File
@@ -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;
}
-40
View File
@@ -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_
-11
View File
@@ -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
-7
View File
@@ -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.
-43
View File
@@ -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_);
-8
View File
@@ -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
-1
View File
@@ -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 \