diff --git a/CMakeLists.txt b/CMakeLists.txt index 91826934..e1729bd2 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,6 +74,7 @@ endif() # Polysolve options option(POLYSOLVE_WITH_SANITIZERS "Enable sanitizers in compilation targets" OFF) +option(POLYSOLVE_WITH_UNICODE "Use Unicode in logging messages" ON) # Polysolve options for enabling/disabling optional libraries option(POLYSOLVE_WITH_ACCELERATE "Enable Apple Accelerate" ${POLYSOLVE_ON_APPLE_SILICON}) @@ -322,6 +323,14 @@ endif() include(polysolve_warnings) target_link_libraries(polysolve_linear PRIVATE polysolve::warnings) +# Unicode +if(POLYSOLVE_WITH_UNICODE) + target_compile_definitions(polysolve_linear PUBLIC POLYSOLVE_WITH_UNICODE) + if(MSVC) + target_compile_options(polysolve_linear PUBLIC /utf-8) + endif() +endif() + # --------- # Nonlinear # --------- diff --git a/src/polysolve/Utils.hpp b/src/polysolve/Utils.hpp index ebb91743..e6141a1a 100644 --- a/src/polysolve/Utils.hpp +++ b/src/polysolve/Utils.hpp @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include "Types.hpp" @@ -62,4 +62,24 @@ namespace polysolve double extract_param(const std::string &key, const std::string &name, const json &json); + namespace log + { +#ifdef POLYSOLVE_WITH_UNICODE + inline std::string f0() { return "f₀"; } + inline std::string dot() { return "⋅"; } + inline std::string ge() { return "≥"; } + inline std::string delta(const std::string &x) { return std::string("Δ") + x; } + inline std::string norm(const std::string &x) { return std::string("‖") + x + "‖"; } + inline std::string grad(const std::string &x) { return std::string("∇") + x; } +#else + inline std::string f0() { return "f0"; } + inline std::string dot() { return "*"; } + inline std::string ge() { return ">="; } + inline std::string delta(const std::string &x) { return std::string("d") + x; } + inline std::string norm(const std::string &x) { return std::string("norm(") + x + ")"; } + inline std::string grad(const std::string &x) { return std::string("grad(") + x + ")"; } +#endif // POLYSOLVE_WITH_UNICODE + + } // namespace log + } // namespace polysolve diff --git a/src/polysolve/nonlinear/Criteria.cpp b/src/polysolve/nonlinear/Criteria.cpp index 3dd6e112..e9bc7390 100644 --- a/src/polysolve/nonlinear/Criteria.cpp +++ b/src/polysolve/nonlinear/Criteria.cpp @@ -3,6 +3,7 @@ #include "Criteria.hpp" #include +#include namespace polysolve::nonlinear { @@ -33,8 +34,12 @@ namespace polysolve::nonlinear } 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); + "iters={:d} {}={:g} {}={:g} {}={:g} {}={:g}", + iterations, + log::delta("f"), fDelta, + log::norm(log::grad("f")), gradNorm, + log::norm(log::delta("x")), xDelta, + log::delta("x") + log::dot() + log::grad("f(x)"), xDeltaDotGrad); } Status checkConvergence(const Criteria &stop, const Criteria ¤t) diff --git a/src/polysolve/nonlinear/Solver.cpp b/src/polysolve/nonlinear/Solver.cpp index 1b98faa1..c796c5e8 100644 --- a/src/polysolve/nonlinear/Solver.cpp +++ b/src/polysolve/nonlinear/Solver.cpp @@ -282,8 +282,8 @@ namespace polysolve::nonlinear stop_watch.start(); m_logger.debug( - "Starting {} with {} solve f₀={:g} (stopping criteria: {})", - descent_strategy_name(), m_line_search->name(), objFunc(x), m_stop.print_message()); + "Starting {} with {} solve {}={:g} (stopping criteria: {})", + descent_strategy_name(), m_line_search->name(), log::f0(), objFunc(x), m_stop.print_message()); update_solver_info(objFunc(x)); objFunc.post_step(PostStepData(m_current.iterations, solver_info, x, grad)); @@ -377,17 +377,21 @@ 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(), status_message(m_status), delta_x.norm(), compute_grad_norm(x, grad), - m_current.xDeltaDotGrad); + m_logger, "[{}][{}] {} on last strategy ({}={:g}; {}={:g}; {}={:g}≥0); stopping", + current_name, m_line_search->name(), status_message(m_status), + log::norm(log::delta("x")), delta_x.norm(), + log::norm("g"), compute_grad_norm(x, grad), + log::delta("x") + log::dot() + "g", m_current.xDeltaDotGrad); } else { m_status = Status::Continue; m_logger.debug( - "[{}][{}] {} (‖Δx‖={:g}; ‖g‖={:g}; Δx⋅g={:g}≥0); reverting to {}", + "[{}][{}] {} ({}={:g}; {}={:g}; {}={:g}{}0); reverting to {}", current_name, m_line_search->name(), status_message(Status::NotDescentDirection), - delta_x.norm(), compute_grad_norm(x, grad), m_current.xDeltaDotGrad, + log::norm(log::delta("x")), delta_x.norm(), + log::norm("g"), compute_grad_norm(x, grad), + log::delta("x") + log::dot() + "g", m_current.xDeltaDotGrad, log::ge(), descent_strategy_name()); } continue; @@ -403,9 +407,9 @@ namespace polysolve::nonlinear // --- Variable update --------------------------------------------- m_logger.trace( - "[{}][{}] pre LS iter={:d} f={:g} ‖∇f‖={:g}", + "[{}][{}] pre LS iter={:d} f={:g} {}={:g}", descent_strategy_name(), m_line_search->name(), - m_current.iterations, energy, m_current.gradNorm); + m_current.iterations, energy, log::norm(log::grad("f")), m_current.gradNorm); // Perform a line_search to compute step scale double rate; diff --git a/src/polysolve/nonlinear/line_search/Backtracking.cpp b/src/polysolve/nonlinear/line_search/Backtracking.cpp index da8ee665..881fb1c1 100644 --- a/src/polysolve/nonlinear/line_search/Backtracking.cpp +++ b/src/polysolve/nonlinear/line_search/Backtracking.cpp @@ -52,7 +52,7 @@ namespace polysolve::nonlinear::line_search continue; } - m_logger.trace("ls it: {} ΔE: {}", cur_iter, new_energy - old_energy); + m_logger.trace("ls it: {} {}: {}", cur_iter, log::delta("E"), new_energy - old_energy); if (criteria(delta_x, objFunc, use_grad_norm, old_energy, old_grad, new_x, new_energy, step_size)) {