alpaqa 1.0.0a16
Nonconvex constrained optimization
Loading...
Searching...
No Matches
dl-problem.hpp
Go to the documentation of this file.
1#pragma once
2
8
9#include <filesystem>
10#include <memory>
11#include <stdexcept>
12#include <string>
13#include <string_view>
14#include <type_traits>
15
16namespace alpaqa::dl {
17
19 public:
20 /// Unique type for calling an extra function that is a member function.
21 struct instance_t;
22
23 ExtraFuncs() = default;
24 ExtraFuncs(std::shared_ptr<function_dict_t> &&extra_funcs)
25 : extra_functions(std::move(extra_funcs)) {}
26
27 /// An associative array of additional functions exposed by the problem.
28 std::shared_ptr<function_dict_t> extra_functions;
29
30 template <class Signature>
31 requires std::is_function_v<Signature>
32 const std::function<Signature> &extra_func(const std::string &name) const {
33 if (!extra_functions)
34 throw std::out_of_range("DLProblem: no extra functions");
35 auto it = extra_functions->dict.find(name);
36 if (it == extra_functions->dict.end())
37 throw std::out_of_range("DLProblem: no extra function named \"" +
38 name + '"');
39 try {
40 return std::any_cast<const std::function<Signature> &>(it->second);
41 } catch (const std::bad_any_cast &) {
42 throw std::logic_error(
43 "DLProblem: incorrect type for extra function \"" + name +
44 "\" (stored type: " + demangled_typename(it->second.type()) +
45 ')');
46 }
47 }
48
49 template <class Func>
50 struct FuncTag {};
51
52 template <class Ret, class... FArgs, class... Args>
53 decltype(auto)
54 call_extra_func_helper(const void *instance,
55 FuncTag<Ret(const instance_t *, FArgs...)>,
56 const std::string &name, Args &&...args) const {
57 return extra_func<Ret(const void *, FArgs...)>(name)(
58 instance, std::forward<Args>(args)...);
59 }
60
61 template <class Ret, class... FArgs, class... Args>
62 decltype(auto)
63 call_extra_func_helper(void *instance, FuncTag<Ret(instance_t *, FArgs...)>,
64 const std::string &name, Args &&...args) {
65 return extra_func<Ret(void *, FArgs...)>(name)(
66 instance, std::forward<Args>(args)...);
67 }
68
69 template <class Ret, class... FArgs, class... Args>
70 decltype(auto) call_extra_func_helper(const void *, FuncTag<Ret(FArgs...)>,
71 const std::string &name,
72 Args &&...args) const {
73 return extra_func<Ret(FArgs...)>(name)(std::forward<Args>(args)...);
74 }
75};
76
77/// Class that loads a problem using `dlopen`.
78///
79/// The shared library should export a C function with the name @c function_name
80/// that accepts a void pointer with user data, and returns a struct of type
81/// @ref alpaqa_problem_register_t that contains all data to represent the
82/// problem, as well as function pointers for all required operations.
83/// See @ref C++/DLProblem/main.cpp and
84/// @ref problems/sparse-logistic-regression.cpp for examples.
85///
86/// @note Copies are shallow, they all share the same problem instance, take
87/// that into account when using multiple threads.
88///
89/// @ingroup grp_Problems
90/// @see @ref TypeErasedProblem
91/// @see @ref alpaqa_problem_functions_t
92/// @see @ref alpaqa_problem_register_t
93class DLProblem : public BoxConstrProblem<DefaultConfig> {
94 public:
97
98 /// Load a problem from a shared library.
100 /// Filename of the shared library to load.
101 const std::filesystem::path &so_filename,
102 /// Name of the problem registration function.
103 /// Should have signature `alpaqa_problem_register_t(void *)`.
104 const std::string &function_name = "register_alpaqa_problem",
105 /// Pointer to custom user data to pass to the registration function.
106 void *user_param = nullptr);
107
108 private:
109 /// Handle to the shared module defining the problem.
110 std::shared_ptr<void> handle;
111 /// Problem instance created by the registration function, including the
112 /// deleter to destroy it.
113 std::shared_ptr<void> instance;
114 /// Pointer to the struct of function pointers for evaluating the objective,
115 /// constraints, their gradients, etc.
117 /// Dictionary of extra functions that were registered by the problem.
119
120 public:
121 // clang-format off
122 real_t eval_prox_grad_step(real_t γ, crvec x, crvec grad_ψ, rvec x̂, rvec p) const;
123 real_t eval_f(crvec x) const;
124 void eval_grad_f(crvec x, rvec grad_fx) const;
125 void eval_g(crvec x, rvec gx) const;
126 void eval_grad_g_prod(crvec x, crvec y, rvec grad_gxy) const;
127 void eval_jac_g(crvec x, rvec J_values) const;
129 void eval_grad_gi(crvec x, index_t i, rvec grad_gi) const;
130 void eval_hess_L_prod(crvec x, crvec y, real_t scale, crvec v, rvec Hv) const;
131 void eval_hess_L(crvec x, crvec y, real_t scale, rvec H_values) const;
133 void eval_hess_ψ_prod(crvec x, crvec y, crvec Σ, real_t scale, crvec v, rvec Hv) const;
134 void eval_hess_ψ(crvec x, crvec y, crvec Σ, real_t scale, rvec H_values) const;
137 real_t eval_f_g(crvec x, rvec g) const;
138 void eval_grad_f_grad_g_prod(crvec x, crvec y, rvec grad_f, rvec grad_gxy) const;
139 void eval_grad_L(crvec x, crvec y, rvec grad_L, rvec work_n) const;
140 real_t eval_ψ(crvec x, crvec y, crvec Σ, rvec ŷ) const;
141 void eval_grad_ψ(crvec x, crvec y, crvec Σ, rvec grad_ψ, rvec work_n, rvec work_m) const;
142 real_t eval_ψ_grad_ψ(crvec x, crvec y, crvec Σ, rvec grad_ψ, rvec work_n, rvec work_m) const;
143
144 [[nodiscard]] bool provides_eval_f() const;
145 [[nodiscard]] bool provides_eval_grad_f() const;
146 [[nodiscard]] bool provides_eval_g() const;
147 [[nodiscard]] bool provides_eval_grad_g_prod() const;
148 [[nodiscard]] bool provides_eval_jac_g() const;
149 [[nodiscard]] bool provides_get_jac_g_sparsity() const;
150 [[nodiscard]] bool provides_eval_grad_gi() const;
151 [[nodiscard]] bool provides_eval_hess_L_prod() const;
152 [[nodiscard]] bool provides_eval_hess_L() const;
154 [[nodiscard]] bool provides_eval_hess_ψ_prod() const;
155 [[nodiscard]] bool provides_eval_hess_ψ() const;
157 [[nodiscard]] bool provides_eval_f_grad_f() const;
158 [[nodiscard]] bool provides_eval_f_g() const;
160 [[nodiscard]] bool provides_eval_grad_L() const;
161 [[nodiscard]] bool provides_eval_ψ() const;
162 [[nodiscard]] bool provides_eval_grad_ψ() const;
163 [[nodiscard]] bool provides_eval_ψ_grad_ψ() const;
164 [[nodiscard]] bool provides_get_box_C() const;
166 // clang-format on
167
168 using instance_t = ExtraFuncs::instance_t;
169
170 template <class Signature, class... Args>
171 decltype(auto) call_extra_func(const std::string &name,
172 Args &&...args) const {
173 return call_extra_func_helper(instance.get(),
175 std::forward<Args>(args)...);
176 }
177
178 template <class Signature, class... Args>
179 decltype(auto) call_extra_func(const std::string &name, Args &&...args) {
182 std::forward<Args>(args)...);
183 }
184};
185
186#if ALPAQA_WITH_OCP
187
188/// Class that loads an optimal control problem using `dlopen`.
189///
190/// The shared library should export a C function with the name @c function_name
191/// that accepts a void pointer with user data, and returns a struct of type
192/// @ref alpaqa_control_problem_register_t that contains all data to represent
193/// the problem, as well as function pointers for all required operations.
194///
195/// @note Copies are shallow, they all share the same problem instance, take
196/// that into account when using multiple threads.
197///
198/// @ingroup grp_Problems
199/// @see @ref TypeErasedControlProblem
201 public:
204
205 /// Load a problem from a shared library.
207 /// Filename of the shared library to load.
208 const std::filesystem::path &so_filename,
209 /// Name of the problem registration function.
210 /// Should have signature `alpaqa_control_problem_register_t(void *)`.
211 const std::string &function_name = "register_alpaqa_control_problem",
212 /// Pointer to custom user data to pass to the registration function.
213 void *user_param = nullptr);
214
215 private:
216 /// Handle to the shared module defining the problem.
217 std::shared_ptr<void> handle;
218 /// Problem instance created by the registration function, including the
219 /// deleter to destroy it.
220 std::shared_ptr<void> instance;
221 /// Pointer to the struct of function pointers for evaluating the objective,
222 /// constraints, their gradients, etc.
224 /// Dictionary of extra functions that were registered by the problem.
226
227 public:
228 length_t get_N() const { return functions->N; }
229 length_t get_nx() const { return functions->nx; }
230 length_t get_nu() const { return functions->nu; }
231 length_t get_nh() const { return functions->nh; }
232 length_t get_nh_N() const { return functions->nh_N; }
233 length_t get_nc() const { return functions->nc; }
234 length_t get_nc_N() const { return functions->nc_N; }
235
236 void check() const {} // TODO
237
238 // clang-format off
239 void get_U(Box &U) const;
240 void get_D(Box &D) const;
241 void get_D_N(Box &D) const;
242 void get_x_init(rvec x_init) const;
243 void eval_f(index_t timestep, crvec x, crvec u, rvec fxu) const;
244 void eval_jac_f(index_t timestep, crvec x, crvec u, rmat J_fxu) const;
246 void eval_h(index_t timestep, crvec x, crvec u, rvec h) const;
247 void eval_h_N(crvec x, rvec h) const;
249 [[nodiscard]] real_t eval_l_N(crvec h) const;
250 void eval_qr(index_t timestep, crvec xu, crvec h, rvec qr) const;
251 void eval_q_N(crvec x, crvec h, rvec q) const;
252 void eval_add_Q(index_t timestep, crvec xu, crvec h, rmat Q) const;
253 void eval_add_Q_N(crvec x, crvec h, rmat Q) const;
254 void eval_add_R_masked(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat R, rvec work) const;
255 void eval_add_S_masked(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat S, rvec work) const;
260 void eval_constr(index_t timestep, crvec x, rvec c) const;
261 void eval_constr_N(crvec x, rvec c) const;
265 void eval_add_gn_hess_constr_N(crvec x, crvec M, rmat out) const;
266
267 [[nodiscard]] bool provides_get_D() const;
268 [[nodiscard]] bool provides_get_D_N() const;
269 [[nodiscard]] bool provides_eval_add_Q_N() const;
272 [[nodiscard]] bool provides_get_R_work_size() const;
273 [[nodiscard]] bool provides_get_S_work_size() const;
274 [[nodiscard]] bool provides_eval_constr() const;
275 [[nodiscard]] bool provides_eval_constr_N() const;
280 // clang-format on
281
282 using instance_t = ExtraFuncs::instance_t;
283
284 template <class Signature, class... Args>
285 decltype(auto) call_extra_func(const std::string &name,
286 Args &&...args) const {
289 std::forward<Args>(args)...);
290 }
291
292 template <class Signature, class... Args>
293 decltype(auto) call_extra_func(const std::string &name, Args &&...args) {
296 std::forward<Args>(args)...);
297 }
298};
299
300#endif
301
302} // namespace alpaqa::dl
Implements common problem functions for minimization problems with box constraints.
Class that loads an optimal control problem using dlopen.
void eval_add_S_masked(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat S, rvec work) const
ExtraFuncs::instance_t instance_t
bool provides_eval_grad_constr_prod() const
void eval_add_Q_N(crvec x, crvec h, rmat Q) const
bool provides_eval_add_gn_hess_constr() const
void eval_q_N(crvec x, crvec h, rvec q) const
void eval_add_gn_hess_constr(index_t timestep, crvec x, crvec M, rmat out) const
void eval_grad_constr_prod(index_t timestep, crvec x, crvec p, rvec grad_cx_p) const
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
bool provides_eval_add_R_prod_masked() const
length_t get_S_work_size() const
void eval_constr_N(crvec x, rvec c) const
void get_D_N(Box &D) const
bool provides_get_S_work_size() const
void eval_grad_f_prod(index_t timestep, crvec x, crvec u, crvec p, rvec grad_fxu_p) const
std::shared_ptr< void > instance
Problem instance created by the registration function, including the deleter to destroy it.
void eval_jac_f(index_t timestep, crvec x, crvec u, rmat J_fxu) const
real_t eval_l_N(crvec h) const
void eval_h_N(crvec x, rvec h) const
real_t eval_l(index_t timestep, crvec h) const
void eval_grad_constr_prod_N(crvec x, crvec p, rvec grad_cx_p) const
control_problem_functions_t * functions
Pointer to the struct of function pointers for evaluating the objective, constraints,...
decltype(auto) call_extra_func(const std::string &name, Args &&...args) const
void eval_add_gn_hess_constr_N(crvec x, crvec M, rmat out) const
void eval_f(index_t timestep, crvec x, crvec u, rvec fxu) const
bool provides_eval_grad_constr_prod_N() const
length_t get_R_work_size() const
void eval_add_S_prod_masked(index_t timestep, crvec xu, crvec h, crindexvec mask_K, crvec v, rvec out, rvec work) const
bool provides_eval_add_S_prod_masked() const
void get_x_init(rvec x_init) const
void eval_h(index_t timestep, crvec x, crvec u, rvec h) const
decltype(auto) call_extra_func(const std::string &name, Args &&...args)
void eval_add_R_masked(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat R, rvec work) const
std::shared_ptr< void > handle
Handle to the shared module defining the problem.
void eval_qr(index_t timestep, crvec xu, crvec h, rvec qr) const
ExtraFuncs extra_funcs
Dictionary of extra functions that were registered by the problem.
void eval_add_Q(index_t timestep, crvec xu, crvec h, rmat Q) const
bool provides_get_R_work_size() const
bool provides_eval_add_gn_hess_constr_N() const
void eval_constr(index_t timestep, crvec x, rvec c) const
Class that loads a problem using dlopen.
bool provides_eval_hess_L() const
real_t eval_prox_grad_step(real_t γ, crvec x, crvec grad_ψ, rvec x̂, rvec p) const
ExtraFuncs::instance_t instance_t
real_t eval_ψ_grad_ψ(crvec x, crvec y, crvec Σ, rvec grad_ψ, rvec work_n, rvec work_m) const
void eval_grad_gi(crvec x, index_t i, rvec grad_gi) const
bool provides_get_hess_L_sparsity() const
void eval_hess_L_prod(crvec x, crvec y, real_t scale, crvec v, rvec Hv) const
bool provides_eval_hess_ψ_prod() const
void eval_hess_ψ_prod(crvec x, crvec y, crvec Σ, real_t scale, crvec v, rvec Hv) const
bool provides_eval_ψ_grad_ψ() const
bool provides_get_box_C() const
Sparsity get_jac_g_sparsity() const
real_t eval_f_g(crvec x, rvec g) const
void eval_grad_f(crvec x, rvec grad_fx) const
Sparsity get_hess_ψ_sparsity() const
bool provides_eval_jac_g() const
Sparsity get_hess_L_sparsity() const
void eval_grad_f_grad_g_prod(crvec x, crvec y, rvec grad_f, rvec grad_gxy) const
real_t eval_ψ(crvec x, crvec y, crvec Σ, rvec ŷ) const
bool provides_eval_inactive_indices_res_lna() const
std::shared_ptr< void > instance
Problem instance created by the registration function, including the deleter to destroy it.
bool provides_eval_g() const
void eval_grad_ψ(crvec x, crvec y, crvec Σ, rvec grad_ψ, rvec work_n, rvec work_m) const
void eval_hess_ψ(crvec x, crvec y, crvec Σ, real_t scale, rvec H_values) const
bool provides_eval_grad_f_grad_g_prod() const
decltype(auto) call_extra_func(const std::string &name, Args &&...args) const
bool provides_eval_f() const
bool provides_get_hess_ψ_sparsity() const
bool provides_eval_hess_L_prod() const
bool provides_eval_grad_g_prod() const
bool provides_get_jac_g_sparsity() const
real_t eval_f_grad_f(crvec x, rvec grad_fx) const
bool provides_eval_f_grad_f() const
bool provides_eval_grad_f() const
bool provides_eval_grad_gi() const
bool provides_eval_f_g() const
problem_functions_t * functions
Pointer to the struct of function pointers for evaluating the objective, constraints,...
void eval_jac_g(crvec x, rvec J_values) const
real_t eval_f(crvec x) const
void eval_hess_L(crvec x, crvec y, real_t scale, rvec H_values) const
bool provides_eval_grad_L() const
void eval_grad_g_prod(crvec x, crvec y, rvec grad_gxy) const
bool provides_eval_grad_ψ() const
decltype(auto) call_extra_func(const std::string &name, Args &&...args)
std::shared_ptr< void > handle
Handle to the shared module defining the problem.
ExtraFuncs extra_funcs
Dictionary of extra functions that were registered by the problem.
bool provides_eval_hess_ψ() const
void eval_grad_L(crvec x, crvec y, rvec grad_L, rvec work_n) const
void eval_g(crvec x, rvec gx) const
bool provides_eval_ψ() const
decltype(auto) call_extra_func_helper(const void *instance, FuncTag< Ret(const instance_t *, FArgs...)>, const std::string &name, Args &&...args) const
decltype(auto) call_extra_func_helper(void *instance, FuncTag< Ret(instance_t *, FArgs...)>, const std::string &name, Args &&...args)
const std::function< Signature > & extra_func(const std::string &name) const
std::shared_ptr< function_dict_t > extra_functions
An associative array of additional functions exposed by the problem.
ExtraFuncs(std::shared_ptr< function_dict_t > &&extra_funcs)
decltype(auto) call_extra_func_helper(const void *, FuncTag< Ret(FArgs...)>, const std::string &name, Args &&...args) const
#define USING_ALPAQA_CONFIG(Conf)
Definition config.hpp:63
std::string demangled_typename(const std::type_info &t)
Get the pretty name of the given type as a string.
typename Conf::rmat rmat
Definition config.hpp:82
typename Conf::real_t real_t
Definition config.hpp:72
typename Conf::index_t index_t
Definition config.hpp:90
typename Conf::length_t length_t
Definition config.hpp:89
constexpr const auto inf
Definition config.hpp:98
typename Conf::rvec rvec
Definition config.hpp:77
typename Conf::crvec crvec
Definition config.hpp:78
typename Conf::crindexvec crindexvec
Definition config.hpp:93
Double-precision double configuration.
Definition config.hpp:160
Stores any of the supported sparsity patterns.
Definition sparsity.hpp:106
C API providing function pointers to problem functions.
Definition dl-problem.h:162