alpaqa 1.0.0a16
Nonconvex constrained optimization
Loading...
Searching...
No Matches
dl-problem.h
Go to the documentation of this file.
1// NOLINTBEGIN(modernize-use-using,modernize-deprecated-headers)
2
3#pragma once
4
5#include <stddef.h>
6#include <stdint.h>
7#include <string.h>
8
9#define ALPAQA_DL_ABI_VERSION 0xA1A000000002
10
11#ifdef __cplusplus
12extern "C" {
13#define ALPAQA_BEGIN_STRUCT(name) struct name
14#define ALPAQA_END_STRUCT(name)
15#define ALPAQA_DEFAULT(...) \
16 { __VA_ARGS__ }
17#else
18#define ALPAQA_BEGIN_STRUCT(name) typedef struct
19#define ALPAQA_END_STRUCT(name) name
20#define ALPAQA_DEFAULT(...)
21#endif
22
23typedef double alpaqa_real_t;
24typedef ptrdiff_t alpaqa_length_t;
26
27/// @see @ref alpaqa::sparsity::Symmetry
33
34/// @see @ref alpaqa::sparsity::Dense
40
41/// @see @ref alpaqa::sparsity::SparseCSC
42typedef struct {
46 const int *inner_idx;
47 const int *outer_ptr;
48 /// @see @ref alpaqa::sparsity::SparseCSC::Order
49 enum {
50 alpaqa_sparse_csc_unsorted = 0,
51 alpaqa_sparse_csc_sorted_rows = 1,
52 } order;
54
55/// @see @ref alpaqa::sparsity::SparseCSC
56typedef struct {
60 const long *inner_idx;
61 const long *outer_ptr;
62 /// @see @ref alpaqa::sparsity::SparseCSC::Order
63 enum {
64 alpaqa_sparse_csc_l_unsorted = 0,
65 alpaqa_sparse_csc_l_sorted_rows = 1,
66 } order;
68
69/// @see @ref alpaqa::sparsity::SparseCSC
70typedef struct {
74 const long long *inner_idx;
75 const long long *outer_ptr;
76 /// @see @ref alpaqa::sparsity::SparseCSC::Order
77 enum {
78 alpaqa_sparse_csc_ll_unsorted = 0,
79 alpaqa_sparse_csc_ll_sorted_rows = 1,
80 } order;
82
83/// @see @ref alpaqa::sparsity::SparseCOO
84typedef struct {
88 const int *row_indices;
89 const int *col_indices;
90 /// @see @ref alpaqa::sparsity::SparseCOO::Order
91 enum {
92 alpaqa_sparse_coo_unsorted = 0,
93 alpaqa_sparse_coo_sorted_by_cols_and_rows = 1,
94 alpaqa_sparse_coo_sorted_by_cols_only = 2,
95 alpaqa_sparse_coo_sorted_by_rows_and_cols = 3,
96 alpaqa_sparse_coo_sorted_by_rows_only = 4,
97 } order;
100
101/// @see @ref alpaqa::sparsity::SparseCOO
102typedef struct {
106 const long *row_indices;
107 const long *col_indices;
108 /// @see @ref alpaqa::sparsity::SparseCOO::Order
109 enum {
110 alpaqa_sparse_coo_l_unsorted = 0,
111 alpaqa_sparse_coo_l_sorted_by_cols_and_rows = 1,
112 alpaqa_sparse_coo_l_sorted_by_cols_only = 2,
113 alpaqa_sparse_coo_l_sorted_by_rows_and_cols = 3,
114 alpaqa_sparse_coo_l_sorted_by_rows_only = 4,
115 } order;
118
119/// @see @ref alpaqa::sparsity::SparseCOO
120typedef struct {
124 const long long *row_indices;
125 const long long *col_indices;
126 /// @see @ref alpaqa::sparsity::SparseCOO::Order
127 enum {
128 alpaqa_sparse_coo_ll_unsorted = 0,
129 alpaqa_sparse_coo_ll_sorted_by_cols_and_rows = 1,
130 alpaqa_sparse_coo_ll_sorted_by_cols_only = 2,
131 alpaqa_sparse_coo_ll_sorted_by_rows_and_cols = 3,
132 alpaqa_sparse_coo_ll_sorted_by_rows_only = 4,
133 } order;
134 long long first_index;
136
137/// Sparsity of matrices.
138/// @see @ref alpaqa::sparsity::Sparsity
159
160/// C API providing function pointers to problem functions.
161/// Used by @ref alpaqa::dl::DLProblem.
163 /// Number of decision variables.
164 /// @see @ref alpaqa::TypeErasedProblem::get_n()
166 /// Number of constraints.
167 /// @see @ref alpaqa::TypeErasedProblem::get_m()
169
170 // clang-format off
171 /// Cost function.
172 /// @see @ref alpaqa::TypeErasedProblem::eval_f()
173 alpaqa_real_t (*eval_f)(
174 void *instance,
175 const alpaqa_real_t *x) ALPAQA_DEFAULT(nullptr);
176 /// Gradient of the cost function.
177 /// @see @ref alpaqa::TypeErasedProblem::eval_grad_f()
178 void (*eval_grad_f)(
179 void *instance,
180 const alpaqa_real_t *x,
181 alpaqa_real_t *grad_fx) ALPAQA_DEFAULT(nullptr);
182 /// Constraints function.
183 /// @see @ref alpaqa::TypeErasedProblem::eval_g()
184 void (*eval_g)(
185 void *instance,
186 const alpaqa_real_t *x,
187 alpaqa_real_t *gx) ALPAQA_DEFAULT(nullptr);
188 /// Gradient-vector product of the constraints function.
189 /// @see @ref alpaqa::TypeErasedProblem::eval_grad_g_prod()
190 void (*eval_grad_g_prod)(
191 void *instance,
192 const alpaqa_real_t *x,
193 const alpaqa_real_t *y,
194 alpaqa_real_t *grad_gxy) ALPAQA_DEFAULT(nullptr);
195 /// Jacobian of the constraints function.
196 /// @see @ref alpaqa::TypeErasedProblem::eval_jac_g()
197 void (*eval_jac_g)(
198 void *instance,
199 const alpaqa_real_t *x,
200 alpaqa_real_t *J_values) ALPAQA_DEFAULT(nullptr);
201 /// Get the sparsity pattern of the Jacobian of the constraints function.
202 /// @see @ref alpaqa::TypeErasedProblem::get_jac_g_sparsity()
203 alpaqa_sparsity_t (*get_jac_g_sparsity)(
204 void *instance) ALPAQA_DEFAULT(nullptr);
205 /// Gradient of specific constraint function.
206 /// @see @ref alpaqa::TypeErasedProblem::eval_grad_gi()
207 void (*eval_grad_gi)(
208 void *instance,
209 const alpaqa_real_t *x,
211 alpaqa_real_t *grad_gi) ALPAQA_DEFAULT(nullptr);
212 /// Hessian-vector product of the Lagrangian.
213 /// @see @ref alpaqa::TypeErasedProblem::eval_hess_L_prod()
214 void (*eval_hess_L_prod)(
215 void *instance,
216 const alpaqa_real_t *x,
217 const alpaqa_real_t *y,
218 alpaqa_real_t scale,
219 const alpaqa_real_t *v,
220 alpaqa_real_t *Hv) ALPAQA_DEFAULT(nullptr);
221 /// Hessian of the Lagrangian.
222 /// @see @ref alpaqa::TypeErasedProblem::eval_hess_L()
223 void (*eval_hess_L)(
224 void *instance,
225 const alpaqa_real_t *x,
226 const alpaqa_real_t *y,
227 alpaqa_real_t scale,
228 alpaqa_real_t *H_values) ALPAQA_DEFAULT(nullptr);
229 /// Get the sparsity pattern of the Hessian of the Lagrangian.
230 /// @see @ref alpaqa::TypeErasedProblem::get_hess_L_sparsity()
231 alpaqa_sparsity_t (*get_hess_L_sparsity)(
232 void *instance) ALPAQA_DEFAULT(nullptr);
233 /// Hessian-vector product of the augmented Lagrangian.
234 /// @see @ref alpaqa::TypeErasedProblem::eval_hess_ψ_prod()
235 void (*eval_hess_ψ_prod)(
236 void *instance,
237 const alpaqa_real_t *x,
238 const alpaqa_real_t *y,
239 const alpaqa_real_t *Σ,
240 alpaqa_real_t scale,
241 const alpaqa_real_t *zl,
242 const alpaqa_real_t *zu,
243 const alpaqa_real_t *v,
244 alpaqa_real_t *Hv) ALPAQA_DEFAULT(nullptr);
245 /// Hessian of the augmented Lagrangian.
246 /// @see @ref alpaqa::TypeErasedProblem::eval_hess_ψ()
247 void (*eval_hess_ψ)(
248 void *instance,
249 const alpaqa_real_t *x,
250 const alpaqa_real_t *y,
251 const alpaqa_real_t *Σ,
252 alpaqa_real_t scale,
253 const alpaqa_real_t *zl,
254 const alpaqa_real_t *zu,
255 alpaqa_real_t *H_values) ALPAQA_DEFAULT(nullptr);
256 /// Get the sparsity pattern of the Hessian of the augmented Lagrangian.
257 /// @see @ref alpaqa::TypeErasedProblem::get_hess_ψ_sparsity()
258 alpaqa_sparsity_t (*get_hess_ψ_sparsity)(
259 void *instance) ALPAQA_DEFAULT(nullptr);
260 /// Cost and its gradient.
261 /// @see @ref alpaqa::TypeErasedProblem::eval_f_grad_f()
262 alpaqa_real_t (*eval_f_grad_f)(
263 void *instance,
264 const alpaqa_real_t *x,
265 alpaqa_real_t *grad_fx) ALPAQA_DEFAULT(nullptr);
266 /// Cost and constraints.
267 /// @see @ref alpaqa::TypeErasedProblem::eval_f_g()
268 alpaqa_real_t (*eval_f_g)(
269 void *instance,
270 const alpaqa_real_t *x,
271 alpaqa_real_t *g) ALPAQA_DEFAULT(nullptr);
272 /// Gradient of the cost and gradient-vector product of the constraints.
273 /// @see @ref alpaqa::TypeErasedProblem::eval_grad_f_grad_g_prod()
274 void (*eval_grad_f_grad_g_prod)(
275 void *instance,
276 const alpaqa_real_t *x,
277 const alpaqa_real_t *y,
278 alpaqa_real_t *grad_f,
279 alpaqa_real_t *grad_gxy) ALPAQA_DEFAULT(nullptr);
280 /// Gradient of the Lagrangian.
281 /// @see @ref alpaqa::TypeErasedProblem::eval_grad_L()
282 void (*eval_grad_L)(
283 void *instance,
284 const alpaqa_real_t *x,
285 const alpaqa_real_t *y,
286 alpaqa_real_t *grad_L,
287 alpaqa_real_t *work_n) ALPAQA_DEFAULT(nullptr);
288 /// Augmented Lagrangian.
289 /// @see @ref alpaqa::TypeErasedProblem::eval_ψ()
290 alpaqa_real_t (*eval_ψ)(
291 void *instance,
292 const alpaqa_real_t *x,
293 const alpaqa_real_t *y,
294 const alpaqa_real_t *Σ,
295 const alpaqa_real_t *zl,
296 const alpaqa_real_t *zu,
297 alpaqa_real_t *ŷ) ALPAQA_DEFAULT(nullptr);
298 /// Gradient of the augmented Lagrangian.
299 /// @see @ref alpaqa::TypeErasedProblem::eval_grad_ψ()
300 void (*eval_grad_ψ)(
301 void *instance,
302 const alpaqa_real_t *x,
303 const alpaqa_real_t *y,
304 const alpaqa_real_t *Σ,
305 const alpaqa_real_t *zl,
306 const alpaqa_real_t *zu,
307 alpaqa_real_t *grad_ψ,
308 alpaqa_real_t *work_n,
309 alpaqa_real_t *work_m) ALPAQA_DEFAULT(nullptr);
310 /// Augmented Lagrangian and its gradient.
311 /// @see @ref alpaqa::TypeErasedProblem::eval_ψ_grad_ψ()
312 alpaqa_real_t (*eval_ψ_grad_ψ)(
313 void *instance,
314 const alpaqa_real_t *x,
315 const alpaqa_real_t *y,
316 const alpaqa_real_t *Σ,
317 const alpaqa_real_t *zl,
318 const alpaqa_real_t *zu,
319 alpaqa_real_t *grad_ψ,
320 alpaqa_real_t *work_n,
321 alpaqa_real_t *work_m) ALPAQA_DEFAULT(nullptr);
322 /// Proximal gradient step.
323 /// @see @ref alpaqa::TypeErasedProblem::eval_prox_grad_step()
324 /// If not set, the default implementation from
325 /// @ref alpaqa::BoxConstrProblem is used.
326 alpaqa_real_t (*eval_prox_grad_step)(
327 void *instance,
328 alpaqa_real_t γ,
329 const alpaqa_real_t *x,
330 const alpaqa_real_t *grad_ψ,
331 alpaqa_real_t *x̂,
332 alpaqa_real_t *p) ALPAQA_DEFAULT(nullptr);
333 /// Provide the initial values for the bounds of
334 /// @ref alpaqa::BoxConstrProblem::C, i.e. the constraints on the decision
335 /// variables.
336 void (*initialize_box_C)(
337 void *instance,
338 alpaqa_real_t *lb,
339 alpaqa_real_t *ub) ALPAQA_DEFAULT(nullptr);
340 /// Provide the initial values for the bounds of
341 /// @ref alpaqa::BoxConstrProblem::D, i.e. the general constraints.
342 void (*initialize_box_D)(
343 void *instance,
344 alpaqa_real_t *lb,
345 alpaqa_real_t *ub) ALPAQA_DEFAULT(nullptr);
346 /// Provide the initial values for @ref alpaqa::BoxConstrProblem::l1_reg,
347 /// the ℓ₁-regularization factor.
348 /// This function is called twice:
349 /// 1. with @p lambda set to `nullptr`, and the user should set the size.
350 /// 2. with @p lambda pointing to an array of that size, and the user
351 /// should initialize this array.
352 void (*initialize_l1_reg)(
353 void *instance,
354 alpaqa_real_t *lambda,
355 alpaqa_length_t *size) ALPAQA_DEFAULT(nullptr);
356 // clang-format on
357}
359
360/// Opaque type for a C++-only map of extra functions.
362/// Opaque type for a C++-only exception pointer.
364
365/// @note When used in C, you should initialize this struct by passing a pointer
366/// to your instance to the @ref ALPAQA_PROBLEM_REGISTER_INIT macro.
367/// In C++, this is not necessary, because all members have default
368/// initializers.
370 /// To check whether the loaded problem is compatible with the version of
371 /// the solver.
373 /// Owning pointer.
374 void *instance ALPAQA_DEFAULT(nullptr);
375 /// Non-owning pointer, lifetime at least as long as @ref instance.
377 /// Pointer to the function to clean up @ref instance.
378 void (*cleanup)(void *) ALPAQA_DEFAULT(nullptr);
379 /// Pointer to a map of extra functions (C++ only).
380 /// @see @ref alpaqa::register_function
381 /// @see @ref alpaqa::register_member_function
382 alpaqa_function_dict_t *extra_functions ALPAQA_DEFAULT(nullptr);
383 /// Pointer to an exception that ocurred during problem creation.
385}
387
392
393 // clang-format off
394 void (*get_U)(
395 void *instance,
396 alpaqa_real_t *lb,
397 alpaqa_real_t *ub) ALPAQA_DEFAULT(nullptr);
398 void (*get_D)(
399 void *instance,
400 alpaqa_real_t *lb,
401 alpaqa_real_t *ub) ALPAQA_DEFAULT(nullptr);
402 void (*get_D_N)(
403 void *instance,
404 alpaqa_real_t *lb,
405 alpaqa_real_t *ub) ALPAQA_DEFAULT(nullptr);
406 void (*get_x_init)(
407 void *instance,
408 alpaqa_real_t *x_init) ALPAQA_DEFAULT(nullptr);
409 void (*eval_f)(
410 void *instance,
411 alpaqa_index_t timestep,
412 const alpaqa_real_t *x,
413 const alpaqa_real_t *u,
414 alpaqa_real_t *fxu) ALPAQA_DEFAULT(nullptr);
415 void (*eval_jac_f)(
416 void *instance,
417 alpaqa_index_t timestep,
418 const alpaqa_real_t *x,
419 const alpaqa_real_t *u,
420 alpaqa_real_t *J_fxu) ALPAQA_DEFAULT(nullptr);
421 void (*eval_grad_f_prod)(
422 void *instance,
423 alpaqa_index_t timestep,
424 const alpaqa_real_t *x,
425 const alpaqa_real_t *u,
426 const alpaqa_real_t *p,
427 alpaqa_real_t *grad_fxu_p) ALPAQA_DEFAULT(nullptr);
428 void (*eval_h)(
429 void *instance,
430 alpaqa_index_t timestep,
431 const alpaqa_real_t *x,
432 const alpaqa_real_t *u,
433 alpaqa_real_t *h) ALPAQA_DEFAULT(nullptr);
434 void (*eval_h_N)(
435 void *instance,
436 const alpaqa_real_t *x,
437 alpaqa_real_t *h) ALPAQA_DEFAULT(nullptr);
438 alpaqa_real_t (*eval_l)(
439 void *instance,
440 alpaqa_index_t timestep,
441 const alpaqa_real_t *h) ALPAQA_DEFAULT(nullptr);
442 alpaqa_real_t (*eval_l_N)(
443 void *instance,
444 const alpaqa_real_t *h) ALPAQA_DEFAULT(nullptr);
445 void (*eval_qr)(
446 void *instance,
447 alpaqa_index_t timestep,
448 const alpaqa_real_t *xu,
449 const alpaqa_real_t *h,
450 alpaqa_real_t *qr) ALPAQA_DEFAULT(nullptr);
451 void (*eval_q_N)(
452 void *instance,
453 const alpaqa_real_t *x,
454 const alpaqa_real_t *h,
455 alpaqa_real_t *q) ALPAQA_DEFAULT(nullptr);
456 void (*eval_add_Q)(
457 void *instance,
458 alpaqa_index_t timestep,
459 const alpaqa_real_t *xu,
460 const alpaqa_real_t *h,
461 alpaqa_real_t *Q) ALPAQA_DEFAULT(nullptr);
462 void (*eval_add_Q_N)(
463 void *instance,
464 const alpaqa_real_t *x,
465 const alpaqa_real_t *h,
466 alpaqa_real_t *Q) ALPAQA_DEFAULT(nullptr);
467 void (*eval_add_R_masked)(
468 void *instance,
469 alpaqa_index_t timestep,
470 const alpaqa_real_t *xu,
471 const alpaqa_real_t *h,
472 const alpaqa_index_t *mask,
473 alpaqa_real_t *R,
474 alpaqa_real_t *work) ALPAQA_DEFAULT(nullptr);
475 void (*eval_add_S_masked)(
476 void *instance,
477 alpaqa_index_t timestep,
478 const alpaqa_real_t *xu,
479 const alpaqa_real_t *h,
480 const alpaqa_index_t *mask,
481 alpaqa_real_t *S,
482 alpaqa_real_t *work) ALPAQA_DEFAULT(nullptr);
483 void (*eval_add_R_prod_masked)(
484 void *instance,
485 alpaqa_index_t timestep,
486 const alpaqa_real_t *xu,
487 const alpaqa_real_t *h,
488 const alpaqa_index_t *mask_J,
489 const alpaqa_index_t *mask_K,
490 const alpaqa_real_t *v,
491 alpaqa_real_t *out,
492 alpaqa_real_t *work) ALPAQA_DEFAULT(nullptr);
493 void (*eval_add_S_prod_masked)(
494 void *instance,
495 alpaqa_index_t timestep,
496 const alpaqa_real_t *xu,
497 const alpaqa_real_t *h,
498 const alpaqa_index_t *mask_K,
499 const alpaqa_real_t *v,
500 alpaqa_real_t *out,
501 alpaqa_real_t *work) ALPAQA_DEFAULT(nullptr);
502 alpaqa_length_t (*get_R_work_size)(
503 void *instance) ALPAQA_DEFAULT(nullptr);
504 alpaqa_length_t (*get_S_work_size)(
505 void *instance) ALPAQA_DEFAULT(nullptr);
506 void (*eval_constr)(
507 void *instance,
508 alpaqa_index_t timestep,
509 const alpaqa_real_t *x,
510 alpaqa_real_t *c) ALPAQA_DEFAULT(nullptr);
511 void (*eval_constr_N)(
512 void *instance,
513 const alpaqa_real_t *x,
514 alpaqa_real_t *c) ALPAQA_DEFAULT(nullptr);
515 void (*eval_grad_constr_prod)(
516 void *instance,
517 alpaqa_index_t timestep,
518 const alpaqa_real_t *x,
519 const alpaqa_real_t *p,
520 alpaqa_real_t *grad_cx_p) ALPAQA_DEFAULT(nullptr);
521 void (*eval_grad_constr_prod_N)(
522 void *instance,
523 const alpaqa_real_t *x,
524 const alpaqa_real_t *p,
525 alpaqa_real_t *grad_cx_p) ALPAQA_DEFAULT(nullptr);
526 void (*eval_add_gn_hess_constr)(
527 void *instance,
528 alpaqa_index_t timestep,
529 const alpaqa_real_t *x,
530 const alpaqa_real_t *M,
531 alpaqa_real_t *out) ALPAQA_DEFAULT(nullptr);
532 void (*eval_add_gn_hess_constr_N)(
533 void *instance,
534 const alpaqa_real_t *x,
535 const alpaqa_real_t *M,
536 alpaqa_real_t *out) ALPAQA_DEFAULT(nullptr);
537 // clang-format on
538}
540
541/// @note When used in C, you should initialize this struct by passing a pointer
542/// to your instance to the @ref ALPAQA_PROBLEM_REGISTER_INIT macro.
543/// In C++, this is not necessary, because all members have default
544/// initializers.
546 /// To check whether the loaded problem is compatible with the version of
547 /// the solver.
549 /// Owning pointer.
550 void *instance ALPAQA_DEFAULT(nullptr);
551 /// Non-owning pointer, lifetime at least as long as @ref instance.
553 /// Pointer to the function to clean up @ref instance.
554 void (*cleanup)(void *) ALPAQA_DEFAULT(nullptr);
555 /// Pointer to a map of extra functions (C++ only).
556 alpaqa_function_dict_t *extra_functions ALPAQA_DEFAULT(nullptr);
557 /// Pointer to an exception that ocurred during problem creation.
559}
561
562#ifdef __cplusplus
563}
564#endif
565
566#if !defined(__cplusplus) || defined(DOXYGEN)
567inline static void
573inline static void
579/// Initialize an instance of @ref alpaqa_problem_register_t or
580/// @ref alpaqa_control_problem_register_t. It initializes all members to zero,
581/// except for the ABI version, which is initialized to the current ABI version.
582/// Available in C only (unnecessary in C++).
583/// @param self
584/// A pointer to the instance to initialize.
585#define ALPAQA_PROBLEM_REGISTER_INIT(self) \
586 _Generic((self), alpaqa_problem_register_t * \
587 : alpaqa_problem_register_init, \
588 alpaqa_control_problem_register_t * \
589 : alpaqa_control_problem_register_init)(self)
590#endif
591
592#if defined(__cplusplus) && \
593 (__cplusplus > 201703L || (defined(_MSVC_LANG) && _MSVC_LANG > 201703L))
594
595#include <any>
596#include <exception>
597#include <functional>
598#include <map>
599#include <string>
600
602 std::map<std::string, std::any> dict{};
603};
604
606 std::exception_ptr exc{};
607};
608
609namespace alpaqa {
610
616
617/// Make the given function available to alpaqa.
618/// @see @ref alpaqa::dl::DLProblem::call_extra_func
619/// @see @ref alpaqa::dl::DLControlProblem::call_extra_func
620template <class Func>
621void register_function(function_dict_t *&extra_functions, std::string name,
622 Func &&func) {
623 if (extra_functions == nullptr)
624 extra_functions = new function_dict_t{};
625 extra_functions->dict.insert_or_assign(
626 std::move(name), std::function{std::forward<Func>(func)});
627}
628
629template <class Func>
630void register_function(problem_register_t &result, std::string name,
631 Func &&func) {
632 register_function(result.extra_functions, std::move(name),
633 std::forward<Func>(func));
634}
635
636template <class Func>
637void register_function(control_problem_register_t &result, std::string name,
638 Func &&func) {
639 register_function(result.extra_functions, std::move(name),
640 std::forward<Func>(func));
641}
642
643template <class Result, class T, class Ret, class... Args>
644void register_member_function(Result &result, std::string name,
645 Ret (T::*member)(Args...)) {
646 register_function(result, std::move(name),
647 [member](void *self_, Args... args) -> Ret {
648 auto *self = reinterpret_cast<T *>(self_);
649 return (self->*member)(std::forward<Args>(args)...);
650 });
651}
652
653template <class Result, class T, class Ret, class... Args>
654void register_member_function(Result &result, std::string name,
655 Ret (T::*member)(Args...) const) {
656 register_function(result, std::move(name),
657 [member](const void *self_, Args... args) -> Ret {
658 const auto *self = reinterpret_cast<const T *>(self_);
659 return (self->*member)(std::forward<Args>(args)...);
660 });
661}
662
663namespace detail {
664/// Overload for non-const-qualified member functions.
665/// @see @ref alpaqa::member_caller
666template <auto Member, class Class, class Ret, class... Args>
667static auto member_caller(Ret (Class::*)(Args...)) {
668 return [](void *self_, Args... args) -> Ret {
669 auto *self = reinterpret_cast<Class *>(self_);
670 return (self->*Member)(std::forward<Args>(args)...);
671 };
672}
673/// Overload for const-qualified member functions.
674/// @see @ref alpaqa::member_caller
675template <auto Member, class Class, class Ret, class... Args>
676static auto member_caller(Ret (Class::*)(Args...) const) {
677 return []<class Self>(Self * self_, Args... args) -> Ret
678 requires std::is_void_v<Self>
679 {
680 const auto *self = reinterpret_cast<const Class *>(self_);
681 return (self->*Member)(std::forward<Args>(args)...);
682 };
683}
684/// Overload for member variables.
685/// @see @ref alpaqa::member_caller
686template <auto Member, class Class, class Ret>
687static auto member_caller(Ret Class::*) {
688 return []<class Self>(Self * self_) -> decltype(auto)
689 requires std::is_void_v<Self>
690 {
691 using CClass = std::conditional_t<std::is_const_v<Self>,
692 std::add_const_t<Class>, Class>;
693 auto *self = reinterpret_cast<CClass *>(self_);
694 return self->*Member;
695 };
696}
697} // namespace detail
698
699/// Wrap the given member function or variable into a (possibly generic) lambda
700/// function that accepts the instance as a type-erased void pointer.
701///
702/// The signature of the resulting function depends on the signature of the
703/// member function:
704///
705/// - `Ret Class::member(args...)` → `Ret(void *self, args...)`
706/// - `Ret Class::member(args...) const` → `Ret(void *self, args...)`
707/// - `Ret Class::member(args...) const` → `Ret(const void *self, args...)`
708///
709/// If the given member is a variable:
710///
711/// - `Type Class::member` → `Type &(void *self)`
712/// - `Type Class::member` → `const Type &(const void *self)`
713template <auto Member>
714static auto member_caller() {
715 return detail::member_caller<Member>(Member);
716}
717
718/// Cleans up the extra functions registered by @ref register_function.
719/// @note This does not need to be called for the functions returned by the
720/// registration function, those functions will be cleaned up by alpaqa.
721/// @note The @ref alpaqa_problem_register_t and
722/// @ref alpaqa_control_problem_register_t structs are part of the C API
723/// and do not automatically clean up their resources when destroyed,
724/// you have to do it manually by calling this function.
725inline void unregister_functions(function_dict_t *&extra_functions) {
726 delete extra_functions;
727 extra_functions = nullptr;
728}
729
730} // namespace alpaqa
731
732#endif
733
734#undef ALPAQA_DEFAULT
735
736// NOLINTEND(modernize-use-using,modernize-deprecated-headers)
static void alpaqa_control_problem_register_init(alpaqa_control_problem_register_t *self)
Definition dl-problem.h:574
#define ALPAQA_DL_ABI_VERSION
Definition dl-problem.h:9
struct alpaqa_function_dict_s alpaqa_function_dict_t
Opaque type for a C++-only map of extra functions.
Definition dl-problem.h:361
ptrdiff_t alpaqa_length_t
Definition dl-problem.h:24
#define ALPAQA_END_STRUCT(name)
Definition dl-problem.h:14
#define ALPAQA_DEFAULT(...)
Definition dl-problem.h:15
alpaqa_length_t alpaqa_index_t
Definition dl-problem.h:25
std::exception_ptr exc
Definition dl-problem.h:606
#define ALPAQA_BEGIN_STRUCT(name)
Definition dl-problem.h:13
double alpaqa_real_t
Definition dl-problem.h:23
std::map< std::string, std::any > dict
Definition dl-problem.h:602
alpaqa_symmetry
Definition dl-problem.h:28
@ alpaqa_unsymmetric
Definition dl-problem.h:29
@ alpaqa_lower
Definition dl-problem.h:31
@ alpaqa_upper
Definition dl-problem.h:30
static void alpaqa_problem_register_init(alpaqa_problem_register_t *self)
Definition dl-problem.h:568
void unregister_functions(function_dict_t *&extra_functions)
Cleans up the extra functions registered by register_function.
Definition dl-problem.h:725
void register_function(function_dict_t *&extra_functions, std::string name, Func &&func)
Make the given function available to alpaqa.
Definition dl-problem.h:621
void register_member_function(Result &result, std::string name, Ret(T::*member)(Args...))
Definition dl-problem.h:644
constexpr const auto inf
Definition config.hpp:98
static auto member_caller()
Wrap the given member function or variable into a (possibly generic) lambda function that accepts the...
Definition dl-problem.h:714
alpaqa_function_dict_t * extra_functions
Pointer to a map of extra functions (C++ only).
Definition dl-problem.h:556
uint64_t abi_version
To check whether the loaded problem is compatible with the version of the solver.
Definition dl-problem.h:548
C API providing function pointers to problem functions.
Definition dl-problem.h:162
alpaqa_function_dict_t * extra_functions
Pointer to a map of extra functions (C++ only).
Definition dl-problem.h:382
uint64_t abi_version
To check whether the loaded problem is compatible with the version of the solver.
Definition dl-problem.h:372
alpaqa_length_t cols
Definition dl-problem.h:103
alpaqa_symmetry symmetry
Definition dl-problem.h:104
alpaqa_length_t nnz
Definition dl-problem.h:105
const long * row_indices
Definition dl-problem.h:106
const long * col_indices
Definition dl-problem.h:107
alpaqa_length_t cols
Definition dl-problem.h:121
alpaqa_symmetry symmetry
Definition dl-problem.h:122
const long long * row_indices
Definition dl-problem.h:124
alpaqa_length_t nnz
Definition dl-problem.h:123
const long long * col_indices
Definition dl-problem.h:125
alpaqa_length_t cols
Definition dl-problem.h:85
const int * col_indices
Definition dl-problem.h:89
alpaqa_symmetry symmetry
Definition dl-problem.h:86
const int * row_indices
Definition dl-problem.h:88
alpaqa_length_t nnz
Definition dl-problem.h:87
alpaqa_length_t cols
Definition dl-problem.h:57
alpaqa_symmetry symmetry
Definition dl-problem.h:58
alpaqa_length_t nnz
Definition dl-problem.h:59
const long * outer_ptr
Definition dl-problem.h:61
const long * inner_idx
Definition dl-problem.h:60
alpaqa_length_t cols
Definition dl-problem.h:71
const long long * inner_idx
Definition dl-problem.h:74
alpaqa_symmetry symmetry
Definition dl-problem.h:72
const long long * outer_ptr
Definition dl-problem.h:75
alpaqa_length_t nnz
Definition dl-problem.h:73
alpaqa_length_t cols
Definition dl-problem.h:43
const int * inner_idx
Definition dl-problem.h:46
alpaqa_symmetry symmetry
Definition dl-problem.h:44
const int * outer_ptr
Definition dl-problem.h:47
alpaqa_length_t nnz
Definition dl-problem.h:45
Sparsity of matrices.
Definition dl-problem.h:139