mirror of
https://github.com/ceres-solver/ceres-solver.git
synced 2026-08-29 08:34:37 +08:00
LinearSolver::Options::num_eliminate_blocks is dead.
Replaced with LinearSolver::Options::elimination_groups. Change-Id: I7c07542ec19279a35ddf6da498d417a79395c77f
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user