alpaqa pantr
Nonconvex constrained optimization
Loading...
Searching...
No Matches
type-erased-problem.hpp
Go to the documentation of this file.
1#pragma once
2
4#include <alpaqa/export.hpp>
11#include <chrono>
12#include <stdexcept>
13#include <type_traits>
14#include <utility>
15
16namespace alpaqa {
17
18template <Config Conf>
22
23 template <class F>
25 template <class F>
28
29 // clang-format off
30
31 // Required
40 required_const_function_t<void(crvec x, rvec grad_fx)>
44 required_const_function_t<void(crvec x, crvec y, rvec grad_gxy)>
48
49 // Second order
50 optional_const_function_t<void(crvec x, rindexvec inner_idx, rindexvec outer_ptr, rvec J_values)>
54 optional_const_function_t<void(crvec x, index_t i, rvec grad_gi)>
56 optional_const_function_t<void(crvec x, crvec y, real_t scale, crvec v, rvec Hv)>
58 optional_const_function_t<void(crvec x, crvec y, real_t scale, rindexvec inner_idx, rindexvec outer_ptr, rvec H_values)>
62 optional_const_function_t<void(crvec x, crvec y, crvec Σ, real_t scale, crvec v, rvec Hv)>
64 optional_const_function_t<void(crvec x, crvec y, crvec Σ, real_t scale, rindexvec inner_idx, rindexvec outer_ptr, rvec H_values)>
68
69 // Combined evaluations
74 optional_const_function_t<void(crvec x, crvec y, rvec grad_f, rvec grad_gxy)>
76
77 // Lagrangian and augmented lagrangian evaluations
78 optional_const_function_t<void(crvec x, crvec y, rvec grad_L, rvec work_n)>
82 optional_const_function_t<void(crvec x, crvec y, crvec Σ, rvec grad_ψ, rvec work_n, rvec work_m)>
84 optional_const_function_t<real_t(crvec x, crvec y, crvec Σ, rvec grad_ψ, rvec work_n, rvec work_m)>
86
87 // Constraint sets
92
93 // Check
96
97 // clang-format on
98
99 ALPAQA_EXPORT static real_t calc_ŷ_dᵀŷ(const void *self, rvec g_ŷ, crvec y, crvec Σ,
100 const ProblemVTable &vtable);
101 ALPAQA_EXPORT static index_t default_eval_inactive_indices_res_lna(const void *, real_t, crvec,
103 const ProblemVTable &);
104 ALPAQA_EXPORT static void default_eval_jac_g(const void *, crvec, rindexvec, rindexvec, rvec,
105 const ProblemVTable &);
106 ALPAQA_EXPORT static length_t default_get_jac_g_num_nonzeros(const void *,
107 const ProblemVTable &);
108 ALPAQA_EXPORT static void default_eval_grad_gi(const void *, crvec, index_t, rvec,
109 const ProblemVTable &);
110 ALPAQA_EXPORT static void default_eval_hess_L_prod(const void *, crvec, crvec, real_t, crvec,
111 rvec, const ProblemVTable &);
112 ALPAQA_EXPORT static void default_eval_hess_L(const void *, crvec, crvec, real_t, rindexvec,
113 rindexvec, rvec, const ProblemVTable &);
114 ALPAQA_EXPORT static length_t default_get_hess_L_num_nonzeros(const void *,
115 const ProblemVTable &);
116 ALPAQA_EXPORT static void default_eval_hess_ψ_prod(const void *self, crvec x, crvec y, crvec,
117 real_t scale, crvec v, rvec Hv,
118 const ProblemVTable &vtable);
119 ALPAQA_EXPORT static void default_eval_hess_ψ(const void *self, crvec x, crvec y, crvec,
120 real_t scale, rindexvec inner_idx,
121 rindexvec outer_ptr, rvec H_values,
122 const ProblemVTable &vtable);
123 ALPAQA_EXPORT static length_t default_get_hess_ψ_num_nonzeros(const void *,
124 const ProblemVTable &);
125 ALPAQA_EXPORT static real_t default_eval_f_grad_f(const void *self, crvec x, rvec grad_fx,
126 const ProblemVTable &vtable);
127 ALPAQA_EXPORT static real_t default_eval_f_g(const void *self, crvec x, rvec g,
128 const ProblemVTable &vtable);
129 ALPAQA_EXPORT static void default_eval_grad_f_grad_g_prod(const void *self, crvec x, crvec y,
130 rvec grad_f, rvec grad_gxy,
131 const ProblemVTable &vtable);
132 ALPAQA_EXPORT static void default_eval_grad_L(const void *self, crvec x, crvec y, rvec grad_L,
133 rvec work_n, const ProblemVTable &vtable);
134 ALPAQA_EXPORT static real_t default_eval_ψ(const void *self, crvec x, crvec y, crvec Σ, rvec ŷ,
135 const ProblemVTable &vtable);
136 ALPAQA_EXPORT static void default_eval_grad_ψ(const void *self, crvec x, crvec y, crvec Σ,
137 rvec grad_ψ, rvec work_n, rvec work_m,
138 const ProblemVTable &vtable);
139 ALPAQA_EXPORT static real_t default_eval_ψ_grad_ψ(const void *self, crvec x, crvec y, crvec Σ,
140 rvec grad_ψ, rvec work_n, rvec work_m,
141 const ProblemVTable &vtable);
142 ALPAQA_EXPORT static const Box &default_get_box_C(const void *, const ProblemVTable &);
143 ALPAQA_EXPORT static const Box &default_get_box_D(const void *, const ProblemVTable &);
144 ALPAQA_EXPORT static void default_check(const void *, const ProblemVTable &);
145
147
148 template <class P>
150 auto &vtable = *this;
151 assert(t.t);
152
153 // Initialize all methods
154
155 // Required
164 // Second order
174 // Combined evaluations
176 ALPAQA_TE_OPTIONAL_METHOD(vtable, P, eval_f_g, t.t);
178 // Lagrangian and augmented lagrangian evaluations
180 ALPAQA_TE_OPTIONAL_METHOD(vtable, P, eval_ψ, t.t);
183 // Constraint set
186 // Check
187 ALPAQA_TE_OPTIONAL_METHOD(vtable, P, check, t.t);
188
189 // Dimensions
190 vtable.n = t.t->get_n();
191 vtable.m = t.t->get_m();
192 }
193 ProblemVTable() = default;
194};
195
200#ifdef ALPAQA_WITH_QUAD_PRECISION
201ALPAQA_EXPORT_EXTERN_TEMPLATE(struct, ProblemVTable, EigenConfigq);
202#endif
203
204/// @addtogroup grp_Problems
205/// @{
206
207template <Config Conf = DefaultConfig, class Allocator = std::allocator<std::byte>>
208class TypeErasedProblem : public util::TypeErased<ProblemVTable<Conf>, Allocator> {
209 public:
213 using allocator_type = Allocator;
216
217 protected:
218 using TypeErased::call;
219 using TypeErased::self;
220 using TypeErased::vtable;
221
222 public:
223 template <class T, class... Args>
224 static TypeErasedProblem make(Args &&...args) {
225 return TypeErased::template make<TypeErasedProblem, T>(std::forward<Args>(args)...);
226 }
227
228 /// @name Problem dimensions
229 /// @{
230
231 /// **[Required]**
232 /// Number of decision variables.
234 /// **[Required]**
235 /// Number of constraints.
237
238 /// @}
239
240 /// @name Required cost and constraint functions
241 /// @{
242
243 /// **[Required]**
244 /// Function that evaluates the cost, @f$ f(x) @f$
245 /// @param [in] x
246 /// Decision variable @f$ x \in \R^n @f$
248 /// **[Required]**
249 /// Function that evaluates the gradient of the cost, @f$ \nabla f(x) @f$
250 /// @param [in] x
251 /// Decision variable @f$ x \in \R^n @f$
252 /// @param [out] grad_fx
253 /// Gradient of cost function @f$ \nabla f(x) \in \R^n @f$
254 void eval_grad_f(crvec x, rvec grad_fx) const;
255 /// **[Required]**
256 /// Function that evaluates the constraints, @f$ g(x) @f$
257 /// @param [in] x
258 /// Decision variable @f$ x \in \R^n @f$
259 /// @param [out] gx
260 /// Value of the constraints @f$ g(x) \in \R^m @f$
261 void eval_g(crvec x, rvec gx) const;
262 /// **[Required]**
263 /// Function that evaluates the gradient of the constraints times a vector,
264 /// @f$ \nabla g(x)\,y = \tp{\jac_g(x)}y @f$
265 /// @param [in] x
266 /// Decision variable @f$ x \in \R^n @f$
267 /// @param [in] y
268 /// Vector @f$ y \in \R^m @f$ to multiply the gradient by
269 /// @param [out] grad_gxy
270 /// Gradient of the constraints
271 /// @f$ \nabla g(x)\,y \in \R^n @f$
272 void eval_grad_g_prod(crvec x, crvec y, rvec grad_gxy) const;
273
274 /// @}
275
276 /// @name Projections onto constraint sets and proximal mappings
277 /// @{
278
279 /// **[Required]**
280 /// Function that evaluates the difference between the given point @f$ z @f$
281 /// and its projection onto the constraint set @f$ D @f$.
282 /// @param [in] z
283 /// Slack variable, @f$ z \in \R^m @f$
284 /// @param [out] e
285 /// The difference relative to its projection,
286 /// @f$ e = z - \Pi_D(z) \in \R^m @f$
287 /// @note @p z and @p e can refer to the same vector.
288 void eval_proj_diff_g(crvec z, rvec e) const;
289 /// **[Required]**
290 /// Function that projects the Lagrange multipliers for ALM.
291 /// @param [inout] y
292 /// Multipliers, @f$ y \leftarrow \Pi_Y(y) \in \R^m @f$
293 /// @param [in] M
294 /// The radius/size of the set @f$ Y @f$.
295 /// See @ref ALMParams::max_multiplier.
297 /// **[Required]**
298 /// Function that computes a proximal gradient step.
299 /// @param [in] γ
300 /// Step size, @f$ \gamma \in \R_{>0} @f$
301 /// @param [in] x
302 /// Decision variable @f$ x \in \R^n @f$
303 /// @param [in] grad_ψ
304 /// Gradient of the subproblem cost, @f$ \nabla\psi(x) \in \R^n @f$
305 /// @param [out] x̂
306 /// Next proximal gradient iterate, @f$ \hat x = T_\gamma(x) =
307 /// \prox_{\gamma h}(x - \gamma\nabla\psi(x)) \in \R^n @f$
308 /// @param [out] p
309 /// The proximal gradient step,
310 /// @f$ p = \hat x - x \in \R^n @f$
311 /// @return The nonsmooth function evaluated at x̂,
312 /// @f$ h(\hat x) @f$.
313 /// @note The vector @f$ p @f$ is often used in stopping criteria, so its
314 /// numerical accuracy is more important than that of @f$ \hat x @f$.
315 real_t eval_prox_grad_step(real_t γ, crvec x, crvec grad_ψ, rvec x̂, rvec p) const;
316 /// **[Optional]**
317 /// Function that computes the inactive indices @f$ \mathcal J(x) @f$ for
318 /// the evaluation of the linear Newton approximation of the residual, as in
319 /// @cite pas2022alpaqa.
320 /// @param [in] γ
321 /// Step size, @f$ \gamma \in \R_{>0} @f$
322 /// @param [in] x
323 /// Decision variable @f$ x \in \R^n @f$
324 /// @param [in] grad_ψ
325 /// Gradient of the subproblem cost, @f$ \nabla\psi(x) \in \R^n @f$
326 /// @param [out] J
327 /// The indices of the components of @f$ x @f$ that are in the
328 /// index set @f$ \mathcal J(x) @f$. In ascending order, at most n.
329 /// @return The number of inactive constraints, @f$ \# \mathcal J(x) @f$.
330 ///
331 /// For example, in the case of box constraints, we have
332 /// @f[ \mathcal J(x) \defeq \defset{i \in \N_{[0, n-1]}}{\underline x_i
333 /// \lt x_i - \gamma\nabla_{\!x_i}\psi(x) \lt \overline x_i}. @f]
335
336 /// @}
337
338 /// @name Constraint sets
339 /// @{
340
341 /// **[Optional]**
342 /// Get the rectangular constraint set of the decision variables,
343 /// @f$ x \in C @f$.
344 const Box &get_box_C() const;
345 /// **[Optional]**
346 /// Get the rectangular constraint set of the general constraint function,
347 /// @f$ g(x) \in D @f$.
348 const Box &get_box_D() const;
349
350 /// @}
351
352 /// @name Functions for second-order solvers
353 /// @{
354
355 /// **[Optional]**
356 /// Function that evaluates the Jacobian of the constraints as a sparse
357 /// matrix, @f$ \jac_g(x) @f$
358 /// @param [in] x
359 /// Decision variable @f$ x \in \R^n @f$
360 /// @param [inout] inner_idx
361 /// Inner indices (row indices of nonzeros).
362 /// @param [inout] outer_ptr
363 /// Outer pointers (points to the first nonzero in each column).
364 /// @param [out] J_values
365 /// Nonzero values of the Jacobian
366 /// @f$ \jac_g(x) \in \R^{m\times n} @f$
367 /// If @p J_values has size zero, this function should initialize
368 /// @p inner_idx and @p outer_ptr. If @p J_values is nonempty, @p inner_idx
369 /// and @p outer_ptr can be assumed to be initialized, and this function
370 /// should evaluate @p J_values.
371 ///
372 /// Required for second-order solvers only.
373 void eval_jac_g(crvec x, rindexvec inner_idx, rindexvec outer_ptr, rvec J_values) const;
374 /// **[Optional]**
375 /// Function that gets the number of nonzeros of the Jacobian of the
376 /// constraints.
377 ///
378 /// Required for second-order solvers only.
380 /// **[Optional]**
381 /// Function that evaluates the gradient of one specific constraint,
382 /// @f$ \nabla g_i(x) @f$
383 /// @param [in] x
384 /// Decision variable @f$ x \in \R^n @f$
385 /// @param [in] i
386 /// Which constraint @f$ 0 \le i \lt m @f$
387 /// @param [out] grad_gi
388 /// Gradient of the constraint
389 /// @f$ \nabla g_i(x) \in \R^n @f$
390 ///
391 /// Required for second-order solvers only.
392 void eval_grad_gi(crvec x, index_t i, rvec grad_gi) const;
393 /// **[Optional]**
394 /// Function that evaluates the Hessian of the Lagrangian multiplied by a
395 /// vector,
396 /// @f$ \nabla_{xx}^2L(x, y)\,v @f$
397 /// @param [in] x
398 /// Decision variable @f$ x \in \R^n @f$
399 /// @param [in] y
400 /// Lagrange multipliers @f$ y \in \R^m @f$
401 /// @param [in] scale
402 /// Scale factor for the cost function.
403 /// @param [in] v
404 /// Vector to multiply by @f$ v \in \R^n @f$
405 /// @param [out] Hv
406 /// Hessian-vector product
407 /// @f$ \nabla_{xx}^2 L(x, y)\,v \in \R^{n} @f$
408 ///
409 /// Required for second-order solvers only.
410 void eval_hess_L_prod(crvec x, crvec y, real_t scale, crvec v, rvec Hv) const;
411 /// **[Optional]**
412 /// Function that evaluates the Hessian of the Lagrangian as a sparse matrix,
413 /// @f$ \nabla_{xx}^2L(x, y) @f$
414 /// @param [in] x
415 /// Decision variable @f$ x \in \R^n @f$
416 /// @param [in] y
417 /// Lagrange multipliers @f$ y \in \R^m @f$
418 /// @param [in] scale
419 /// Scale factor for the cost function.
420 /// @param [inout] inner_idx
421 /// Inner indices (row indices of nonzeros).
422 /// @param [inout] outer_ptr
423 /// Outer pointers (points to the first nonzero in each column).
424 /// @param [out] H_values
425 /// Nonzero values of the Hessian
426 /// @f$ \nabla_{xx}^2 L(x, y) \in \R^{n\times n} @f$.
427 /// If @p H_values has size zero, this function should initialize
428 /// @p inner_idx and @p outer_ptr. If @p H_values is nonempty, @p inner_idx
429 /// and @p outer_ptr can be assumed to be initialized, and this function
430 /// should evaluate @p H_values.
431 ///
432 /// Required for second-order solvers only.
433 void eval_hess_L(crvec x, crvec y, real_t scale, rindexvec inner_idx, rindexvec outer_ptr,
434 rvec H_values) const;
435 /// **[Optional]**
436 /// Function that gets the number of nonzeros of the Hessian of the
437 /// Lagrangian.
438 ///
439 /// Required for second-order solvers only.
441 /// **[Optional]**
442 /// Function that evaluates the Hessian of the augmented Lagrangian
443 /// multiplied by a vector,
444 /// @f$ \nabla_{xx}^2L_\Sigma(x, y)\,v @f$
445 /// @param [in] x
446 /// Decision variable @f$ x \in \R^n @f$
447 /// @param [in] y
448 /// Lagrange multipliers @f$ y \in \R^m @f$
449 /// @param [in] Σ
450 /// Penalty weights @f$ \Sigma @f$
451 /// @param [in] scale
452 /// Scale factor for the cost function.
453 /// @param [in] v
454 /// Vector to multiply by @f$ v \in \R^n @f$
455 /// @param [out] Hv
456 /// Hessian-vector product
457 /// @f$ \nabla_{xx}^2 L_\Sigma(x, y)\,v \in \R^{n} @f$
458 ///
459 /// Required for second-order solvers only.
460 void eval_hess_ψ_prod(crvec x, crvec y, crvec Σ, real_t scale, crvec v, rvec Hv) const;
461 /// **[Optional]**
462 /// Function that evaluates the Hessian of the augmented Lagrangian,
463 /// @f$ \nabla_{xx}^2L_\Sigma(x, y) @f$
464 /// @param [in] x
465 /// Decision variable @f$ x \in \R^n @f$
466 /// @param [in] y
467 /// Lagrange multipliers @f$ y \in \R^m @f$
468 /// @param [in] Σ
469 /// Penalty weights @f$ \Sigma @f$
470 /// @param [in] scale
471 /// Scale factor for the cost function.
472 /// @param [inout] inner_idx
473 /// Inner indices (row indices of nonzeros).
474 /// @param [inout] outer_ptr
475 /// Outer pointers (points to the first nonzero in each column).
476 /// @param [out] H_values
477 /// Nonzero values of the Hessian
478 /// @f$ \nabla_{xx}^2 L_\Sigma(x, y) \in \R^{n\times n} @f$
479 /// If @p H_values has size zero, this function should initialize
480 /// @p inner_idx and @p outer_ptr. If @p H_values is nonempty, @p inner_idx
481 /// and @p outer_ptr can be assumed to be initialized, and this function
482 /// should evaluate @p H_values.
483 ///
484 /// Required for second-order solvers only.
485 void eval_hess_ψ(crvec x, crvec y, crvec Σ, real_t scale, rindexvec inner_idx,
486 rindexvec outer_ptr, rvec H_values) const;
487 /// **[Optional]**
488 /// Function that gets the number of nonzeros of the Hessian of the
489 /// augmented Lagrangian.
490 ///
491 /// Required for second-order solvers only.
493
494 /// @}
495
496 /// @name Combined evaluations
497 /// @{
498
499 /// **[Optional]**
500 /// Evaluate both @f$ f(x) @f$ and its gradient, @f$ \nabla f(x) @f$.
501 /// @default_impl ProblemVTable::default_eval_f_grad_f
502 real_t eval_f_grad_f(crvec x, rvec grad_fx) const;
503 /// **[Optional]**
504 /// Evaluate both @f$ f(x) @f$ and @f$ g(x) @f$.
505 /// @default_impl ProblemVTable::default_eval_f_g
507 /// **[Optional]**
508 /// Evaluate both @f$ \nabla f(x) @f$ and @f$ \nabla g(x)\,y @f$.
509 /// @default_impl ProblemVTable::default_eval_grad_f_grad_g_prod
510 void eval_grad_f_grad_g_prod(crvec x, crvec y, rvec grad_f, rvec grad_gxy) const;
511 /// **[Optional]**
512 /// Evaluate the gradient of the Lagrangian
513 /// @f$ \nabla_x L(x, y) = \nabla f(x) + \nabla g(x)\,y @f$
514 /// @default_impl ProblemVTable::default_eval_grad_L
515 void eval_grad_L(crvec x, crvec y, rvec grad_L, rvec work_n) const;
516
517 /// @}
518
519 /// @name Augmented Lagrangian
520 /// @{
521
522 /// **[Optional]**
523 /// Calculate both ψ(x) and the vector ŷ that can later be used to compute
524 /// ∇ψ.
525 /// @f[ \psi(x) = f(x) + \tfrac{1}{2}
526 /// \text{dist}_\Sigma^2\left(g(x) + \Sigma^{-1}y,\;D\right) @f]
527 /// @f[ \hat y = \Sigma\, \left(g(x) + \Sigma^{-1}y - \Pi_D\left(g(x)
528 /// + \Sigma^{-1}y\right)\right) @f]
529 /// @default_impl ProblemVTable::default_eval_ψ
530 real_t eval_ψ(crvec x, ///< [in] Decision variable @f$ x @f$
531 crvec y, ///< [in] Lagrange multipliers @f$ y @f$
532 crvec Σ, ///< [in] Penalty weights @f$ \Sigma @f$
533 rvec ŷ ///< [out] @f$ \hat y @f$
534 ) const;
535 /// **[Optional]**
536 /// Calculate the gradient ∇ψ(x).
537 /// @f[ \nabla \psi(x) = \nabla f(x) + \nabla g(x)\,\hat y(x) @f]
538 /// @default_impl ProblemVTable::default_eval_grad_ψ
539 void eval_grad_ψ(crvec x, ///< [in] Decision variable @f$ x @f$
540 crvec y, ///< [in] Lagrange multipliers @f$ y @f$
541 crvec Σ, ///< [in] Penalty weights @f$ \Sigma @f$
542 rvec grad_ψ, ///< [out] @f$ \nabla \psi(x) @f$
543 rvec work_n, ///< Dimension @f$ n @f$
544 rvec work_m ///< Dimension @f$ m @f$
545 ) const;
546 /// **[Optional]**
547 /// Calculate both ψ(x) and its gradient ∇ψ(x).
548 /// @f[ \psi(x) = f(x) + \tfrac{1}{2}
549 /// \text{dist}_\Sigma^2\left(g(x) + \Sigma^{-1}y,\;D\right) @f]
550 /// @f[ \nabla \psi(x) = \nabla f(x) + \nabla g(x)\,\hat y(x) @f]
551 /// @default_impl ProblemVTable::default_eval_ψ_grad_ψ
552 real_t eval_ψ_grad_ψ(crvec x, ///< [in] Decision variable @f$ x @f$
553 crvec y, ///< [in] Lagrange multipliers @f$ y @f$
554 crvec Σ, ///< [in] Penalty weights @f$ \Sigma @f$
555 rvec grad_ψ, ///< [out] @f$ \nabla \psi(x) @f$
556 rvec work_n, ///< Dimension @f$ n @f$
557 rvec work_m ///< Dimension @f$ m @f$
558 ) const;
559
560 /// @}
561
562 /// @name Checks
563 /// @{
564
565 /// **[Optional]**
566 /// Check that the problem formulation is well-defined, the dimensions match,
567 /// etc. Throws an exception if this is not the case.
568 void check() const;
569
570 /// @}
571
572 /// @name Querying specialized implementations
573 /// @{
574
575 /// Returns true if the problem provides an implementation of
576 /// @ref eval_inactive_indices_res_lna.
579 }
580 /// Returns true if the problem provides an implementation of
581 /// @ref eval_jac_g.
583 /// Returns true if the problem provides an implementation of
584 /// @ref get_jac_g_num_nonzeros.
587 }
588 /// Returns true if the problem provides an implementation of
589 /// @ref eval_grad_gi.
592 }
593 /// Returns true if the problem provides an implementation of
594 /// @ref eval_hess_L_prod.
597 }
598 /// Returns true if the problem provides an implementation of
599 /// @ref eval_hess_L.
601 /// Returns true if the problem provides an implementation of
602 /// @ref get_hess_L_num_nonzeros.
605 }
606 /// Returns true if the problem provides an implementation of
607 /// @ref eval_hess_ψ_prod.
610 }
611 /// Returns true if the problem provides an implementation of
612 /// @ref eval_hess_ψ.
614 /// Returns true if the problem provides an implementation of
615 /// @ref get_hess_ψ_num_nonzeros.
618 }
619 /// Returns true if the problem provides a specialized implementation of
620 /// @ref eval_f_grad_f, false if it uses the default implementation.
623 }
624 /// Returns true if the problem provides a specialized implementation of
625 /// @ref eval_f_g, false if it uses the default implementation.
627 /// Returns true if the problem provides a specialized implementation of
628 /// @ref eval_grad_f_grad_g_prod, false if it uses the default implementation.
631 }
632 /// Returns true if the problem provides a specialized implementation of
633 /// @ref eval_grad_L, false if it uses the default implementation.
635 /// Returns true if the problem provides a specialized implementation of
636 /// @ref eval_ψ, false if it uses the default implementation.
638 /// Returns true if the problem provides a specialized implementation of
639 /// @ref eval_grad_ψ, false if it uses the default implementation.
641 /// Returns true if the problem provides a specialized implementation of
642 /// @ref eval_ψ_grad_ψ, false if it uses the default implementation.
645 }
646 /// Returns true if the problem provides an implementation of
647 /// @ref get_box_C.
649 /// Returns true if the problem provides an implementation of
650 /// @ref get_box_D.
652 /// Returns true if the problem provides an implementation of @ref check.
653 bool provides_check() const { return vtable.check != vtable.default_check; }
654
655 /// @}
656
657 /// @name Helpers
658 /// @{
659
660 /// Given g(x), compute the intermediate results ŷ and dᵀŷ that can later be
661 /// used to compute ψ(x) and ∇ψ(x).
662 ///
663 /// Computes the result using the following algorithm:
664 /// @f[ \begin{aligned}
665 /// \zeta &= g(x) + \Sigma^{-1} y \\[]
666 /// d &= \zeta - \Pi_D(\zeta)
667 /// = \operatorname{eval\_proj\_diff\_g}(\zeta, \zeta) \\[]
668 /// \hat y &= \Sigma d \\[]
669 /// \end{aligned} @f]
670 /// @see @ref page_math
671 ///
672 /// @param[inout] g_ŷ
673 /// Input @f$ g(x) @f$, outputs @f$ \hat y @f$
674 /// @param[in] y
675 /// Lagrange multipliers @f$ y @f$
676 /// @param[in] Σ
677 /// Penalty weights @f$ \Sigma @f$
678 /// @return The inner product @f$ d^\top \hat y @f$
680
681 /// @}
682};
683
684/// @}
685
686#ifndef DOXYGEN
687template <class Tref>
688explicit TypeErasedProblem(Tref &&d)
690
691template <class Tref, class Allocator>
692explicit TypeErasedProblem(Tref &&d, Allocator alloc)
694#endif
695
696template <Config Conf, class Allocator>
698 return vtable.n;
699}
700template <Config Conf, class Allocator>
702 return vtable.m;
703}
704
705template <Config Conf, class Allocator>
707 return call(vtable.eval_proj_diff_g, z, e);
708}
709template <Config Conf, class Allocator>
711 return call(vtable.eval_proj_multipliers, y, M);
712}
713template <Config Conf, class Allocator>
715 rvec x̂, rvec p) const -> real_t {
716 return call(vtable.eval_prox_grad_step, γ, x, grad_ψ, x̂, p);
717}
718template <Config Conf, class Allocator>
720 crvec grad_ψ,
721 rindexvec J) const
722 -> index_t {
723 return call(vtable.eval_inactive_indices_res_lna, γ, x, grad_ψ, J);
724}
725template <Config Conf, class Allocator>
727 return call(vtable.eval_f, x);
728}
729template <Config Conf, class Allocator>
731 return call(vtable.eval_grad_f, x, grad_fx);
732}
733template <Config Conf, class Allocator>
735 return call(vtable.eval_g, x, gx);
736}
737template <Config Conf, class Allocator>
739 return call(vtable.eval_grad_g_prod, x, y, grad_gxy);
740}
741template <Config Conf, class Allocator>
743 return call(vtable.eval_grad_gi, x, i, grad_gi);
744}
745template <Config Conf, class Allocator>
747 rindexvec outer_ptr, rvec J_values) const {
748 return call(vtable.eval_jac_g, x, inner_idx, outer_ptr, J_values);
749}
750template <Config Conf, class Allocator>
752 return call(vtable.get_jac_g_num_nonzeros);
753}
754template <Config Conf, class Allocator>
756 rvec Hv) const {
757 return call(vtable.eval_hess_L_prod, x, y, scale, v, Hv);
758}
759template <Config Conf, class Allocator>
761 rindexvec inner_idx, rindexvec outer_ptr,
762 rvec H_values) const {
763 return call(vtable.eval_hess_L, x, y, scale, inner_idx, outer_ptr, H_values);
764}
765template <Config Conf, class Allocator>
767 return call(vtable.get_hess_L_num_nonzeros);
768}
769template <Config Conf, class Allocator>
771 crvec v, rvec Hv) const {
772 return call(vtable.eval_hess_ψ_prod, x, y, Σ, scale, v, Hv);
773}
774template <Config Conf, class Allocator>
776 rindexvec inner_idx, rindexvec outer_ptr,
777 rvec H_values) const {
778 return call(vtable.eval_hess_ψ, x, y, Σ, scale, inner_idx, outer_ptr, H_values);
779}
780template <Config Conf, class Allocator>
782 return call(vtable.get_hess_ψ_num_nonzeros);
783}
784template <Config Conf, class Allocator>
786 return call(vtable.eval_f_grad_f, x, grad_fx);
787}
788template <Config Conf, class Allocator>
790 return call(vtable.eval_f_g, x, g);
791}
792template <Config Conf, class Allocator>
794 rvec grad_gxy) const {
795 return call(vtable.eval_grad_f_grad_g_prod, x, y, grad_f, grad_gxy);
796}
797template <Config Conf, class Allocator>
799 rvec work_n) const {
800 return call(vtable.eval_grad_L, x, y, grad_L, work_n);
801}
802template <Config Conf, class Allocator>
804 return call(vtable.eval_ψ, x, y, Σ, ŷ);
805}
806template <Config Conf, class Allocator>
808 rvec work_n, rvec work_m) const {
809 return call(vtable.eval_grad_ψ, x, y, Σ, grad_ψ, work_n, work_m);
810}
811template <Config Conf, class Allocator>
813 rvec work_n, rvec work_m) const -> real_t {
814 return call(vtable.eval_ψ_grad_ψ, x, y, Σ, grad_ψ, work_n, work_m);
815}
816template <Config Conf, class Allocator>
818 return call(vtable.calc_ŷ_dᵀŷ, g_ŷ, y, Σ);
819}
820template <Config Conf, class Allocator>
822 return call(vtable.get_box_C);
823}
824template <Config Conf, class Allocator>
826 return call(vtable.get_box_D);
827}
828template <Config Conf, class Allocator>
830 return call(vtable.check);
831}
832
833/// @addtogroup grp_Problems
834/// @{
835
836template <Config Conf>
837void print_provided_functions(std::ostream &os, const TypeErasedProblem<Conf> &problem) {
838 os << "inactive_indices_res_lna: " << problem.provides_eval_inactive_indices_res_lna() << '\n'
839 << " grad_gi: " << problem.provides_eval_grad_gi() << '\n'
840 << " jac_g: " << problem.provides_eval_jac_g() << '\n'
841 << " hess_L_prod: " << problem.provides_eval_hess_L_prod() << '\n'
842 << " hess_L: " << problem.provides_eval_hess_L() << '\n'
843 << " hess_ψ_prod: " << problem.provides_eval_hess_ψ_prod() << '\n'
844 << " hess_ψ: " << problem.provides_eval_hess_ψ() << '\n'
845 << " f_grad_f: " << problem.provides_eval_f_grad_f() << '\n'
846 << " f_g: " << problem.provides_eval_f_g() << '\n'
847 << " grad_f_grad_g_prod: " << problem.provides_eval_grad_f_grad_g_prod() << '\n'
848 << " grad_L: " << problem.provides_eval_grad_L() << '\n'
849 << " ψ: " << problem.provides_eval_ψ() << '\n'
850 << " grad_ψ: " << problem.provides_eval_grad_ψ() << '\n'
851 << " ψ_grad_ψ: " << problem.provides_eval_ψ_grad_ψ() << '\n'
852 << " get_box_C: " << problem.provides_get_box_C() << '\n'
853 << " get_box_D: " << problem.provides_get_box_D() << '\n'
854 << " check: " << problem.provides_check() << '\n';
855}
856
857/// @}
858
859} // namespace alpaqa
bool provides_eval_hess_L() const
Returns true if the problem provides an implementation of eval_hess_L.
real_t eval_prox_grad_step(real_t γ, crvec x, crvec grad_ψ, rvec x̂, rvec p) const
[Required] Function that computes a proximal gradient step.
real_t eval_ψ_grad_ψ(crvec x, crvec y, crvec Σ, rvec grad_ψ, rvec work_n, rvec work_m) const
[Optional] Calculate both ψ(x) and its gradient ∇ψ(x).
const Box & get_box_D() const
[Optional] Get the rectangular constraint set of the general constraint function, .
void eval_grad_gi(crvec x, index_t i, rvec grad_gi) const
[Optional] Function that evaluates the gradient of one specific constraint,
void eval_hess_ψ(crvec x, crvec y, crvec Σ, real_t scale, rindexvec inner_idx, rindexvec outer_ptr, rvec H_values) const
[Optional] Function that evaluates the Hessian of the augmented Lagrangian,
bool provides_eval_hess_ψ_prod() const
Returns true if the problem provides an implementation of eval_hess_ψ_prod.
bool provides_eval_ψ_grad_ψ() const
Returns true if the problem provides a specialized implementation of eval_ψ_grad_ψ,...
bool provides_get_box_C() const
Returns true if the problem provides an implementation of get_box_C.
real_t eval_f_g(crvec x, rvec g) const
[Optional] Evaluate both and .
bool provides_get_hess_L_num_nonzeros() const
Returns true if the problem provides an implementation of get_hess_L_num_nonzeros.
bool provides_get_jac_g_num_nonzeros() const
Returns true if the problem provides an implementation of get_jac_g_num_nonzeros.
bool provides_eval_jac_g() const
Returns true if the problem provides an implementation of eval_jac_g.
bool provides_check() const
Returns true if the problem provides an implementation of check.
length_t get_n() const
[Required] Number of decision variables.
void check() const
[Optional] Check that the problem formulation is well-defined, the dimensions match,...
length_t get_m() const
[Required] Number of constraints.
real_t eval_ψ(crvec x, crvec y, crvec Σ, rvec ŷ) const
[Optional] Calculate both ψ(x) and the vector ŷ that can later be used to compute ∇ψ.
bool provides_eval_inactive_indices_res_lna() const
Returns true if the problem provides an implementation of eval_inactive_indices_res_lna.
void eval_grad_L(crvec x, crvec y, rvec grad_L, rvec work_n) const
[Optional] Evaluate the gradient of the Lagrangian
void eval_grad_f_grad_g_prod(crvec x, crvec y, rvec grad_f, rvec grad_gxy) const
[Optional] Evaluate both and .
bool provides_eval_grad_f_grad_g_prod() const
Returns true if the problem provides a specialized implementation of eval_grad_f_grad_g_prod,...
void eval_hess_L(crvec x, crvec y, real_t scale, rindexvec inner_idx, rindexvec outer_ptr, rvec H_values) const
[Optional] Function that evaluates the Hessian of the Lagrangian as a sparse matrix,
static TypeErasedProblem make(Args &&...args)
index_t eval_inactive_indices_res_lna(real_t γ, crvec x, crvec grad_ψ, rindexvec J) const
[Optional] Function that computes the inactive indices for the evaluation of the linear Newton appro...
bool provides_eval_hess_L_prod() const
Returns true if the problem provides an implementation of eval_hess_L_prod.
bool provides_get_hess_ψ_num_nonzeros() const
Returns true if the problem provides an implementation of get_hess_ψ_num_nonzeros.
real_t eval_f_grad_f(crvec x, rvec grad_fx) const
[Optional] Evaluate both and its gradient, .
bool provides_eval_f_grad_f() const
Returns true if the problem provides a specialized implementation of eval_f_grad_f,...
void eval_grad_g_prod(crvec x, crvec y, rvec grad_gxy) const
[Required] Function that evaluates the gradient of the constraints times a vector,
void eval_hess_L_prod(crvec x, crvec y, real_t scale, crvec v, rvec Hv) const
[Optional] Function that evaluates the Hessian of the Lagrangian multiplied by a vector,
bool provides_eval_grad_gi() const
Returns true if the problem provides an implementation of eval_grad_gi.
void eval_proj_multipliers(rvec y, real_t M) const
[Required] Function that projects the Lagrange multipliers for ALM.
bool provides_eval_f_g() const
Returns true if the problem provides a specialized implementation of eval_f_g, false if it uses the d...
void eval_grad_f(crvec x, rvec grad_fx) const
[Required] Function that evaluates the gradient of the cost,
real_t eval_f(crvec x) const
[Required] Function that evaluates the cost,
bool provides_eval_grad_L() const
Returns true if the problem provides a specialized implementation of eval_grad_L, false if it uses th...
bool provides_eval_grad_ψ() const
Returns true if the problem provides a specialized implementation of eval_grad_ψ, false if it uses th...
void eval_g(crvec x, rvec gx) const
[Required] Function that evaluates the constraints,
length_t get_jac_g_num_nonzeros() const
[Optional] Function that gets the number of nonzeros of the Jacobian of the constraints.
bool provides_eval_hess_ψ() const
Returns true if the problem provides an implementation of eval_hess_ψ.
real_t calc_ŷ_dᵀŷ(rvec g_ŷ, crvec y, crvec Σ) const
Given g(x), compute the intermediate results ŷ and dᵀŷ that can later be used to compute ψ(x) and ∇ψ(...
bool provides_get_box_D() const
Returns true if the problem provides an implementation of get_box_D.
const Box & get_box_C() const
[Optional] Get the rectangular constraint set of the decision variables, .
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...
void eval_jac_g(crvec x, rindexvec inner_idx, rindexvec outer_ptr, rvec J_values) const
[Optional] Function that evaluates the Jacobian of the constraints as a sparse matrix,
void eval_grad_ψ(crvec x, crvec y, crvec Σ, rvec grad_ψ, rvec work_n, rvec work_m) const
[Optional] Calculate the gradient ∇ψ(x).
bool provides_eval_ψ() const
Returns true if the problem provides a specialized implementation of eval_ψ, false if it uses the def...
void eval_hess_ψ_prod(crvec x, crvec y, crvec Σ, real_t scale, crvec v, rvec Hv) const
[Optional] Function that evaluates the Hessian of the augmented Lagrangian multiplied by a vector,
length_t get_hess_ψ_num_nonzeros() const
[Optional] Function that gets the number of nonzeros of the Hessian of the augmented Lagrangian.
length_t get_hess_L_num_nonzeros() const
[Optional] Function that gets the number of nonzeros of the Hessian of the Lagrangian.
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 ALPAQA_EXPORT_EXTERN_TEMPLATE(...)
Definition: export.hpp:21
void print_provided_functions(std::ostream &os, const TypeErasedProblem< Conf > &problem)
typename Conf::real_t real_t
Definition: config.hpp:51
typename Conf::rindexvec rindexvec
Definition: config.hpp:65
typename Conf::index_t index_t
Definition: config.hpp:63
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
#define ALPAQA_TE_REQUIRED_METHOD(vtable, type, member)
#define ALPAQA_TE_OPTIONAL_METHOD(vtable, type, member, instance_p)
Double-precision double configuration.
Definition: config.hpp:115
Single-precision float configuration.
Definition: config.hpp:111
long double configuration.
Definition: config.hpp:120
required_const_function_t< real_t(crvec x)> eval_f
util::BasicVTable::optional_const_function_t< F, ProblemVTable > optional_const_function_t
optional_const_function_t< void(crvec x, crvec y, real_t scale, crvec v, rvec Hv)> eval_hess_L_prod
required_const_function_t< real_t(real_t γ, crvec x, crvec grad_ψ, rvec x̂, rvec p)> eval_prox_grad_step
static real_t default_eval_ψ(const void *self, crvec x, crvec y, crvec Σ, rvec ŷ, const ProblemVTable &vtable)
optional_const_function_t< real_t(crvec x, rvec grad_fx)> eval_f_grad_f
ProblemVTable(util::VTableTypeTag< P > t)
static length_t default_get_hess_L_num_nonzeros(const void *, const ProblemVTable &)
optional_const_function_t< void(crvec x, crvec y, crvec Σ, rvec grad_ψ, rvec work_n, rvec work_m)> eval_grad_ψ
static void default_eval_hess_L(const void *, crvec, crvec, real_t, rindexvec, rindexvec, rvec, const ProblemVTable &)
static void default_eval_hess_L_prod(const void *, crvec, crvec, real_t, crvec, rvec, const ProblemVTable &)
optional_const_function_t< void(crvec x, crvec y, rvec grad_L, rvec work_n)> eval_grad_L
static void default_eval_hess_ψ_prod(const void *self, crvec x, crvec y, crvec, real_t scale, crvec v, rvec Hv, const ProblemVTable &vtable)
optional_const_function_t< real_t(crvec x, crvec y, crvec Σ, rvec ŷ)> eval_ψ
optional_const_function_t< index_t(real_t γ, crvec x, crvec grad_ψ, rindexvec J)> eval_inactive_indices_res_lna
optional_const_function_t< void(crvec x, crvec y, crvec Σ, real_t scale, crvec v, rvec Hv)> eval_hess_ψ_prod
static void default_eval_jac_g(const void *, crvec, rindexvec, rindexvec, rvec, const ProblemVTable &)
optional_const_function_t< length_t()> get_hess_ψ_num_nonzeros
optional_const_function_t< void()> check
optional_const_function_t< real_t(crvec x, rvec g)> eval_f_g
static void default_eval_grad_gi(const void *, crvec, index_t, rvec, const ProblemVTable &)
optional_const_function_t< real_t(crvec x, crvec y, crvec Σ, rvec grad_ψ, rvec work_n, rvec work_m)> eval_ψ_grad_ψ
util::BasicVTable::optional_function_t< F, ProblemVTable > optional_function_t
static length_t default_get_jac_g_num_nonzeros(const void *, const ProblemVTable &)
static void default_eval_grad_ψ(const void *self, crvec x, crvec y, crvec Σ, rvec grad_ψ, rvec work_n, rvec work_m, const ProblemVTable &vtable)
required_const_function_t< void(crvec x, rvec gx)> eval_g
optional_const_function_t< length_t()> get_jac_g_num_nonzeros
optional_const_function_t< void(crvec x, crvec y, crvec Σ, real_t scale, rindexvec inner_idx, rindexvec outer_ptr, rvec H_values)> eval_hess_ψ
optional_const_function_t< const Box &()> get_box_D
optional_const_function_t< void(crvec x, crvec y, real_t scale, rindexvec inner_idx, rindexvec outer_ptr, rvec H_values)> eval_hess_L
static const Box & default_get_box_C(const void *, const ProblemVTable &)
static void default_eval_grad_L(const void *self, crvec x, crvec y, rvec grad_L, rvec work_n, const ProblemVTable &vtable)
static const Box & default_get_box_D(const void *, const ProblemVTable &)
optional_const_function_t< void(crvec x, crvec y, rvec grad_f, rvec grad_gxy)> eval_grad_f_grad_g_prod
required_const_function_t< void(crvec z, rvec e)> eval_proj_diff_g
static real_t default_eval_f_g(const void *self, crvec x, rvec g, const ProblemVTable &vtable)
optional_const_function_t< void(crvec x, index_t i, rvec grad_gi)> eval_grad_gi
optional_const_function_t< length_t()> get_hess_L_num_nonzeros
static void default_eval_hess_ψ(const void *self, crvec x, crvec y, crvec, real_t scale, rindexvec inner_idx, rindexvec outer_ptr, rvec H_values, const ProblemVTable &vtable)
static index_t default_eval_inactive_indices_res_lna(const void *, real_t, crvec, crvec, rindexvec, const ProblemVTable &)
static void default_check(const void *, const ProblemVTable &)
static real_t calc_ŷ_dᵀŷ(const void *self, rvec g_ŷ, crvec y, crvec Σ, const ProblemVTable &vtable)
static void default_eval_grad_f_grad_g_prod(const void *self, crvec x, crvec y, rvec grad_f, rvec grad_gxy, const ProblemVTable &vtable)
required_const_function_t< void(crvec x, crvec y, rvec grad_gxy)> eval_grad_g_prod
static real_t default_eval_f_grad_f(const void *self, crvec x, rvec grad_fx, const ProblemVTable &vtable)
required_const_function_t< void(rvec y, real_t M)> eval_proj_multipliers
required_const_function_t< void(crvec x, rvec grad_fx)> eval_grad_f
optional_const_function_t< void(crvec x, rindexvec inner_idx, rindexvec outer_ptr, rvec J_values)> eval_jac_g
static length_t default_get_hess_ψ_num_nonzeros(const void *, const ProblemVTable &)
static real_t default_eval_ψ_grad_ψ(const void *self, crvec x, crvec y, crvec Σ, rvec grad_ψ, rvec work_n, rvec work_m, const ProblemVTable &vtable)
optional_const_function_t< const Box &()> get_box_C
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...