alpaqa develop
Nonconvex constrained optimization
Loading...
Searching...
No Matches
alm.tpp
Go to the documentation of this file.
1#pragma once
2
4
5#include <algorithm>
6#include <iomanip>
7#include <iostream>
8#include <utility>
9
15
16namespace alpaqa {
17
18template <class InnerSolverT>
19typename ALMSolver<InnerSolverT>::Stats
21 std::optional<rvec> Σ) {
22 using std::chrono::duration_cast;
23 using std::chrono::nanoseconds;
24 auto start_time = std::chrono::steady_clock::now();
25
26 // Check the problem dimensions etc.
27 p.check();
28
29 if (params.max_iter == 0)
30 return {.status = SolverStatus::MaxIter};
31
32 auto m = p.get_m();
33 if (m == 0) { // No general constraints, only box constraints
34 Stats s;
35 vec Σ_curr(0), error(0);
38 .max_time = params.max_time,
39 .tolerance = params.tolerance,
40 .os = os,
41 .check = false,
42 };
43 auto ps = inner_solver(p, opts, x, y, Σ_curr, error);
45 auto time_elapsed = std::chrono::steady_clock::now() - start_time;
47 s.inner += ps;
48 s.ε = ps.ε;
49 s.δ = 0;
50 s.norm_penalty = 0;
51 s.outer_iterations = 1;
53 s.status = ps.status;
54 return s;
55 }
56
57 constexpr auto NaN = alpaqa::NaN<config_t>;
58 vec Σ_curr = vec::Constant(m, NaN);
59 vec error = vec::Constant(m, NaN);
60 vec error_old = vec::Constant(m, NaN);
62
63 std::array<char, 64> printbuf;
64 auto print_real = [&](real_t x) {
65 return float_to_str_vw(printbuf, x, params.print_precision);
66 };
67
68 Stats s;
69
70 if (Σ && Σ->allFinite() && Σ->norm() > 0) {
71 Σ_curr = *Σ;
72 }
73 // Initialize the penalty weights
74 else if (params.initial_penalty > 0) {
75 Σ_curr.setConstant(params.initial_penalty);
76 }
77 // Initial penalty weights from problem
78 else {
79 Helpers::initialize_penalty(p, params, x, Σ_curr);
80 }
81
82 // Inner solver tolerance
83 real_t ε = params.initial_tolerance;
84
85 for (unsigned i = 0; i < params.max_iter; ++i) {
86 p.eval_proj_multipliers(y, params.max_multiplier);
87 bool out_of_iter = i + 1 == params.max_iter;
88
89 auto time_elapsed = std::chrono::steady_clock::now() - start_time;
90 auto time_remaining = time_elapsed < params.max_time
91 ? params.max_time - time_elapsed
92 : decltype(time_elapsed){0};
95 .max_time = time_remaining,
96 .tolerance = ε,
97 .os = os,
98 .outer_iter = i,
99 .check = false,
100 };
101 // Call the inner solver to minimize the augmented lagrangian for fixed
102 // Lagrange multipliers y.
103 auto ps = inner_solver(p, opts, x, y, Σ_curr, error);
104 // Check if the inner solver converged
106 // Accumulate the inner solver statistics
108 s.inner += ps;
109 // Compute the constraint violation
110 using vec_util::norm_inf;
111 norm_e = norm_inf(error);
112
113 time_elapsed = std::chrono::steady_clock::now() - start_time;
114 bool out_of_time = time_elapsed > params.max_time;
115
116 // Print statistics of current iteration
117 if (params.print_interval != 0 && i % params.print_interval == 0) {
118 const char *color = inner_converged ? "\x1b[0;32m" : "\x1b[0;31m";
119 const char *color_end = "\x1b[0m";
120 *os << "[\x1b[0;34mALM\x1b[0m] " << std::setw(5) << i
121 << ": ‖Σ‖ = " << print_real(Σ_curr.norm())
122 << ", ‖y‖ = " << print_real(y.norm())
123 << ", δ = " << print_real(norm_e)
124 << ", ε = " << print_real(ps.ε) << ", status = " << color
125 << std::setw(13) << ps.status << color_end
126 << ", iter = " << std::setw(13) << ps.iterations
127 << std::endl; // Flush for Python buffering
128 }
129
130 // TODO: check penalty size?
131 if (ps.status == SolverStatus::Interrupted) {
132 s.ε = ps.ε;
133 s.δ = norm_e;
134 s.norm_penalty = Σ_curr.norm() / std::sqrt(real_t(m));
135 s.outer_iterations = i + 1;
137 s.status = ps.status;
138 if (Σ)
139 *Σ = Σ_curr;
140 return s;
141 }
142
143 // Check the termination criteria
144 bool alm_converged = ps.ε <= params.tolerance && inner_converged &&
145 norm_e <= params.dual_tolerance;
147 if (exit) {
148 s.ε = ps.ε;
149 s.δ = norm_e;
150 s.norm_penalty = Σ_curr.norm() / std::sqrt(real_t(m));
151 s.outer_iterations = i + 1;
157 if (Σ)
158 *Σ = Σ_curr;
159 return s;
160 }
161 // Update Σ to contain the penalty to use on the next iteration.
162 Helpers::update_penalty_weights(params, params.penalty_update_factor,
163 i == 0, error, error_old, norm_e,
165 // Lower the primal tolerance for the inner solver.
166 ε = std::fmax(params.tolerance_update_factor * ε, params.tolerance);
167 // Save previous error
169 error.swap(error_old);
170 }
171 throw std::logic_error("[ALM] loop error");
172}
173
174} // namespace alpaqa
real_t δ
Final dual tolerance or constraint violation that was reached:
Definition alm.hpp:93
real_t norm_penalty
2-norm of the final penalty factors .
Definition alm.hpp:95
typename InnerSolver::Problem Problem
Definition alm.hpp:75
std::chrono::nanoseconds elapsed_time
Total elapsed time.
Definition alm.hpp:82
InnerStatsAccumulator< typename InnerSolver::Stats > inner
The statistics of the inner solver invocations, accumulated over all ALM iterations.
Definition alm.hpp:103
unsigned inner_convergence_failures
The total number of times that the inner solver failed to converge.
Definition alm.hpp:84
real_t ε
Final primal tolerance that was reached, depends on the stopping criterion used by the inner solver,...
Definition alm.hpp:88
unsigned outer_iterations
Total number of outer ALM iterations (i.e.
Definition alm.hpp:80
Stats operator()(const Problem &problem, rvec x, rvec y, std::optional< rvec > Σ=std::nullopt)
Definition alm.tpp:20
SolverStatus status
Whether the solver converged or not.
Definition alm.hpp:99
auto norm_inf(const Eigen::MatrixBase< Derived > &v)
Get the maximum or infinity-norm of the given vector.
Definition config.hpp:204
@ Interrupted
Solver was interrupted by the user.
@ MaxTime
Maximum allowed execution time exceeded.
@ MaxIter
Maximum number of iterations exceeded.
@ Busy
In progress.
@ Converged
Converged and reached given tolerance.
typename Conf::real_t real_t
Definition config.hpp:86
bool always_overwrite_results
Return the final iterate and multipliers, even if the solver did not converge.
constexpr const auto NaN
Definition config.hpp:114
constexpr const auto inf
Definition config.hpp:112
typename Conf::rvec rvec
Definition config.hpp:91
std::string_view float_to_str_vw(auto &buf, double value, int precision=std::numeric_limits< double >::max_digits10)
Definition print.tpp:39
typename Conf::vec vec
Definition config.hpp:88