#pragma once #include #include #include #include #include #include #include #include #include namespace alpaqa::lbfgsb { struct LBFGSB_ADAPTER_EXPORT LBFGSBParams { USING_ALPAQA_CONFIG(alpaqa::DefaultConfig); unsigned memory = 10; unsigned max_iter = 1000; std::chrono::nanoseconds max_time = std::chrono::minutes(5); PANOCStopCrit stop_crit = PANOCStopCrit::ProjGradUnitNorm; int print = -1; unsigned print_interval = 0; int print_precision = std::numeric_limits::max_digits10 / 2; }; struct LBFGSB_ADAPTER_EXPORT LBFGSBStats { USING_ALPAQA_CONFIG(alpaqa::DefaultConfig); SolverStatus status = SolverStatus::Busy; real_t ε = inf; std::chrono::nanoseconds elapsed_time{}; unsigned iterations = 0; real_t final_ψ = 0; unsigned lbfgs_rejected = 0; }; /// L-BFGS-B solver for ALM. /// @ingroup grp_InnerSolvers class LBFGSB_ADAPTER_EXPORT LBFGSBSolver { public: USING_ALPAQA_CONFIG(alpaqa::DefaultConfig); using Problem = TypeErasedProblem; using Params = LBFGSBParams; using Stats = LBFGSBStats; using SolveOptions = InnerSolveOptions; LBFGSBSolver(const Params ¶ms) : params(params) {} Stats operator()(const Problem &problem, // in const SolveOptions &opts, // in rvec x, // inout rvec y, // inout crvec Σ, // in rvec err_z); // out template Stats operator()(const P &problem, const SolveOptions &opts, rvec u, rvec y, crvec Σ, rvec e) { return operator()(Problem::template make

(problem), opts, u, y, Σ, e); } std::string get_name() const; void stop() { stop_signal.stop(); } const Params &get_params() const { return params; } private: Params params; AtomicStopSignal stop_signal; public: std::ostream *os = &std::cout; }; } // namespace alpaqa::lbfgsb namespace alpaqa { template struct InnerStatsAccumulator; template <> struct InnerStatsAccumulator { USING_ALPAQA_CONFIG(alpaqa::DefaultConfig); /// Total elapsed time in the inner solver. std::chrono::nanoseconds elapsed_time{}; /// Total number of inner PANOC iterations. unsigned iterations = 0; /// Final value of the smooth cost @f$ \psi(\hat x) @f$. real_t final_ψ = 0; /// Total number of times that the L-BFGS update was rejected (i.e. it /// could have resulted in a non-positive definite Hessian estimate). unsigned lbfgs_rejected = 0; }; inline InnerStatsAccumulator & operator+=(InnerStatsAccumulator &acc, const lbfgsb::LBFGSBStats &s) { acc.iterations += s.iterations; acc.elapsed_time += s.elapsed_time; acc.final_ψ = s.final_ψ; acc.lbfgs_rejected += s.lbfgs_rejected; return acc; } } // namespace alpaqa