16 using std::chrono::duration_cast;
17 using std::chrono::microseconds;
19 template <
class DirectionProv
iderT>
21 return "PANOCSolver<" + direction_provider.get_name() +
">";
24 template <
class DirectionProv
iderT>
34 bool always_overwrite_results,
42 std::chrono::microseconds time_remaining) {
44 std::chrono::microseconds delta_time = std::chrono::microseconds(0);
45 if (time_remaining > std::chrono::microseconds(0) &&
params.max_time > time_remaining) {
46 delta_time =
params.max_time - time_remaining;
49 auto start_time = std::chrono::steady_clock::now();
73 vec work_n(
n), work_m(
m);
76 unsigned no_progress = 0;
105 xₖ, ψₖ, grad_ψₖ,
y,
Σ, x̂ₖ, pₖ, ŷx̂ₖ, ψx̂ₖ, pₖᵀpₖ, grad_ψₖᵀpₖ, Lₖ, γₖ);
109 std::cout <<
"[PANOC] " << std::setw(6) << k
110 <<
": ψ = " << std::setw(13) << ψₖ
111 <<
", ‖∇ψ‖ = " << std::setw(13) << grad_ψₖ.norm()
112 <<
", ‖p‖ = " << std::setw(13) << std::sqrt(pₖᵀpₖ)
113 <<
", γ = " << std::setw(13) << γₖ
114 <<
", εₖ = " << std::setw(13) << εₖ <<
"\r\n";
121 if (
params.Lipschitz.L₀ <= 0) {
125 ψₖ, grad_ψₖ, x̂ₖ, grad_̂ψₖ, work_n, work_m);
133 if (not std::isfinite(Lₖ)) {
134 s.
status = SolverStatus::NotFinite;
143 calc_x̂(γₖ, xₖ, grad_ψₖ, x̂ₖ, pₖ);
146 real_t grad_ψₖᵀpₖ = grad_ψₖ.dot(pₖ);
147 real_t pₖᵀpₖ = pₖ.squaredNorm();
149 real_t φₖ = ψₖ + 1 / (2 * γₖ) * pₖᵀpₖ + grad_ψₖᵀpₖ;
153 for (
unsigned k = 0; k <=
params.max_iter; ++k) {
156 if (k == 0 ||
params.update_lipschitz_in_linesearch ==
false) {
161 ψx̂ₖ, pₖᵀpₖ, grad_ψₖᵀpₖ, Lₖ, γₖ);
162 if (k > 0 && γₖ != old_γₖ)
163 direction_provider.changed_γ(γₖ, old_γₖ);
165 direction_provider.initialize(xₖ, x̂ₖ, pₖ, grad_ψₖ);
167 φₖ = ψₖ + 1 / (2 * γₖ) * pₖᵀpₖ + grad_ψₖᵀpₖ;
177 if (
params.print_interval != 0 && k %
params.print_interval == 0)
180 progress_cb({k, xₖ, pₖ, pₖᵀpₖ, x̂ₖ, φₖ, ψₖ, grad_ψₖ, ψx̂ₖ, grad_̂ψₖ,
183 auto time_elapsed = std::chrono::steady_clock::now() - start_time;
185 params, time_elapsed + delta_time, k, stop_signal,
ε, εₖ, no_progress);
186 if (stop_status != SolverStatus::Unknown) {
191 if (stop_status == SolverStatus::Converged ||
193 stop_status == SolverStatus::MaxTime ||
194 always_overwrite_results) {
201 s.
elapsed_time = duration_cast<microseconds>(time_elapsed);
208 params.lbfgs_stepsize == LBFGSStepSize::BasedOnGradientStepSize
212 direction_provider.apply(xₖ, x̂ₖ, pₖ, step_size,
217 real_t σₖγₖ⁻¹pₖᵀpₖ = (1 - γₖ * Lₖ) * pₖᵀpₖ / (2 * γₖ);
218 real_t φₖ₊₁, ψₖ₊₁, ψx̂ₖ₊₁, grad_ψₖ₊₁ᵀpₖ₊₁, pₖ₊₁ᵀpₖ₊₁;
223 (1 + std::abs(φₖ)) *
params.quadratic_upperbound_tolerance_factor;
228 }
else if (not qₖ.allFinite()) {
231 direction_provider.reset();
240 if (τ / 2 <
params.τ_min) {
243 grad_ψₖ₊₁.swap(grad_̂ψₖ);
248 xₖ₊₁ = xₖ + (1 - τ) * pₖ + τ * qₖ;
254 calc_x̂(γₖ₊₁, xₖ₊₁, grad_ψₖ₊₁, x̂ₖ₊₁, pₖ₊₁);
259 grad_ψₖ₊₁ᵀpₖ₊₁ = grad_ψₖ₊₁.dot(pₖ₊₁);
260 pₖ₊₁ᵀpₖ₊₁ = pₖ₊₁.squaredNorm();
261 real_t pₖ₊₁ᵀpₖ₊₁_ₖ = pₖ₊₁ᵀpₖ₊₁;
263 if (
params.update_lipschitz_in_linesearch ==
true) {
268 grad_ψₖ₊₁ᵀpₖ₊₁, Lₖ₊₁, γₖ₊₁);
272 φₖ₊₁ = ψₖ₊₁ + 1 / (2 * γₖ₊₁) * pₖ₊₁ᵀpₖ₊₁ + grad_ψₖ₊₁ᵀpₖ₊₁;
274 ls_cond = φₖ₊₁ - (φₖ - σₖγₖ⁻¹pₖᵀpₖ);
275 if (
params.alternative_linesearch_cond)
276 ls_cond -= (0.5 / γₖ₊₁ - 0.5 / γₖ) * pₖ₊₁ᵀpₖ₊₁_ₖ;
279 }
while (ls_cond > margin && τ >=
params.τ_min);
282 if (τ <
params.τ_min && k != 0) {
294 direction_provider.changed_γ(γₖ₊₁, γₖ);
297 xₖ, xₖ₊₁, pₖ, pₖ₊₁, grad_ψₖ₊₁,
problem.C, γₖ₊₁);
300 if (no_progress > 0 || k %
params.max_no_progress == 0)
301 no_progress = xₖ == xₖ₊₁ ? no_progress + 1 : 0;
315 grad_ψₖ.swap(grad_ψₖ₊₁);
316 grad_ψₖᵀpₖ = grad_ψₖ₊₁ᵀpₖ₊₁;
319 throw std::logic_error(
"[PANOC] loop error");
322 template <
class DirectionProv
iderT>
324 return "PANOCSolverFull<" + direction_provider.get_name() +
">";
327 template <
class DirectionProv
iderT>
339 bool always_overwrite_results,
349 std::chrono::microseconds time_remaining) {
351 std::chrono::microseconds delta_time = std::chrono::microseconds(0);
352 if (time_remaining > std::chrono::microseconds(0) &&
params.max_time > time_remaining) {
353 delta_time =
params.max_time - time_remaining;
356 auto start_time = std::chrono::steady_clock::now();
383 vec work_n(
n), work_m1(m1), work_m2(m2);
386 unsigned no_progress = 0;
415 xₖ, ψₖ, grad_ψₖ,
y, Σ1, Σ2, x̂ₖ, pₖ, ŷx̂ₖ1, ŷx̂ₖ2, ψx̂ₖ, pₖᵀpₖ, grad_ψₖᵀpₖ, Lₖ, γₖ);
419 std::cout <<
"[PANOC] " << std::setw(6) << k
420 <<
": ψ = " << std::setw(13) << ψₖ
421 <<
", ‖∇ψ‖ = " << std::setw(13) << grad_ψₖ.norm()
422 <<
", ‖p‖ = " << std::setw(13) << std::sqrt(pₖᵀpₖ)
423 <<
", γ = " << std::setw(13) << γₖ
424 <<
", εₖ = " << std::setw(13) << εₖ <<
"\r\n";
431 if (
params.Lipschitz.L₀ <= 0) {
434 ψₖ, grad_ψₖ, x̂ₖ, grad_̂ψₖ, work_n, work_m1, work_m2);
442 if (not std::isfinite(Lₖ)) {
443 s.
status = SolverStatus::NotFinite;
452 calc_x̂(γₖ, xₖ, grad_ψₖ, x̂ₖ, pₖ);
455 real_t grad_ψₖᵀpₖ = grad_ψₖ.dot(pₖ);
456 real_t pₖᵀpₖ = pₖ.squaredNorm();
458 real_t φₖ = ψₖ + 1 / (2 * γₖ) * pₖᵀpₖ + grad_ψₖᵀpₖ;
462 for (
unsigned k = 0; k <=
params.max_iter; ++k) {
465 if (k == 0 ||
params.update_lipschitz_in_linesearch ==
false) {
469 x̂ₖ, pₖ, ŷx̂ₖ1, ŷx̂ₖ2,
470 ψx̂ₖ, pₖᵀpₖ, grad_ψₖᵀpₖ, Lₖ, γₖ);
471 if (k > 0 && γₖ != old_γₖ)
472 direction_provider.changed_γ(γₖ, old_γₖ);
474 direction_provider.initialize(xₖ, x̂ₖ, pₖ, grad_ψₖ);
476 φₖ = ψₖ + 1 / (2 * γₖ) * pₖᵀpₖ + grad_ψₖᵀpₖ;
486 if (
params.print_interval != 0 && k %
params.print_interval == 0)
489 progress_cb({k, xₖ, pₖ, pₖᵀpₖ, x̂ₖ, φₖ, ψₖ, grad_ψₖ, ψx̂ₖ, grad_̂ψₖ,
492 auto time_elapsed = std::chrono::steady_clock::now() - start_time;
494 params, time_elapsed + delta_time, k, stop_signal,
ε, εₖ, no_progress);
495 if (stop_status != SolverStatus::Unknown) {
500 if (stop_status == SolverStatus::Converged ||
502 stop_status == SolverStatus::MaxTime ||
503 always_overwrite_results) {
506 y = std::move(ŷx̂ₖ1);
510 s.
elapsed_time = duration_cast<microseconds>(time_elapsed);
517 params.lbfgs_stepsize == LBFGSStepSize::BasedOnGradientStepSize
521 direction_provider.apply(xₖ, x̂ₖ, pₖ, step_size,
526 real_t σₖγₖ⁻¹pₖᵀpₖ = (1 - γₖ * Lₖ) * pₖᵀpₖ / (2 * γₖ);
527 real_t φₖ₊₁, ψₖ₊₁, ψx̂ₖ₊₁, grad_ψₖ₊₁ᵀpₖ₊₁, pₖ₊₁ᵀpₖ₊₁;
532 (1 + std::abs(φₖ)) *
params.quadratic_upperbound_tolerance_factor;
537 }
else if (not qₖ.allFinite()) {
540 direction_provider.reset();
549 if (τ / 2 <
params.τ_min) {
552 grad_ψₖ₊₁.swap(grad_̂ψₖ);
557 xₖ₊₁ = xₖ + (1 - τ) * pₖ + τ * qₖ;
563 calc_x̂(γₖ₊₁, xₖ₊₁, grad_ψₖ₊₁, x̂ₖ₊₁, pₖ₊₁);
565 ψx̂ₖ₊₁ =
calc_ψ_ŷ(x̂ₖ₊₁, ŷx̂ₖ₊₁1, ŷx̂ₖ₊₁2);
568 grad_ψₖ₊₁ᵀpₖ₊₁ = grad_ψₖ₊₁.dot(pₖ₊₁);
569 pₖ₊₁ᵀpₖ₊₁ = pₖ₊₁.squaredNorm();
570 real_t pₖ₊₁ᵀpₖ₊₁_ₖ = pₖ₊₁ᵀpₖ₊₁;
572 if (
params.update_lipschitz_in_linesearch ==
true) {
575 x̂ₖ₊₁, pₖ₊₁, ŷx̂ₖ₊₁1, ŷx̂ₖ₊₁2,
577 grad_ψₖ₊₁ᵀpₖ₊₁, Lₖ₊₁, γₖ₊₁);
581 φₖ₊₁ = ψₖ₊₁ + 1 / (2 * γₖ₊₁) * pₖ₊₁ᵀpₖ₊₁ + grad_ψₖ₊₁ᵀpₖ₊₁;
583 ls_cond = φₖ₊₁ - (φₖ - σₖγₖ⁻¹pₖᵀpₖ);
584 if (
params.alternative_linesearch_cond)
585 ls_cond -= (0.5 / γₖ₊₁ - 0.5 / γₖ) * pₖ₊₁ᵀpₖ₊₁_ₖ;
588 }
while (ls_cond > margin && τ >=
params.τ_min);
591 if (τ <
params.τ_min && k != 0) {
603 direction_provider.changed_γ(γₖ₊₁, γₖ);
606 xₖ, xₖ₊₁, pₖ, pₖ₊₁, grad_ψₖ₊₁,
problem.C, γₖ₊₁);
609 if (no_progress > 0 || k %
params.max_no_progress == 0)
610 no_progress = xₖ == xₖ₊₁ ? no_progress + 1 : 0;
625 grad_ψₖ.swap(grad_ψₖ₊₁);
626 grad_ψₖᵀpₖ = grad_ψₖ₊₁ᵀpₖ₊₁;
629 throw std::logic_error(
"[PANOC] loop error");