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 <<
" ──"
186 .outer_iter =
opts.outer_iter,
199 if (params.Lipschitz.L_0 <= 0) {
200 curr->L = Helpers::initial_lipschitz_estimate(
201 problem,
curr->x, y, Σ, params.Lipschitz.ε, params.Lipschitz.δ,
202 params.L_min, params.L_max,
208 curr->L = params.Lipschitz.L_0;
210 eval_ψ_grad_ψ(*
curr);
212 if (
not std::isfinite(
curr->L)) {
216 curr->γ = params.Lipschitz.Lγ_factor /
curr->L;
220 eval_prox_grad_step(*
curr);
231 real_t Δ = params.initial_radius;
232 if (!std::isfinite(Δ) || Δ == 0)
234 Δ = std::fmax(Δ, params.min_radius);
251 real_t εₖ = Helpers::calc_error_stop_crit(
258 params.print_interval != 0 && k % params.print_interval == 0;
266 auto stop_status = Helpers::check_all_stop_conditions(
280 opts.always_overwrite_results) {
282 if (
err_z.size() > 0)
283 err_z = Σ.asDiagonal().inverse() * (
ŷ - y);
284 x = std::move(
curr->x̂);
285 y = std::move(
curr->ŷx̂);
313 eval_ψ_grad_ψ(*
prox);
314 eval_prox_grad_step(*
prox);
323 direction.initialize(problem, y, Σ,
prox->γ,
prox->x,
prox->x̂,
332 eval_ψ_grad_ψ(*
cand);
336 eval_prox_grad_step(*
cand);
339 if (params.compute_ratio_using_new_stepsize) {
351 return params.ratio_approx_fbe_quadratic_model
352 ? ρ / (1 - params.Lipschitz.Lγ_factor)
359 if (ρ >= params.ratio_threshold_good)
360 return std::max(params.radius_factor_good * q.norm(),
old_Δ);
362 else if (ρ >= params.ratio_threshold_acceptable)
363 return old_Δ * params.radius_factor_acceptable;
366 return params.radius_factor_rejected * q.norm();
371 auto t0 = std::chrono::steady_clock::now();
374 auto t1 = std::chrono::steady_clock::now();
378 if (
not q.allFinite()) {
379 *os <<
"Direction fail: not finite" << std::endl;
385 *os <<
"Direction fail: no decrease on model (" <<
q_model
412 if (!params.compute_ratio_using_new_stepsize) {
418 direction.changed_γ(
cand->γ,
prox->γ);
419 if (params.recompute_last_prox_step_after_direction_reset) {
421 eval_prox_grad_step(*
prox);
442 direction.changed_γ(
prox->γ,
curr->γ);
443 if (params.recompute_last_prox_step_after_direction_reset) {
445 eval_prox_grad_step(*
curr);
449 if (params.update_direction_on_prox_step)
471 throw std::logic_error(
"[PANTR] loop error");