2#include <alpaqa/example-util.hpp>
6
7#include <iomanip>
8#include <iostream>
9
10struct Problem {
13
14 length_t N = 32,
15 nu = 1,
16 nx = 2,
17 nh = nu + nx,
18 nh_N = nx,
19 nc = 0,
20 nc_N = 0;
21
22 mat A, B;
23
24 Problem() : A(nx, nx), B(nx, nu) {
25 A.setIdentity();
26 B.setIdentity();
27 }
28
29
30 [[nodiscard]] length_t get_N() const { return N; }
31
32 [[nodiscard]] length_t get_nu() const { return nu; }
33
34 [[nodiscard]] length_t get_nx() const { return nx; }
35
36 [[nodiscard]] length_t get_nh() const { return nh; }
37
38 [[nodiscard]] length_t get_nh_N() const { return nh_N; }
39
40 [[nodiscard]] length_t get_nc() const { return nc; }
41
42 [[nodiscard]] length_t get_nc_N() const { return nc_N; }
43
44
45 void get_U(Box &U) const {
46 U.lower.setConstant(-1);
47 U.upper.setConstant(+1);
48 }
49
50 void get_D([[maybe_unused]] Box &D) const {}
51
52 void get_D_N([[maybe_unused]] Box &D) const {}
53
54
55 void get_x_init(rvec x_init) const { x_init.setConstant(10.); }
56
57
58 void eval_f([[maybe_unused]] index_t timestep, crvec x, crvec u,
59 rvec fxu) const {
60 fxu.noalias() = A * x + B * u;
61 }
62
63 void eval_jac_f([[maybe_unused]] index_t timestep, [[maybe_unused]] crvec x,
64 [[maybe_unused]] crvec u, rmat J_fxu) const {
65 J_fxu.leftCols(nx).noalias() = A;
66 J_fxu.rightCols(nu).noalias() = B;
67 }
68
69 void eval_grad_f_prod([[maybe_unused]] index_t timestep,
70 [[maybe_unused]] crvec x, [[maybe_unused]] crvec u,
71 crvec p, rvec grad_fxu_p) const {
72 grad_fxu_p.topRows(nx).noalias() = A.transpose() * p;
73 grad_fxu_p.bottomRows(nu).noalias() = B.transpose() * p;
74 }
75
76 void eval_h([[maybe_unused]] index_t timestep, crvec x, crvec u,
77 rvec h) const {
78 h.topRows(nx) = x;
79 h.bottomRows(nu) = u;
80 }
81
82 void eval_h_N(crvec x, rvec h) const { h = x; }
83
84 [[nodiscard]] real_t eval_l([[maybe_unused]] index_t timestep,
85 crvec h) const {
86 return 0.5 * h.squaredNorm();
87 }
88
89 [[nodiscard]] real_t eval_l_N(crvec h) const {
90 return 5.0 * h.squaredNorm();
91 }
92
93 void eval_qr([[maybe_unused]] index_t timestep, [[maybe_unused]] crvec xu,
94 crvec h, rvec qr) const {
95 auto Jh_xu = mat::Identity(nx + nu, nx + nu);
96 auto &&grad_l = h;
97 qr = Jh_xu.transpose() * grad_l;
98 }
99
100 void eval_q_N([[maybe_unused]] crvec x, crvec h, rvec q) const {
101 auto Jh_x = mat::Identity(nx, nx);
102 auto grad_l = 10 * h;
103 q = Jh_x.transpose() * grad_l;
104 }
105
106 void eval_add_Q([[maybe_unused]] index_t timestep,
107 [[maybe_unused]] crvec xu, [[maybe_unused]] crvec h,
108 rmat Q) const {
109 Q += mat::Identity(nx, nx);
110 }
111
112 void eval_add_Q_N([[maybe_unused]] crvec x, [[maybe_unused]] crvec h,
113 rmat Q) const {
114 Q += 10 * mat::Identity(nx, nx);
115 }
116
117 void eval_add_R_masked([[maybe_unused]] index_t timestep,
118 [[maybe_unused]] crvec xu, [[maybe_unused]] crvec h,
119 crindexvec mask, rmat R,
120 [[maybe_unused]] rvec work) const {
121 auto R_full = mat::Identity(nu, nu);
122 R.noalias() += R_full(mask, mask);
123 }
124
125 void eval_add_S_masked([[maybe_unused]] index_t timestep,
126 [[maybe_unused]] crvec xu, [[maybe_unused]] crvec h,
127 crindexvec mask, rmat S,
128 [[maybe_unused]] rvec work) const {
129
130 using Eigen::indexing::all;
131 auto S_full = mat::Zero(nu, nx);
132 S += S_full(mask, all);
133 }
134
135 void eval_add_R_prod_masked([[maybe_unused]] index_t timestep,
136 [[maybe_unused]] crvec xu,
137 [[maybe_unused]] crvec h, crindexvec mask_J,
138 crindexvec mask_K, crvec v, rvec out,
139 [[maybe_unused]] rvec work) const {
140
141 auto R_full = mat::Identity(nu, nu);
142 out.noalias() += R_full(mask_J, mask_K) * v(mask_K);
143 }
144
145 void eval_add_S_prod_masked([[maybe_unused]] index_t timestep,
146 [[maybe_unused]] crvec xu,
147 [[maybe_unused]] crvec h,
148 [[maybe_unused]] crindexvec mask_K,
149 [[maybe_unused]] crvec v,
150 [[maybe_unused]] rvec out,
151 [[maybe_unused]] rvec work) const {
152
153 using Eigen::indexing::all;
154 auto Sᵀ = mat::Zero(nx, nu);
155 out.noalias() += Sᵀ(all, mask_K) * v(mask_K);
156 }
157 [[nodiscard]] length_t get_R_work_size() const {
158
159
160 return 0;
161 }
162 [[nodiscard]] length_t get_S_work_size() const {
163
164
165 return 0;
166 }
167
168
169 void eval_projection_multipliers([[maybe_unused]] rvec y,
170 [[maybe_unused]] real_t M) const {
171
172 }
173
174
175 void eval_projecting_difference_constraints([[maybe_unused]] crvec z,
176 [[maybe_unused]] rvec e) const {
177
178 }
179
180 void check() const {
181
182 }
183};
184
186 alpaqa::init_stdout();
188
189
191
192
195
196
197 vec u = vec::Zero(n);
198 vec y = vec::Zero(m);
199 vec μ = vec::Ones(m);
200 vec e(m);
201
202
208
209
210 auto stats = solver(problem, {.tolerance = 1e-8}, u, y, μ, e);
211
212
213 auto δ = e.lpNorm<Eigen::Infinity>();
214 auto time_s = std::chrono::duration<double>(stats.elapsed_time).count();
215 std::cout << '\n'
217 <<
"solver: " << solver.
get_name() <<
'\n'
218 << "status: " << stats.status << '\n'
219 << "ψ = " << alpaqa::float_to_str(stats.final_ψ) << '\n'
220 << "ε = " << alpaqa::float_to_str(stats.ε) << '\n'
221 << "δ = " << alpaqa::float_to_str(δ) << '\n'
222 << "time: " << alpaqa::float_to_str(time_s, 3) << " s\n"
223 << "iter: " << std::setw(6) << stats.iterations << '\n'
224 << "line search backtrack: " << std::setw(6)
225 << stats.linesearch_backtracks << '\n'
226 << "step size backtrack: " << std::setw(6)
227 << stats.stepsize_backtracks << '\n'
228 << "solution: ";
230}
int main(int argc, const char *argv[])
std::string get_name() const
#define USING_ALPAQA_CONFIG(Conf)
unsigned print_interval
When to print progress.
unsigned gn_interval
How often to use a Gauss-Newton step. Zero to disable GN entirely.
PANOCStopCrit stop_crit
What stopping criterion to use.
Tuning parameters for the PANOC algorithm.
@ ProjGradUnitNorm
∞-norm of the projected gradient with unit step size:
EigenConfigd DefaultConfig
std::ostream & print_python(std::ostream &os, const Eigen::DenseBase< Derived > &M)
length_t get_nc_N() const
std::shared_ptr< OCPEvalCounter > evaluations