LinearSolver::Options::num_eliminate_blocks is dead.

Replaced with LinearSolver::Options::elimination_groups.

Change-Id: I7c07542ec19279a35ddf6da498d417a79395c77f
This commit is contained in:
Sameer Agarwal
2012-09-17 11:30:14 -07:00
parent 91c9bfee33
commit 0c52f1e29b
11 changed files with 59 additions and 35 deletions
@@ -83,7 +83,7 @@ class ImplicitSchurComplementTest : public ::testing::Test {
const int num_schur_rows = blhs.num_rows();
LinearSolver::Options options;
options.num_eliminate_blocks = num_eliminate_blocks_;
options.elimination_groups.push_back(num_eliminate_blocks_);
options.type = DENSE_SCHUR;
scoped_ptr<SchurEliminatorBase> eliminator(
@@ -67,7 +67,7 @@ LinearSolver::Summary IterativeSchurComplementSolver::SolveImpl(
// Initialize a ImplicitSchurComplement object.
if (schur_complement_ == NULL) {
schur_complement_.reset(
new ImplicitSchurComplement(options_.num_eliminate_blocks,
new ImplicitSchurComplement(options_.elimination_groups[0],
options_.preconditioner_type == JACOBI));
}
schur_complement_->Init(*A, per_solve_options.D, b);
@@ -89,7 +89,7 @@ class IterativeSchurComplementSolverTest : public ::testing::Test {
Vector reference_solution(num_cols_);
qr->Solve(&dense_A, b_.get(), per_solve_options, reference_solution.data());
options.num_eliminate_blocks = num_eliminate_blocks_;
options.elimination_groups.push_back(num_eliminate_blocks_);
options.max_num_iterations = num_cols_;
IterativeSchurComplementSolver isc(options);
+18 -10
View File
@@ -35,6 +35,7 @@
#define CERES_INTERNAL_LINEAR_SOLVER_H_
#include <cstddef>
#include <vector>
#include <glog/logging.h>
#include "ceres/block_sparse_matrix.h"
@@ -76,7 +77,6 @@ class LinearSolver {
min_num_iterations(1),
max_num_iterations(1),
num_threads(1),
num_eliminate_blocks(0),
residual_reset_period(10),
row_block_size(Dynamic),
e_block_size(Dynamic),
@@ -100,15 +100,23 @@ class LinearSolver {
// If possible, how many threads can the solver use.
int num_threads;
// Eliminate 0 to num_eliminate_blocks - 1 from the Normal
// equations to form a schur complement. Only used by the Schur
// complement based solver. The most common use for this parameter
// is in the case of structure from motion problems where we have
// camera blocks and point blocks. Then setting the
// num_eliminate_blocks to the number of points allows the solver
// to use the Schur complement trick. For more details see the
// description of this parameter in solver.h.
int num_eliminate_blocks;
// Hints about the order in which the parameter blocks should be
// eliminated by the linear solver.
//
// For example if elimination_groups is a vector of size k, then
// the linear solver is informed that it should eliminate the
// parameter blocks 0 - elimination_groups[0] - 1 first, and then
// elimination_groups[0] - elimination_groups[1] and so on. Within
// each elimination group, the linear solver is free to choose how
// the parameter blocks are ordered. Different linear solvers have
// differing requirements on elimination_groups.
//
// The most common use is for Schur type solvers, where there
// should be at least two elimination groups and the first
// elimination group must form an independent set in the normal
// equations. The first elimination group corresponds to the
// num_eliminate_blocks in the Schur type solvers.
vector<int> elimination_groups;
// Iterative solvers, e.g. Preconditioned Conjugate Gradients
// maintain a cheap estimate of the residual which may become
+4 -4
View File
@@ -66,12 +66,12 @@ LinearSolver::Summary SchurComplementSolver::SolveImpl(
if (eliminator_.get() == NULL) {
InitStorage(A->block_structure());
DetectStructure(*A->block_structure(),
options_.num_eliminate_blocks,
options_.elimination_groups[0],
&options_.row_block_size,
&options_.e_block_size,
&options_.f_block_size);
eliminator_.reset(CHECK_NOTNULL(SchurEliminatorBase::Create(options_)));
eliminator_->Init(options_.num_eliminate_blocks, A->block_structure());
eliminator_->Init(options_.elimination_groups[0], A->block_structure());
};
const time_t init_time = time(NULL);
fill(x, x + A->num_cols(), 0.0);
@@ -106,7 +106,7 @@ LinearSolver::Summary SchurComplementSolver::SolveImpl(
// complement.
void DenseSchurComplementSolver::InitStorage(
const CompressedRowBlockStructure* bs) {
const int num_eliminate_blocks = options().num_eliminate_blocks;
const int num_eliminate_blocks = options().elimination_groups[0];
const int num_col_blocks = bs->cols.size();
vector<int> blocks(num_col_blocks - num_eliminate_blocks, 0);
@@ -178,7 +178,7 @@ SparseSchurComplementSolver::~SparseSchurComplementSolver() {
// initialize a BlockRandomAccessSparseMatrix object.
void SparseSchurComplementSolver::InitStorage(
const CompressedRowBlockStructure* bs) {
const int num_eliminate_blocks = options().num_eliminate_blocks;
const int num_eliminate_blocks = options().elimination_groups[0];
const int num_col_blocks = bs->cols.size();
const int num_row_blocks = bs->rows.size();
+3 -2
View File
@@ -97,13 +97,14 @@ class BlockSparseMatrixBase;
// The two solvers can be instantiated by calling
// LinearSolver::CreateLinearSolver with LinearSolver::Options::type
// set to DENSE_SCHUR and SPARSE_SCHUR
// respectively. LinearSolver::Options::num_eliminate_blocks should be
// respectively. LinearSolver::Options::elimination_groups[0] should be
// at least 1.
class SchurComplementSolver : public BlockSparseMatrixBaseSolver {
public:
explicit SchurComplementSolver(const LinearSolver::Options& options)
: options_(options) {
CHECK_GT(options.num_eliminate_blocks, 0);
CHECK_GT(options.elimination_groups.size(), 1);
CHECK_GT(options.elimination_groups[0], 0);
}
// LinearSolver methods
@@ -98,7 +98,9 @@ class SchurComplementSolverTest : public ::testing::Test {
ceres::SparseLinearAlgebraLibraryType sparse_linear_algebra_library) {
SetUpFromProblemId(problem_id);
LinearSolver::Options options;
options.num_eliminate_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);
options.type = linear_solver_type;
options.sparse_linear_algebra_library = sparse_linear_algebra_library;
+2 -2
View File
@@ -149,10 +149,10 @@ class SchurEliminatorTest : public ::testing::Test {
Vector rhs(schur_size);
LinearSolver::Options options;
options.num_eliminate_blocks = num_eliminate_blocks;
options.elimination_groups.push_back(num_eliminate_blocks);
if (use_static_structure) {
DetectStructure(*bs,
options.num_eliminate_blocks,
num_eliminate_blocks,
&options.row_block_size,
&options.e_block_size,
&options.f_block_size);
+12 -3
View File
@@ -652,10 +652,19 @@ LinearSolver* SolverImpl::CreateLinearSolver(Solver::Options* options,
#endif
linear_solver_options.num_threads = options->num_linear_solver_threads;
linear_solver_options.num_eliminate_blocks =
options->num_eliminate_blocks;
if (options->num_eliminate_blocks > 0) {
linear_solver_options
.elimination_groups.push_back(options->num_eliminate_blocks);
}
if ((linear_solver_options.num_eliminate_blocks == 0) &&
// TODO(sameeragarwal): Fix this. Right now these are dummy values
// and violate the contract that elimination_groups should sum to
// the number of parameter blocks, but fixing this requires a bit
// more refactoring in solver_impl.cc, which is better done as we
// start deprecating the old API.
linear_solver_options.elimination_groups.push_back(1);
if (linear_solver_options.elimination_groups.size() == 1 &&
IsSchurType(linear_solver_options.type)) {
#if defined(CERES_NO_SUITESPARSE) && defined(CERES_NO_CXSPARSE)
LOG(INFO) << "No elimination block remaining switching to DENSE_QR.";
@@ -70,12 +70,13 @@ VisibilityBasedPreconditioner::VisibilityBasedPreconditioner(
num_blocks_(0),
num_clusters_(0),
factor_(NULL) {
CHECK_GT(options_.num_eliminate_blocks, 0);
CHECK_GT(options_.elimination_groups.size(), 1);
CHECK_GT(options_.elimination_groups[0], 0);
CHECK(options_.preconditioner_type == SCHUR_JACOBI ||
options_.preconditioner_type == CLUSTER_JACOBI ||
options_.preconditioner_type == CLUSTER_TRIDIAGONAL)
<< "Unknown preconditioner type: " << options_.preconditioner_type;
num_blocks_ = bs.cols.size() - options_.num_eliminate_blocks;
num_blocks_ = bs.cols.size() - options_.elimination_groups[0];
CHECK_GT(num_blocks_, 0)
<< "Jacobian should have atleast 1 f_block for "
<< "visibility based preconditioning.";
@@ -83,7 +84,7 @@ VisibilityBasedPreconditioner::VisibilityBasedPreconditioner(
// Vector of camera block sizes
block_size_.resize(num_blocks_);
for (int i = 0; i < num_blocks_; ++i) {
block_size_[i] = bs.cols[i + options_.num_eliminate_blocks].size;
block_size_[i] = bs.cols[i + options_.elimination_groups[0]].size;
}
const time_t start_time = time(NULL);
@@ -155,7 +156,7 @@ void VisibilityBasedPreconditioner::ComputeSchurJacobiSparsity(
void VisibilityBasedPreconditioner::ComputeClusterJacobiSparsity(
const CompressedRowBlockStructure& bs) {
vector<set<int> > visibility;
ComputeVisibility(bs, options_.num_eliminate_blocks, &visibility);
ComputeVisibility(bs, options_.elimination_groups[0], &visibility);
CHECK_EQ(num_blocks_, visibility.size());
ClusterCameras(visibility);
cluster_pairs_.clear();
@@ -173,7 +174,7 @@ void VisibilityBasedPreconditioner::ComputeClusterJacobiSparsity(
void VisibilityBasedPreconditioner::ComputeClusterTridiagonalSparsity(
const CompressedRowBlockStructure& bs) {
vector<set<int> > visibility;
ComputeVisibility(bs, options_.num_eliminate_blocks, &visibility);
ComputeVisibility(bs, options_.elimination_groups[0], &visibility);
CHECK_EQ(num_blocks_, visibility.size());
ClusterCameras(visibility);
@@ -253,7 +254,7 @@ void VisibilityBasedPreconditioner::ComputeBlockPairsInPreconditioner(
int r = 0;
const int num_row_blocks = bs.rows.size();
const int num_eliminate_blocks = options_.num_eliminate_blocks;
const int num_eliminate_blocks = options_.elimination_groups[0];
// Iterate over each row of the matrix. The block structure of the
// matrix is assumed to be sorted in order of the e_blocks/point
@@ -331,16 +332,17 @@ void VisibilityBasedPreconditioner::ComputeBlockPairsInPreconditioner(
void VisibilityBasedPreconditioner::InitEliminator(
const CompressedRowBlockStructure& bs) {
LinearSolver::Options eliminator_options;
eliminator_options.num_eliminate_blocks = options_.num_eliminate_blocks;
eliminator_options.elimination_groups = options_.elimination_groups;
eliminator_options.num_threads = options_.num_threads;
DetectStructure(bs, options_.num_eliminate_blocks,
DetectStructure(bs, options_.elimination_groups[0],
&eliminator_options.row_block_size,
&eliminator_options.e_block_size,
&eliminator_options.f_block_size);
eliminator_.reset(SchurEliminatorBase::Create(eliminator_options));
eliminator_->Init(options_.num_eliminate_blocks, &bs);
eliminator_->Init(options_.elimination_groups[0], &bs);
}
// Update the values of the preconditioner matrix and factorize it.
@@ -80,7 +80,9 @@ class VisibilityBasedPreconditionerTest : public ::testing::Test {
num_rows_ = A_->num_rows();
num_eliminate_blocks_ = problem->num_eliminate_blocks;
num_camera_blocks_ = num_col_blocks - num_eliminate_blocks_;
options_.num_eliminate_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_);
vector<int> blocks(num_col_blocks - num_eliminate_blocks_, 0);
for (int i = num_eliminate_blocks_; i < num_col_blocks; ++i) {