Make LineSearchMinizer work correctly with negative valued functions. When reasoning about the function_tolerance based convergence, LineSearchMinimizer assumed that the objective function is positive. This used to be the case when LineSearchMinimizer was used for minimizing non-linear least squares problems. However, with GradientProblemSolver, the objective function can be negative (for example when maximizing a function). This change the minimizer to use the absolute value of the change from one iteration to another. https://github.com/ceres-solver/ceres-solver/issues/478 Change-Id: I831e2db96b092374e167c582ab1480b1831d5650
diff --git a/internal/ceres/line_search_minimizer.cc b/internal/ceres/line_search_minimizer.cc index ac0a192..f57c047 100644 --- a/internal/ceres/line_search_minimizer.cc +++ b/internal/ceres/line_search_minimizer.cc
@@ -429,14 +429,14 @@ } const double absolute_function_tolerance = - options.function_tolerance * previous_state.cost; - if (fabs(iteration_summary.cost_change) <= absolute_function_tolerance) { - summary->message = - StringPrintf("Function tolerance reached. " - "|cost_change|/cost: %e <= %e", - fabs(iteration_summary.cost_change) / - previous_state.cost, - options.function_tolerance); + options.function_tolerance * std::abs(previous_state.cost); + if (std::abs(iteration_summary.cost_change) <= + absolute_function_tolerance) { + summary->message = StringPrintf( + "Function tolerance reached. " + "|cost_change|/cost: %e <= %e", + std::abs(iteration_summary.cost_change) / previous_state.cost, + options.function_tolerance); summary->termination_type = CONVERGENCE; VLOG_IF(1, is_not_silent) << "Terminating: " << summary->message; break;