42 using std::chrono::nanoseconds;
43 auto os =
opts.os ?
opts.os : this->os;
44 auto start_time = std::chrono::steady_clock::now();
47 const auto n = problem.get_n();
48 const auto m = problem.get_m();
73 : x(n), x̂(n), grad_ψ(n),
grad_ψx̂(n), p(n),
ŷx̂(m) {}
78 bool need_grad_ψx̂ = Helpers::stop_crit_requires_grad_ψx̂(params.stop_crit);
79 vec work_n(n), work_m(m);
86 (1 + std::abs(i.ψx)) * params.quadratic_upperbound_tolerance_factor;
87 return i.ψx̂ > i.ψx + i.grad_ψᵀp +
real_t(0.5) * i.L * i.pᵀp +
margin;
92 if (params.force_linesearch)
94 real_t β = params.linesearch_strictness_factor;
97 real_t margin = (1 + std::abs(φγ)) * params.linesearch_tolerance_factor;
103 auto eval_ψ_grad_ψ = [&problem, &y, &Σ, &work_n, &work_m](
Iterate &i) {
104 i.ψx = problem.eval_ψ_grad_ψ(i.x, y, Σ, i.grad_ψ, work_n, work_m);
106 auto eval_prox_grad_step = [&problem](
Iterate &i) {
107 i.hx̂ = problem.eval_prox_grad_step(i.γ, i.x, i.grad_ψ, i.x̂, i.p);
108 i.pᵀp = i.p.squaredNorm();
109 i.grad_ψᵀp = i.p.dot(i.grad_ψ);
112 if (params.eager_gradient_eval)
113 i.ψx̂ = problem.eval_ψ_grad_ψ(i.x̂, y, Σ, i.grad_ψx̂, work_n, i.ŷx̂);
115 i.ψx̂ = problem.eval_ψ(i.x̂, y, Σ, i.ŷx̂);
116 i.have_grad_ψx̂ = params.eager_gradient_eval;
119 problem.eval_grad_L(i.x̂, i.ŷx̂, i.grad_ψx̂, work_n);
120 i.have_grad_ψx̂ =
true;
136 *os <<
"┌─[PANOC]\n";
138 *os <<
"├─ " << std::setw(6) << k <<
'\n';
148 const char *
color =
τₖ == 1 ?
"\033[0;32m"
149 :
τₖ > 0 ?
"\033[0;33m"
154 << (
reject ?
"\033[0;31mrejected\033[0m"
155 :
"\033[0;32maccepted\033[0m")
159 *os <<
"└─ " << status <<
" ──"
192 .outer_iter =
opts.outer_iter,
205 if (params.Lipschitz.L_0 <= 0) {
206 curr->L = Helpers::initial_lipschitz_estimate(
207 problem,
curr->x, y, Σ, params.Lipschitz.ε, params.Lipschitz.δ,
208 params.L_min, params.L_max,
214 curr->L = params.Lipschitz.L_0;
216 eval_ψ_grad_ψ(*
curr);
218 if (
not std::isfinite(
curr->L)) {
222 curr->γ = params.Lipschitz.Lγ_factor /
curr->L;
226 eval_prox_grad_step(*
curr);
233 eval_prox_grad_step(*
curr);
257 real_t εₖ = Helpers::calc_error_stop_crit(
263 params.print_interval != 0 && k % params.print_interval == 0;
271 auto stop_status = Helpers::check_all_stop_conditions(
283 opts.always_overwrite_results) {
285 if (
err_z.size() > 0)
286 err_z = Σ.asDiagonal().inverse() * (ŷ - y);
287 x = std::move(
curr->x̂);
288 y = std::move(
curr->ŷx̂);
306 direction.initialize(problem, y, Σ,
curr->γ,
curr->x,
curr->x̂,
310 if (k > 0 || direction.has_initial_direction()) {
342 curr->have_grad_ψx̂ =
next->have_grad_ψx̂ =
false;
352 eval_ψ_grad_ψ(*
next);
353 next->have_grad_ψx̂ =
false;
356 while (!stop_signal.stop_requested()) {
367 bool fail = !std::isfinite(
next->ψx);
368 fail |=
next->L >= params.L_max && !(
curr->L >= params.L_max);
383 eval_prox_grad_step(*
next);
411 if (τ < params.min_linesearch_coefficient)
427 if (
no_progress > 0 || k % params.max_no_progress == 0)
434 direction.changed_γ(
next->γ,
curr->γ);
435 if (params.recompute_last_prox_step_after_stepsize_change) {
438 eval_prox_grad_step(*
curr);
448 if (
do_print && (k != 0 || direction.has_initial_direction()))
455 throw std::logic_error(
"[PANOC] loop error");