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 <<
" ──"
199 .outer_iter =
opts.outer_iter,
212 if (params.Lipschitz.L_0 <= 0) {
213 curr->L = Helpers::initial_lipschitz_estimate(
214 problem,
curr->x, y, Σ, params.Lipschitz.ε, params.Lipschitz.δ,
215 params.L_min, params.L_max,
221 curr->L = params.Lipschitz.L_0;
223 eval_ψ_grad_ψ(*
curr);
225 if (
not std::isfinite(
curr->L)) {
229 curr->γ = params.Lipschitz.Lγ_factor /
curr->L;
234 eval_prox_grad_step(*
curr);
241 eval_prox_grad_step(*
curr);
265 real_t εₖ = Helpers::calc_error_stop_crit(
271 params.print_interval != 0 && k % params.print_interval == 0;
279 auto stop_status = Helpers::check_all_stop_conditions(
292 opts.always_overwrite_results) {
294 if (
err_z.size() > 0)
295 err_z = Σ.asDiagonal().inverse() * (
ŷ - y);
296 x = std::move(
curr->x̂);
297 y = std::move(
curr->ŷx̂);
315 direction.initialize(problem, y, Σ,
curr->γ,
curr->x̂,
prox->x̂,
319 if (k > 0 || direction.has_initial_direction()) {
358 eval_ψ_grad_ψ(*
next);
361 while (!stop_signal.stop_requested()) {
372 bool fail = !std::isfinite(
next->ψx);
373 fail |=
next->L >= params.L_max && !(
curr->L >= params.L_max);
388 eval_prox_grad_step(*
next);
406 if (params.update_direction_from_prox_step) {
422 if (τ < params.min_linesearch_coefficient)
438 if (
no_progress > 0 || k % params.max_no_progress == 0)
445 direction.changed_γ(
next->γ,
curr->γ);
446 if (params.recompute_last_prox_step_after_lbfgs_flush) {
452 if (τ > 0 && params.update_direction_from_prox_step) {
465 if (
do_print && (k != 0 || direction.has_initial_direction()))
480 throw std::logic_error(
"[ZeroFPR] loop error");