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 <<
" ──"
191 .outer_iter =
opts.outer_iter,
204 if (params.Lipschitz.L_0 <= 0) {
205 curr->L = Helpers::initial_lipschitz_estimate(
206 problem,
curr->x, y, Σ, params.Lipschitz.ε, params.Lipschitz.δ,
207 params.L_min, params.L_max,
213 curr->L = params.Lipschitz.L_0;
215 eval_ψ_grad_ψ(*
curr);
217 if (
not std::isfinite(
curr->L)) {
221 curr->γ = params.Lipschitz.Lγ_factor /
curr->L;
225 eval_prox_grad_step(*
curr);
232 eval_prox_grad_step(*
curr);
256 real_t εₖ = Helpers::calc_error_stop_crit(
262 params.print_interval != 0 && k % params.print_interval == 0;
270 auto stop_status = Helpers::check_all_stop_conditions(
282 opts.always_overwrite_results) {
284 if (
err_z.size() > 0)
285 err_z = Σ.asDiagonal().inverse() * (
ŷ - y);
286 x = std::move(
curr->x̂);
287 y = std::move(
curr->ŷx̂);
305 direction.initialize(problem, y, Σ,
curr->γ,
curr->x,
curr->x̂,
309 if (k > 0 || direction.has_initial_direction()) {
341 curr->have_grad_ψx̂ =
next->have_grad_ψx̂ =
false;
351 eval_ψ_grad_ψ(*
next);
352 next->have_grad_ψx̂ =
false;
355 while (!stop_signal.stop_requested()) {
366 bool fail = !std::isfinite(
next->ψx);
367 fail |=
next->L >= params.L_max && !(
curr->L >= params.L_max);
382 eval_prox_grad_step(*
next);
410 if (τ < params.min_linesearch_coefficient)
426 if (
no_progress > 0 || k % params.max_no_progress == 0)
433 direction.changed_γ(
next->γ,
curr->γ);
434 if (params.recompute_last_prox_step_after_lbfgs_flush) {
437 eval_prox_grad_step(*
curr);
447 if (
do_print && (k != 0 || direction.has_initial_direction()))
454 throw std::logic_error(
"[PANOC] loop error");