alpaqa 0.0.1
Nonconvex constrained optimization
anderson-helpers.hpp
Go to the documentation of this file.
1#pragma once
2
4
5namespace alpaqa {
6
7/**
8 * @brief Solve one step of Anderson acceleration to find a fixed point of a
9 * function g(x):
10 *
11 * @f$ g(x^\star) - x^\star = 0 @f$
12 *
13 * Updates the QR factorization of @f$ \mathcal{R}_k = QR @f$, solves the least
14 * squares problem to find @f$ \gamma_\text{LS} @f$, computes the next
15 * iterate @f$ x_{k+1} @f$, and stores the current function value @f$ g_k @f$
16 * in the matrix @f$ G @f$, which is used as a circular buffer.
17 * @f[ \begin{aligned}
18 * \mathcal{R}_k &= \begin{pmatrix} \Delta r_{k-m_k} & \dots & \Delta r_{k-1} \end{pmatrix} \in \mathbb{R}^{n\times m_k} \\
19 * \Delta r_i &= r_{i+1} - r_i \\
20 * r_i &= g_i - x_i \\
21 * g_i &= g(x_i) \\
22 * \DeclareMathOperator*{\argmin}{argmin}
23 * \gamma_\text{LS} &= \argmin_\gamma \left\| \mathcal{R}_k \gamma - r_k \right\|_2 \\
24 * \alpha_i &= \begin{cases} \gamma_\text{LS}[0] & i = 0 \\
25 * \gamma_\text{LS}[i] - \gamma_\text{LS}[i-1] & 0 < i < m_k \\
26 * 1 - \gamma_\text{LS}[m_k - 1] & i = m_k \end{cases} \\
27 * x_{k+1} &= \sum_{i=0}^{m_k} \alpha_i\,g_i
28 * \end{aligned} @f]
29 */
31 crvec rₖ₋₁, crvec gₖ, rvec γ_LS,
32 rvec xₖ_aa) {
33 // Update QR factorization for Anderson acceleration
34 if (qr.num_columns() == qr.m()) // if the history buffer is full
35 qr.remove_column();
36 qr.add_column(rₖ - rₖ₋₁);
37
38 // Solve least squares problem Anderson acceleration
39 // γ = argmin ‖ ΔR γ - rₖ ‖²
40 qr.solve_col(rₖ, γ_LS);
41
42 // Iterate over columns of G, whose indices match the indices of the matrix
43 // R in the QR factorization, stored as a circular buffer.
44 auto g_it = qr.ring_iter().begin();
45 auto g_end = qr.ring_iter().end();
46 assert(g_it != g_end);
47
48 // Compute Anderson acceleration next iterate yₑₓₜ = ∑ₙ₌₀ αₙ gₙ
49 // α₀ = γ₀ if n = 0
50 // αₙ = γₙ - γₙ₋₁ if 0 < n < mₖ
51 // αₘ = 1 - γₘ₋₁ if n = mₖ
52 real_t α = γ_LS(0);
53 xₖ_aa = α * G.col((*g_it).circular);
54 while (++g_it != g_end) {
55 auto [i, g_idx] = *g_it; // [zero based index, circular index]
56 α = γ_LS(i) - γ_LS(i - 1);
57 xₖ_aa += α * G.col(g_idx);
58 }
59 α = 1 - γ_LS(qr.num_columns() - 1);
60 xₖ_aa += α * gₖ;
61
62 // Add the new column to G
63 G.col(qr.ring_tail()) = gₖ; // TODO: avoid copy, make G an array of vectors
64}
65
66} // namespace alpaqa
Incremental QR factorization using modified Gram-Schmidt with reorthogonalization.
size_t ring_tail() const
Get the tail index of the circular buffer (points to one past the most recent element).
void remove_column()
Remove the leftmost column.
void add_column(const VecV &v)
Add the given column to the right.
void solve_col(const VecB &b, VecX &x) const
Solve the least squares problem Ax = b.
size_t num_columns() const
Get the number of columns that are currently stored.
CircularRange< size_t > ring_iter() const
Get iterators in the circular buffer.
void minimize_update_anderson(LimitedMemoryQR &qr, rmat G, crvec rₖ, crvec rₖ₋₁, crvec gₖ, rvec γ_LS, rvec xₖ_aa)
Solve one step of Anderson acceleration to find a fixed point of a function g(x):
Eigen::Ref< const vec > crvec
Default type for immutable references to vectors.
Definition: vec.hpp:18
Eigen::Ref< mat > rmat
Default type for mutable references to matrices.
Definition: vec.hpp:22
double real_t
Default floating point type.
Definition: vec.hpp:8
Eigen::Ref< vec > rvec
Default type for mutable references to vectors.
Definition: vec.hpp:16