Line data Source code
1 : #pragma once 2 : 3 : #include <panoc-alm/inner/decl/lbfgs-stepsize.hpp> 4 : #include <panoc-alm/inner/decl/panoc-fwd.hpp> 5 : #include <panoc-alm/inner/decl/panoc-stop-crit.hpp> 6 : #include <panoc-alm/inner/directions/decl/panoc-direction-update.hpp> 7 : #include <panoc-alm/util/atomic_stop_signal.hpp> 8 : #include <panoc-alm/util/lipschitz.hpp> 9 : #include <panoc-alm/util/problem.hpp> 10 : #include <panoc-alm/util/solverstatus.hpp> 11 : 12 : #include <atomic> 13 : #include <chrono> 14 : #include <limits> 15 : #include <string> 16 : 17 : namespace pa { 18 : 19 : /// Tuning parameters for the PANOC algorithm. 20 18 : struct PANOCParams { 21 : /// Parameters related to the Lipschitz constant estimate and step size. 22 : LipschitzEstimateParams Lipschitz; 23 : /// Maximum number of inner PANOC iterations. 24 9 : unsigned max_iter = 100; 25 : /// Maximum duration. 26 9 : std::chrono::microseconds max_time = std::chrono::minutes(5); 27 : /// Minimum weight factor between Newton step and projected gradient step. 28 9 : real_t τ_min = 1. / 256; 29 : /// Minimum Lipschitz constant estimate. 30 9 : real_t L_min = 1e-5; 31 : /// Maximum Lipschitz constant estimate. 32 9 : real_t L_max = 1e20; 33 : /// What stopping criterion to use. 34 9 : PANOCStopCrit stop_crit = PANOCStopCrit::ApproxKKT; 35 : /// Maximum number of iterations without any progress before giving up. 36 9 : unsigned max_no_progress = 10; 37 : 38 : /// When to print progress. If set to zero, nothing will be printed. 39 : /// If set to N != 0, progress is printed every N iterations. 40 9 : unsigned print_interval = 0; 41 : 42 18 : real_t quadratic_upperbound_tolerance_factor = 43 9 : 10 * std::numeric_limits<real_t>::epsilon(); 44 : 45 9 : bool update_lipschitz_in_linesearch = true; 46 9 : bool alternative_linesearch_cond = false; 47 : 48 9 : LBFGSStepSize lbfgs_stepsize = LBFGSStepSize::BasedOnCurvature; 49 : }; 50 : 51 20072 : struct PANOCStats { 52 10036 : SolverStatus status = SolverStatus::Unknown; 53 10036 : real_t ε = inf; 54 : std::chrono::microseconds elapsed_time; 55 10036 : unsigned iterations = 0; 56 10036 : unsigned linesearch_failures = 0; 57 10036 : unsigned lbfgs_failures = 0; 58 10036 : unsigned lbfgs_rejected = 0; 59 10036 : unsigned τ_1_accepted = 0; 60 10036 : unsigned count_τ = 0; 61 10036 : real_t sum_τ = 0; 62 : }; 63 : 64 0 : struct PANOCProgressInfo { 65 : unsigned k; 66 : crvec x; 67 : crvec p; 68 : real_t norm_sq_p; 69 : crvec x_hat; 70 : real_t φγ; 71 : real_t ψ; 72 : crvec grad_ψ; 73 : real_t ψ_hat; 74 : crvec grad_ψ_hat; 75 : real_t L; 76 : real_t γ; 77 : real_t τ; 78 : real_t ε; 79 : crvec Σ; 80 : crvec y; 81 : const Problem &problem; 82 : const PANOCParams ¶ms; 83 : }; 84 : 85 : /// PANOC solver for ALM. 86 : /// @ingroup grp_InnerSolvers 87 : template <class DirectionProviderT> 88 9 : class PANOCSolver { 89 : public: 90 : using Params = PANOCParams; 91 : using DirectionProvider = DirectionProviderT; 92 : using Stats = PANOCStats; 93 : using ProgressInfo = PANOCProgressInfo; 94 : 95 10 : PANOCSolver(Params params, 96 : PANOCDirection<DirectionProvider> &&direction_provider) 97 10 : : params(params), direction_provider(std::move(direction_provider)) {} 98 0 : PANOCSolver(Params params, 99 : const PANOCDirection<DirectionProvider> &direction_provider) 100 0 : : params(params), direction_provider(direction_provider) {} 101 : 102 : Stats operator()(const Problem &problem, // in 103 : crvec Σ, // in 104 : real_t ε, // in 105 : bool always_overwrite_results, // in 106 : rvec x, // inout 107 : rvec y, // inout 108 : rvec err_z); // out 109 : 110 : PANOCSolver & 111 0 : set_progress_callback(std::function<void(const ProgressInfo &)> cb) { 112 0 : this->progress_cb = cb; 113 0 : return *this; 114 : } 115 : 116 : std::string get_name() const; 117 : 118 0 : void stop() { stop_signal.stop(); } 119 : 120 0 : const Params &get_params() const { return params; } 121 : 122 : private: 123 : Params params; 124 : AtomicStopSignal stop_signal; 125 : std::function<void(const ProgressInfo &)> progress_cb; 126 : 127 : public: 128 : PANOCDirection<DirectionProvider> direction_provider; 129 : }; 130 : 131 : template <class InnerSolverStats> 132 : struct InnerStatsAccumulator; 133 : 134 : template <> 135 10 : struct InnerStatsAccumulator<PANOCStats> { 136 : std::chrono::microseconds elapsed_time; 137 5 : unsigned iterations = 0; 138 5 : unsigned linesearch_failures = 0; 139 5 : unsigned lbfgs_failures = 0; 140 5 : unsigned lbfgs_rejected = 0; 141 5 : unsigned τ_1_accepted = 0; 142 5 : unsigned count_τ = 0; 143 5 : real_t sum_τ = 0; 144 : }; 145 : 146 : inline InnerStatsAccumulator<PANOCStats> & 147 30 : operator+=(InnerStatsAccumulator<PANOCStats> &acc, const PANOCStats &s) { 148 30 : acc.iterations += s.iterations; 149 30 : acc.elapsed_time += s.elapsed_time; 150 30 : acc.linesearch_failures += s.linesearch_failures; 151 30 : acc.lbfgs_failures += s.lbfgs_failures; 152 30 : acc.lbfgs_rejected += s.lbfgs_rejected; 153 30 : acc.τ_1_accepted += s.τ_1_accepted; 154 30 : acc.count_τ += s.count_τ; 155 30 : acc.sum_τ += s.sum_τ; 156 30 : return acc; 157 : } 158 : 159 : } // namespace pa