Consolidate SolverTerminationType enum. 1. Rename SolverTerminationType to TerminationType. 2. Consolidate the enum as a. CONVERGENCE - subsumes FUNCTION_TOLERANCE, PARAMETER_TOLERANCE and GRADIENT_TOLERANCE b. NO_CONVERGENCE c. FAILURE - captures all kinds of failures including DID_NOT_RUN. d. USER_SUCCESS e. USER_FAILURE 3. Solver::Summary::error is renamed to be Solver::Summary::message, to both reduce confusion as well as capture its true meaning. Change-Id: I27a382e66e67f5a4750d0ee914d941f6b53c326d
diff --git a/docs/source/solving.rst b/docs/source/solving.rst index d9b7e8f..25b19b0 100644 --- a/docs/source/solving.rst +++ b/docs/source/solving.rst
@@ -1703,7 +1703,7 @@ situation. The solver returns without updating the parameter blocks (unless ``Solver::Options::update_state_every_iteration`` is set true). Solver returns with ``Solver::Summary::termination_type`` - set to ``USER_ABORT``. + set to ``USER_FAILURE``. #. ``SOLVER_TERMINATE_SUCCESSFULLY`` indicates that there is no need to optimize anymore (some user specified termination criterion @@ -1832,14 +1832,14 @@ Type of minimization algorithm used. -.. member:: SolverTerminationType Solver::Summary::termination_type +.. member:: TerminationType Solver::Summary::termination_type The cause of the minimizer terminating. -.. member:: string Solver::Summary::error +.. member:: string Solver::Summary::message - If the solver did not run, or there was a failure, a description of - the error. + Reason why the solver terminated. + .. member:: double Solver::Summary::initial_cost
diff --git a/examples/nist.cc b/examples/nist.cc index 1773a0f..b29b285 100644 --- a/examples/nist.cc +++ b/examples/nist.cc
@@ -159,14 +159,6 @@ } } -bool IsSuccessfulTermination(ceres::SolverTerminationType status) { - return - (status == ceres::FUNCTION_TOLERANCE) || - (status == ceres::GRADIENT_TOLERANCE) || - (status == ceres::PARAMETER_TOLERANCE) || - (status == ceres::USER_SUCCESS); -} - class NISTProblem { public: explicit NISTProblem(const std::string& filename) {
diff --git a/include/ceres/solver.h b/include/ceres/solver.h index 7776c47..f0d5be6 100644 --- a/include/ceres/solver.h +++ b/include/ceres/solver.h
@@ -714,14 +714,15 @@ // termination. string FullReport() const; + bool IsSolutionUsable() const; + // Minimizer summary ------------------------------------------------- MinimizerType minimizer_type; - SolverTerminationType termination_type; + TerminationType termination_type; - // If the solver did not run, or there was a failure, a - // description of the error. - string error; + // Reason why the solver terminated. + string message; // Cost of the problem (value of the objective function) before // the optimization.
diff --git a/include/ceres/types.h b/include/ceres/types.h index 617bec0..600d226 100644 --- a/include/ceres/types.h +++ b/include/ceres/types.h
@@ -301,41 +301,42 @@ SUBSPACE_DOGLEG }; -enum SolverTerminationType { - // The minimizer did not run at all; usually due to errors in the user's - // Problem or the solver options. - DID_NOT_RUN, +enum TerminationType { + // Minimizer terminated because one of the convergence criterion set + // by the user was satisfied. + // + // 1. (new_cost - old_cost) < function_tolerance * old_cost; + // 2. max_i |gradient_i| < gradient_tolerance * max_i|initial_gradient_i| + // 3. |step|_2 <= parameter_tolerance * ( |x|_2 + parameter_tolerance) + // + // The user's parameter blocks will be updated with the solution. + CONVERGENCE, - // The solver ran for maximum number of iterations specified by the - // user, but none of the convergence criterion specified by the user - // were met. + // The solver ran for maximum number of iterations or maximum amount + // of time specified by the user, but none of the convergence + // criterion specified by the user were met. The user's parameter + // blocks will be updated with the solution found so far. NO_CONVERGENCE, - // Minimizer terminated because - // (new_cost - old_cost) < function_tolerance * old_cost; - FUNCTION_TOLERANCE, - - // Minimizer terminated because - // max_i |gradient_i| < gradient_tolerance * max_i|initial_gradient_i| - GRADIENT_TOLERANCE, - - // Minimized terminated because - // |step|_2 <= parameter_tolerance * ( |x|_2 + parameter_tolerance) - PARAMETER_TOLERANCE, - - // The minimizer terminated because it encountered a numerical error - // that it could not recover from. - NUMERICAL_FAILURE, + // The minimizer terminated because of an error. The user's + // parameter blocks will not be updated. + FAILURE, // Using an IterationCallback object, user code can control the // minimizer. The following enums indicate that the user code was // responsible for termination. + // + // Minimizer terminated successfully because a user + // IterationCallback returned SOLVER_TERMINATE_SUCCESSFULLY. + // + // The user's parameter blocks will be updated with the solution. + USER_SUCCESS, - // User's IterationCallback returned SOLVER_ABORT. - USER_ABORT, - - // User's IterationCallback returned SOLVER_TERMINATE_SUCCESSFULLY - USER_SUCCESS + // Minimizer terminated because because a user IterationCallback + // returned SOLVER_ABORT. + // + // The user's parameter blocks will not be updated. + USER_FAILURE }; // Enums used by the IterationCallback instances to indicate to the @@ -459,7 +460,7 @@ string value, CovarianceAlgorithmType* type); -const char* SolverTerminationTypeToString(SolverTerminationType type); +const char* TerminationTypeToString(TerminationType type); bool IsSchurType(LinearSolverType type); bool IsSparseLinearAlgebraLibraryTypeAvailable(
diff --git a/internal/ceres/covariance_test.cc b/internal/ceres/covariance_test.cc index f3a5051..4680244 100644 --- a/internal/ceres/covariance_test.cc +++ b/internal/ceres/covariance_test.cc
@@ -727,7 +727,7 @@ parameter_block_size_, jacobian.data()), NULL, - block_i ); + block_i); for (int j = i; j < num_parameter_blocks_; ++j) { double* block_j = parameters_.get() + j * parameter_block_size_; all_covariance_blocks_.push_back(make_pair(block_i, block_j));
diff --git a/internal/ceres/line_search_minimizer.cc b/internal/ceres/line_search_minimizer.cc index 67c2648..339d275 100644 --- a/internal/ceres/line_search_minimizer.cc +++ b/internal/ceres/line_search_minimizer.cc
@@ -126,9 +126,9 @@ // Do initial cost and Jacobian evaluation. if (!Evaluate(evaluator, x, ¤t_state)) { - summary->error = "Terminating: Cost and gradient evaluation failed."; - summary->termination_type = NUMERICAL_FAILURE; - LOG_IF(WARNING, is_not_silent) << summary->error; + summary->message = "Terminating: Cost and gradient evaluation failed."; + summary->termination_type = FAILURE; + LOG_IF(WARNING, is_not_silent) << summary->message; return; } @@ -146,14 +146,14 @@ options.gradient_tolerance * initial_gradient_max_norm; if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) { - summary->error = + summary->message = StringPrintf("Terminating: Gradient tolerance reached. " "Relative gradient max norm: %e <= %e", iteration_summary.gradient_max_norm / initial_gradient_max_norm, options.gradient_tolerance); - summary->termination_type = GRADIENT_TOLERANCE; - VLOG_IF(1, is_not_silent) << summary->error; + summary->termination_type = CONVERGENCE; + VLOG_IF(1, is_not_silent) << summary->message; return; } @@ -198,10 +198,10 @@ scoped_ptr<LineSearch> line_search(LineSearch::Create(options.line_search_type, line_search_options, - &summary->error)); + &summary->message)); if (line_search.get() == NULL) { - summary->termination_type = DID_NOT_RUN; - LOG_IF(ERROR, is_not_silent) << summary->error; + summary->termination_type = FAILURE; + LOG_IF(ERROR, is_not_silent) << summary->message; return; } @@ -215,18 +215,18 @@ iteration_start_time = WallTimeInSeconds(); if (iteration_summary.iteration >= options.max_num_iterations) { - summary->error = "Terminating: Maximum number of iterations reached."; + summary->message = "Terminating: Maximum number of iterations reached."; summary->termination_type = NO_CONVERGENCE; - VLOG_IF(1, is_not_silent) << summary->error; + VLOG_IF(1, is_not_silent) << summary->message; break; } const double total_solver_time = iteration_start_time - start_time + summary->preprocessor_time_in_seconds; if (total_solver_time >= options.max_solver_time_in_seconds) { - summary->error = "Terminating: Maximum solver time reached."; + summary->message = "Terminating: Maximum solver time reached."; summary->termination_type = NO_CONVERGENCE; - VLOG_IF(1, is_not_silent) << summary->error; + VLOG_IF(1, is_not_silent) << summary->message; break; } @@ -251,12 +251,12 @@ // Line search direction failed to generate a new direction, and we // have already reached our specified maximum number of restarts, // terminate optimization. - summary->error = + summary->message = StringPrintf("Terminating: Line search direction failure: specified " "max_num_line_search_direction_restarts: %d reached.", options.max_num_line_search_direction_restarts); - summary->termination_type = NUMERICAL_FAILURE; - LOG_IF(WARNING, is_not_silent) << summary->error; + summary->termination_type = FAILURE; + LOG_IF(WARNING, is_not_silent) << summary->message; break; } else if (!line_search_status) { // Restart line search direction with gradient descent on first iteration @@ -299,14 +299,14 @@ // direction in a line search, most likely cause for this being violated // would be a numerical failure in the line search direction calculation. if (initial_step_size < 0.0) { - summary->error = + summary->message = StringPrintf("Numerical failure in line search, initial_step_size is " "negative: %.5e, directional_derivative: %.5e, " "(current_cost - previous_cost): %.5e", initial_step_size, current_state.directional_derivative, (current_state.cost - previous_state.cost)); - summary->termination_type = NUMERICAL_FAILURE; - LOG_IF(WARNING, is_not_silent) << summary->error; + summary->termination_type = FAILURE; + LOG_IF(WARNING, is_not_silent) << summary->message; break; } @@ -315,15 +315,15 @@ current_state.directional_derivative, &line_search_summary); if (!line_search_summary.success) { - summary->error = + summary->message = StringPrintf("Numerical failure in line search, failed to find " "a valid step size, (did not run out of iterations) " "using initial_step_size: %.5e, initial_cost: %.5e, " "initial_gradient: %.5e.", initial_step_size, current_state.cost, current_state.directional_derivative); - LOG_IF(WARNING, is_not_silent) << summary->error; - summary->termination_type = NUMERICAL_FAILURE; + LOG_IF(WARNING, is_not_silent) << summary->message; + summary->termination_type = FAILURE; break; } @@ -355,14 +355,14 @@ iteration_summary.gradient_norm = sqrt(current_state.gradient_squared_norm); if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) { - summary->error = + summary->message = StringPrintf("Terminating: Gradient tolerance reached. " "Relative gradient max norm: %e <= %e. ", (iteration_summary.gradient_max_norm / initial_gradient_max_norm), options.gradient_tolerance); - summary->termination_type = GRADIENT_TOLERANCE; - VLOG_IF(1, is_not_silent) << summary->error; + summary->termination_type = CONVERGENCE; + VLOG_IF(1, is_not_silent) << summary->message; break; } @@ -370,14 +370,14 @@ const double absolute_function_tolerance = options.function_tolerance * previous_state.cost; if (fabs(iteration_summary.cost_change) < absolute_function_tolerance) { - summary->error = + summary->message = StringPrintf("Terminating. Function tolerance reached. " "|cost_change|/cost: %e <= %e", fabs(iteration_summary.cost_change) / previous_state.cost, options.function_tolerance); - summary->termination_type = FUNCTION_TOLERANCE; - VLOG_IF(1, is_not_silent) << summary->error; + summary->termination_type = CONVERGENCE; + VLOG_IF(1, is_not_silent) << summary->message; return; }
diff --git a/internal/ceres/minimizer.cc b/internal/ceres/minimizer.cc index 2e2c15a..bdb6a11 100644 --- a/internal/ceres/minimizer.cc +++ b/internal/ceres/minimizer.cc
@@ -54,7 +54,7 @@ VLOG(1) << "Terminating: User callback returned USER_SUCCESS."; return false; case SOLVER_ABORT: - summary->termination_type = USER_ABORT; + summary->termination_type = USER_FAILURE; VLOG(1) << "Terminating: User callback returned USER_ABORT."; return false; default:
diff --git a/internal/ceres/rotation_test.cc b/internal/ceres/rotation_test.cc index 42fdfee..fab0a7a 100644 --- a/internal/ceres/rotation_test.cc +++ b/internal/ceres/rotation_test.cc
@@ -576,7 +576,8 @@ RotationMatrixToAngleAxis(matrix, round_trip); for (int i = 0; i < 3; ++i) { - EXPECT_NEAR(round_trip[i], axis_angle[i], std::numeric_limits<double>::epsilon()); + EXPECT_NEAR(round_trip[i], axis_angle[i], + std::numeric_limits<double>::epsilon()); } } }
diff --git a/internal/ceres/solver.cc b/internal/ceres/solver.cc index 67e168c..da87de1 100644 --- a/internal/ceres/solver.cc +++ b/internal/ceres/solver.cc
@@ -85,8 +85,8 @@ // Invalid values for most fields, to ensure that we are not // accidentally reporting default values. : minimizer_type(TRUST_REGION), - termination_type(DID_NOT_RUN), - error("ceres::Solve was not called."), + termination_type(FAILURE), + message("ceres::Solve was not called."), initial_cost(-1.0), final_cost(-1.0), fixed_cost(-1.0), @@ -131,64 +131,40 @@ max_lbfgs_rank(-1) { } -string Solver::Summary::BriefReport() const { - string report = "Ceres Solver Report: "; - if (termination_type == DID_NOT_RUN) { - return report + "Termination: DID_NOT_RUN, because " + error; - } - - internal::StringAppendF(&report, "Iterations: %d", - num_successful_steps + num_unsuccessful_steps); - internal::StringAppendF(&report, ", Initial cost: %e", initial_cost); - - // If the solver failed or was aborted, then the final_cost has no - // meaning. - if (termination_type != NUMERICAL_FAILURE && - termination_type != USER_ABORT) { - internal::StringAppendF(&report, ", Final cost: %e", final_cost); - } - - internal::StringAppendF(&report, ", Termination: %s.", - SolverTerminationTypeToString(termination_type)); - return report; -}; - using internal::StringAppendF; using internal::StringPrintf; +string Solver::Summary::BriefReport() const { + return StringPrintf("Ceres Solver Report: " + "Iterations: %d, " + "Initial cost: %e, " + "Final cost: %e, " + "Termination: %s", + num_successful_steps + num_unsuccessful_steps, + initial_cost, + final_cost, + TerminationTypeToString(termination_type)); +}; + string Solver::Summary::FullReport() const { string report = "\n" "Ceres Solver Report\n" "-------------------\n"; - if (termination_type == DID_NOT_RUN) { - StringAppendF(&report, " Original\n"); - StringAppendF(&report, "Parameter blocks % 10d\n", num_parameter_blocks); - StringAppendF(&report, "Parameters % 10d\n", num_parameters); - if (num_effective_parameters != num_parameters) { - StringAppendF(&report, "Effective parameters% 10d\n", num_parameters); - } - - StringAppendF(&report, "Residual blocks % 10d\n", - num_residual_blocks); - StringAppendF(&report, "Residuals % 10d\n\n", - num_residuals); - } else { - StringAppendF(&report, "%45s %21s\n", "Original", "Reduced"); - StringAppendF(&report, "Parameter blocks % 25d% 25d\n", - num_parameter_blocks, num_parameter_blocks_reduced); - StringAppendF(&report, "Parameters % 25d% 25d\n", - num_parameters, num_parameters_reduced); - if (num_effective_parameters_reduced != num_parameters_reduced) { - StringAppendF(&report, "Effective parameters% 25d% 25d\n", - num_effective_parameters, num_effective_parameters_reduced); - } - StringAppendF(&report, "Residual blocks % 25d% 25d\n", - num_residual_blocks, num_residual_blocks_reduced); - StringAppendF(&report, "Residual % 25d% 25d\n", - num_residuals, num_residuals_reduced); + StringAppendF(&report, "%45s %21s\n", "Original", "Reduced"); + StringAppendF(&report, "Parameter blocks % 25d% 25d\n", + num_parameter_blocks, num_parameter_blocks_reduced); + StringAppendF(&report, "Parameters % 25d% 25d\n", + num_parameters, num_parameters_reduced); + if (num_effective_parameters_reduced != num_parameters_reduced) { + StringAppendF(&report, "Effective parameters% 25d% 25d\n", + num_effective_parameters, num_effective_parameters_reduced); } + StringAppendF(&report, "Residual blocks % 25d% 25d\n", + num_residual_blocks, num_residual_blocks_reduced); + StringAppendF(&report, "Residual % 25d% 25d\n", + num_residuals, num_residuals_reduced); if (minimizer_type == TRUST_REGION) { // TRUST_SEARCH HEADER @@ -314,17 +290,10 @@ num_threads_given, num_threads_used); } - if (termination_type == DID_NOT_RUN) { - StringAppendF(&report, "Termination: %20s\n", - "DID_NOT_RUN"); - StringAppendF(&report, "Reason: %s\n", error.c_str()); - return report; - } - StringAppendF(&report, "\nCost:\n"); StringAppendF(&report, "Initial % 30e\n", initial_cost); - if (termination_type != NUMERICAL_FAILURE && - termination_type != USER_ABORT) { + if (termination_type != FAILURE && + termination_type != USER_FAILURE) { StringAppendF(&report, "Final % 30e\n", final_cost); StringAppendF(&report, "Change % 30e\n", initial_cost - final_cost); @@ -376,8 +345,14 @@ total_time_in_seconds); StringAppendF(&report, "Termination: %25s\n", - SolverTerminationTypeToString(termination_type)); + TerminationTypeToString(termination_type)); return report; }; +bool Solver::Summary::IsSolutionUsable() const { + return (termination_type == CONVERGENCE || + termination_type == NO_CONVERGENCE || + termination_type == USER_SUCCESS); +} + } // namespace ceres
diff --git a/internal/ceres/solver_impl.cc b/internal/ceres/solver_impl.cc index 1ebf442..f48ad3b 100644 --- a/internal/ceres/solver_impl.cc +++ b/internal/ceres/solver_impl.cc
@@ -360,14 +360,14 @@ // Empty programs are usually a user error. if (summary->num_parameter_blocks == 0) { - summary->error = "Problem contains no parameter blocks."; - LOG(ERROR) << summary->error; + summary->message = "Problem contains no parameter blocks."; + LOG(ERROR) << summary->message; return; } if (summary->num_residual_blocks == 0) { - summary->error = "Problem contains no residual blocks."; - LOG(ERROR) << summary->error; + summary->message = "Problem contains no residual blocks."; + LOG(ERROR) << summary->message; return; } @@ -404,9 +404,9 @@ if (options.trust_region_minimizer_iterations_to_dump.size() > 0 && options.trust_region_problem_dump_format_type != CONSOLE && options.trust_region_problem_dump_directory.empty()) { - summary->error = + summary->message = "Solver::Options::trust_region_problem_dump_directory is empty."; - LOG(ERROR) << summary->error; + LOG(ERROR) << summary->message; return; } @@ -434,8 +434,8 @@ } if (original_options.linear_solver_ordering != NULL) { - if (!IsOrderingValid(original_options, problem_impl, &summary->error)) { - LOG(ERROR) << summary->error; + if (!IsOrderingValid(original_options, problem_impl, &summary->message)) { + LOG(ERROR) << summary->message; return; } event_logger.AddEvent("CheckOrdering"); @@ -466,7 +466,7 @@ scoped_ptr<Program> reduced_program(CreateReducedProgram(&options, problem_impl, &summary->fixed_cost, - &summary->error)); + &summary->message)); event_logger.AddEvent("CreateReducedProgram"); if (reduced_program == NULL) { @@ -488,17 +488,16 @@ WallTimeInSeconds() - solver_start_time; double post_process_start_time = WallTimeInSeconds(); - LOG(INFO) << "Terminating: FUNCTION_TOLERANCE reached. " - << "No non-constant parameter blocks found."; + + summary->message = + "Terminating: Function tolerance reached. " + "No non-constant parameter blocks found."; + summary->termination_type = CONVERGENCE; + VLOG(1) << summary->message; summary->initial_cost = summary->fixed_cost; summary->final_cost = summary->fixed_cost; - // FUNCTION_TOLERANCE is the right convergence here, as we know - // that the objective function is constant and cannot be changed - // any further. - summary->termination_type = FUNCTION_TOLERANCE; - // Ensure the program state is set to the user parameters on the way out. original_program->SetParameterBlockStatePtrsToUserStatePtrs(); original_program->SetParameterOffsetsAndIndex(); @@ -509,7 +508,7 @@ } scoped_ptr<LinearSolver> - linear_solver(CreateLinearSolver(&options, &summary->error)); + linear_solver(CreateLinearSolver(&options, &summary->message)); event_logger.AddEvent("CreateLinearSolver"); if (linear_solver == NULL) { return; @@ -536,7 +535,7 @@ scoped_ptr<Evaluator> evaluator(CreateEvaluator(options, problem_impl->parameter_map(), reduced_program.get(), - &summary->error)); + &summary->message)); event_logger.AddEvent("CreateEvaluator"); @@ -556,7 +555,7 @@ problem_impl->parameter_map(), summary)); if (inner_iteration_minimizer == NULL) { - LOG(ERROR) << summary->error; + LOG(ERROR) << summary->message; return; } } @@ -590,8 +589,8 @@ // If the user aborted mid-optimization or the optimization // terminated because of a numerical failure, then return without // updating user state. - if (summary->termination_type == USER_ABORT || - summary->termination_type == NUMERICAL_FAILURE) { + if (summary->termination_type == USER_FAILURE || + summary->termination_type == FAILURE) { return; } @@ -662,45 +661,46 @@ if ((original_options.line_search_direction_type == ceres::BFGS || original_options.line_search_direction_type == ceres::LBFGS) && original_options.line_search_type != ceres::WOLFE) { - summary->error = + summary->message = string("Invalid configuration: require line_search_type == " "ceres::WOLFE when using (L)BFGS to ensure that underlying " "assumptions are guaranteed to be satisfied."); - LOG(ERROR) << summary->error; + LOG(ERROR) << summary->message; return; } if (original_options.max_lbfgs_rank <= 0) { - summary->error = + summary->message = string("Invalid configuration: require max_lbfgs_rank > 0"); - LOG(ERROR) << summary->error; + LOG(ERROR) << summary->message; return; } if (original_options.min_line_search_step_size <= 0.0) { - summary->error = "Invalid configuration: min_line_search_step_size <= 0.0."; - LOG(ERROR) << summary->error; + summary->message = + "Invalid configuration: min_line_search_step_size <= 0.0."; + LOG(ERROR) << summary->message; return; } if (original_options.line_search_sufficient_function_decrease <= 0.0) { - summary->error = + summary->message = string("Invalid configuration: require ") + string("line_search_sufficient_function_decrease <= 0.0."); - LOG(ERROR) << summary->error; + LOG(ERROR) << summary->message; return; } if (original_options.max_line_search_step_contraction <= 0.0 || original_options.max_line_search_step_contraction >= 1.0) { - summary->error = string("Invalid configuration: require ") + + summary->message = string("Invalid configuration: require ") + string("0.0 < max_line_search_step_contraction < 1.0."); - LOG(ERROR) << summary->error; + LOG(ERROR) << summary->message; return; } if (original_options.min_line_search_step_contraction <= original_options.max_line_search_step_contraction || original_options.min_line_search_step_contraction > 1.0) { - summary->error = string("Invalid configuration: require ") + + summary->message = string("Invalid configuration: require ") + string("max_line_search_step_contraction < ") + string("min_line_search_step_contraction <= 1.0."); - LOG(ERROR) << summary->error; + LOG(ERROR) << summary->message; return; } // Warn user if they have requested BISECTION interpolation, but constraints @@ -718,37 +718,37 @@ << original_options.min_line_search_step_contraction << ", prevent bisection (0.5) scaling, continuing with solve regardless."; if (original_options.max_num_line_search_step_size_iterations <= 0) { - summary->error = string("Invalid configuration: require ") + + summary->message = string("Invalid configuration: require ") + string("max_num_line_search_step_size_iterations > 0."); - LOG(ERROR) << summary->error; + LOG(ERROR) << summary->message; return; } if (original_options.line_search_sufficient_curvature_decrease <= original_options.line_search_sufficient_function_decrease || original_options.line_search_sufficient_curvature_decrease > 1.0) { - summary->error = string("Invalid configuration: require ") + + summary->message = string("Invalid configuration: require ") + string("line_search_sufficient_function_decrease < ") + string("line_search_sufficient_curvature_decrease < 1.0."); - LOG(ERROR) << summary->error; + LOG(ERROR) << summary->message; return; } if (original_options.max_line_search_step_expansion <= 1.0) { - summary->error = string("Invalid configuration: require ") + + summary->message = string("Invalid configuration: require ") + string("max_line_search_step_expansion > 1.0."); - LOG(ERROR) << summary->error; + LOG(ERROR) << summary->message; return; } // Empty programs are usually a user error. if (summary->num_parameter_blocks == 0) { - summary->error = "Problem contains no parameter blocks."; - LOG(ERROR) << summary->error; + summary->message = "Problem contains no parameter blocks."; + LOG(ERROR) << summary->message; return; } if (summary->num_residual_blocks == 0) { - summary->error = "Problem contains no residual blocks."; - LOG(ERROR) << summary->error; + summary->message = "Problem contains no residual blocks."; + LOG(ERROR) << summary->message; return; } @@ -777,8 +777,8 @@ summary->num_threads_used = options.num_threads; if (original_options.linear_solver_ordering != NULL) { - if (!IsOrderingValid(original_options, problem_impl, &summary->error)) { - LOG(ERROR) << summary->error; + if (!IsOrderingValid(original_options, problem_impl, &summary->message)) { + LOG(ERROR) << summary->message; return; } options.linear_solver_ordering = @@ -819,7 +819,7 @@ scoped_ptr<Program> reduced_program(CreateReducedProgram(&options, problem_impl, &summary->fixed_cost, - &summary->error)); + &summary->message)); if (reduced_program == NULL) { return; } @@ -835,16 +835,13 @@ summary->preprocessor_time_in_seconds = WallTimeInSeconds() - solver_start_time; - LOG(INFO) << "Terminating: FUNCTION_TOLERANCE reached. " - << "No non-constant parameter blocks found."; - - // FUNCTION_TOLERANCE is the right convergence here, as we know - // that the objective function is constant and cannot be changed - // any further. - summary->termination_type = FUNCTION_TOLERANCE; + summary->message = + "Terminating: Function tolerance reached. " + "No non-constant parameter blocks found."; + summary->termination_type = CONVERGENCE; + VLOG(1) << summary->message; const double post_process_start_time = WallTimeInSeconds(); - SetSummaryFinalCost(summary); // Ensure the program state is set to the user parameters on the way out. @@ -859,7 +856,7 @@ scoped_ptr<Evaluator> evaluator(CreateEvaluator(options, problem_impl->parameter_map(), reduced_program.get(), - &summary->error)); + &summary->message)); if (evaluator == NULL) { return; } @@ -886,8 +883,8 @@ // If the user aborted mid-optimization or the optimization // terminated because of a numerical failure, then return without // updating user state. - if (summary->termination_type == USER_ABORT || - summary->termination_type == NUMERICAL_FAILURE) { + if (summary->termination_type == USER_FAILURE || + summary->termination_type == FAILURE) { return; } @@ -1456,7 +1453,7 @@ for ( ; it != group_to_elements.end(); ++it) { if (!IsParameterBlockSetIndependent(it->second, program.residual_blocks())) { - summary->error = + summary->message = StringPrintf("The user-provided " "parameter_blocks_for_inner_iterations does not " "form an independent set. Group Id: %d", it->first); @@ -1469,7 +1466,7 @@ if (!inner_iteration_minimizer->Init(program, parameter_map, *ordering_ptr, - &summary->error)) { + &summary->message)) { return NULL; }
diff --git a/internal/ceres/solver_impl.h b/internal/ceres/solver_impl.h index aef63b0..5191bc4 100644 --- a/internal/ceres/solver_impl.h +++ b/internal/ceres/solver_impl.h
@@ -93,7 +93,7 @@ static Program* CreateReducedProgram(Solver::Options* options, ProblemImpl* problem_impl, double* fixed_cost, - string* error); + string* message); // Create the appropriate linear solver, taking into account any // config changes decided by CreateTransformedProgram(). The @@ -101,7 +101,7 @@ // selected; consider the case that the remaining elimininated // blocks is zero after removing fixed blocks. static LinearSolver* CreateLinearSolver(Solver::Options* options, - string* error); + string* message); // Reorder the residuals for program, if necessary, so that the // residuals involving e block (i.e., the first num_eliminate_block @@ -110,14 +110,14 @@ static bool LexicographicallyOrderResidualBlocks( const int num_eliminate_blocks, Program* program, - string* error); + string* message); // Create the appropriate evaluator for the transformed program. static Evaluator* CreateEvaluator( const Solver::Options& options, const ProblemImpl::ParameterMap& parameter_map, Program* program, - string* error); + string* message); // Remove the fixed or unused parameter blocks and residuals // depending only on fixed parameters from the program. @@ -131,17 +131,17 @@ // fixed_cost. // // If a failure is encountered, the function returns false with a - // description of the failure in error. + // description of the failure in message. static bool RemoveFixedBlocksFromProgram( Program* program, ParameterBlockOrdering* linear_solver_ordering, ParameterBlockOrdering* inner_iteration_ordering, double* fixed_cost, - string* error); + string* message); static bool IsOrderingValid(const Solver::Options& options, const ProblemImpl* problem_impl, - string* error); + string* message); static bool IsParameterBlockSetIndependent( const set<double*>& parameter_block_ptrs, @@ -176,7 +176,7 @@ const ProblemImpl::ParameterMap& parameter_map, const ParameterBlockOrdering* parameter_block_ordering, Program* program, - string* error); + string* message); // Sparse cholesky factorization routines when doing the sparse // cholesky factorization of the Jacobian matrix, reorders its @@ -192,7 +192,7 @@ const SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type, const ParameterBlockOrdering* parameter_block_ordering, Program* program, - string* error); + string* message); // Schur type solvers require that all parameter blocks eliminated // by the Schur eliminator occur before others and the residuals be @@ -216,7 +216,7 @@ const ProblemImpl::ParameterMap& parameter_map, ParameterBlockOrdering* parameter_block_ordering, Program* program, - string* error); + string* message); // array contains a list of (possibly repeating) non-negative // integers. Let us assume that we have constructed another array
diff --git a/internal/ceres/solver_impl_test.cc b/internal/ceres/solver_impl_test.cc index a605de0..43a3b97 100644 --- a/internal/ceres/solver_impl_test.cc +++ b/internal/ceres/solver_impl_test.cc
@@ -86,7 +86,7 @@ problem.AddResidualBlock(new BinaryCostFunction(), NULL, &x, &y); problem.AddResidualBlock(new TernaryCostFunction(), NULL, &x, &y, &z); - string error; + string message; { ParameterBlockOrdering linear_solver_ordering; linear_solver_ordering.AddElementToGroup(&x, 0); @@ -104,7 +104,7 @@ &linear_solver_ordering, &inner_iteration_ordering, NULL, - &error)); + &message)); EXPECT_EQ(program.NumParameterBlocks(), 3); EXPECT_EQ(program.NumResidualBlocks(), 3); EXPECT_EQ(linear_solver_ordering.NumElements(), 3); @@ -127,13 +127,13 @@ inner_iteration_ordering.AddElementToGroup(&x, 0); Program program(problem.program()); - string error; + string message; EXPECT_TRUE(SolverImpl::RemoveFixedBlocksFromProgram( &program, &linear_solver_ordering, &inner_iteration_ordering, NULL, - &error)); + &message)); EXPECT_EQ(program.NumParameterBlocks(), 0); EXPECT_EQ(program.NumResidualBlocks(), 0); EXPECT_EQ(linear_solver_ordering.NumElements(), 0); @@ -161,13 +161,13 @@ inner_iteration_ordering.AddElementToGroup(&z, 0); Program program(problem.program()); - string error; + string message; EXPECT_TRUE(SolverImpl::RemoveFixedBlocksFromProgram( &program, &linear_solver_ordering, &inner_iteration_ordering, NULL, - &error)); + &message)); EXPECT_EQ(program.NumParameterBlocks(), 0); EXPECT_EQ(program.NumResidualBlocks(), 0); EXPECT_EQ(linear_solver_ordering.NumElements(), 0); @@ -200,13 +200,13 @@ Program program(problem.program()); - string error; + string message; EXPECT_TRUE(SolverImpl::RemoveFixedBlocksFromProgram( &program, &linear_solver_ordering, &inner_iteration_ordering, NULL, - &error)); + &message)); EXPECT_EQ(program.NumParameterBlocks(), 1); EXPECT_EQ(program.NumResidualBlocks(), 1); EXPECT_EQ(linear_solver_ordering.NumElements(), 1); @@ -238,13 +238,13 @@ inner_iteration_ordering.AddElementToGroup(&z, 1); Program program(problem.program()); - string error; + string message; EXPECT_TRUE(SolverImpl::RemoveFixedBlocksFromProgram( &program, &linear_solver_ordering, &inner_iteration_ordering, NULL, - &error)); + &message)); EXPECT_EQ(program.NumParameterBlocks(), 2); EXPECT_EQ(program.NumResidualBlocks(), 2); EXPECT_EQ(linear_solver_ordering.NumElements(), 2); @@ -287,13 +287,13 @@ NULL, scratch.get()); - string error; + string message; EXPECT_TRUE(SolverImpl::RemoveFixedBlocksFromProgram( &program, &linear_solver_ordering, NULL, &fixed_cost, - &error)); + &message)); EXPECT_EQ(program.NumParameterBlocks(), 2); EXPECT_EQ(program.NumResidualBlocks(), 2); EXPECT_EQ(linear_solver_ordering.NumElements(), 2); @@ -347,11 +347,11 @@ Program* program = problem.mutable_program(); program->SetParameterOffsetsAndIndex(); - string error; + string message; EXPECT_TRUE(SolverImpl::LexicographicallyOrderResidualBlocks( 2, problem.mutable_program(), - &error)); + &message)); EXPECT_EQ(residual_blocks.size(), expected_residual_blocks.size()); for (int i = 0; i < expected_residual_blocks.size(); ++i) { EXPECT_EQ(residual_blocks[i], expected_residual_blocks[i]); @@ -392,9 +392,9 @@ // Create the reduced program. This should remove the fixed block "z", // marking the index to -1 at the same time. x and y also get indices. - string error; + string message; scoped_ptr<Program> reduced_program( - SolverImpl::CreateReducedProgram(&options, &problem, NULL, &error)); + SolverImpl::CreateReducedProgram(&options, &problem, NULL, &message)); const vector<ResidualBlock*>& residual_blocks = problem.program().residual_blocks(); @@ -459,9 +459,9 @@ options.linear_solver_type = DENSE_SCHUR; options.linear_solver_ordering = linear_solver_ordering; - string error; + string message; scoped_ptr<Program> reduced_program( - SolverImpl::CreateReducedProgram(&options, &problem, NULL, &error)); + SolverImpl::CreateReducedProgram(&options, &problem, NULL, &message)); const vector<ResidualBlock*>& residual_blocks = reduced_program->residual_blocks(); @@ -499,11 +499,11 @@ linear_solver_ordering.AddElementToGroup(&y, 1); Program program(problem.program()); - string error; + string message; EXPECT_FALSE(SolverImpl::ApplyUserOrdering(problem.parameter_map(), &linear_solver_ordering, &program, - &error)); + &message)); } TEST(SolverImpl, ApplyUserOrderingNormal) { @@ -522,12 +522,12 @@ linear_solver_ordering.AddElementToGroup(&z, 1); Program* program = problem.mutable_program(); - string error; + string message; EXPECT_TRUE(SolverImpl::ApplyUserOrdering(problem.parameter_map(), &linear_solver_ordering, program, - &error)); + &message)); const vector<ParameterBlock*>& parameter_blocks = program->parameter_blocks(); EXPECT_EQ(parameter_blocks.size(), 3); @@ -542,8 +542,8 @@ options.linear_solver_type = SPARSE_NORMAL_CHOLESKY; // CreateLinearSolver assumes a non-empty ordering. options.linear_solver_ordering = new ParameterBlockOrdering; - string error; - EXPECT_FALSE(SolverImpl::CreateLinearSolver(&options, &error)); + string message; + EXPECT_FALSE(SolverImpl::CreateLinearSolver(&options, &message)); } #endif @@ -553,8 +553,8 @@ options.max_linear_solver_iterations = -1; // CreateLinearSolver assumes a non-empty ordering. options.linear_solver_ordering = new ParameterBlockOrdering; - string error; - EXPECT_EQ(SolverImpl::CreateLinearSolver(&options, &error), + string message; + EXPECT_EQ(SolverImpl::CreateLinearSolver(&options, &message), static_cast<LinearSolver*>(NULL)); } @@ -564,8 +564,8 @@ options.min_linear_solver_iterations = -1; // CreateLinearSolver assumes a non-empty ordering. options.linear_solver_ordering = new ParameterBlockOrdering; - string error; - EXPECT_EQ(SolverImpl::CreateLinearSolver(&options, &error), + string message; + EXPECT_EQ(SolverImpl::CreateLinearSolver(&options, &message), static_cast<LinearSolver*>(NULL)); } @@ -575,8 +575,8 @@ options.min_linear_solver_iterations = 10; options.max_linear_solver_iterations = 5; options.linear_solver_ordering = new ParameterBlockOrdering; - string error; - EXPECT_EQ(SolverImpl::CreateLinearSolver(&options, &error), + string message; + EXPECT_EQ(SolverImpl::CreateLinearSolver(&options, &message), static_cast<LinearSolver*>(NULL)); } @@ -592,9 +592,9 @@ options.linear_solver_ordering->AddElementToGroup(&x, 0); options.linear_solver_ordering->AddElementToGroup(&y, 0); - string error; + string message; scoped_ptr<LinearSolver> solver( - SolverImpl::CreateLinearSolver(&options, &error)); + SolverImpl::CreateLinearSolver(&options, &message)); EXPECT_TRUE(solver != NULL); EXPECT_EQ(options.linear_solver_type, DENSE_SCHUR); EXPECT_EQ(options.num_linear_solver_threads, 2); @@ -605,13 +605,13 @@ options.trust_region_strategy_type = DOGLEG; // CreateLinearSolver assumes a non-empty ordering. options.linear_solver_ordering = new ParameterBlockOrdering; - string error; + string message; options.linear_solver_type = ITERATIVE_SCHUR; - EXPECT_EQ(SolverImpl::CreateLinearSolver(&options, &error), + EXPECT_EQ(SolverImpl::CreateLinearSolver(&options, &message), static_cast<LinearSolver*>(NULL)); options.linear_solver_type = CGNR; - EXPECT_EQ(SolverImpl::CreateLinearSolver(&options, &error), + EXPECT_EQ(SolverImpl::CreateLinearSolver(&options, &message), static_cast<LinearSolver*>(NULL)); } @@ -621,20 +621,20 @@ options.linear_solver_type = DENSE_QR; // CreateLinearSolver assumes a non-empty ordering. options.linear_solver_ordering = new ParameterBlockOrdering; - string error; - solver.reset(SolverImpl::CreateLinearSolver(&options, &error)); + string message; + solver.reset(SolverImpl::CreateLinearSolver(&options, &message)); EXPECT_EQ(options.linear_solver_type, DENSE_QR); EXPECT_TRUE(solver.get() != NULL); options.linear_solver_type = DENSE_NORMAL_CHOLESKY; - solver.reset(SolverImpl::CreateLinearSolver(&options, &error)); + solver.reset(SolverImpl::CreateLinearSolver(&options, &message)); EXPECT_EQ(options.linear_solver_type, DENSE_NORMAL_CHOLESKY); EXPECT_TRUE(solver.get() != NULL); #ifndef CERES_NO_SUITESPARSE options.linear_solver_type = SPARSE_NORMAL_CHOLESKY; options.sparse_linear_algebra_library_type = SUITE_SPARSE; - solver.reset(SolverImpl::CreateLinearSolver(&options, &error)); + solver.reset(SolverImpl::CreateLinearSolver(&options, &message)); EXPECT_EQ(options.linear_solver_type, SPARSE_NORMAL_CHOLESKY); EXPECT_TRUE(solver.get() != NULL); #endif @@ -642,7 +642,7 @@ #ifndef CERES_NO_CXSPARSE options.linear_solver_type = SPARSE_NORMAL_CHOLESKY; options.sparse_linear_algebra_library_type = CX_SPARSE; - solver.reset(SolverImpl::CreateLinearSolver(&options, &error)); + solver.reset(SolverImpl::CreateLinearSolver(&options, &message)); EXPECT_EQ(options.linear_solver_type, SPARSE_NORMAL_CHOLESKY); EXPECT_TRUE(solver.get() != NULL); #endif @@ -653,22 +653,22 @@ options.linear_solver_ordering->AddElementToGroup(&y, 0); options.linear_solver_type = DENSE_SCHUR; - solver.reset(SolverImpl::CreateLinearSolver(&options, &error)); + solver.reset(SolverImpl::CreateLinearSolver(&options, &message)); EXPECT_EQ(options.linear_solver_type, DENSE_SCHUR); EXPECT_TRUE(solver.get() != NULL); options.linear_solver_type = SPARSE_SCHUR; - solver.reset(SolverImpl::CreateLinearSolver(&options, &error)); + solver.reset(SolverImpl::CreateLinearSolver(&options, &message)); #if defined(CERES_NO_SUITESPARSE) && defined(CERES_NO_CXSPARSE) - EXPECT_TRUE(SolverImpl::CreateLinearSolver(&options, &error) == NULL); + EXPECT_TRUE(SolverImpl::CreateLinearSolver(&options, &message) == NULL); #else EXPECT_TRUE(solver.get() != NULL); EXPECT_EQ(options.linear_solver_type, SPARSE_SCHUR); #endif options.linear_solver_type = ITERATIVE_SCHUR; - solver.reset(SolverImpl::CreateLinearSolver(&options, &error)); + solver.reset(SolverImpl::CreateLinearSolver(&options, &message)); EXPECT_EQ(options.linear_solver_type, ITERATIVE_SCHUR); EXPECT_TRUE(solver.get() != NULL); } @@ -803,8 +803,8 @@ Solver::Options options; Solver::Summary summary; SolverImpl::Solve(options, &problem_impl, &summary); - EXPECT_EQ(summary.termination_type, DID_NOT_RUN); - EXPECT_EQ(summary.error, "Problem contains no parameter blocks."); + EXPECT_EQ(summary.termination_type, FAILURE); + EXPECT_EQ(summary.message, "Problem contains no parameter blocks."); } TEST(SolverImpl, NoResiduals) { @@ -814,8 +814,8 @@ double x = 1; problem_impl.AddParameterBlock(&x, 1); SolverImpl::Solve(options, &problem_impl, &summary); - EXPECT_EQ(summary.termination_type, DID_NOT_RUN); - EXPECT_EQ(summary.error, "Problem contains no residual blocks."); + EXPECT_EQ(summary.termination_type, FAILURE); + EXPECT_EQ(summary.message, "Problem contains no residual blocks."); } @@ -827,7 +827,7 @@ problem_impl.AddResidualBlock(new UnaryIdentityCostFunction, NULL, &x); problem_impl.SetParameterBlockConstant(&x); SolverImpl::Solve(options, &problem_impl, &summary); - EXPECT_EQ(summary.termination_type, FUNCTION_TOLERANCE); + EXPECT_EQ(summary.termination_type, CONVERGENCE); EXPECT_EQ(summary.initial_cost, 1.0 / 2.0); EXPECT_EQ(summary.final_cost, 1.0 / 2.0); }
diff --git a/internal/ceres/system_test.cc b/internal/ceres/system_test.cc index 7b0e02d..eb2e24c 100644 --- a/internal/ceres/system_test.cc +++ b/internal/ceres/system_test.cc
@@ -63,9 +63,10 @@ // Struct used for configuring the solver. struct SolverConfig { - SolverConfig(LinearSolverType linear_solver_type, - SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type, - bool use_automatic_ordering) + SolverConfig( + LinearSolverType linear_solver_type, + SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type, + bool use_automatic_ordering) : linear_solver_type(linear_solver_type), sparse_linear_algebra_library_type(sparse_linear_algebra_library_type), use_automatic_ordering(use_automatic_ordering), @@ -73,10 +74,11 @@ num_threads(1) { } - SolverConfig(LinearSolverType linear_solver_type, - SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type, - bool use_automatic_ordering, - PreconditionerType preconditioner_type) + SolverConfig( + LinearSolverType linear_solver_type, + SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type, + bool use_automatic_ordering, + PreconditionerType preconditioner_type) : linear_solver_type(linear_solver_type), sparse_linear_algebra_library_type(sparse_linear_algebra_library_type), use_automatic_ordering(use_automatic_ordering), @@ -88,7 +90,8 @@ return StringPrintf( "(%s, %s, %s, %s, %d)", LinearSolverTypeToString(linear_solver_type), - SparseLinearAlgebraLibraryTypeToString(sparse_linear_algebra_library_type), + SparseLinearAlgebraLibraryTypeToString( + sparse_linear_algebra_library_type), use_automatic_ordering ? "AUTOMATIC" : "USER", PreconditionerTypeToString(preconditioner_type), num_threads); @@ -157,7 +160,7 @@ NULL, NULL); - CHECK_NE(summary.termination_type, ceres::NUMERICAL_FAILURE) + CHECK_NE(summary.termination_type, ceres::FAILURE) << "Solver configuration " << i << " failed."; problems.push_back(system_test_problem);
diff --git a/internal/ceres/trust_region_minimizer.cc b/internal/ceres/trust_region_minimizer.cc index 8c5800e..f9f14e0 100644 --- a/internal/ceres/trust_region_minimizer.cc +++ b/internal/ceres/trust_region_minimizer.cc
@@ -128,9 +128,9 @@ residuals.data(), gradient.data(), jacobian)) { - summary->error = "Terminating: Residual and Jacobian evaluation failed."; - summary->termination_type = NUMERICAL_FAILURE; - LOG_IF(WARNING, is_not_silent) << summary->error; + summary->message = "Terminating: Residual and Jacobian evaluation failed."; + summary->termination_type = FAILURE; + LOG_IF(WARNING, is_not_silent) << summary->message; return; } @@ -154,13 +154,13 @@ options_.gradient_tolerance * initial_gradient_max_norm; if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) { - summary->error = StringPrintf("Terminating: Gradient tolerance reached. " + summary->message = StringPrintf("Terminating: Gradient tolerance reached. " "Relative gradient max norm: %e <= %e", (iteration_summary.gradient_max_norm / initial_gradient_max_norm), options_.gradient_tolerance); - summary->termination_type = GRADIENT_TOLERANCE; - VLOG_IF(1, is_not_silent) << summary->error; + summary->termination_type = CONVERGENCE; + VLOG_IF(1, is_not_silent) << summary->message; return; } @@ -188,18 +188,18 @@ iteration_start_time = WallTimeInSeconds(); if (iteration_summary.iteration >= options_.max_num_iterations) { - summary->error = "Terminating: Maximum number of iterations reached."; + summary->message = "Terminating: Maximum number of iterations reached."; summary->termination_type = NO_CONVERGENCE; - VLOG_IF(1, is_not_silent) << summary->error; + VLOG_IF(1, is_not_silent) << summary->message; return; } const double total_solver_time = iteration_start_time - start_time + summary->preprocessor_time_in_seconds; if (total_solver_time >= options_.max_solver_time_in_seconds) { - summary->error = "Terminating: Maximum solver time reached."; + summary->message = "Terminating: Maximum solver time reached."; summary->termination_type = NO_CONVERGENCE; - VLOG_IF(1, is_not_silent) << summary->error; + VLOG_IF(1, is_not_silent) << summary->message; return; } @@ -228,11 +228,11 @@ trust_region_step.data()); if (strategy_summary.termination_type == LINEAR_SOLVER_FATAL_ERROR) { - summary->error = + summary->message = "Terminating. Linear solver failed due to unrecoverable " "non-numeric causes. Please see the error log for clues. "; - summary->termination_type = NUMERICAL_FAILURE; - LOG_IF(WARNING, is_not_silent) << summary->error; + summary->termination_type = FAILURE; + LOG_IF(WARNING, is_not_silent) << summary->message; return; } @@ -272,15 +272,15 @@ if (!iteration_summary.step_is_valid) { // Invalid steps can happen due to a number of reasons, and we // allow a limited number of successive failures, and return with - // NUMERICAL_FAILURE if this limit is exceeded. + // FAILURE if this limit is exceeded. if (++num_consecutive_invalid_steps >= options_.max_num_consecutive_invalid_steps) { - summary->error = StringPrintf( + summary->message = StringPrintf( "Terminating. Number of successive invalid steps more " "than Solver::Options::max_num_consecutive_invalid_steps: %d", options_.max_num_consecutive_invalid_steps); - summary->termination_type = NUMERICAL_FAILURE; - LOG_IF(WARNING, is_not_silent) << summary->error; + summary->termination_type = FAILURE; + LOG_IF(WARNING, is_not_silent) << summary->message; return; } @@ -367,14 +367,14 @@ const double step_size_tolerance = options_.parameter_tolerance * (x_norm + options_.parameter_tolerance); if (iteration_summary.step_norm <= step_size_tolerance) { - summary->error = + summary->message = StringPrintf("Terminating. Parameter tolerance reached. " "relative step_norm: %e <= %e.", (iteration_summary.step_norm / (x_norm + options_.parameter_tolerance)), options_.parameter_tolerance); - summary->termination_type = PARAMETER_TOLERANCE; - VLOG_IF(1, is_not_silent) << summary->error; + summary->termination_type = CONVERGENCE; + VLOG_IF(1, is_not_silent) << summary->message; return; } @@ -382,13 +382,13 @@ const double absolute_function_tolerance = options_.function_tolerance * cost; if (fabs(iteration_summary.cost_change) < absolute_function_tolerance) { - summary->error = + summary->message = StringPrintf("Terminating. Function tolerance reached. " "|cost_change|/cost: %e <= %e", fabs(iteration_summary.cost_change) / cost, options_.function_tolerance); - summary->termination_type = FUNCTION_TOLERANCE; - VLOG_IF(1, is_not_silent) << summary->error; + summary->termination_type = CONVERGENCE; + VLOG_IF(1, is_not_silent) << summary->message; return; } @@ -485,10 +485,10 @@ residuals.data(), gradient.data(), jacobian)) { - summary->error = + summary->message = "Terminating: Residual and Jacobian evaluation failed."; - summary->termination_type = NUMERICAL_FAILURE; - LOG_IF(WARNING, is_not_silent) << summary->error; + summary->termination_type = FAILURE; + LOG_IF(WARNING, is_not_silent) << summary->message; return; } @@ -496,14 +496,14 @@ iteration_summary.gradient_norm = gradient.norm(); if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) { - summary->error = + summary->message = StringPrintf("Terminating: Gradient tolerance reached. " "Relative gradient max norm: %e <= %e", (iteration_summary.gradient_max_norm / initial_gradient_max_norm), options_.gradient_tolerance); - summary->termination_type = GRADIENT_TOLERANCE; - VLOG_IF(1, is_not_silent) << summary->error; + summary->termination_type = CONVERGENCE; + VLOG_IF(1, is_not_silent) << summary->message; return; } @@ -566,9 +566,9 @@ iteration_summary.trust_region_radius = strategy->Radius(); if (iteration_summary.trust_region_radius < options_.min_trust_region_radius) { - summary->error = "Termination. Minimum trust region radius reached."; - summary->termination_type = PARAMETER_TOLERANCE; - VLOG_IF(1, is_not_silent) << summary->error; + summary->message = "Termination. Minimum trust region radius reached."; + summary->termination_type = CONVERGENCE; + VLOG_IF(1, is_not_silent) << summary->message; return; }
diff --git a/internal/ceres/types.cc b/internal/ceres/types.cc index 5f3455f..5a344ea 100644 --- a/internal/ceres/types.cc +++ b/internal/ceres/types.cc
@@ -297,16 +297,13 @@ return false; } -const char* SolverTerminationTypeToString(SolverTerminationType type) { +const char* TerminationTypeToString(TerminationType type) { switch (type) { + CASESTR(CONVERGENCE); CASESTR(NO_CONVERGENCE); - CASESTR(FUNCTION_TOLERANCE); - CASESTR(GRADIENT_TOLERANCE); - CASESTR(PARAMETER_TOLERANCE); - CASESTR(NUMERICAL_FAILURE); - CASESTR(USER_ABORT); + CASESTR(FAILURE); CASESTR(USER_SUCCESS); - CASESTR(DID_NOT_RUN); + CASESTR(USER_FAILURE); default: return "UNKNOWN"; }