diff --git a/src/polysolve/Utils.cpp b/src/polysolve/Utils.cpp index 8148df1..ec830cb 100644 --- a/src/polysolve/Utils.cpp +++ b/src/polysolve/Utils.cpp @@ -53,7 +53,7 @@ namespace polysolve void StopWatch::log_msg() { - const static std::string log_fmt_text = + const static auto log_fmt_text = fmt::format("[{}] {{}} {{:.3g}}s", fmt::format(fmt::fg(fmt::terminal_color::magenta), "timing")); if (!m_name.empty()) @@ -64,7 +64,7 @@ namespace polysolve void log_and_throw_error(spdlog::logger &logger, const std::string &msg) { - logger.error(msg); + logger.error("{}", msg); throw std::runtime_error(msg); } diff --git a/src/polysolve/Utils.hpp b/src/polysolve/Utils.hpp index 2f2446b..ebb9174 100644 --- a/src/polysolve/Utils.hpp +++ b/src/polysolve/Utils.hpp @@ -55,7 +55,7 @@ namespace polysolve template [[noreturn]] void log_and_throw_error(spdlog::logger &logger, const std::string &msg, const Args &...args) { - log_and_throw_error(logger, fmt::format(msg, args...)); + log_and_throw_error(logger, fmt::format(fmt::runtime(msg), args...)); } Eigen::SparseMatrix sparse_identity(int rows, int cols); diff --git a/src/polysolve/nonlinear/Criteria.cpp b/src/polysolve/nonlinear/Criteria.cpp index 97ef602..3dd6e11 100644 --- a/src/polysolve/nonlinear/Criteria.cpp +++ b/src/polysolve/nonlinear/Criteria.cpp @@ -29,7 +29,10 @@ namespace polysolve::nonlinear void Criteria::print(std::ostream &os) const { - os << fmt::format( + os << print_message(); + } + std::string Criteria::print_message() const { + return fmt::format( "iters={:d} Δf={:g} ‖∇f‖={:g} ‖Δx‖={:g} Δx⋅∇f(x)={:g}", iterations, fDelta, gradNorm, xDelta, xDeltaDotGrad); } @@ -61,47 +64,39 @@ namespace polysolve::nonlinear return Status::Continue; } - std::ostream &operator<<(std::ostream &os, const Status &s) - { + std::string_view status_message(Status s) { switch (s) { case Status::NotStarted: - os << "Solver not started"; - break; + return "Solver not started"; case Status::Continue: - os << "Convergence criteria not reached"; - break; + return "Convergence criteria not reached"; case Status::IterationLimit: - os << "Iteration limit reached"; - break; + return "Iteration limit reached"; case Status::XDeltaTolerance: - os << "Change in parameter vector too small"; - break; + return "Change in parameter vector too small"; case Status::FDeltaTolerance: - os << "Change in cost function value too small"; - break; + return "Change in cost function value too small"; case Status::GradNormTolerance: - os << "Gradient vector norm too small"; - break; + return "Gradient vector norm too small"; case Status::ObjectiveCustomStop: - os << "Objective function specified to stop"; - break; + return "Objective function specified to stop"; case Status::NanEncountered: - os << "Objective or gradient function returned NaN"; - break; + return "Objective or gradient function returned NaN"; case Status::NotDescentDirection: - os << "Search direction not a descent direction"; - break; + return "Search direction not a descent direction"; case Status::LineSearchFailed: - os << "Line search failed"; - break; + return "Line search failed"; case Status::UpdateDirectionFailed: - os << "Update direction could not be computed"; - break; + return "Update direction could not be computed"; default: - os << "Unknown status"; - break; + return "Unknown status"; } + } + + std::ostream &operator<<(std::ostream &os, const Status &s) + { + os << status_message(s); return os; } @@ -110,4 +105,4 @@ namespace polysolve::nonlinear c.print(os); return os; } -} // namespace polysolve::nonlinear \ No newline at end of file +} // namespace polysolve::nonlinear diff --git a/src/polysolve/nonlinear/Criteria.hpp b/src/polysolve/nonlinear/Criteria.hpp index 86a89e1..d4e770c 100644 --- a/src/polysolve/nonlinear/Criteria.hpp +++ b/src/polysolve/nonlinear/Criteria.hpp @@ -2,6 +2,7 @@ #include #include +#include namespace polysolve::nonlinear { @@ -43,11 +44,15 @@ namespace polysolve::nonlinear void reset(); void print(std::ostream &os) const; + std::string print_message() const; }; Status checkConvergence(const Criteria &stop, const Criteria ¤t); + std::string_view status_message(Status s); + std::string criteria_message(const Criteria& s); + std::ostream &operator<<(std::ostream &os, const Status &s); std::ostream &operator<<(std::ostream &os, const Criteria &c); -} // namespace polysolve::nonlinear \ No newline at end of file +} // namespace polysolve::nonlinear diff --git a/src/polysolve/nonlinear/Solver.cpp b/src/polysolve/nonlinear/Solver.cpp index e7c67a3..0cbb864 100644 --- a/src/polysolve/nonlinear/Solver.cpp +++ b/src/polysolve/nonlinear/Solver.cpp @@ -283,7 +283,7 @@ namespace polysolve::nonlinear m_logger.debug( "Starting {} with {} solve f₀={:g} (stopping criteria: {})", - descent_strategy_name(), m_line_search->name(), objFunc(x), m_stop); + descent_strategy_name(), m_line_search->name(), objFunc(x), m_stop.print_message()); update_solver_info(objFunc(x)); objFunc.post_step(PostStepData(m_current.iterations, solver_info, x, grad)); @@ -354,12 +354,12 @@ namespace polysolve::nonlinear m_status = Status::UpdateDirectionFailed; log_and_throw_error( m_logger, "[{}][{}] {} on last strategy; stopping", - current_name, m_line_search->name(), m_status); + current_name, m_line_search->name(), status_message(m_status)); } m_logger.debug( "[{}][{}] {}; reverting to {}", current_name, m_line_search->name(), - Status::UpdateDirectionFailed, descent_strategy_name()); + status_message(Status::UpdateDirectionFailed), descent_strategy_name()); m_status = Status::Continue; continue; } @@ -378,7 +378,7 @@ namespace polysolve::nonlinear m_status = Status::NotDescentDirection; log_and_throw_error( m_logger, "[{}][{}] {} on last strategy (‖Δx‖={:g}; ‖g‖={:g}; Δx⋅g={:g}≥0); stopping", - current_name, m_line_search->name(), m_status, delta_x.norm(), compute_grad_norm(x, grad), + current_name, m_line_search->name(), status_message(m_status), delta_x.norm(), compute_grad_norm(x, grad), m_current.xDeltaDotGrad); } else @@ -386,7 +386,7 @@ namespace polysolve::nonlinear m_status = Status::Continue; m_logger.debug( "[{}][{}] {} (‖Δx‖={:g}; ‖g‖={:g}; Δx⋅g={:g}≥0); reverting to {}", - current_name, m_line_search->name(), Status::NotDescentDirection, + current_name, m_line_search->name(), status_message(Status::NotDescentDirection), delta_x.norm(), compute_grad_norm(x, grad), m_current.xDeltaDotGrad, descent_strategy_name()); } @@ -477,7 +477,7 @@ namespace polysolve::nonlinear m_logger.debug( "[{}][{}] {} (stopping criteria: {})", - descent_strategy_name(), m_line_search->name(), m_current, m_stop); + descent_strategy_name(), m_line_search->name(), m_current.print_message(), m_stop.print_message()); if (++m_current.iterations >= m_stop.iterations) m_status = Status::IterationLimit; @@ -499,8 +499,8 @@ namespace polysolve::nonlinear m_logger.log( succeeded ? spdlog::level::info : spdlog::level::err, "[{}][{}] Finished: {} took {:g}s ({}) (stopping criteria: {})", - descent_strategy_name(), m_line_search->name(), m_status, tot_time, - m_current, m_stop); + descent_strategy_name(), m_line_search->name(), status_message(m_status), tot_time, + m_current.print_message(), m_stop.print_message()); log_times(); update_solver_info(objFunc(x));