|
Packit |
ea1746 |
// Ceres Solver - A fast non-linear least squares minimizer
|
|
Packit |
ea1746 |
// Copyright 2015 Google Inc. All rights reserved.
|
|
Packit |
ea1746 |
// http://ceres-solver.org/
|
|
Packit |
ea1746 |
//
|
|
Packit |
ea1746 |
// Redistribution and use in source and binary forms, with or without
|
|
Packit |
ea1746 |
// modification, are permitted provided that the following conditions are met:
|
|
Packit |
ea1746 |
//
|
|
Packit |
ea1746 |
// * Redistributions of source code must retain the above copyright notice,
|
|
Packit |
ea1746 |
// this list of conditions and the following disclaimer.
|
|
Packit |
ea1746 |
// * Redistributions in binary form must reproduce the above copyright notice,
|
|
Packit |
ea1746 |
// this list of conditions and the following disclaimer in the documentation
|
|
Packit |
ea1746 |
// and/or other materials provided with the distribution.
|
|
Packit |
ea1746 |
// * Neither the name of Google Inc. nor the names of its contributors may be
|
|
Packit |
ea1746 |
// used to endorse or promote products derived from this software without
|
|
Packit |
ea1746 |
// specific prior written permission.
|
|
Packit |
ea1746 |
//
|
|
Packit |
ea1746 |
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
Packit |
ea1746 |
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
Packit |
ea1746 |
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
Packit |
ea1746 |
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
Packit |
ea1746 |
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
Packit |
ea1746 |
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
Packit |
ea1746 |
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
Packit |
ea1746 |
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
Packit |
ea1746 |
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
Packit |
ea1746 |
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
Packit |
ea1746 |
// POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
ea1746 |
//
|
|
Packit |
ea1746 |
// Author: sameeragarwal@google.com (Sameer Agarwal)
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
#include "ceres/trust_region_preprocessor.h"
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
#include <numeric>
|
|
Packit |
ea1746 |
#include <string>
|
|
Packit |
ea1746 |
#include "ceres/callbacks.h"
|
|
Packit |
ea1746 |
#include "ceres/evaluator.h"
|
|
Packit |
ea1746 |
#include "ceres/linear_solver.h"
|
|
Packit |
ea1746 |
#include "ceres/minimizer.h"
|
|
Packit |
ea1746 |
#include "ceres/parameter_block.h"
|
|
Packit |
ea1746 |
#include "ceres/preconditioner.h"
|
|
Packit |
ea1746 |
#include "ceres/preprocessor.h"
|
|
Packit |
ea1746 |
#include "ceres/problem_impl.h"
|
|
Packit |
ea1746 |
#include "ceres/program.h"
|
|
Packit |
ea1746 |
#include "ceres/reorder_program.h"
|
|
Packit |
ea1746 |
#include "ceres/suitesparse.h"
|
|
Packit |
ea1746 |
#include "ceres/trust_region_strategy.h"
|
|
Packit |
ea1746 |
#include "ceres/wall_time.h"
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
namespace ceres {
|
|
Packit |
ea1746 |
namespace internal {
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
using std::vector;
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
namespace {
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
ParameterBlockOrdering* CreateDefaultLinearSolverOrdering(
|
|
Packit |
ea1746 |
const Program& program) {
|
|
Packit |
ea1746 |
ParameterBlockOrdering* ordering = new ParameterBlockOrdering;
|
|
Packit |
ea1746 |
const vector<ParameterBlock*>& parameter_blocks =
|
|
Packit |
ea1746 |
program.parameter_blocks();
|
|
Packit |
ea1746 |
for (int i = 0; i < parameter_blocks.size(); ++i) {
|
|
Packit |
ea1746 |
ordering->AddElementToGroup(
|
|
Packit |
ea1746 |
const_cast<double*>(parameter_blocks[i]->user_state()), 0);
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
return ordering;
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
// Check if all the user supplied values in the parameter blocks are
|
|
Packit |
ea1746 |
// sane or not, and if the program is feasible or not.
|
|
Packit |
ea1746 |
bool IsProgramValid(const Program& program, std::string* error) {
|
|
Packit |
ea1746 |
return (program.ParameterBlocksAreFinite(error) &&
|
|
Packit |
ea1746 |
program.IsFeasible(error));
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
void AlternateLinearSolverAndPreconditionerForSchurTypeLinearSolver(
|
|
Packit |
ea1746 |
Solver::Options* options) {
|
|
Packit |
ea1746 |
if (!IsSchurType(options->linear_solver_type)) {
|
|
Packit |
ea1746 |
return;
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
const LinearSolverType linear_solver_type_given = options->linear_solver_type;
|
|
Packit |
ea1746 |
const PreconditionerType preconditioner_type_given =
|
|
Packit |
ea1746 |
options->preconditioner_type;
|
|
Packit |
ea1746 |
options->linear_solver_type = LinearSolver::LinearSolverForZeroEBlocks(
|
|
Packit |
ea1746 |
linear_solver_type_given);
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
std::string message;
|
|
Packit |
ea1746 |
if (linear_solver_type_given == ITERATIVE_SCHUR) {
|
|
Packit |
ea1746 |
options->preconditioner_type = Preconditioner::PreconditionerForZeroEBlocks(
|
|
Packit |
ea1746 |
preconditioner_type_given);
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
message =
|
|
Packit |
ea1746 |
StringPrintf(
|
|
Packit |
ea1746 |
"No E blocks. Switching from %s(%s) to %s(%s).",
|
|
Packit |
ea1746 |
LinearSolverTypeToString(linear_solver_type_given),
|
|
Packit |
ea1746 |
PreconditionerTypeToString(preconditioner_type_given),
|
|
Packit |
ea1746 |
LinearSolverTypeToString(options->linear_solver_type),
|
|
Packit |
ea1746 |
PreconditionerTypeToString(options->preconditioner_type));
|
|
Packit |
ea1746 |
} else {
|
|
Packit |
ea1746 |
message =
|
|
Packit |
ea1746 |
StringPrintf(
|
|
Packit |
ea1746 |
"No E blocks. Switching from %s to %s.",
|
|
Packit |
ea1746 |
LinearSolverTypeToString(linear_solver_type_given),
|
|
Packit |
ea1746 |
LinearSolverTypeToString(options->linear_solver_type));
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
VLOG_IF(1, options->logging_type != SILENT) << message;
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
// For Schur type and SPARSE_NORMAL_CHOLESKY linear solvers, reorder
|
|
Packit |
ea1746 |
// the program to reduce fill-in and increase cache coherency.
|
|
Packit |
ea1746 |
bool ReorderProgram(PreprocessedProblem* pp) {
|
|
Packit |
ea1746 |
Solver::Options& options = pp->options;
|
|
Packit |
ea1746 |
if (IsSchurType(options.linear_solver_type)) {
|
|
Packit |
ea1746 |
return ReorderProgramForSchurTypeLinearSolver(
|
|
Packit |
ea1746 |
options.linear_solver_type,
|
|
Packit |
ea1746 |
options.sparse_linear_algebra_library_type,
|
|
Packit |
ea1746 |
pp->problem->parameter_map(),
|
|
Packit |
ea1746 |
options.linear_solver_ordering.get(),
|
|
Packit |
ea1746 |
pp->reduced_program.get(),
|
|
Packit |
ea1746 |
&pp->error);
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
if (options.linear_solver_type == SPARSE_NORMAL_CHOLESKY &&
|
|
Packit |
ea1746 |
!options.dynamic_sparsity) {
|
|
Packit |
ea1746 |
return ReorderProgramForSparseNormalCholesky(
|
|
Packit |
ea1746 |
options.sparse_linear_algebra_library_type,
|
|
Packit |
ea1746 |
*options.linear_solver_ordering,
|
|
Packit |
ea1746 |
pp->reduced_program.get(),
|
|
Packit |
ea1746 |
&pp->error);
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
return true;
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
// Configure and create a linear solver object. In doing so, if a
|
|
Packit |
ea1746 |
// sparse direct factorization based linear solver is being used, then
|
|
Packit |
ea1746 |
// find a fill reducing ordering and reorder the program as needed
|
|
Packit |
ea1746 |
// too.
|
|
Packit |
ea1746 |
bool SetupLinearSolver(PreprocessedProblem* pp) {
|
|
Packit |
ea1746 |
Solver::Options& options = pp->options;
|
|
Packit |
ea1746 |
if (options.linear_solver_ordering.get() == NULL) {
|
|
Packit |
ea1746 |
// If the user has not supplied a linear solver ordering, then we
|
|
Packit |
ea1746 |
// assume that they are giving all the freedom to us in choosing
|
|
Packit |
ea1746 |
// the best possible ordering. This intent can be indicated by
|
|
Packit |
ea1746 |
// putting all the parameter blocks in the same elimination group.
|
|
Packit |
ea1746 |
options.linear_solver_ordering.reset(
|
|
Packit |
ea1746 |
CreateDefaultLinearSolverOrdering(*pp->reduced_program));
|
|
Packit |
ea1746 |
} else {
|
|
Packit |
ea1746 |
// If the user supplied an ordering, then check if the first
|
|
Packit |
ea1746 |
// elimination group is still non-empty after the reduced problem
|
|
Packit |
ea1746 |
// has been constructed.
|
|
Packit |
ea1746 |
//
|
|
Packit |
ea1746 |
// This is important for Schur type linear solvers, where the
|
|
Packit |
ea1746 |
// first elimination group is special -- it needs to be an
|
|
Packit |
ea1746 |
// independent set.
|
|
Packit |
ea1746 |
//
|
|
Packit |
ea1746 |
// If the first elimination group is empty, then we cannot use the
|
|
Packit |
ea1746 |
// user's requested linear solver (and a preconditioner as the
|
|
Packit |
ea1746 |
// case may be) so we must use a different one.
|
|
Packit |
ea1746 |
ParameterBlockOrdering* ordering = options.linear_solver_ordering.get();
|
|
Packit |
ea1746 |
const int min_group_id = ordering->MinNonZeroGroup();
|
|
Packit |
ea1746 |
ordering->Remove(pp->removed_parameter_blocks);
|
|
Packit |
ea1746 |
if (IsSchurType(options.linear_solver_type) &&
|
|
Packit |
ea1746 |
min_group_id != ordering->MinNonZeroGroup()) {
|
|
Packit |
ea1746 |
AlternateLinearSolverAndPreconditionerForSchurTypeLinearSolver(
|
|
Packit |
ea1746 |
&options);
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
// Reorder the program to reduce fill in and improve cache coherency
|
|
Packit |
ea1746 |
// of the Jacobian.
|
|
Packit |
ea1746 |
if (!ReorderProgram(pp)) {
|
|
Packit |
ea1746 |
return false;
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
// Configure the linear solver.
|
|
Packit |
ea1746 |
pp->linear_solver_options = LinearSolver::Options();
|
|
Packit |
ea1746 |
pp->linear_solver_options.min_num_iterations =
|
|
Packit |
ea1746 |
options.min_linear_solver_iterations;
|
|
Packit |
ea1746 |
pp->linear_solver_options.max_num_iterations =
|
|
Packit |
ea1746 |
options.max_linear_solver_iterations;
|
|
Packit |
ea1746 |
pp->linear_solver_options.type = options.linear_solver_type;
|
|
Packit |
ea1746 |
pp->linear_solver_options.preconditioner_type = options.preconditioner_type;
|
|
Packit |
ea1746 |
pp->linear_solver_options.visibility_clustering_type =
|
|
Packit |
ea1746 |
options.visibility_clustering_type;
|
|
Packit |
ea1746 |
pp->linear_solver_options.sparse_linear_algebra_library_type =
|
|
Packit |
ea1746 |
options.sparse_linear_algebra_library_type;
|
|
Packit |
ea1746 |
pp->linear_solver_options.dense_linear_algebra_library_type =
|
|
Packit |
ea1746 |
options.dense_linear_algebra_library_type;
|
|
Packit |
ea1746 |
pp->linear_solver_options.use_explicit_schur_complement =
|
|
Packit |
ea1746 |
options.use_explicit_schur_complement;
|
|
Packit |
ea1746 |
pp->linear_solver_options.dynamic_sparsity = options.dynamic_sparsity;
|
|
Packit |
ea1746 |
pp->linear_solver_options.num_threads = options.num_linear_solver_threads;
|
|
Packit |
ea1746 |
pp->linear_solver_options.use_postordering = options.use_postordering;
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
if (IsSchurType(pp->linear_solver_options.type)) {
|
|
Packit |
ea1746 |
OrderingToGroupSizes(options.linear_solver_ordering.get(),
|
|
Packit |
ea1746 |
&pp->linear_solver_options.elimination_groups);
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
// Schur type solvers expect at least two elimination groups. If
|
|
Packit |
ea1746 |
// there is only one elimination group, then it is guaranteed that
|
|
Packit |
ea1746 |
// this group only contains e_blocks. Thus we add a dummy
|
|
Packit |
ea1746 |
// elimination group with zero blocks in it.
|
|
Packit |
ea1746 |
if (pp->linear_solver_options.elimination_groups.size() == 1) {
|
|
Packit |
ea1746 |
pp->linear_solver_options.elimination_groups.push_back(0);
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
if (options.linear_solver_type == SPARSE_SCHUR) {
|
|
Packit |
ea1746 |
// When using SPARSE_SCHUR, we ignore the user's postordering
|
|
Packit |
ea1746 |
// preferences in certain cases.
|
|
Packit |
ea1746 |
//
|
|
Packit |
ea1746 |
// 1. SUITE_SPARSE is the sparse linear algebra library requested
|
|
Packit |
ea1746 |
// but cholmod_camd is not available.
|
|
Packit |
ea1746 |
// 2. CX_SPARSE is the sparse linear algebra library requested.
|
|
Packit |
ea1746 |
//
|
|
Packit |
ea1746 |
// This ensures that the linear solver does not assume that a
|
|
Packit |
ea1746 |
// fill-reducing pre-ordering has been done.
|
|
Packit |
ea1746 |
//
|
|
Packit |
ea1746 |
// TODO(sameeragarwal): Implement the reordering of parameter
|
|
Packit |
ea1746 |
// blocks for CX_SPARSE.
|
|
Packit |
ea1746 |
if ((options.sparse_linear_algebra_library_type == SUITE_SPARSE &&
|
|
Packit |
ea1746 |
!SuiteSparse::
|
|
Packit |
ea1746 |
IsConstrainedApproximateMinimumDegreeOrderingAvailable()) ||
|
|
Packit |
ea1746 |
(options.sparse_linear_algebra_library_type == CX_SPARSE)) {
|
|
Packit |
ea1746 |
pp->linear_solver_options.use_postordering = true;
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
pp->linear_solver.reset(LinearSolver::Create(pp->linear_solver_options));
|
|
Packit |
ea1746 |
return (pp->linear_solver.get() != NULL);
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
// Configure and create the evaluator.
|
|
Packit |
ea1746 |
bool SetupEvaluator(PreprocessedProblem* pp) {
|
|
Packit |
ea1746 |
const Solver::Options& options = pp->options;
|
|
Packit |
ea1746 |
pp->evaluator_options = Evaluator::Options();
|
|
Packit |
ea1746 |
pp->evaluator_options.linear_solver_type = options.linear_solver_type;
|
|
Packit |
ea1746 |
pp->evaluator_options.num_eliminate_blocks = 0;
|
|
Packit |
ea1746 |
if (IsSchurType(options.linear_solver_type)) {
|
|
Packit |
ea1746 |
pp->evaluator_options.num_eliminate_blocks =
|
|
Packit |
ea1746 |
options
|
|
Packit |
ea1746 |
.linear_solver_ordering
|
|
Packit |
ea1746 |
->group_to_elements().begin()
|
|
Packit |
ea1746 |
->second.size();
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
pp->evaluator_options.num_threads = options.num_threads;
|
|
Packit |
ea1746 |
pp->evaluator_options.dynamic_sparsity = options.dynamic_sparsity;
|
|
Packit |
ea1746 |
pp->evaluator.reset(Evaluator::Create(pp->evaluator_options,
|
|
Packit |
ea1746 |
pp->reduced_program.get(),
|
|
Packit |
ea1746 |
&pp->error));
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
return (pp->evaluator.get() != NULL);
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
// If the user requested inner iterations, then find an inner
|
|
Packit |
ea1746 |
// iteration ordering as needed and configure and create a
|
|
Packit |
ea1746 |
// CoordinateDescentMinimizer object to perform the inner iterations.
|
|
Packit |
ea1746 |
bool SetupInnerIterationMinimizer(PreprocessedProblem* pp) {
|
|
Packit |
ea1746 |
Solver::Options& options = pp->options;
|
|
Packit |
ea1746 |
if (!options.use_inner_iterations) {
|
|
Packit |
ea1746 |
return true;
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
// With just one parameter block, the outer iteration of the trust
|
|
Packit |
ea1746 |
// region method and inner iterations are doing exactly the same
|
|
Packit |
ea1746 |
// thing, and thus inner iterations are not needed.
|
|
Packit |
ea1746 |
if (pp->reduced_program->NumParameterBlocks() == 1) {
|
|
Packit |
ea1746 |
LOG(WARNING) << "Reduced problem only contains one parameter block."
|
|
Packit |
ea1746 |
<< "Disabling inner iterations.";
|
|
Packit |
ea1746 |
return true;
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
if (options.inner_iteration_ordering.get() != NULL) {
|
|
Packit |
ea1746 |
// If the user supplied an ordering, then remove the set of
|
|
Packit |
ea1746 |
// inactive parameter blocks from it
|
|
Packit |
ea1746 |
options.inner_iteration_ordering->Remove(pp->removed_parameter_blocks);
|
|
Packit |
ea1746 |
if (options.inner_iteration_ordering->NumElements() == 0) {
|
|
Packit |
ea1746 |
LOG(WARNING) << "No remaining elements in the inner iteration ordering.";
|
|
Packit |
ea1746 |
return true;
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
// Validate the reduced ordering.
|
|
Packit |
ea1746 |
if (!CoordinateDescentMinimizer::IsOrderingValid(
|
|
Packit |
ea1746 |
*pp->reduced_program,
|
|
Packit |
ea1746 |
*options.inner_iteration_ordering,
|
|
Packit |
ea1746 |
&pp->error)) {
|
|
Packit |
ea1746 |
return false;
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
} else {
|
|
Packit |
ea1746 |
// The user did not supply an ordering, so create one.
|
|
Packit |
ea1746 |
options.inner_iteration_ordering.reset(
|
|
Packit |
ea1746 |
CoordinateDescentMinimizer::CreateOrdering(*pp->reduced_program));
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
pp->inner_iteration_minimizer.reset(new CoordinateDescentMinimizer);
|
|
Packit |
ea1746 |
return pp->inner_iteration_minimizer->Init(*pp->reduced_program,
|
|
Packit |
ea1746 |
pp->problem->parameter_map(),
|
|
Packit |
ea1746 |
*options.inner_iteration_ordering,
|
|
Packit |
ea1746 |
&pp->error);
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
// Configure and create a TrustRegionMinimizer object.
|
|
Packit |
ea1746 |
void SetupMinimizerOptions(PreprocessedProblem* pp) {
|
|
Packit |
ea1746 |
const Solver::Options& options = pp->options;
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
SetupCommonMinimizerOptions(pp);
|
|
Packit |
ea1746 |
pp->minimizer_options.is_constrained =
|
|
Packit |
ea1746 |
pp->reduced_program->IsBoundsConstrained();
|
|
Packit |
ea1746 |
pp->minimizer_options.jacobian.reset(pp->evaluator->CreateJacobian());
|
|
Packit |
ea1746 |
pp->minimizer_options.inner_iteration_minimizer =
|
|
Packit |
ea1746 |
pp->inner_iteration_minimizer;
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
TrustRegionStrategy::Options strategy_options;
|
|
Packit |
ea1746 |
strategy_options.linear_solver = pp->linear_solver.get();
|
|
Packit |
ea1746 |
strategy_options.initial_radius =
|
|
Packit |
ea1746 |
options.initial_trust_region_radius;
|
|
Packit |
ea1746 |
strategy_options.max_radius = options.max_trust_region_radius;
|
|
Packit |
ea1746 |
strategy_options.min_lm_diagonal = options.min_lm_diagonal;
|
|
Packit |
ea1746 |
strategy_options.max_lm_diagonal = options.max_lm_diagonal;
|
|
Packit |
ea1746 |
strategy_options.trust_region_strategy_type =
|
|
Packit |
ea1746 |
options.trust_region_strategy_type;
|
|
Packit |
ea1746 |
strategy_options.dogleg_type = options.dogleg_type;
|
|
Packit |
ea1746 |
pp->minimizer_options.trust_region_strategy.reset(
|
|
Packit |
ea1746 |
CHECK_NOTNULL(TrustRegionStrategy::Create(strategy_options)));
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
} // namespace
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
TrustRegionPreprocessor::~TrustRegionPreprocessor() {
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
bool TrustRegionPreprocessor::Preprocess(const Solver::Options& options,
|
|
Packit |
ea1746 |
ProblemImpl* problem,
|
|
Packit |
ea1746 |
PreprocessedProblem* pp) {
|
|
Packit |
ea1746 |
CHECK_NOTNULL(pp);
|
|
Packit |
ea1746 |
pp->options = options;
|
|
Packit |
ea1746 |
ChangeNumThreadsIfNeeded(&pp->options);
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
pp->problem = problem;
|
|
Packit |
ea1746 |
Program* program = problem->mutable_program();
|
|
Packit |
ea1746 |
if (!IsProgramValid(*program, &pp->error)) {
|
|
Packit |
ea1746 |
return false;
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
pp->reduced_program.reset(
|
|
Packit |
ea1746 |
program->CreateReducedProgram(&pp->removed_parameter_blocks,
|
|
Packit |
ea1746 |
&pp->fixed_cost,
|
|
Packit |
ea1746 |
&pp->error));
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
if (pp->reduced_program.get() == NULL) {
|
|
Packit |
ea1746 |
return false;
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
if (pp->reduced_program->NumParameterBlocks() == 0) {
|
|
Packit |
ea1746 |
// The reduced problem has no parameter or residual blocks. There
|
|
Packit |
ea1746 |
// is nothing more to do.
|
|
Packit |
ea1746 |
return true;
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
if (!SetupLinearSolver(pp) ||
|
|
Packit |
ea1746 |
!SetupEvaluator(pp) ||
|
|
Packit |
ea1746 |
!SetupInnerIterationMinimizer(pp)) {
|
|
Packit |
ea1746 |
return false;
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
SetupMinimizerOptions(pp);
|
|
Packit |
ea1746 |
return true;
|
|
Packit |
ea1746 |
}
|
|
Packit |
ea1746 |
|
|
Packit |
ea1746 |
} // namespace internal
|
|
Packit |
ea1746 |
} // namespace ceres
|