Improve logging in Solver::Options::IsValid. The error message now includes the value of the offending option. Change-Id: Ic2493709f54f7efe59313d51d1ff9638191c8b38
diff --git a/internal/ceres/solver.cc b/internal/ceres/solver.cc index 39efb23..8f19886 100644 --- a/internal/ceres/solver.cc +++ b/internal/ceres/solver.cc
@@ -31,65 +31,51 @@ #include "ceres/solver.h" +#include <iostream> // NOLINT #include <vector> +#include "ceres/internal/port.h" #include "ceres/problem.h" #include "ceres/problem_impl.h" #include "ceres/program.h" #include "ceres/solver_impl.h" #include "ceres/stringprintf.h" -#include "ceres/wall_time.h" +#include "ceres/types.h" #include "ceres/version.h" +#include "ceres/wall_time.h" namespace ceres { namespace { -// TODO(sameeragarwal): These macros are not terribly informative when -// things do crash. It would be nice to actually print the offending -// value. - -#define OPTION_GT(x, y) \ - if (options.x <= y) { \ - *error = string("Invalid configuration. Violated constraint " \ - "Solver::Options::" #x " > " #y); \ +#define OPTION_OP(x, y, OP) \ + if (!(options.x OP y)) { \ + std::stringstream ss; \ + ss << "Invalid configuration. "; \ + ss << string("Solver::Options::" #x " = ") << options.x << ". "; \ + ss << "Violated constraint: "; \ + ss << string("Solver::Options::" #x " " #OP " "#y); \ + *error = ss.str(); \ return false; \ } -#define OPTION_GE(x, y) \ - if (options.x < y) { \ - *error = string("Invalid configuration. Violated constraint " \ - "Solver::Options::" #x " >= " #y); \ +#define OPTION_OP_OPTION(x, y, OP) \ + if (!(options.x OP options.y)) { \ + std::stringstream ss; \ + ss << "Invalid configuration. "; \ + ss << string("Solver::Options::" #x " = ") << options.x << ". "; \ + ss << string("Solver::Options::" #y " = ") << options.y << ". "; \ + ss << "Violated constraint: "; \ + ss << string("Solver::Options::" #x ); \ + ss << string(#OP " Solver::Options::" #y "."); \ + *error = ss.str(); \ return false; \ } -#define OPTION_LE(x, y) \ - if (options.x > y) { \ - *error = string("Invalid configuration. Violated constraint " \ - "Solver::Options::" #x " <= " #y); \ - return false; \ - } - -#define OPTION_LT(x, y) \ - if (options.x >= y) { \ - *error = string("Invalid configuration. Violated constraint " \ - "Solver::Options::" #x " < " #y); \ - return false; \ - } - -#define OPTION_LE_OPTION(x, y) \ - if (options.x > options.y) { \ - *error = string("Invalid configuration. Violated constraint " \ - "Solver::Options::" #x " <= " \ - "Solver::Options::" #y); \ - return false; \ - } - -#define OPTION_LT_OPTION(x, y) \ - if (options.x >= options.y) { \ - *error = string("Invalid configuration. Violated constraint " \ - "Solver::Options::" #x " < " \ - "Solver::Options::" #y); \ - return false; \ - } +#define OPTION_GE(x, y) OPTION_OP(x, y, >=); +#define OPTION_GT(x, y) OPTION_OP(x, y, >); +#define OPTION_LE(x, y) OPTION_OP(x, y, <=); +#define OPTION_LT(x, y) OPTION_OP(x, y, <); +#define OPTION_LE_OPTION(x, y) OPTION_OP_OPTION(x ,y, <=) +#define OPTION_LT_OPTION(x, y) OPTION_OP_OPTION(x ,y, <) bool CommonOptionsAreValid(const Solver::Options& options, string* error) { OPTION_GE(max_num_iterations, 0); @@ -251,10 +237,12 @@ if ((options.line_search_direction_type == ceres::BFGS || options.line_search_direction_type == ceres::LBFGS) && options.line_search_type != ceres::WOLFE) { + *error = - string("Invalid configuration: require line_search_type == " - "ceres::WOLFE when using (L)BFGS to ensure that underlying " - "assumptions are guaranteed to be satisfied."); + string("Invalid configuration: Solver::Options::line_search_type = ") + + string(LineSearchTypeToString(options.line_search_type)) + + string(". When using (L)BFGS, " + "Solver::Options::line_search_type must be set to WOLFE."); return false; } @@ -276,6 +264,8 @@ return true; } +#undef OPTION_OP +#undef OPTION_OP_OPTION #undef OPTION_GT #undef OPTION_GE #undef OPTION_LE