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();
71 }
iterates[3]{{n, m}, {n, m}, {n, m}};
76 bool need_grad_ψx̂ = Helpers::stop_crit_requires_grad_ψx̂(params.stop_crit);
78 vec work_n(n), work_m(m);
84 auto eval_ψ_grad_ψ = [&problem, &y, &Σ, &work_n, &work_m](
Iterate &i) {
85 i.ψx = problem.eval_ψ_grad_ψ(i.x, y, Σ, i.grad_ψ, work_n, work_m);
87 auto eval_prox_grad_step = [&problem](
Iterate &i) {
88 i.hx̂ = problem.eval_prox_grad_step(i.γ, i.x, i.grad_ψ, i.x̂, i.p);
89 i.pᵀp = i.p.squaredNorm();
90 i.grad_ψᵀp = i.p.dot(i.grad_ψ);
93 i.ψx̂ = problem.eval_ψ(i.x̂, y, Σ, i.ŷx̂);
96 problem.eval_grad_L(i.x̂, i.ŷx̂,
grad_ψx̂, work_n);
103 (1 + std::abs(i.ψx)) * params.quadratic_upperbound_tolerance_factor;
104 return i.ψx̂ > i.ψx + i.grad_ψᵀp +
real_t(0.5) * i.L * i.pᵀp +
margin;
111 eval_prox_grad_step(i);
130 *os <<
"┌─[PANTR]\n";
132 *os <<
"├─ " << std::setw(6) << k <<
" ──\n";
150 << (
accept ?
"\033[0;32maccepted\033[0m"
151 :
"\033[0;35mrejected\033[0m")
155 *os <<
"└─ " << status <<
" ──"
188 .outer_iter =
opts.outer_iter,
201 if (params.Lipschitz.L_0 <= 0) {
202 curr->L = Helpers::initial_lipschitz_estimate(
203 problem,
curr->x, y, Σ, params.Lipschitz.ε, params.Lipschitz.δ,
204 params.L_min, params.L_max,
210 curr->L = params.Lipschitz.L_0;
212 eval_ψ_grad_ψ(*
curr);
214 if (
not std::isfinite(
curr->L)) {
218 curr->γ = params.Lipschitz.Lγ_factor /
curr->L;
222 eval_prox_grad_step(*
curr);
233 real_t Δ = params.initial_radius;
234 if (!std::isfinite(Δ) || Δ == 0)
236 Δ = std::fmax(Δ, params.min_radius);
253 real_t εₖ = Helpers::calc_error_stop_crit(
260 params.print_interval != 0 && k % params.print_interval == 0;
268 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̂);
315 eval_ψ_grad_ψ(*
prox);
316 eval_prox_grad_step(*
prox);
325 direction.initialize(problem, y, Σ,
prox->γ,
prox->x,
prox->x̂,
334 eval_ψ_grad_ψ(*
cand);
338 eval_prox_grad_step(*
cand);
341 if (params.compute_ratio_using_new_stepsize) {
353 return params.ratio_approx_fbe_quadratic_model
354 ? ρ / (1 - params.Lipschitz.Lγ_factor)
361 if (ρ >= params.ratio_threshold_good)
362 return std::max(params.radius_factor_good * q.norm(),
old_Δ);
364 else if (ρ >= params.ratio_threshold_acceptable)
365 return old_Δ * params.radius_factor_acceptable;
368 return params.radius_factor_rejected * q.norm();
373 auto t0 = std::chrono::steady_clock::now();
376 auto t1 = std::chrono::steady_clock::now();
380 if (
not q.allFinite()) {
381 *os <<
"Direction fail: not finite" << std::endl;
387 *os <<
"Direction fail: no decrease on model (" <<
q_model
415 if (!params.compute_ratio_using_new_stepsize) {
421 direction.changed_γ(
cand->γ,
prox->γ);
422 if (params.recompute_last_prox_step_after_direction_reset) {
424 eval_prox_grad_step(*
prox);
445 direction.changed_γ(
prox->γ,
curr->γ);
446 if (params.recompute_last_prox_step_after_direction_reset) {
448 eval_prox_grad_step(*
curr);
452 if (params.update_direction_on_prox_step)
474 throw std::logic_error(
"[PANTR] loop error");