Use the evaluator to compute the gradient in TrustRegionMinimizer. Evaluator now uses custom BLAS for gradient computations. Update the evaluator in trust_region_minimizer_test to compute gradients. Change-Id: I3f565bc203b47b2b795a0609d67f25775648653c
diff --git a/internal/ceres/program_evaluator.h b/internal/ceres/program_evaluator.h index de56ac2..1f7fc0f 100644 --- a/internal/ceres/program_evaluator.h +++ b/internal/ceres/program_evaluator.h
@@ -85,6 +85,7 @@ #include <map> #include <vector> +#include "ceres/blas.h" #include "ceres/execution_summary.h" #include "ceres/internal/eigen.h" #include "ceres/internal/scoped_ptr.h" @@ -230,14 +231,13 @@ if (parameter_block->IsConstant()) { continue; } - MatrixRef block_jacobian(block_jacobians[j], - num_residuals, - parameter_block->LocalSize()); - VectorRef block_gradient(scratch->gradient.get() + - parameter_block->delta_offset(), - parameter_block->LocalSize()); - VectorRef block_residual(block_residuals, num_residuals); - block_gradient += block_residual.transpose() * block_jacobian; + + MatrixTransposeVectorMultiply<Eigen::Dynamic, Eigen::Dynamic, 1>( + block_jacobians[j], + num_residuals, + parameter_block->LocalSize(), + block_residuals, + scratch->gradient.get() + parameter_block->delta_offset()); } } }
diff --git a/internal/ceres/trust_region_minimizer.cc b/internal/ceres/trust_region_minimizer.cc index 981c60a..7d4c093 100644 --- a/internal/ceres/trust_region_minimizer.cc +++ b/internal/ceres/trust_region_minimizer.cc
@@ -139,15 +139,16 @@ // Do initial cost and Jacobian evaluation. double cost = 0.0; - if (!evaluator->Evaluate(x.data(), &cost, residuals.data(), NULL, jacobian)) { + if (!evaluator->Evaluate(x.data(), + &cost, + residuals.data(), + gradient.data(), + jacobian)) { LOG(WARNING) << "Terminating: Residual and Jacobian evaluation failed."; summary->termination_type = NUMERICAL_FAILURE; return; } - summary->initial_cost = cost + summary->fixed_cost; - iteration_summary.cost = cost + summary->fixed_cost; - int num_consecutive_nonmonotonic_steps = 0; double minimum_cost = cost; double reference_cost = cost; @@ -155,17 +156,10 @@ double candidate_cost = cost; double accumulated_candidate_model_cost_change = 0.0; - gradient.setZero(); - jacobian->LeftMultiply(residuals.data(), gradient.data()); + summary->initial_cost = cost + summary->fixed_cost; + iteration_summary.cost = cost + summary->fixed_cost; iteration_summary.gradient_max_norm = gradient.lpNorm<Eigen::Infinity>(); - if (options_.jacobi_scaling) { - EstimateScale(*jacobian, scale.data()); - jacobian->ScaleColumns(scale.data()); - } else { - scale.setOnes(); - } - // The initial gradient max_norm is bounded from below so that we do // not divide by zero. const double initial_gradient_max_norm = @@ -189,6 +183,13 @@ + summary->preprocessor_time_in_seconds; summary->iterations.push_back(iteration_summary); + if (options_.jacobi_scaling) { + EstimateScale(*jacobian, scale.data()); + jacobian->ScaleColumns(scale.data()); + } else { + scale.setOnes(); + } + int num_consecutive_invalid_steps = 0; while (true) { if (!RunCallbacks(options.callbacks, iteration_summary, summary)) { @@ -419,7 +420,7 @@ if (!evaluator->Evaluate(x.data(), &cost, residuals.data(), - NULL, + gradient.data(), jacobian)) { summary->termination_type = NUMERICAL_FAILURE; summary->error = @@ -428,8 +429,6 @@ return; } - gradient.setZero(); - jacobian->LeftMultiply(residuals.data(), gradient.data()); iteration_summary.gradient_max_norm = gradient.lpNorm<Eigen::Infinity>(); if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) {
diff --git a/internal/ceres/trust_region_minimizer_test.cc b/internal/ceres/trust_region_minimizer_test.cc index 52d682d..ed00ab2 100644 --- a/internal/ceres/trust_region_minimizer_test.cc +++ b/internal/ceres/trust_region_minimizer_test.cc
@@ -86,12 +86,12 @@ const double* state, double* cost, double* residuals, - double* /* gradient */, + double* gradient, SparseMatrix* jacobian) { - double x1 = state[0]; - double x2 = state[1]; - double x3 = state[2]; - double x4 = state[3]; + const double x1 = state[0]; + const double x2 = state[1]; + const double x3 = state[2]; + const double x4 = state[3]; VLOG(1) << "State: " << "x1=" << x1 << ", " @@ -99,10 +99,10 @@ << "x3=" << x3 << ", " << "x4=" << x4 << "."; - double f1 = x1 + 10.0 * x2; - double f2 = sqrt(5.0) * (x3 - x4); - double f3 = pow(x2 - 2.0 * x3, 2.0); - double f4 = sqrt(10.0) * pow(x1 - x4, 2.0); + const double f1 = x1 + 10.0 * x2; + const double f2 = sqrt(5.0) * (x3 - x4); + const double f3 = pow(x2 - 2.0 * x3, 2.0); + const double f4 = sqrt(10.0) * pow(x1 - x4, 2.0); VLOG(1) << "Function: " << "f1=" << f1 << ", " @@ -162,6 +162,28 @@ } VLOG(1) << "\n" << jacobian_matrix; } + + if (gradient != NULL) { + int column_index = 0; + if (col1) { + gradient[column_index++] = f1 + f4 * sqrt(10.0) * 2.0 * (x1 - x4); + } + + if (col2) { + gradient[column_index++] = f1 * 10.0 + f3 * 2.0 * (x2 - 2.0 * x3); + } + + if (col3) { + gradient[column_index++] = + f2 * sqrt(5.0) + f3 * (2.0 * 2.0 * (2.0 * x3 - x2)); + } + + if (col4) { + gradient[column_index++] = + -f2 * sqrt(5.0) + f4 * sqrt(10.0) * 2.0 * (x4 - x1); + } + } + return true; }