alpaqa pantr
Nonconvex constrained optimization
Loading...
Searching...
No Matches
ocproblem.hpp
Go to the documentation of this file.
1#pragma once
2
11#include <array>
12#include <concepts>
13#include <stdexcept>
14#include <type_traits>
15
16#ifndef NDEBUG
17#include <iostream>
18#endif
19
20namespace alpaqa {
21
22template <Config Conf>
23struct OCPDim {
26};
27
28template <Config Conf>
32
33 template <class F>
35 template <class F>
38
39 // clang-format off
47 get_D = nullptr;
52 required_const_function_t<void(index_t timestep, crvec x, crvec u, rvec fxu)>
54 required_const_function_t<void(index_t timestep, crvec x, crvec u, rmat J_fxu)>
56 required_const_function_t<void(index_t timestep, crvec x, crvec u, crvec p, rvec grad_fxu_p)>
58 optional_const_function_t<void(index_t timestep, crvec x, crvec u, rvec h)>
59 eval_h = nullptr;
61 eval_h_N = nullptr;
66 required_const_function_t<void(index_t timestep, crvec xu, crvec h, rvec qr)>
70 required_const_function_t<void(index_t timestep, crvec xu, crvec h, rmat Q)>
74 required_const_function_t<void(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat R, rvec work)>
76 required_const_function_t<void(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat S, rvec work)>
78 optional_const_function_t<void(index_t timestep, crvec xu, crvec h, crindexvec mask_J, crindexvec mask_K, crvec v, rvec out, rvec work)>
80 optional_const_function_t<void(index_t timestep, crvec xu, crvec h, crindexvec mask_K, crvec v, rvec out, rvec work)>
86 optional_const_function_t<void(index_t timestep, crvec x, rvec c)>
87 eval_constr = nullptr;
90 optional_const_function_t<void(index_t timestep, crvec x, crvec p, rvec grad_cx_p)>
92 optional_const_function_t<void(crvec x, crvec p, rvec grad_cx_p)>
94 optional_const_function_t<void(index_t timestep, crvec x, crvec M, rmat out)>
100 // clang-format on
101
103
104 template <class P>
109 ALPAQA_TE_OPTIONAL_METHOD(*this, P, get_D, t.t);
110 ALPAQA_TE_OPTIONAL_METHOD(*this, P, get_D_N, t.t);
115 ALPAQA_TE_OPTIONAL_METHOD(*this, P, eval_h, t.t);
136 N = t.t->get_N();
137 nu = t.t->get_nu();
138 nx = t.t->get_nx();
139 nh = t.t->get_nh();
140 nh_N = t.t->get_nh_N();
141 nc = t.t->get_nc();
142 nc_N = t.t->get_nc_N();
143 if (nc > 0 && get_D == nullptr)
144 throw std::runtime_error("ControlProblem: missing 'get_D'");
145 if (nc > 0 && eval_constr == nullptr)
146 throw std::runtime_error("ControlProblem: missing 'eval_constr'");
147 if (nc > 0 && eval_grad_constr_prod == nullptr)
148 throw std::runtime_error("ControlProblem: missing 'eval_grad_constr_prod'");
149 if (nh > 0 && eval_h == nullptr)
150 throw std::runtime_error("ControlProblem: missing 'eval_h'");
151 if (nh_N > 0 && eval_h_N == nullptr)
152 throw std::runtime_error("ControlProblem: missing 'eval_h_N'");
153 }
155
156 static void default_get_D_N(const void *self, Box &D, const ControlProblemVTable &vtable) {
157 vtable.get_D(self, D, vtable);
158 }
159 static void default_eval_add_Q_N(const void *self, crvec x, crvec h, rmat Q,
160 const ControlProblemVTable &vtable) {
161 vtable.eval_add_Q(self, vtable.N, x, h, Q);
162 }
165 const ControlProblemVTable &) {
166 throw not_implemented_error("default_eval_add_R_prod_masked");
167 }
169 crvec, rvec, rvec, const ControlProblemVTable &) {
170 throw not_implemented_error("default_eval_add_S_prod_masked");
171 }
172 [[nodiscard]] static length_t default_get_R_work_size(const void *,
173 const ControlProblemVTable &) {
174 return 0;
175 }
176 [[nodiscard]] static length_t default_get_S_work_size(const void *,
177 const ControlProblemVTable &) {
178 return 0;
179 }
180 static void default_eval_constr_N(const void *self, crvec x, rvec c,
181 const ControlProblemVTable &vtable) {
182 vtable.eval_constr(self, vtable.N, x, c, vtable);
183 }
184 static void default_eval_grad_constr_prod_N(const void *self, crvec x, crvec p, rvec grad_cx_p,
185 const ControlProblemVTable &vtable) {
186 vtable.eval_grad_constr_prod(self, vtable.N, x, p, grad_cx_p, vtable);
187 }
188 static void default_eval_add_gn_hess_constr_N(const void *self, crvec x, crvec M, rmat out,
189 const ControlProblemVTable &vtable) {
190 vtable.eval_add_gn_hess_constr(self, vtable.N, x, M, out, vtable);
191 }
192};
193
194/**
195 * Nonlinear optimal control problem with finite horizon @f$ N @f$.
196 * @f[
197 * \newcommand\U{U}
198 * \newcommand\D{D}
199 * \newcommand\nnu{{n_u}}
200 * \newcommand\nnx{{n_x}}
201 * \newcommand\nny{{n_y}}
202 * \newcommand\xinit{x_\text{init}}
203 * \begin{equation}\label{eq:OCP} \tag{OCP}\hspace{-0.8em}
204 * \begin{aligned}
205 * &\minimize_{u,x} && \sum_{k=0}^{N-1} \ell_k\big(h_k(x^k, u^k)\big) + \ell_N\big(h_N(x^N)\big)\hspace{-0.8em} \\
206 * &\subjto && u^k \in \U \\
207 * &&& c_k(x^k) \in \D \\
208 * &&& c_N(x^N) \in \D_N \\
209 * &&& x^0 = \xinit \\
210 * &&& x^{k+1} = f(x^k, u^k) \quad\quad (0 \le k \lt N)
211 * \end{aligned}
212 * \end{equation}
213 * @f]
214 *
215 * The function @f$ f : \R^\nnx \times \R^\nnu \to \R^\nnx @f$ models the
216 * discrete-time, nonlinear dynamics of the system, which starts from an initial
217 * state @f$ \xinit @f$.
218 * The functions @f$ h_k : \R^\nnx \times \R^\nnu \to \R^{n_h} @f$ for
219 * @f$ 0 \le k \lt N @f$ and @f$ h_N : \R^\nnx \to \R^{n_h^N} @f$ can be used to
220 * represent the (possibly time-varying) output mapping of the system,
221 * and the convex functions @f$ \ell_k : \R^{n_h} \to \R @f$ and
222 * @f$ \ell_N : \R^{n_h^N} \to \R @f$ define the stage costs and the terminal
223 * cost respectively. Stage constraints and terminal constraints are represented
224 * by the functions @f$ c_k : \R^{n_x} \to \R^{n_c} @f$ and
225 * @f$ c_N : \R^{n_x} \to \R^{n_c^N} @f$, and the boxes @f$ D @f$ and
226 * @f$ D_N @f$.
227 *
228 * Additional functions for computing Gauss-Newton approximations of the cost
229 * Hessian are included as well:
230 * @f[ \begin{aligned}
231 * q^k &\defeq \tp{\jac_{h_k}^x\!(\barxuk)} \nabla \ell_k(\hhbar^k) \\
232 * r^k &\defeq \tp{\jac_{h_k}^u\!(\barxuk)} \nabla \ell_k(\hhbar^k) \\
233 * \Lambda_k &\defeq \partial^2 \ell_k(\hhbar^k) \\
234 * Q_k &\defeq \tp{\jac_{h_k}^x\!(\barxuk)} \Lambda_k\, \jac_{h_k}^x\!(\barxuk) \\
235 * S_k &\defeq \tp{\jac_{h_k}^u\!(\barxuk)} \Lambda_k\, \jac_{h_k}^x\!(\barxuk) \\
236 * R_k &\defeq \tp{\jac_{h_k}^u\!(\barxuk)} \Lambda_k\, \jac_{h_k}^u\!(\barxuk). \\
237 * \end{aligned} @f]
238 * See @cite pas2022gaussnewton for more details.
239 *
240 * @ingroup grp_Problems
241 */
242template <Config Conf = DefaultConfig, class Allocator = std::allocator<std::byte>>
243class TypeErasedControlProblem : public util::TypeErased<ControlProblemVTable<Conf>, Allocator> {
244 public:
247 using allocator_type = Allocator;
248 using Box = typename VTable::Box;
252
253 protected:
254 using TypeErased::call;
255 using TypeErased::self;
256 using TypeErased::vtable;
257
258 public:
259 template <class T, class... Args>
260 static TypeErasedControlProblem make(Args &&...args) {
261 return TypeErased::template make<TypeErasedControlProblem, T>(std::forward<Args>(args)...);
262 }
263
264 /// @name Problem dimensions
265 /// @{
266
267 /// Horizon length.
268 [[nodiscard]] length_t get_N() const { return vtable.N; }
269 /// Number of inputs.
270 [[nodiscard]] length_t get_nu() const { return vtable.nu; }
271 /// Number of states.
272 [[nodiscard]] length_t get_nx() const { return vtable.nx; }
273 /// Number of outputs.
274 [[nodiscard]] length_t get_nh() const { return vtable.nh; }
275 [[nodiscard]] length_t get_nh_N() const { return vtable.nh_N; }
276 /// Number of constraints.
277 [[nodiscard]] length_t get_nc() const { return vtable.nc; }
278 [[nodiscard]] length_t get_nc_N() const { return vtable.nc_N; }
279 /// All dimensions
280 [[nodiscard]] Dim get_dim() const {
281 return {
282 .N = vtable.N,
283 .nx = vtable.nx,
284 .nu = vtable.nu,
285 .nh = vtable.nh,
286 .nh_N = vtable.nh_N,
287 .nc = vtable.nc,
288 .nc_N = vtable.nc_N,
289 };
290 }
291 /// Total number of variables.
292 [[nodiscard]] length_t get_n() const { return get_N() * get_nu(); }
293 /// Total number of constraints.
294 [[nodiscard]] length_t get_m() const { return get_N() * get_nc() + get_nc_N(); }
295
296 /// @}
297
298 /// @name Projections onto constraint sets
299 /// @{
300
301 /// **[Required]**
302 /// Function that evaluates the difference between the given point @f$ z @f$
303 /// and its projection onto the constraint set @f$ D @f$.
304 /// @param [in] z
305 /// Slack variable, @f$ z \in \R^m @f$
306 /// @param [out] e
307 /// The difference relative to its projection,
308 /// @f$ e = z - \Pi_D(z) \in \R^m @f$
309 /// @note @p z and @p e can refer to the same vector.
310 void eval_proj_diff_g(crvec z, rvec e) const;
311 /// **[Required]**
312 /// Function that projects the Lagrange multipliers for ALM.
313 /// @param [inout] y
314 /// Multipliers, @f$ y \leftarrow \Pi_Y(y) \in \R^m @f$
315 /// @param [in] M
316 /// The radius/size of the set @f$ Y @f$.
317 /// See @ref ALMParams::max_multiplier.
319
320 /// @}
321
322 /// @name Constraint sets
323 /// @{
324
325 /// Input box constraints @f$ U @f$.
326 void get_U(Box &U) const;
327 /// Stage box constraints @f$ D @f$.
328 void get_D(Box &D) const;
329 /// Terminal box constraints @f$ D_N @f$.
330 void get_D_N(Box &D) const;
331
332 /// @}
333
334 /// @name Dynamics and initial state
335 /// @{
336
337 /// Initial state @f$ x_\text{init} @f$.
338 void get_x_init(rvec x_init) const;
339 /// Discrete-time dynamics @f$ x^{k+1} = f_k(x^k, u^k) @f$.
340 void eval_f(index_t timestep, crvec x, crvec u, rvec fxu) const;
341 /// Jacobian of discrete-time dynamics @f$ \jac_f(x^k, u^k) @f$.
342 void eval_jac_f(index_t timestep, crvec x, crvec u, rmat J_fxu) const;
343 /// Gradient-vector product of discrete-time dynamics @f$ \nabla f(x^k, u^k)\,p @f$.
344 void eval_grad_f_prod(index_t timestep, crvec x, crvec u, crvec p, rvec grad_fxu_p) const;
345
346 /// @}
347
348 /// @name Output mapping
349 /// @{
350
351 /// Stage output mapping @f$ h_k(x^k, u^k) @f$.
352 void eval_h(index_t timestep, crvec x, crvec u, rvec h) const;
353 /// Terminal output mapping @f$ h_N(x^N) @f$.
354 void eval_h_N(crvec x, rvec h) const;
355
356 /// @}
357
358 /// @name Stage and terminal cost
359 /// @{
360
361 /// Stage cost @f$ \ell_k(\hbar^k) @f$.
362 [[nodiscard]] real_t eval_l(index_t timestep, crvec h) const;
363 /// Terminal cost @f$ \ell_N(\hbar^N) @f$.
364 [[nodiscard]] real_t eval_l_N(crvec h) const;
365
366 /// @}
367
368 /// @name Gauss-Newton approximations
369 /// @{
370
371 /// Cost gradients w.r.t. states and inputs
372 /// @f$ q^k = \tp{\jac_{h_k}^x\!(\barxuk)} \nabla \ell_k(\hbar^k) @f$ and
373 /// @f$ r^k = \tp{\jac_{h_k}^u\!(\barxuk)} \nabla \ell_k(\hbar^k) @f$.
374 void eval_qr(index_t timestep, crvec xu, crvec h, rvec qr) const;
375 /// Terminal cost gradient w.r.t. states
376 /// @f$ q^N = \tp{\jac_{h_N}(\bar x^N)} \nabla \ell_k(\hbar^N) @f$.
377 void eval_q_N(crvec x, crvec h, rvec q) const;
378 /// Cost Hessian w.r.t. states @f$ Q_k = \tp{\jac_{h_k}^x\!(\barxuk)}
379 /// \partial^2\ell_k(\hbar^k)\, \jac_{h_k}^x\!(\barxuk) @f$,
380 /// added to the given matrix @p Q.
381 /// @f$ Q \leftarrow Q + Q_k @f$.
382 void eval_add_Q(index_t timestep, crvec xu, crvec h, rmat Q) const;
383 /// Terminal cost Hessian w.r.t. states @f$ Q_N = \tp{\jac_{h_N}(\bar x^N)}
384 /// \partial^2\ell_N(\hbar^N)\, \jac_{h_N}(\bar x^N) @f$,
385 /// added to the given matrix @p Q.
386 /// @f$ Q \leftarrow Q + Q_N @f$.
387 void eval_add_Q_N(crvec x, crvec h, rmat Q) const;
388 /// Cost Hessian w.r.t. inputs @f$ R_k = \tp{\jac_{h_k}^u\!(\barxuk)}
389 /// \partial^2\ell_k(\hbar^k)\, \jac_{h_k}^u\!(\barxuk) @f$, keeping only
390 /// rows and columns in the mask @f$ \mathcal J @f$, added to the given
391 /// matrix @p R.
392 /// @f$ R \leftarrow R + R_k[\mathcal J, \mathcal J] @f$.
393 /// The size of @p work should be @ref get_R_work_size().
394 void eval_add_R_masked(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat R,
395 rvec work) const;
396 /// Cost Hessian w.r.t. inputs and states @f$ S_k = \tp{\jac_{h_k}^u\!(\barxuk)}
397 /// \partial^2\ell_k(\hbar^k)\, \jac_{h_k}^x\!(\barxuk) @f$, keeping only
398 /// rows in the mask @f$ \mathcal J @f$, added to the given matrix @p S.
399 /// @f$ S \leftarrow S + S_k[\mathcal J, \cdot] @f$.
400 /// The size of @p work should be @ref get_S_work_size().
401 void eval_add_S_masked(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat S,
402 rvec work) const;
403 /// @f$ out \leftarrow out + R[\mathcal J, \mathcal K]\,v[\mathcal K] @f$.
404 /// Work should contain the contents written to it by a prior call to
405 /// @ref eval_add_R_masked() in the same point.
407 crindexvec mask_K, crvec v, rvec out, rvec work) const;
408 /// @f$ out \leftarrow out + \tp{S[\mathcal K, \cdot]}\, v[\mathcal K] @f$.
409 /// Work should contain the contents written to it by a prior call to
410 /// @ref eval_add_S_masked() in the same point.
411 void eval_add_S_prod_masked(index_t timestep, crvec xu, crvec h, crindexvec mask_K, crvec v,
412 rvec out, rvec work) const;
413 /// Size of the workspace required by @ref eval_add_R_masked() and
414 /// @ref eval_add_R_prod_masked().
415 [[nodiscard]] length_t get_R_work_size() const;
416 /// Size of the workspace required by @ref eval_add_S_masked() and
417 /// @ref eval_add_S_prod_masked().
418 [[nodiscard]] length_t get_S_work_size() const;
419
420 /// @}
421
422 /// @name Constraints
423 /// @{
424
425 /// Stage constraints @f$ c_k(x^k) @f$.
426 void eval_constr(index_t timestep, crvec x, rvec c) const;
427 /// Terminal constraints @f$ c_N(x^N) @f$.
428 void eval_constr_N(crvec x, rvec c) const;
429 /// Gradient-vector product of stage constraints @f$ \nabla c_k(x^k)\, p @f$.
430 void eval_grad_constr_prod(index_t timestep, crvec x, crvec p, rvec grad_cx_p) const;
431 /// Gradient-vector product of terminal constraints @f$ \nabla c_N(x^N)\, p @f$.
432 void eval_grad_constr_prod_N(crvec x, crvec p, rvec grad_cx_p) const;
433 /// Gauss-Newton Hessian of stage constraints @f$ \tp{\jac_{c_k}}(x^k)\,
434 /// \operatorname{diag}(M)\; \jac_{c_k}(x^k) @f$.
435 void eval_add_gn_hess_constr(index_t timestep, crvec x, crvec M, rmat out) const;
436 /// Gauss-Newton Hessian of terminal constraints @f$ \tp{\jac_{c_N}}(x^N)\,
437 /// \operatorname{diag}(M)\; \jac_{c_N}(x^N) @f$.
439
440 /// @}
441
442 /// @name Checks
443 /// @{
444
445 /// Check that the problem formulation is well-defined, the dimensions match,
446 /// etc. Throws an exception if this is not the case.
447 void check() const;
448
449 /// @}
450
451 /// @name Querying specialized implementations
452 /// @{
453
454 // clang-format off
455 [[nodiscard]] bool provides_get_D() const { return vtable.get_D != nullptr; }
456 [[nodiscard]] bool provides_get_D_N() const { return vtable.get_D_N != &vtable.default_get_D_N; }
457 [[nodiscard]] bool provides_eval_h() const { return vtable.eval_h != nullptr; }
458 [[nodiscard]] bool provides_eval_h_N() const { return vtable.eval_h_N != nullptr; }
459 [[nodiscard]] bool provides_eval_add_Q_N() const { return vtable.eval_add_Q_N != &vtable.default_eval_add_Q_N; }
464 [[nodiscard]] bool provides_eval_constr() const { return vtable.eval_constr != nullptr; }
465 [[nodiscard]] bool provides_eval_constr_N() const { return vtable.eval_constr_N != &vtable.default_eval_constr_N; }
466 [[nodiscard]] bool provides_eval_grad_constr_prod() const { return vtable.eval_grad_constr_prod != nullptr; }
468 [[nodiscard]] bool provides_eval_add_gn_hess_constr() const { return vtable.eval_add_gn_hess_constr != nullptr; }
470 // clang-format on
471
472 /// @}
473};
474
475// clang-format off
476#ifdef NDEBUG
477[[gnu::always_inline]] inline void check_finiteness(auto &&, auto &&) {}
478template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_proj_diff_g(crvec z, rvec e) const { return call(vtable.eval_proj_diff_g, z, e); }
479template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_proj_multipliers(rvec y, real_t M) const { return call(vtable.eval_proj_multipliers, y, M); }
480template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::get_U(Box &U) const { return call(vtable.get_U, U); }
481template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::get_D(Box &D) const { return call(vtable.get_D, D); }
482template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::get_D_N(Box &D) const { return call(vtable.get_D_N, D); }
483template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::get_x_init(rvec x_init) const { return call(vtable.get_x_init, x_init); }
484template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_f(index_t timestep, crvec x, crvec u, rvec fxu) const { return call(vtable.eval_f, timestep, x, u, fxu); }
485template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_jac_f(index_t timestep, crvec x, crvec u, rmat J_fxu) const { return call(vtable.eval_jac_f, timestep, x, u, J_fxu); }
486template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_grad_f_prod(index_t timestep, crvec x, crvec u, crvec p, rvec grad_fxu_p) const { return call(vtable.eval_grad_f_prod, timestep, x, u, p, grad_fxu_p); }
487template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_h(index_t timestep, crvec x, crvec u, rvec h) const { return call(vtable.eval_h, timestep, x, u, h); }
488template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_h_N(crvec x, rvec h) const { return call(vtable.eval_h_N, x, h); }
489template <Config Conf, class Allocator> [[gnu::always_inline]] inline auto TypeErasedControlProblem<Conf, Allocator>::eval_l(index_t timestep, crvec h) const -> real_t { return call(vtable.eval_l, timestep, h); }
490template <Config Conf, class Allocator> [[gnu::always_inline]] inline auto TypeErasedControlProblem<Conf, Allocator>::eval_l_N(crvec h) const -> real_t { return call(vtable.eval_l_N, h); }
491template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_qr(index_t timestep, crvec xu, crvec h, rvec qr) const { return call(vtable.eval_qr, timestep, xu, h, qr); }
492template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_q_N(crvec x, crvec h, rvec q) const { return call(vtable.eval_q_N, x, h, q); }
493template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_add_Q(index_t timestep, crvec xu, crvec h, rmat Q) const { return call(vtable.eval_add_Q, timestep, xu, h, Q); }
494template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_add_Q_N(crvec x, crvec h, rmat Q) const { return call(vtable.eval_add_Q_N, x, h, Q); }
495template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_add_R_masked(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat R, rvec work) const { return call(vtable.eval_add_R_masked, timestep, xu, h, mask, R, work); }
496template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_add_S_masked(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat S, rvec work) const { return call(vtable.eval_add_S_masked, timestep, xu, h, mask, S, work); }
497template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_add_R_prod_masked(index_t timestep, crvec xu, crvec h, crindexvec mask_J, crindexvec mask_K, crvec v, rvec out, rvec work) const { return call(vtable.eval_add_R_prod_masked, timestep, xu, h, mask_J, mask_K, v, out, work); }
498template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_add_S_prod_masked(index_t timestep, crvec xu, crvec h, crindexvec mask_K, crvec v, rvec out, rvec work) const { return call(vtable.eval_add_S_prod_masked, timestep, xu, h, mask_K, v, out, work); }
499template <Config Conf, class Allocator> [[gnu::always_inline]] inline auto TypeErasedControlProblem<Conf, Allocator>::get_R_work_size() const -> length_t { return call(vtable.get_R_work_size); }
500template <Config Conf, class Allocator> [[gnu::always_inline]] inline auto TypeErasedControlProblem<Conf, Allocator>::get_S_work_size() const -> length_t { return call(vtable.get_S_work_size); }
501template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_constr(index_t timestep, crvec x, rvec c) const { return call(vtable.eval_constr, timestep, x, c); }
502template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_constr_N(crvec x, rvec c) const { return call(vtable.eval_constr_N, x, c); }
503template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_grad_constr_prod(index_t timestep, crvec x, crvec p, rvec grad_cx_p) const { return call(vtable.eval_grad_constr_prod, timestep, x, p, grad_cx_p); }
504template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_grad_constr_prod_N(crvec x, crvec p, rvec grad_cx_p) const { return call(vtable.eval_grad_constr_prod_N, x, p, grad_cx_p); }
505template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_add_gn_hess_constr(index_t timestep, crvec x, crvec M, rmat out) const { return call(vtable.eval_add_gn_hess_constr, timestep, x, M, out); }
506template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_add_gn_hess_constr_N(crvec x, crvec M, rmat out) const { return call(vtable.eval_add_gn_hess_constr_N, x, M, out); }
507template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::check() const { return call(vtable.check); }
508#else
509/// If the given vector @p v is not finite, break or throw an exception with the
510/// given message @p msg.
511inline void check_finiteness(const auto &v, std::string_view msg) {
512 using std::begin;
513 using std::end;
514 if (!v.allFinite()) {
515 std::cout << msg << std::endl;
516 throw std::runtime_error(std::string(msg));
517 }
518}
519inline void check_finiteness(const std::floating_point auto &v, std::string_view msg) {
520 if (!std::isfinite(v)) {
521 std::cout << msg << std::endl;
522 throw std::runtime_error(std::string(msg));
523 }
524}
525template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_proj_diff_g(crvec z, rvec e) const { return call(vtable.eval_proj_diff_g, z, e); }
526template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_proj_multipliers(rvec y, real_t M) const { return call(vtable.eval_proj_multipliers, y, M); }
527template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::get_U(Box &U) const { return call(vtable.get_U, U); }
528template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::get_D(Box &D) const { return call(vtable.get_D, D); }
529template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::get_D_N(Box &D_N) const { return call(vtable.get_D_N, D_N); }
530template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::get_x_init(rvec x_init) const { call(vtable.get_x_init, x_init); check_finiteness(x_init, "Infinite output of get_x_init"); }
531template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_f(index_t timestep, crvec x, crvec u, rvec fxu) const { check_finiteness(x, "Infinite input x of f"); check_finiteness(u, "Infinite input u of f"); call(vtable.eval_f, timestep, x, u, fxu); check_finiteness(fxu, "Infinite output of f"); }
532template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_jac_f(index_t timestep, crvec x, crvec u, rmat J_fxu) const { check_finiteness(x, "Infinite input x of jac_f"); check_finiteness(u, "Infinite input u of jac_f"); call(vtable.eval_jac_f, timestep, x, u, J_fxu); check_finiteness(J_fxu.reshaped(), "Infinite output of jac_f"); }
533template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_grad_f_prod(index_t timestep, crvec x, crvec u, crvec p, rvec grad_fxu_p) const { check_finiteness(x, "Infinite input x of grad_f_prod"); check_finiteness(u, "Infinite input u of grad_f_prod"); check_finiteness(p, "Infinite input p of grad_f_prod"); call(vtable.eval_grad_f_prod, timestep, x, u, p, grad_fxu_p); check_finiteness(grad_fxu_p, "Infinite output of jac_f"); }
534template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_h(index_t timestep, crvec x, crvec u, rvec h) const { check_finiteness(x, "Infinite input x of h"); check_finiteness(u, "Infinite input u of h"); call(vtable.eval_h, timestep, x, u, h); check_finiteness(h, "Infinite output of h"); }
535template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_h_N(crvec x, rvec h) const { check_finiteness(x, "Infinite input x of h_N"); call(vtable.eval_h_N, x, h); check_finiteness(h, "Infinite output of h_N"); }
536template <Config Conf, class Allocator> [[gnu::always_inline]] inline auto TypeErasedControlProblem<Conf, Allocator>::eval_l(index_t timestep, crvec h) const -> real_t { check_finiteness(h, "Infinite input h of l"); auto l = call(vtable.eval_l, timestep, h); check_finiteness(l, "Infinite output of l"); return l; }
537template <Config Conf, class Allocator> [[gnu::always_inline]] inline auto TypeErasedControlProblem<Conf, Allocator>::eval_l_N(crvec h) const -> real_t { check_finiteness(h, "Infinite input h of l_N"); auto l = call(vtable.eval_l_N, h); check_finiteness(l, "Infinite output of l_N"); return l; }
538template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_qr(index_t timestep, crvec xu, crvec h, rvec qr) const { return call(vtable.eval_qr, timestep, xu, h, qr); }
539template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_q_N(crvec x, crvec h, rvec q) const { check_finiteness(x, "Infinite input x of q_N"); check_finiteness(h, "Infinite input h of q_N"); call(vtable.eval_q_N, x, h, q); check_finiteness(q, "Infinite output of q_N"); }
540template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_add_Q(index_t timestep, crvec xu, crvec h, rmat Q) const { return call(vtable.eval_add_Q, timestep, xu, h, Q); }
541template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_add_Q_N(crvec x, crvec h, rmat Q) const { return call(vtable.eval_add_Q_N, x, h, Q); }
542template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_add_R_masked(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat R, rvec work) const { return call(vtable.eval_add_R_masked, timestep, xu, h, mask, R, work); }
543template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_add_S_masked(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat S, rvec work) const { return call(vtable.eval_add_S_masked, timestep, xu, h, mask, S, work); }
544template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_add_R_prod_masked(index_t timestep, crvec xu, crvec h, crindexvec mask_J, crindexvec mask_K, crvec v, rvec out, rvec work) const { return call(vtable.eval_add_R_prod_masked, timestep, xu, h, mask_J, mask_K, v, out, work); }
545template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_add_S_prod_masked(index_t timestep, crvec xu, crvec h, crindexvec mask_K, crvec v, rvec out, rvec work) const { return call(vtable.eval_add_S_prod_masked, timestep, xu, h, mask_K, v, out, work); }
546template <Config Conf, class Allocator> [[gnu::always_inline]] inline auto TypeErasedControlProblem<Conf, Allocator>::get_R_work_size() const -> length_t { return call(vtable.get_R_work_size); }
547template <Config Conf, class Allocator> [[gnu::always_inline]] inline auto TypeErasedControlProblem<Conf, Allocator>::get_S_work_size() const -> length_t { return call(vtable.get_S_work_size); }
548template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_constr(index_t timestep, crvec x, rvec c) const { return call(vtable.eval_constr, timestep, x, c); }
549template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_constr_N(crvec x, rvec c) const { return call(vtable.eval_constr_N, x, c); }
550template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_grad_constr_prod(index_t timestep, crvec x, crvec p, rvec grad_cx_p) const { return call(vtable.eval_grad_constr_prod, timestep, x, p, grad_cx_p); }
551template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_grad_constr_prod_N(crvec x, crvec p, rvec grad_cx_p) const { return call(vtable.eval_grad_constr_prod_N, x, p, grad_cx_p); }
552template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_add_gn_hess_constr(index_t timestep, crvec x, crvec M, rmat out) const { return call(vtable.eval_add_gn_hess_constr, timestep, x, M, out); }
553template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::eval_add_gn_hess_constr_N(crvec x, crvec M, rmat out) const { return call(vtable.eval_add_gn_hess_constr_N, x, M, out); }
554template <Config Conf, class Allocator> [[gnu::always_inline]] inline void TypeErasedControlProblem<Conf, Allocator>::check() const { return call(vtable.check); }
555#endif
556// clang-format on
557
558template <class Problem>
560 USING_ALPAQA_CONFIG_TEMPLATE(std::remove_cvref_t<Problem>::config_t);
562
563 [[nodiscard, gnu::always_inline]] length_t get_N() const { return problem.get_N(); }
564 [[nodiscard, gnu::always_inline]] length_t get_nu() const { return problem.get_nu(); }
565 [[nodiscard, gnu::always_inline]] length_t get_nx() const { return problem.get_nx(); }
566 [[nodiscard, gnu::always_inline]] length_t get_nh() const { return problem.get_nh(); }
567 [[nodiscard, gnu::always_inline]] length_t get_nh_N() const { return problem.get_nh_N(); }
568 [[nodiscard, gnu::always_inline]] length_t get_nc() const { return problem.get_nc(); }
569 [[nodiscard, gnu::always_inline]] length_t get_nc_N() const { return problem.get_nc_N(); }
570
571 // clang-format off
572 [[gnu::always_inline]] void eval_proj_diff_g(crvec z, rvec e) const { return problem.eval_proj_diff_g(z, e); }
573 [[gnu::always_inline]] void eval_proj_multipliers(rvec y, real_t M) const { return problem.eval_proj_multipliers(y, M); }
574 [[gnu::always_inline]] void get_x_init(rvec x_init) const { return problem.get_x_init(x_init); }
575 [[nodiscard, gnu::always_inline]] length_t get_R_work_size() const requires requires { &std::remove_cvref_t<Problem>::get_R_work_size; } { return problem.get_R_work_size(); }
576 [[nodiscard, gnu::always_inline]] length_t get_S_work_size() const requires requires { &std::remove_cvref_t<Problem>::get_S_work_size; } { return problem.get_S_work_size(); }
577 [[gnu::always_inline]] void get_U(Box &U) const requires requires { &std::remove_cvref_t<Problem>::get_U; } { return problem.get_U(U); }
578 [[gnu::always_inline]] void get_D(Box &D) const requires requires { &std::remove_cvref_t<Problem>::get_D; } { return problem.get_D(D); }
579 [[gnu::always_inline]] void get_D_N(Box &D) const requires requires { &std::remove_cvref_t<Problem>::get_D_N; } { return problem.get_D_N(D); }
580 [[gnu::always_inline]] void eval_f(index_t timestep, crvec x, crvec u, rvec fxu) const { ++evaluations->f; return timed(evaluations->time.f, std::bind(&std::remove_cvref_t<Problem>::eval_f, &problem, timestep, x, u, fxu)); }
581 [[gnu::always_inline]] void eval_jac_f(index_t timestep, crvec x, crvec u, rmat J_fxu) const { ++evaluations->jac_f; return timed(evaluations->time.jac_f, std::bind(&std::remove_cvref_t<Problem>::eval_jac_f, &problem, timestep, x, u, J_fxu)); }
582 [[gnu::always_inline]] void eval_grad_f_prod(index_t timestep, crvec x, crvec u, crvec p, rvec grad_fxu_p) const { ++evaluations->grad_f_prod; return timed(evaluations->time.grad_f_prod, std::bind(&std::remove_cvref_t<Problem>::eval_grad_f_prod, &problem, timestep, x, u, p, grad_fxu_p)); }
583 [[gnu::always_inline]] void eval_h(index_t timestep, crvec x, crvec u, rvec h) const { ++evaluations->h; return timed(evaluations->time.h, std::bind(&std::remove_cvref_t<Problem>::eval_h, &problem, timestep, x, u, h)); }
584 [[gnu::always_inline]] void eval_h_N(crvec x, rvec h) const { ++evaluations->h_N; return timed(evaluations->time.h_N, std::bind(&std::remove_cvref_t<Problem>::eval_h_N, &problem, x, h)); }
585 [[nodiscard, gnu::always_inline]] real_t eval_l(index_t timestep, crvec h) const { ++evaluations->l; return timed(evaluations->time.l, std::bind(&std::remove_cvref_t<Problem>::eval_l, &problem, timestep, h)); }
586 [[nodiscard, gnu::always_inline]] real_t eval_l_N(crvec h) const { ++evaluations->l_N; return timed(evaluations->time.l_N, std::bind(&std::remove_cvref_t<Problem>::eval_l_N, &problem, h)); }
587 [[gnu::always_inline]] void eval_qr(index_t timestep, crvec xu, crvec h, rvec qr) const { ++evaluations->qr; return timed(evaluations->time.qr, std::bind(&std::remove_cvref_t<Problem>::eval_qr, &problem, timestep, xu, h, qr)); }
588 [[gnu::always_inline]] void eval_q_N(crvec x, crvec h, rvec q) const requires requires { &std::remove_cvref_t<Problem>::eval_q_N; } { ++evaluations->q_N; return timed(evaluations->time.q_N, std::bind(&std::remove_cvref_t<Problem>::eval_q_N, &problem, x, h, q)); }
589 [[gnu::always_inline]] void eval_add_Q(index_t timestep, crvec xu, crvec h, rmat Q) const { ++evaluations->add_Q; return timed(evaluations->time.add_Q, std::bind(&std::remove_cvref_t<Problem>::eval_add_Q, &problem, timestep, xu, h, Q)); }
590 [[gnu::always_inline]] void eval_add_Q_N(crvec x, crvec h, rmat Q) const requires requires { &std::remove_cvref_t<Problem>::eval_add_Q_N; } { ++evaluations->add_Q_N; return timed(evaluations->time.add_Q_N, std::bind(&std::remove_cvref_t<Problem>::eval_add_Q_N, &problem, x, h, Q)); }
591 [[gnu::always_inline]] void eval_add_R_masked(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat R, rvec work) const { ++evaluations->add_R_masked; return timed(evaluations->time.add_R_masked, std::bind(&std::remove_cvref_t<Problem>::eval_add_R_masked, &problem, timestep, xu, h, mask, R, work)); }
592 [[gnu::always_inline]] void eval_add_S_masked(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat S, rvec work) const { ++evaluations->add_S_masked; return timed(evaluations->time.add_S_masked, std::bind(&std::remove_cvref_t<Problem>::eval_add_S_masked, &problem, timestep, xu, h, mask, S, work)); }
593 [[gnu::always_inline]] void eval_add_R_prod_masked(index_t timestep, crvec xu, crvec h, crindexvec mask_J, crindexvec mask_K, crvec v, rvec out, rvec work) const requires requires { &std::remove_cvref_t<Problem>::eval_add_R_prod_masked; } { ++evaluations->add_R_prod_masked; return timed(evaluations->time.add_R_prod_masked, std::bind(&std::remove_cvref_t<Problem>::eval_add_R_prod_masked, &problem, timestep, xu, h, mask_J, mask_K, v, out, work)); }
594 [[gnu::always_inline]] void eval_add_S_prod_masked(index_t timestep, crvec xu, crvec h, crindexvec mask_K, crvec v, rvec out, rvec work) const requires requires { &std::remove_cvref_t<Problem>::eval_add_S_prod_masked; } { ++evaluations->add_S_prod_masked; return timed(evaluations->time.add_S_prod_masked, std::bind(&std::remove_cvref_t<Problem>::eval_add_S_prod_masked, &problem, timestep, xu, h, mask_K, v, out, work)); }
595 [[gnu::always_inline]] void eval_constr(index_t timestep, crvec x, rvec c) const requires requires { &std::remove_cvref_t<Problem>::eval_constr; } { ++evaluations->constr; return timed(evaluations->time.constr, std::bind(&std::remove_cvref_t<Problem>::eval_constr, &problem, timestep, x, c)); }
596 [[gnu::always_inline]] void eval_constr_N(crvec x, rvec c) const requires requires { &std::remove_cvref_t<Problem>::eval_constr_N; } { ++evaluations->constr_N; return timed(evaluations->time.constr_N, std::bind(&std::remove_cvref_t<Problem>::eval_constr_N, &problem, x, c)); }
597 [[gnu::always_inline]] void eval_grad_constr_prod(index_t timestep, crvec x, crvec p, rvec grad_cx_p) const requires requires { &std::remove_cvref_t<Problem>::eval_grad_constr_prod; } { ++evaluations->grad_constr_prod; return timed(evaluations->time.grad_constr_prod, std::bind(&std::remove_cvref_t<Problem>::eval_grad_constr_prod, &problem, timestep, x, p, grad_cx_p)); }
598 [[gnu::always_inline]] void eval_grad_constr_prod_N(crvec x, crvec p, rvec grad_cx_p) const requires requires { &std::remove_cvref_t<Problem>::eval_grad_constr_prod_N; } { ++evaluations->grad_constr_prod_N; return timed(evaluations->time.grad_constr_prod_N, std::bind(&std::remove_cvref_t<Problem>::eval_grad_constr_prod_N, &problem, x, p, grad_cx_p)); }
599 [[gnu::always_inline]] void eval_add_gn_hess_constr(index_t timestep, crvec x, crvec M, rmat out) const requires requires { &std::remove_cvref_t<Problem>::eval_add_gn_hess_constr; } { ++evaluations->add_gn_hess_constr; return timed(evaluations->time.add_gn_hess_constr, std::bind(&std::remove_cvref_t<Problem>::eval_add_gn_hess_constr, &problem, timestep, x, M, out)); }
600 [[gnu::always_inline]] void eval_add_gn_hess_constr_N(crvec x, crvec M, rmat out) const requires requires { &std::remove_cvref_t<Problem>::eval_add_gn_hess_constr_N; } { ++evaluations->add_gn_hess_constr_N; return timed(evaluations->time.add_gn_hess_constr_N, std::bind(&std::remove_cvref_t<Problem>::eval_add_gn_hess_constr_N, &problem, x, M, out)); }
601 [[gnu::always_inline]] void check() const { problem.check(); }
602
603 [[nodiscard]] bool provides_get_D() const requires requires (Problem p) { { p.provides_get_D() } -> std::convertible_to<bool>; } { return problem.provides_get_D(); }
604 [[nodiscard]] bool provides_get_D_N() const requires requires (Problem p) { { p.provides_get_D_N() } -> std::convertible_to<bool>; } { return problem.provides_get_D_N(); }
605 [[nodiscard]] bool provides_eval_add_Q_N() const requires requires (Problem p) { { p.provides_eval_add_Q_N() } -> std::convertible_to<bool>; } { return problem.provides_eval_add_Q_N(); }
606 [[nodiscard]] bool provides_eval_add_R_prod_masked() const requires requires (Problem p) { { p.provides_eval_add_R_prod_masked() } -> std::convertible_to<bool>; } { return problem.provides_eval_add_R_prod_masked(); }
607 [[nodiscard]] bool provides_eval_add_S_prod_masked() const requires requires (Problem p) { { p.provides_eval_add_S_prod_masked() } -> std::convertible_to<bool>; } { return problem.provides_eval_add_S_prod_masked(); }
608 [[nodiscard]] bool provides_get_R_work_size() const requires requires (Problem p) { { p.provides_get_R_work_size() } -> std::convertible_to<bool>; } { return problem.provides_get_R_work_size(); }
609 [[nodiscard]] bool provides_get_S_work_size() const requires requires (Problem p) { { p.provides_get_S_work_size() } -> std::convertible_to<bool>; } { return problem.provides_get_S_work_size(); }
610 [[nodiscard]] bool provides_eval_constr() const requires requires (Problem p) { { p.provides_eval_constr() } -> std::convertible_to<bool>; } { return problem.provides_eval_constr(); }
611 [[nodiscard]] bool provides_eval_constr_N() const requires requires (Problem p) { { p.provides_eval_constr_N() } -> std::convertible_to<bool>; } { return problem.provides_eval_constr_N(); }
612 [[nodiscard]] bool provides_eval_grad_constr_prod() const requires requires (Problem p) { { p.provides_eval_grad_constr_prod() } -> std::convertible_to<bool>; } { return problem.provides_eval_grad_constr_prod(); }
613 [[nodiscard]] bool provides_eval_grad_constr_prod_N() const requires requires (Problem p) { { p.provides_eval_grad_constr_prod_N() } -> std::convertible_to<bool>; } { return problem.provides_eval_grad_constr_prod_N(); }
614 [[nodiscard]] bool provides_eval_add_gn_hess_constr() const requires requires (Problem p) { { p.provides_eval_add_gn_hess_constr() } -> std::convertible_to<bool>; } { return problem.provides_eval_add_gn_hess_constr(); }
615 [[nodiscard]] bool provides_eval_add_gn_hess_constr_N() const requires requires (Problem p) { { p.provides_eval_add_gn_hess_constr_N() } -> std::convertible_to<bool>; } { return problem.provides_eval_add_gn_hess_constr_N(); }
616 // clang-format on
617
618 std::shared_ptr<OCPEvalCounter> evaluations = std::make_shared<OCPEvalCounter>();
619 Problem problem;
620
622 requires std::is_default_constructible_v<Problem>
623 = default;
624 template <class P>
626 requires std::is_same_v<std::remove_cvref_t<P>, std::remove_cvref_t<Problem>>
627 : problem{std::forward<P>(problem)} {}
628 template <class... Args>
629 explicit ControlProblemWithCounters(std::in_place_t, Args &&...args)
630 requires(!std::is_lvalue_reference_v<Problem>)
631 : problem{std::forward<Args>(args)...} {}
632
633 /// Reset all evaluation counters and timers to zero. Affects all instances
634 /// that share the same evaluations. If you only want to reset the counters
635 /// of this instance, use @ref decouple_evaluations first.
636 void reset_evaluations() { evaluations.reset(); }
637 /// Give this instance its own evaluation counters and timers, decoupling
638 /// it from any other instances they might have previously been shared with.
639 /// The evaluation counters and timers are preserved (a copy is made).
640 void decouple_evaluations() { evaluations = std::make_shared<OCPEvalCounter>(*evaluations); }
641
642 private:
643 template <class TimeT, class FunT>
644 [[gnu::always_inline]] static decltype(auto) timed(TimeT &time, FunT &&f) {
646 return std::forward<FunT>(f)();
647 }
648};
649
650template <class Problem>
651[[nodiscard]] auto ocproblem_with_counters(Problem &&p) {
652 using Prob = std::remove_cvref_t<Problem>;
653 using ProbWithCnt = ControlProblemWithCounters<Prob>;
654 return ProbWithCnt{std::forward<Problem>(p)};
655}
656
657template <class Problem>
658[[nodiscard]] auto ocproblem_with_counters_ref(Problem &p) {
659 using Prob = std::remove_cvref_t<Problem>;
661 return ProbWithCnt{p};
662}
663
664} // namespace alpaqa
Nonlinear optimal control problem with finite horizon .
Definition: ocproblem.hpp:243
Dim get_dim() const
All dimensions.
Definition: ocproblem.hpp:280
void eval_jac_f(index_t timestep, crvec x, crvec u, rmat J_fxu) const
Jacobian of discrete-time dynamics .
Definition: ocproblem.hpp:532
bool provides_eval_grad_constr_prod() const
Definition: ocproblem.hpp:466
bool provides_eval_add_gn_hess_constr() const
Definition: ocproblem.hpp:468
void eval_add_R_prod_masked(index_t timestep, crvec xu, crvec h, crindexvec mask_J, crindexvec mask_K, crvec v, rvec out, rvec work) const
.
Definition: ocproblem.hpp:544
bool provides_eval_add_R_prod_masked() const
Definition: ocproblem.hpp:460
length_t get_nc() const
Number of constraints.
Definition: ocproblem.hpp:277
void eval_add_gn_hess_constr_N(crvec x, crvec M, rmat out) const
Gauss-Newton Hessian of terminal constraints .
Definition: ocproblem.hpp:553
length_t get_S_work_size() const
Size of the workspace required by eval_add_S_masked() and eval_add_S_prod_masked().
Definition: ocproblem.hpp:547
typename VTable::Box Box
Definition: ocproblem.hpp:248
void check() const
Check that the problem formulation is well-defined, the dimensions match, etc.
Definition: ocproblem.hpp:554
void eval_qr(index_t timestep, crvec xu, crvec h, rvec qr) const
Cost gradients w.r.t.
Definition: ocproblem.hpp:538
void eval_add_S_prod_masked(index_t timestep, crvec xu, crvec h, crindexvec mask_K, crvec v, rvec out, rvec work) const
.
Definition: ocproblem.hpp:545
void eval_constr_N(crvec x, rvec c) const
Terminal constraints .
Definition: ocproblem.hpp:549
void eval_grad_constr_prod_N(crvec x, crvec p, rvec grad_cx_p) const
Gradient-vector product of terminal constraints .
Definition: ocproblem.hpp:551
length_t get_nu() const
Number of inputs.
Definition: ocproblem.hpp:270
void eval_add_R_masked(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat R, rvec work) const
Cost Hessian w.r.t.
Definition: ocproblem.hpp:542
void get_U(Box &U) const
Input box constraints .
Definition: ocproblem.hpp:527
real_t eval_l_N(crvec h) const
Terminal cost .
Definition: ocproblem.hpp:537
length_t get_m() const
Total number of constraints.
Definition: ocproblem.hpp:294
real_t eval_l(index_t timestep, crvec h) const
Stage cost .
Definition: ocproblem.hpp:536
void eval_grad_f_prod(index_t timestep, crvec x, crvec u, crvec p, rvec grad_fxu_p) const
Gradient-vector product of discrete-time dynamics .
Definition: ocproblem.hpp:533
void eval_add_gn_hess_constr(index_t timestep, crvec x, crvec M, rmat out) const
Gauss-Newton Hessian of stage constraints .
Definition: ocproblem.hpp:552
void eval_constr(index_t timestep, crvec x, rvec c) const
Stage constraints .
Definition: ocproblem.hpp:548
length_t get_nh() const
Number of outputs.
Definition: ocproblem.hpp:274
void eval_h(index_t timestep, crvec x, crvec u, rvec h) const
Stage output mapping .
Definition: ocproblem.hpp:534
void get_D_N(Box &D) const
Terminal box constraints .
Definition: ocproblem.hpp:529
static TypeErasedControlProblem make(Args &&...args)
Definition: ocproblem.hpp:260
bool provides_eval_grad_constr_prod_N() const
Definition: ocproblem.hpp:467
length_t get_R_work_size() const
Size of the workspace required by eval_add_R_masked() and eval_add_R_prod_masked().
Definition: ocproblem.hpp:546
length_t get_nx() const
Number of states.
Definition: ocproblem.hpp:272
void eval_add_S_masked(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat S, rvec work) const
Cost Hessian w.r.t.
Definition: ocproblem.hpp:543
void get_x_init(rvec x_init) const
Initial state .
Definition: ocproblem.hpp:530
void get_D(Box &D) const
Stage box constraints .
Definition: ocproblem.hpp:528
void eval_proj_multipliers(rvec y, real_t M) const
[Required] Function that projects the Lagrange multipliers for ALM.
Definition: ocproblem.hpp:526
void eval_q_N(crvec x, crvec h, rvec q) const
Terminal cost gradient w.r.t.
Definition: ocproblem.hpp:539
bool provides_eval_add_S_prod_masked() const
Definition: ocproblem.hpp:461
void eval_add_Q_N(crvec x, crvec h, rmat Q) const
Terminal cost Hessian w.r.t.
Definition: ocproblem.hpp:541
void eval_grad_constr_prod(index_t timestep, crvec x, crvec p, rvec grad_cx_p) const
Gradient-vector product of stage constraints .
Definition: ocproblem.hpp:550
void eval_add_Q(index_t timestep, crvec xu, crvec h, rmat Q) const
Cost Hessian w.r.t.
Definition: ocproblem.hpp:540
length_t get_n() const
Total number of variables.
Definition: ocproblem.hpp:292
void eval_proj_diff_g(crvec z, rvec e) const
[Required] Function that evaluates the difference between the given point and its projection onto th...
Definition: ocproblem.hpp:525
void eval_f(index_t timestep, crvec x, crvec u, rvec fxu) const
Discrete-time dynamics .
Definition: ocproblem.hpp:531
void eval_h_N(crvec x, rvec h) const
Terminal output mapping .
Definition: ocproblem.hpp:535
bool provides_eval_add_gn_hess_constr_N() const
Definition: ocproblem.hpp:469
length_t get_N() const
Horizon length.
Definition: ocproblem.hpp:268
Class for polymorphism through type erasure.
decltype(auto) call(Ret(*f)(const void *, FArgs...), Args &&...args) const
Call the vtable function f with the given arguments args, implicitly passing the self pointer and vta...
TypeErased() noexcept(noexcept(allocator_type()))=default
Default constructor.
void * self
Pointer to the stored object.
#define USING_ALPAQA_CONFIG(Conf)
Definition: config.hpp:42
#define USING_ALPAQA_CONFIG_TEMPLATE(Conf)
Definition: config.hpp:46
length_t nh
Definition: ocproblem.hpp:25
length_t nx
Definition: ocproblem.hpp:25
auto ocproblem_with_counters_ref(Problem &p)
Definition: ocproblem.hpp:658
typename Conf::rmat rmat
Definition: config.hpp:60
length_t nc
Definition: ocproblem.hpp:25
auto ocproblem_with_counters(Problem &&p)
Definition: ocproblem.hpp:651
length_t N
Definition: ocproblem.hpp:25
length_t nu
Definition: ocproblem.hpp:25
typename Conf::real_t real_t
Definition: config.hpp:51
typename Conf::index_t index_t
Definition: config.hpp:63
void check_finiteness(const auto &v, std::string_view msg)
If the given vector v is not finite, break or throw an exception with the given message msg.
Definition: ocproblem.hpp:511
typename Conf::length_t length_t
Definition: config.hpp:62
typename Conf::rvec rvec
Definition: config.hpp:55
typename Conf::crvec crvec
Definition: config.hpp:56
typename Conf::crindexvec crindexvec
Definition: config.hpp:66
#define ALPAQA_TE_REQUIRED_METHOD(vtable, type, member)
#define ALPAQA_TE_OPTIONAL_METHOD(vtable, type, member, instance_p)
required_const_function_t< void(index_t timestep, crvec x, crvec u, rmat J_fxu)> eval_jac_f
Definition: ocproblem.hpp:55
static void default_eval_add_S_prod_masked(const void *, index_t, crvec, crvec, crindexvec, crvec, rvec, rvec, const ControlProblemVTable &)
Definition: ocproblem.hpp:168
static void default_eval_add_R_prod_masked(const void *, index_t, crvec, crvec, crindexvec, crindexvec, crvec, rvec, rvec, const ControlProblemVTable &)
Definition: ocproblem.hpp:163
optional_const_function_t< length_t()> get_S_work_size
Definition: ocproblem.hpp:85
optional_const_function_t< void(crvec x, crvec h, rmat Q)> eval_add_Q_N
Definition: ocproblem.hpp:73
optional_const_function_t< void(index_t timestep, crvec x, crvec p, rvec grad_cx_p)> eval_grad_constr_prod
Definition: ocproblem.hpp:91
static length_t default_get_R_work_size(const void *, const ControlProblemVTable &)
Definition: ocproblem.hpp:172
static void default_eval_add_gn_hess_constr_N(const void *self, crvec x, crvec M, rmat out, const ControlProblemVTable &vtable)
Definition: ocproblem.hpp:188
ControlProblemVTable(util::VTableTypeTag< P > t)
Definition: ocproblem.hpp:105
required_const_function_t< void(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat S, rvec work)> eval_add_S_masked
Definition: ocproblem.hpp:77
optional_const_function_t< void(Box &D)> get_D
Definition: ocproblem.hpp:47
optional_const_function_t< void(crvec x, crvec M, rmat out)> eval_add_gn_hess_constr_N
Definition: ocproblem.hpp:97
static length_t default_get_S_work_size(const void *, const ControlProblemVTable &)
Definition: ocproblem.hpp:176
required_const_function_t< real_t(crvec h)> eval_l_N
Definition: ocproblem.hpp:65
optional_const_function_t< void(crvec x, rvec h)> eval_h_N
Definition: ocproblem.hpp:61
optional_const_function_t< void(crvec x, rvec c)> eval_constr_N
Definition: ocproblem.hpp:89
optional_const_function_t< void(Box &D)> get_D_N
Definition: ocproblem.hpp:49
required_const_function_t< real_t(index_t timestep, crvec h)> eval_l
Definition: ocproblem.hpp:63
required_const_function_t< void()> check
Definition: ocproblem.hpp:99
optional_const_function_t< void(crvec x, crvec p, rvec grad_cx_p)> eval_grad_constr_prod_N
Definition: ocproblem.hpp:93
optional_const_function_t< void(index_t timestep, crvec x, crvec u, rvec h)> eval_h
Definition: ocproblem.hpp:59
required_const_function_t< void(crvec x, crvec h, rvec q)> eval_q_N
Definition: ocproblem.hpp:69
static void default_eval_grad_constr_prod_N(const void *self, crvec x, crvec p, rvec grad_cx_p, const ControlProblemVTable &vtable)
Definition: ocproblem.hpp:184
required_const_function_t< void(rvec x_init)> get_x_init
Definition: ocproblem.hpp:51
required_const_function_t< void(crvec z, rvec e)> eval_proj_diff_g
Definition: ocproblem.hpp:41
util::BasicVTable::optional_const_function_t< F, ControlProblemVTable > optional_const_function_t
Definition: ocproblem.hpp:37
alpaqa::Box< config_t > Box
Definition: ocproblem.hpp:31
required_const_function_t< void(index_t timestep, crvec x, crvec u, crvec p, rvec grad_fxu_p)> eval_grad_f_prod
Definition: ocproblem.hpp:57
util::BasicVTable::optional_function_t< F, ControlProblemVTable > optional_function_t
Definition: ocproblem.hpp:34
static void default_eval_constr_N(const void *self, crvec x, rvec c, const ControlProblemVTable &vtable)
Definition: ocproblem.hpp:180
static void default_get_D_N(const void *self, Box &D, const ControlProblemVTable &vtable)
Definition: ocproblem.hpp:156
optional_const_function_t< void(index_t timestep, crvec xu, crvec h, crindexvec mask_J, crindexvec mask_K, crvec v, rvec out, rvec work)> eval_add_R_prod_masked
Definition: ocproblem.hpp:79
required_const_function_t< void(Box &U)> get_U
Definition: ocproblem.hpp:45
required_const_function_t< void(index_t timestep, crvec xu, crvec h, rvec qr)> eval_qr
Definition: ocproblem.hpp:67
optional_const_function_t< void(index_t timestep, crvec xu, crvec h, crindexvec mask_K, crvec v, rvec out, rvec work)> eval_add_S_prod_masked
Definition: ocproblem.hpp:81
optional_const_function_t< void(index_t timestep, crvec x, crvec M, rmat out)> eval_add_gn_hess_constr
Definition: ocproblem.hpp:95
required_const_function_t< void(index_t timestep, crvec x, crvec u, rvec fxu)> eval_f
Definition: ocproblem.hpp:53
required_const_function_t< void(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat R, rvec work)> eval_add_R_masked
Definition: ocproblem.hpp:75
optional_const_function_t< length_t()> get_R_work_size
Definition: ocproblem.hpp:83
required_const_function_t< void(rvec y, real_t M)> eval_proj_multipliers
Definition: ocproblem.hpp:43
required_const_function_t< void(index_t timestep, crvec xu, crvec h, rmat Q)> eval_add_Q
Definition: ocproblem.hpp:71
optional_const_function_t< void(index_t timestep, crvec x, rvec c)> eval_constr
Definition: ocproblem.hpp:87
static void default_eval_add_Q_N(const void *self, crvec x, crvec h, rmat Q, const ControlProblemVTable &vtable)
Definition: ocproblem.hpp:159
void eval_jac_f(index_t timestep, crvec x, crvec u, rmat J_fxu) const
Definition: ocproblem.hpp:581
void eval_add_gn_hess_constr_N(crvec x, crvec M, rmat out) const
Definition: ocproblem.hpp:600
void eval_add_gn_hess_constr(index_t timestep, crvec x, crvec M, rmat out) const
Definition: ocproblem.hpp:599
void decouple_evaluations()
Give this instance its own evaluation counters and timers, decoupling it from any other instances the...
Definition: ocproblem.hpp:640
void eval_qr(index_t timestep, crvec xu, crvec h, rvec qr) const
Definition: ocproblem.hpp:587
void eval_add_R_masked(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat R, rvec work) const
Definition: ocproblem.hpp:591
void eval_grad_f_prod(index_t timestep, crvec x, crvec u, crvec p, rvec grad_fxu_p) const
Definition: ocproblem.hpp:582
bool provides_eval_add_R_prod_masked() const
Definition: ocproblem.hpp:606
void eval_constr(index_t timestep, crvec x, rvec c) const
Definition: ocproblem.hpp:595
real_t eval_l(index_t timestep, crvec h) const
Definition: ocproblem.hpp:585
void eval_grad_constr_prod_N(crvec x, crvec p, rvec grad_cx_p) const
Definition: ocproblem.hpp:598
void eval_h(index_t timestep, crvec x, crvec u, rvec h) const
Definition: ocproblem.hpp:583
void reset_evaluations()
Reset all evaluation counters and timers to zero.
Definition: ocproblem.hpp:636
void eval_add_S_prod_masked(index_t timestep, crvec xu, crvec h, crindexvec mask_K, crvec v, rvec out, rvec work) const
Definition: ocproblem.hpp:594
bool provides_eval_add_gn_hess_constr() const
Definition: ocproblem.hpp:614
void eval_q_N(crvec x, crvec h, rvec q) const
Definition: ocproblem.hpp:588
void eval_add_S_masked(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat S, rvec work) const
Definition: ocproblem.hpp:592
std::shared_ptr< OCPEvalCounter > evaluations
Definition: ocproblem.hpp:618
ControlProblemWithCounters(std::in_place_t, Args &&...args)
Definition: ocproblem.hpp:629
void get_x_init(rvec x_init) const
Definition: ocproblem.hpp:574
typename TypeErasedControlProblem< config_t >::Box Box
Definition: ocproblem.hpp:561
void eval_proj_multipliers(rvec y, real_t M) const
Definition: ocproblem.hpp:573
bool provides_eval_add_S_prod_masked() const
Definition: ocproblem.hpp:607
void eval_add_Q_N(crvec x, crvec h, rmat Q) const
Definition: ocproblem.hpp:590
real_t eval_l_N(crvec h) const
Definition: ocproblem.hpp:586
void eval_add_Q(index_t timestep, crvec xu, crvec h, rmat Q) const
Definition: ocproblem.hpp:589
void eval_constr_N(crvec x, rvec c) const
Definition: ocproblem.hpp:596
void eval_grad_constr_prod(index_t timestep, crvec x, crvec p, rvec grad_cx_p) const
Definition: ocproblem.hpp:597
bool provides_eval_grad_constr_prod_N() const
Definition: ocproblem.hpp:613
void eval_proj_diff_g(crvec z, rvec e) const
Definition: ocproblem.hpp:572
void eval_f(index_t timestep, crvec x, crvec u, rvec fxu) const
Definition: ocproblem.hpp:580
static decltype(auto) timed(TimeT &time, FunT &&f)
Definition: ocproblem.hpp:644
void eval_add_R_prod_masked(index_t timestep, crvec xu, crvec h, crindexvec mask_J, crindexvec mask_K, crvec v, rvec out, rvec work) const
Definition: ocproblem.hpp:593
bool provides_eval_add_gn_hess_constr_N() const
Definition: ocproblem.hpp:615
void eval_h_N(crvec x, rvec h) const
Definition: ocproblem.hpp:584
Struct that stores the size of a polymorphic object, as well as pointers to functions to copy,...
typename optional_function< F, VTable >::type optional_function_t
An optional function includes a void pointer to self, the arguments of F, and an additional reference...
typename required_const_function< F >::type required_const_function_t
A required function includes a void pointer to self, in addition to the arguments of F.
typename optional_const_function< F, VTable >::type optional_const_function_t
An optional function includes a void pointer to self, the arguments of F, and an additional reference...