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();
88 vec work_n(n), work_m(m);
95 (1 + std::abs(i.ψx)) * params.quadratic_upperbound_tolerance_factor;
96 return i.ψx̂ > i.ψx + i.grad_ψᵀp +
real_t(0.5) * i.L * i.pᵀp +
margin;
101 if (params.force_linesearch)
103 real_t β = params.linesearch_strictness_factor;
106 real_t margin = (1 + std::abs(φγ)) * params.linesearch_tolerance_factor;
112 auto eval_ψ_grad_ψ = [&problem, &y, &Σ, &work_n, &work_m](
Iterate &i) {
113 i.ψx = problem.eval_ψ_grad_ψ(i.x, y, Σ, i.grad_ψ, work_n, work_m);
115 auto eval_prox_grad_step = [&problem](
Iterate &i) {
116 i.hx̂ = problem.eval_prox_grad_step(i.γ, i.x, i.grad_ψ, i.x̂, i.p);
117 i.pᵀp = i.p.squaredNorm();
118 i.grad_ψᵀp = i.p.dot(i.grad_ψ);
121 i.ψx̂ = problem.eval_ψ(i.x̂, y, Σ, i.ŷx̂);
124 problem.eval_grad_L(i.x̂, i.ŷx̂,
prox->grad_ψ, work_n);
127 prox->hx̂ = problem.eval_prox_grad_step(i.γ, i.x̂,
prox->grad_ψ,
prox->x̂,
146 *os <<
"┌─[ZeroFPR]\n";
148 *os <<
"├─ " << std::setw(6) << k <<
'\n';
158 const char *
color =
τₖ == 1 ?
"\033[0;32m"
159 :
τₖ > 0 ?
"\033[0;33m"
164 << (
reject ?
"\033[0;31mrejected\033[0m"
165 :
"\033[0;32maccepted\033[0m")
169 *os <<
"└─ " << status <<
" ──"
200 .outer_iter =
opts.outer_iter,
213 if (params.Lipschitz.L_0 <= 0) {
214 curr->L = Helpers::initial_lipschitz_estimate(
215 problem,
curr->x, y, Σ, params.Lipschitz.ε, params.Lipschitz.δ,
216 params.L_min, params.L_max,
222 curr->L = params.Lipschitz.L_0;
224 eval_ψ_grad_ψ(*
curr);
226 if (
not std::isfinite(
curr->L)) {
230 curr->γ = params.Lipschitz.Lγ_factor /
curr->L;
235 eval_prox_grad_step(*
curr);
242 eval_prox_grad_step(*
curr);
266 real_t εₖ = Helpers::calc_error_stop_crit(
272 params.print_interval != 0 && k % params.print_interval == 0;
280 auto stop_status = Helpers::check_all_stop_conditions(
293 opts.always_overwrite_results) {
295 if (
err_z.size() > 0)
296 err_z = Σ.asDiagonal().inverse() * (ŷ - y);
297 x = std::move(
curr->x̂);
298 y = std::move(
curr->ŷx̂);
316 direction.initialize(problem, y, Σ,
curr->γ,
curr->x̂,
prox->x̂,
320 if (k > 0 || direction.has_initial_direction()) {
359 eval_ψ_grad_ψ(*
next);
362 while (!stop_signal.stop_requested()) {
373 bool fail = !std::isfinite(
next->ψx);
374 fail |=
next->L >= params.L_max && !(
curr->L >= params.L_max);
389 eval_prox_grad_step(*
next);
407 if (params.update_direction_from_prox_step) {
423 if (τ < params.min_linesearch_coefficient)
439 if (
no_progress > 0 || k % params.max_no_progress == 0)
446 direction.changed_γ(
next->γ,
curr->γ);
447 if (params.recompute_last_prox_step_after_stepsize_change) {
453 if (τ > 0 && params.update_direction_from_prox_step) {
466 if (
do_print && (k != 0 || direction.has_initial_direction()))
481 throw std::logic_error(
"[ZeroFPR] loop error");