Remove extraneous initial and final evals. Change-Id: I80ed87435f399cbf452c68be7ea1e7139696aa4a
diff --git a/internal/ceres/line_search_minimizer.cc b/internal/ceres/line_search_minimizer.cc index 636289f..ca7d639 100644 --- a/internal/ceres/line_search_minimizer.cc +++ b/internal/ceres/line_search_minimizer.cc
@@ -124,7 +124,9 @@ return; } + summary->initial_cost = current_state.cost + summary->fixed_cost; iteration_summary.cost = current_state.cost + summary->fixed_cost; + iteration_summary.gradient_max_norm = current_state.gradient_max_norm; // The initial gradient max_norm is bounded from below so that we do
diff --git a/internal/ceres/solver_impl.cc b/internal/ceres/solver_impl.cc index 3dfbb67..9b56f28 100644 --- a/internal/ceres/solver_impl.cc +++ b/internal/ceres/solver_impl.cc
@@ -77,6 +77,30 @@ double* parameters_; }; +// Macro used to evaluate initial and final residuals, gradient and +// jacobian if requested by the user. +// +// We need a macro here, instead of a simple function call, since the +// multiplexing happens on variable names. +#define CERES_EVALUATE(which) \ + Evaluator::Evaluate( \ + original_program, \ + options.num_threads, \ + &summary->final_cost, \ + options.return_ ## which ## _residuals ? &summary->which ## _residuals : NULL, \ + options.return_ ## which ## _gradient ? &summary->which ## _gradient : NULL, \ + options.return_ ## which ## _jacobian ? &summary->which ## _jacobian : NULL) + +void SetSummaryFinalCost(Solver::Summary* summary) { + summary->final_cost = summary->initial_cost; + // We need the loop here, instead of just looking at the last + // iteration because the minimizer maybe making non-monotonic steps. + for (int i = 0; i < summary->iterations.size(); ++i) { + const IterationSummary& iteration_summary = summary->iterations[i]; + summary->final_cost = min(iteration_summary.cost, summary->final_cost); + } +} + // Callback for logging the state of the minimizer to STDERR or STDOUT // depending on the user's preferences and logging level. class TrustRegionLoggingCallback : public IterationCallback { @@ -373,27 +397,18 @@ } event_logger.AddEvent("Init"); + // Evaluate the initial cost, residual vector and the jacobian - // matrix if requested by the user. The initial cost needs to be - // computed on the original unpreprocessed problem, as it is used to - // determine the value of the "fixed" part of the objective function - // after the problem has undergone reduction. - if (!Evaluator::Evaluate(original_program, - options.num_threads, - &(summary->initial_cost), - options.return_initial_residuals - ? &summary->initial_residuals - : NULL, - options.return_initial_gradient - ? &summary->initial_gradient - : NULL, - options.return_initial_jacobian - ? &summary->initial_jacobian - : NULL)) { - summary->termination_type = NUMERICAL_FAILURE; - summary->error = "Unable to evaluate the initial cost."; - LOG(ERROR) << summary->error; - return; + // matrix if requested by the user. + if (options.return_initial_residuals || + options.return_initial_gradient || + options.return_initial_jacobian) { + if (!CERES_EVALUATE(initial)) { + summary->termination_type = NUMERICAL_FAILURE; + summary->error = "Unable to evaluate the initial cost."; + LOG(ERROR) << summary->error; + return; + } } event_logger.AddEvent("InitialEvaluate"); @@ -470,24 +485,21 @@ summary->termination_type = FUNCTION_TOLERANCE; double post_process_start_time = WallTimeInSeconds(); + + + + // Evaluate the final cost, residual vector and the jacobian // matrix if requested by the user. - if (!Evaluator::Evaluate(original_program, - options.num_threads, - &summary->final_cost, - options.return_final_residuals - ? &summary->final_residuals - : NULL, - options.return_final_gradient - ? &summary->final_gradient - : NULL, - options.return_final_jacobian - ? &summary->final_jacobian - : NULL)) { - summary->termination_type = NUMERICAL_FAILURE; - summary->error = "Unable to evaluate the final cost."; - LOG(ERROR) << summary->error; - return; + if (options.return_final_residuals || + options.return_final_gradient || + options.return_final_jacobian) { + if (!CERES_EVALUATE(final)) { + summary->termination_type = NUMERICAL_FAILURE; + summary->error = "Unable to evaluate the final cost."; + LOG(ERROR) << summary->error; + return; + } } // Ensure the program state is set to the user parameters on the way out. @@ -588,6 +600,8 @@ summary); event_logger.AddEvent("Minimize"); + SetSummaryFinalCost(summary); + // If the user aborted mid-optimization or the optimization // terminated because of a numerical failure, then return without // updating user state. @@ -604,35 +618,27 @@ // Evaluate the final cost, residual vector and the jacobian // matrix if requested by the user. - if (!Evaluator::Evaluate(original_program, - options.num_threads, - &summary->final_cost, - options.return_final_residuals - ? &summary->final_residuals - : NULL, - options.return_final_gradient - ? &summary->final_gradient - : NULL, - options.return_final_jacobian - ? &summary->final_jacobian - : NULL)) { - // This failure requires careful handling. - // - // At this point, we have modified the user's state, but the - // evaluation failed and we inform him of NUMERICAL_FAILURE. Ceres - // guarantees that user's state is not modified if the solver - // returns with NUMERICAL_FAILURE. Thus, we need to restore the - // user's state to their original values. + if (options.return_final_residuals || + options.return_final_gradient || + options.return_final_jacobian) { + if (!CERES_EVALUATE(final)) { + // This failure requires careful handling. + // + // At this point, we have modified the user's state, but the + // evaluation failed and we inform him of NUMERICAL_FAILURE. Ceres + // guarantees that user's state is not modified if the solver + // returns with NUMERICAL_FAILURE. Thus, we need to restore the + // user's state to their original values. + reduced_program->StateVectorToParameterBlocks(original_parameters.data()); + reduced_program->CopyParameterBlockStateToUserState(); - reduced_program->StateVectorToParameterBlocks(original_parameters.data()); - reduced_program->CopyParameterBlockStateToUserState(); + summary->termination_type = NUMERICAL_FAILURE; + summary->error = "Unable to evaluate the final cost."; + LOG(ERROR) << summary->error; - summary->termination_type = NUMERICAL_FAILURE; - summary->error = "Unable to evaluate the final cost."; - LOG(ERROR) << summary->error; - - event_logger.AddEvent("PostProcess"); - return; + event_logger.AddEvent("PostProcess"); + return; + } } // Ensure the program state is set to the user parameters on the way out. @@ -729,26 +735,16 @@ } // Evaluate the initial cost, residual vector and the jacobian - // matrix if requested by the user. The initial cost needs to be - // computed on the original unpreprocessed problem, as it is used to - // determine the value of the "fixed" part of the objective function - // after the problem has undergone reduction. - if (!Evaluator::Evaluate(original_program, - options.num_threads, - &(summary->initial_cost), - options.return_initial_residuals - ? &summary->initial_residuals - : NULL, - options.return_initial_gradient - ? &summary->initial_gradient - : NULL, - options.return_initial_jacobian - ? &summary->initial_jacobian - : NULL)) { - summary->termination_type = NUMERICAL_FAILURE; - summary->error = "Unable to evaluate the initial cost."; - LOG(ERROR) << summary->error; - return; + // matrix if requested by the user. + if (options.return_initial_residuals || + options.return_initial_gradient || + options.return_initial_jacobian) { + if (!CERES_EVALUATE(initial)) { + summary->termination_type = NUMERICAL_FAILURE; + summary->error = "Unable to evaluate the initial cost."; + LOG(ERROR) << summary->error; + return; + } } original_program->SetParameterBlockStatePtrsToUserStatePtrs(); @@ -799,24 +795,20 @@ summary->termination_type = FUNCTION_TOLERANCE; const double post_process_start_time = WallTimeInSeconds(); + + SetSummaryFinalCost(summary); + // Evaluate the final cost, residual vector and the jacobian // matrix if requested by the user. - if (!Evaluator::Evaluate(original_program, - options.num_threads, - &summary->final_cost, - options.return_final_residuals - ? &summary->final_residuals - : NULL, - options.return_final_gradient - ? &summary->final_gradient - : NULL, - options.return_final_jacobian - ? &summary->final_jacobian - : NULL)) { - summary->termination_type = NUMERICAL_FAILURE; - summary->error = "Unable to evaluate the final cost."; - LOG(ERROR) << summary->error; - return; + if (options.return_final_residuals || + options.return_final_gradient || + options.return_final_jacobian) { + if (!CERES_EVALUATE(final)) { + summary->termination_type = NUMERICAL_FAILURE; + summary->error = "Unable to evaluate the final cost."; + LOG(ERROR) << summary->error; + return; + } } // Ensure the program state is set to the user parameters on the way out. @@ -868,35 +860,30 @@ reduced_program->StateVectorToParameterBlocks(parameters.data()); reduced_program->CopyParameterBlockStateToUserState(); + SetSummaryFinalCost(summary); + // Evaluate the final cost, residual vector and the jacobian // matrix if requested by the user. - if (!Evaluator::Evaluate(original_program, - options.num_threads, - &summary->final_cost, - options.return_final_residuals - ? &summary->final_residuals - : NULL, - options.return_final_gradient - ? &summary->final_gradient - : NULL, - options.return_final_jacobian - ? &summary->final_jacobian - : NULL)) { - // This failure requires careful handling. - // - // At this point, we have modified the user's state, but the - // evaluation failed and we inform him of NUMERICAL_FAILURE. Ceres - // guarantees that user's state is not modified if the solver - // returns with NUMERICAL_FAILURE. Thus, we need to restore the - // user's state to their original values. + if (options.return_final_residuals || + options.return_final_gradient || + options.return_final_jacobian) { + if (!CERES_EVALUATE(final)) { + // This failure requires careful handling. + // + // At this point, we have modified the user's state, but the + // evaluation failed and we inform him of NUMERICAL_FAILURE. Ceres + // guarantees that user's state is not modified if the solver + // returns with NUMERICAL_FAILURE. Thus, we need to restore the + // user's state to their original values. - reduced_program->StateVectorToParameterBlocks(original_parameters.data()); - reduced_program->CopyParameterBlockStateToUserState(); + reduced_program->StateVectorToParameterBlocks(original_parameters.data()); + reduced_program->CopyParameterBlockStateToUserState(); - summary->termination_type = NUMERICAL_FAILURE; - summary->error = "Unable to evaluate the final cost."; - LOG(ERROR) << summary->error; - return; + summary->termination_type = NUMERICAL_FAILURE; + summary->error = "Unable to evaluate the final cost."; + LOG(ERROR) << summary->error; + return; + } } // Ensure the program state is set to the user parameters on the way out.
diff --git a/internal/ceres/trust_region_minimizer.cc b/internal/ceres/trust_region_minimizer.cc index 5ea9374..fc405f5 100644 --- a/internal/ceres/trust_region_minimizer.cc +++ b/internal/ceres/trust_region_minimizer.cc
@@ -145,6 +145,7 @@ return; } + summary->initial_cost = cost + summary->fixed_cost; iteration_summary.cost = cost + summary->fixed_cost; int num_consecutive_nonmonotonic_steps = 0;
diff --git a/internal/ceres/wall_time.cc b/internal/ceres/wall_time.cc index 8dc4e1f..7de7e06 100644 --- a/internal/ceres/wall_time.cc +++ b/internal/ceres/wall_time.cc
@@ -86,10 +86,10 @@ last_event_time_ = current_time; StringAppendF(&events_, - " %25s : %5.3e %5.3e\n", + " %25s : %8.3f %8.3f\n", event_name.c_str(), - relative_time_delta, - absolute_time_delta); + 1000 * relative_time_delta, + 1000 * absolute_time_delta); } } // namespace internal