Compute the gradient if requested in the evaluator

This extends the Evaluator interface to support evaluating the
gradient in addition to the residuals and jacobian, if requested.

   bool Evaluate(const double* state,
                 double* cost,
                 double* residuals,
                 double* gradient,  <----------- NEW
                 SparseMatrix* jacobian) = 0;

The ProgramEvaluator is extended to support the new gradient
evaluation. This required some gymnastics around the block
evaluate preparer, which now contains a scratch evaluate preparer
for the case that no jacobian is requested but the gradient is.

Gradient evaluation is a prerequisite for the planned suite of
first order methods, including nonlinear conjugate gradient,
CG_DESCENT, L-BFGS, trust region with line search, and more.

This also considerably refactors the evaluator_test to make it
shorter and check the results for all combinations of the optional
parameters [residuals, gradient, jacobian].

Change-Id: Ic7d0fec028dc5ffebc08ee079ad04eeaf6e02582
This commit is contained in:
Keir Mierle
2012-07-06 13:52:32 -07:00
parent 9d5fea19f1
commit f44907f702
10 changed files with 362 additions and 427 deletions
+13 -3
View File
@@ -36,6 +36,8 @@
#ifndef CERES_INTERNAL_BLOCK_EVALUATE_PREPARER_H_
#define CERES_INTERNAL_BLOCK_EVALUATE_PREPARER_H_
#include "ceres/scratch_evaluate_preparer.h"
namespace ceres {
namespace internal {
@@ -47,18 +49,26 @@ class BlockEvaluatePreparer {
// Using Init() instead of a constructor allows for allocating this structure
// with new[]. This is because C++ doesn't allow passing arguments to objects
// constructed with new[] (as opposed to plain 'new').
void Init(int** jacobian_layout);
void Init(int const* const* jacobian_layout,
int max_derivatives_per_residual_block);
// EvaluatePreparer interface
// Point the jacobian blocks directly into the block sparse matrix.
// Point the jacobian blocks directly into the block sparse matrix, if
// jacobian is non-null. Otherwise, uses an internal per-thread buffer to
// store the jacobians temporarily.
void Prepare(const ResidualBlock* residual_block,
int residual_block_index,
SparseMatrix* jacobian,
double** jacobians) const;
double** jacobians);
private:
int const* const* jacobian_layout_;
// For the case that the overall jacobian is not available, but the
// individual jacobians are requested, use a pass-through scratch evaluate
// preparer.
ScratchEvaluatePreparer scratch_evaluate_preparer_;
};
} // namespace internal