alpaqa 1.0.0a17
Nonconvex constrained optimization
Loading...
Searching...
No Matches
dl-problem.cpp
Go to the documentation of this file.
5
6#include <algorithm>
7#include <cassert>
8#include <charconv>
9#include <iostream>
10#include <list>
11#include <memory>
12#include <mutex>
13#include <stdexcept>
14
15#if _WIN32
16#include <windows.h>
17#else
18#include <dlfcn.h>
19#endif
20
21namespace alpaqa::dl {
22
23namespace {
24
26 std::string s(16, '0');
27 auto begin = s.data(), end = begin + s.size();
28 auto [ptr, ec] = std::to_chars(begin, end, version, 16);
29 if (ec != std::errc())
30 throw std::logic_error(std::make_error_code(ec).message());
31 std::rotate(begin, ptr, end);
32 return s;
33}
34
35void check_abi_version(uint64_t abi_version) {
36 if (abi_version != ALPAQA_DL_ABI_VERSION) {
37 auto prob_version = format_abi_version(abi_version);
40 "alpaqa::dl::DLProblem::DLProblem: "
41 "Incompatible problem definition (problem ABI version 0x" +
42 prob_version + ", this version of alpaqa supports 0x" +
43 alpaqa_version + ")");
44 }
45}
46
47#if _WIN32
48std::shared_ptr<char> get_last_error_msg() {
49 char *err = nullptr;
54 reinterpret_cast<char *>(&err), 0, NULL) != 0) {
55 return std::shared_ptr<char>{err, [](char *e) { LocalFree(e); }};
56 } else {
57 static char msg[] = "(failed to get error message)";
58 return std::shared_ptr<char>{msg, [](char *) {}};
59 }
60}
61
62std::shared_ptr<void> load_lib(const std::filesystem::path &so_filename) {
63 assert(!so_filename.empty());
64 void *h = LoadLibraryW(so_filename.c_str());
65 if (!h)
66 throw function_load_error("Unable to load \"" + so_filename.string() +
67 "\": " + get_last_error_msg().get());
68#if ALPAQA_NO_DLCLOSE
69 return std::shared_ptr<void>{h, +[](void *) {}};
70#else
71 return std::shared_ptr<void>{
72 h, +[](void *h) { FreeLibrary(static_cast<HMODULE>(h)); }};
73#endif
74}
75
76template <class F>
77F *load_func(void *handle, const std::string &name) {
78 assert(handle);
79 auto *h = GetProcAddress(static_cast<HMODULE>(handle), name.c_str());
80 if (!h)
81 throw function_load_error("Unable to load function '" + name +
82 "': " + get_last_error_msg().get());
83 // We can only hope that the user got the signature right ...
84 return reinterpret_cast<F *>(h);
85}
86#else
87std::shared_ptr<void> load_lib(const std::filesystem::path &so_filename) {
88 assert(!so_filename.empty());
89 ::dlerror();
90 void *h = ::dlopen(so_filename.c_str(), RTLD_LOCAL | RTLD_NOW);
91 if (auto *err = ::dlerror())
93#if ALPAQA_NO_DLCLOSE
94 return std::shared_ptr<void>{h, +[](void *) {}};
95#else
96 return std::shared_ptr<void>{h, &::dlclose};
97#endif
98}
99
100template <class F>
101F *load_func(void *handle, const std::string &name) {
102 assert(handle);
103 ::dlerror();
104 auto *h = ::dlsym(handle, name.c_str());
105 if (auto *err = ::dlerror())
106 throw function_load_error("Unable to load function '" + name +
107 "': " + err);
108 // We can only hope that the user got the signature right ...
109 return reinterpret_cast<F *>(h);
110}
111#endif
112
114std::list<std::shared_ptr<void>> leaked_modules;
115void leak_lib(std::shared_ptr<void> handle) {
116 std::lock_guard lck{leaked_modules_mutex};
117 leaked_modules.emplace_back(std::move(handle));
118}
119
120// clang-format off
121template <Config Conf>
124 switch (sp.kind) {
125 using sparsity::Symmetry;
127 using Dense = sparsity::Dense<config_t>;
128 return Dense{
129 .rows = sp.dense.rows,
130 .cols = sp.dense.cols,
131 .symmetry = static_cast<Symmetry>(sp.dense.symmetry),
132 };
134 using SparseCSC = sparsity::SparseCSC<config_t, int>;
135 return SparseCSC{
136 .rows = sp.sparse_csc.rows,
137 .cols = sp.sparse_csc.cols,
138 .symmetry = static_cast<Symmetry>(sp.sparse_csc.symmetry),
139 .inner_idx = typename SparseCSC::index_vector_map_t{sp.sparse_csc.inner_idx, sp.sparse_csc.nnz},
140 .outer_ptr = typename SparseCSC::index_vector_map_t{sp.sparse_csc.outer_ptr, sp.sparse_csc.cols + 1},
141 .order = static_cast<typename SparseCSC::Order>(sp.sparse_csc.order),
142 };
145 return SparseCSCl{
146 .rows = sp.sparse_csc_l.rows,
147 .cols = sp.sparse_csc_l.cols,
148 .symmetry = static_cast<Symmetry>(sp.sparse_csc_l.symmetry),
149 .inner_idx = typename SparseCSCl::index_vector_map_t{sp.sparse_csc_l.inner_idx, sp.sparse_csc_l.nnz},
150 .outer_ptr = typename SparseCSCl::index_vector_map_t{sp.sparse_csc_l.outer_ptr, sp.sparse_csc_l.cols + 1},
151 .order = static_cast<typename SparseCSCl::Order>(sp.sparse_csc_l.order),
152 };
155 return SparseCSCll{
156 .rows = sp.sparse_csc_ll.rows,
157 .cols = sp.sparse_csc_ll.cols,
158 .symmetry = static_cast<Symmetry>(sp.sparse_csc_ll.symmetry),
159 .inner_idx = typename SparseCSCll::index_vector_map_t{sp.sparse_csc_ll.inner_idx, sp.sparse_csc_ll.nnz},
160 .outer_ptr = typename SparseCSCll::index_vector_map_t{sp.sparse_csc_ll.outer_ptr, sp.sparse_csc_ll.cols + 1},
161 .order = static_cast<typename SparseCSCll::Order>(sp.sparse_csc_ll.order),
162 };
164 using SparseCOO = sparsity::SparseCOO<config_t, int>;
165 return SparseCOO{
166 .rows = sp.sparse_coo.rows,
167 .cols = sp.sparse_coo.cols,
168 .symmetry = static_cast<Symmetry>(sp.sparse_coo.symmetry),
169 .row_indices = typename SparseCOO::index_vector_map_t{sp.sparse_coo.row_indices, sp.sparse_coo.nnz},
170 .col_indices = typename SparseCOO::index_vector_map_t{sp.sparse_coo.col_indices, sp.sparse_coo.nnz},
171 .order = static_cast<typename SparseCOO::Order>(sp.sparse_coo.order),
172 .first_index = sp.sparse_coo.first_index,
173 };
176 return SparseCOOl{
177 .rows = sp.sparse_coo_l.rows,
178 .cols = sp.sparse_coo_l.cols,
179 .symmetry = static_cast<Symmetry>(sp.sparse_coo_l.symmetry),
180 .row_indices = typename SparseCOOl::index_vector_map_t{sp.sparse_coo_l.row_indices, sp.sparse_coo_l.nnz},
181 .col_indices = typename SparseCOOl::index_vector_map_t{sp.sparse_coo_l.col_indices, sp.sparse_coo_l.nnz},
182 .order = static_cast<typename SparseCOOl::Order>(sp.sparse_coo_l.order),
183 .first_index = sp.sparse_coo_l.first_index,
184 };
187 return SparseCOOll{
188 .rows = sp.sparse_coo_ll.rows,
189 .cols = sp.sparse_coo_ll.cols,
190 .symmetry = static_cast<Symmetry>(sp.sparse_coo_ll.symmetry),
191 .row_indices = typename SparseCOOll::index_vector_map_t{sp.sparse_coo_ll.row_indices, sp.sparse_coo_ll.nnz},
192 .col_indices = typename SparseCOOll::index_vector_map_t{sp.sparse_coo_ll.col_indices, sp.sparse_coo_ll.nnz},
193 .order = static_cast<typename SparseCOOll::Order>(sp.sparse_coo_ll.order),
194 .first_index = sp.sparse_coo_ll.first_index,
195 };
196 default: throw std::invalid_argument("Invalid sparsity kind");
197 }
198}
199// clang-format on
200
201} // namespace
202
203DLProblem::DLProblem(const std::filesystem::path &so_filename,
204 const std::string &function_name,
206 : BoxConstrProblem{0, 0}, file{so_filename} {
207 if (so_filename.empty())
208 throw std::invalid_argument("Invalid problem filename");
209 handle = load_lib(so_filename);
210 try {
212 handle.get(), function_name + "_version");
213 check_abi_version(version_func());
214 } catch (const function_load_error &) {
215 std::cerr << "Warning: problem " << so_filename
216 << " does not provide a function to query the ABI version, "
217 "alpaqa_dl_abi_version_t "
218 << function_name << "_version(void)\n";
219 }
221 handle.get(), function_name);
222 auto r = register_func(user_param);
223 // Avoid leaking if we throw (or if std::shared_ptr constructor throws)
224 std::unique_ptr<void, void (*)(void *)> unique_inst{r.instance, r.cleanup};
225 std::unique_ptr<alpaqa_function_dict_t> unique_extra{r.extra_functions};
226 std::unique_ptr<alpaqa_exception_ptr_t> unique_exception{r.exception};
227 check_abi_version(r.abi_version);
228 // Check exception thrown by plugin
229 if (unique_exception) {
230 // Here we're facing an interesting problem: the exception we throw
231 // might propagate upwards to a point where this instance is destroyed.
232 // This would cause the shared module to be closed using dlclose.
233 // However, the exception is still stored somewhere in the memory of
234 // that module, causing a segmentation fault when accessed.
235 // To get around this issue, we need to ensure that the shared module
236 // is not closed. Here we simply leak it by storing a shared_ptr to it
237 // in a global variable.
238 leak_lib(handle);
239 std::rethrow_exception(unique_exception->exc);
240 }
241 if (!r.functions)
242 throw std::logic_error("alpaqa::dl::DLProblem::DLProblem: plugin did "
243 "not return any functions");
244 // Store data returned by plugin
245 instance = std::shared_ptr<void>{std::move(unique_inst)};
246 functions = r.functions;
247 extra_funcs = std::shared_ptr<function_dict_t>{std::move(unique_extra)};
248
249 this->n = functions->n;
250 this->m = functions->m;
251 this->C = Box{this->n};
252 this->D = Box{this->m};
254 functions->initialize_box_C(instance.get(), this->C.lowerbound.data(),
255 this->C.upperbound.data());
257 functions->initialize_box_D(instance.get(), this->D.lowerbound.data(),
258 this->D.upperbound.data());
260 length_t = 0;
261 functions->initialize_l1_reg(instance.get(), nullptr, &);
262 if ( > 0) {
263 this->l1_reg.resize(nλ);
264 functions->initialize_l1_reg(instance.get(), this->l1_reg.data(),
265 &);
266 }
267 }
268}
269
275
276DLProblem::DLProblem(const std::filesystem::path &so_filename,
277 const std::string &function_name,
278 std::span<std::string_view> user_param)
282
283auto DLProblem::eval_proj_diff_g(crvec z, rvec e) const -> void {
284 if (functions->eval_proj_diff_g)
285 return functions->eval_proj_diff_g(instance.get(), z.data(), e.data());
287}
288
290 if (functions->eval_proj_multipliers)
291 return functions->eval_proj_multipliers(instance.get(), y.data(), M);
293}
294
296 rvec p) const -> real_t {
297 if (functions->eval_prox_grad_step)
298 return functions->eval_prox_grad_step(
299 instance.get(), γ, x.data(), grad_ψ.data(), x̂.data(), p.data());
300 return BoxConstrProblem<config_t>::eval_prox_grad_step(γ, x, grad_ψ, x̂, p);
301}
302
304 rindexvec J) const -> index_t {
305 if (functions->eval_inactive_indices_res_lna)
306 return functions->eval_inactive_indices_res_lna(
307 instance.get(), γ, x.data(), grad_ψ.data(), J.data());
309 grad_ψ, J);
310}
311
312auto DLProblem::get_name() const -> std::string {
313 if (functions->name)
314 return functions->name;
315 return file.filename().string();
316}
317
318// clang-format off
319auto DLProblem::eval_f(crvec x) const -> real_t { return functions->eval_f(instance.get(), x.data()); }
320auto DLProblem::eval_grad_f(crvec x, rvec grad_fx) const -> void { return functions->eval_grad_f(instance.get(), x.data(), grad_fx.data()); }
321auto DLProblem::eval_g(crvec x, rvec gx) const -> void { return functions->eval_g(instance.get(), x.data(), gx.data()); }
322auto DLProblem::eval_grad_g_prod(crvec x, crvec y, rvec grad_gxy) const -> void { return functions->eval_grad_g_prod(instance.get(), x.data(), y.data(), grad_gxy.data()); }
323auto DLProblem::eval_grad_gi(crvec x, index_t i, rvec grad_gi) const -> void { return functions->eval_grad_gi(instance.get(), x.data(), i, grad_gi.data()); }
324auto DLProblem::eval_jac_g(crvec x, rvec J_values) const -> void { return functions->eval_jac_g(instance.get(), x.data(), J_values.size() == 0 ? nullptr : J_values.data()); }
326auto DLProblem::eval_hess_L_prod(crvec x, crvec y, real_t scale, crvec v, rvec Hv) const -> void { return functions->eval_hess_L_prod(instance.get(), x.data(), y.data(), scale, v.data(), Hv.data()); }
327auto DLProblem::eval_hess_L(crvec x, crvec y, real_t scale, rvec H_values) const -> void { return functions->eval_hess_L(instance.get(), x.data(), y.data(), scale, H_values.size() == 0 ? nullptr : H_values.data()); }
329auto DLProblem::eval_hess_ψ_prod(crvec x, crvec y, crvec Σ, real_t scale, crvec v, rvec Hv) const -> void { return functions->eval_hess_ψ_prod(instance.get(), x.data(), y.data(), Σ.data(), scale, D.lowerbound.data(), D.upperbound.data(), v.data(), Hv.data()); }
330auto DLProblem::eval_hess_ψ(crvec x, crvec y, crvec Σ, real_t scale, rvec H_values) const -> void { return functions->eval_hess_ψ(instance.get(), x.data(), y.data(), Σ.data(), scale, D.lowerbound.data(), D.upperbound.data(), H_values.size() == 0 ? nullptr : H_values.data()); }
332auto DLProblem::eval_f_grad_f(crvec x, rvec grad_fx) const -> real_t { return functions->eval_f_grad_f(instance.get(), x.data(), grad_fx.data()); }
333auto DLProblem::eval_f_g(crvec x, rvec g) const -> real_t { return functions->eval_f_g(instance.get(), x.data(), g.data()); }
334auto DLProblem::eval_grad_f_grad_g_prod(crvec x, crvec y, rvec grad_f, rvec grad_gxy) const -> void { return functions->eval_grad_f_grad_g_prod(instance.get(), x.data(), y.data(), grad_f.data(), grad_gxy.data()); }
335auto DLProblem::eval_grad_L(crvec x, crvec y, rvec grad_L, rvec work_n) const -> void { return functions->eval_grad_L(instance.get(), x.data(), y.data(), grad_L.data(), work_n.data()); }
336auto DLProblem::eval_ψ(crvec x, crvec y, crvec Σ, rvec ŷ) const -> real_t { return functions->eval_ψ(instance.get(), x.data(), y.data(), Σ.data(), D.lowerbound.data(), D.upperbound.data(), ŷ.data()); }
337auto DLProblem::eval_grad_ψ(crvec x, crvec y, crvec Σ, rvec grad_ψ, rvec work_n, rvec work_m) const -> void { return functions->eval_grad_ψ(instance.get(), x.data(), y.data(), Σ.data(), D.lowerbound.data(), D.upperbound.data(), grad_ψ.data(), work_n.data(), work_m.data()); }
338auto DLProblem::eval_ψ_grad_ψ(crvec x, crvec y, crvec Σ, rvec grad_ψ, rvec work_n, rvec work_m) const -> real_t { return functions->eval_ψ_grad_ψ(instance.get(), x.data(), y.data(), Σ.data(), D.lowerbound.data(), D.upperbound.data(), grad_ψ.data(), work_n.data(), work_m.data()); }
339
340bool DLProblem::provides_eval_f() const { return functions->eval_f != nullptr; }
341bool DLProblem::provides_eval_grad_f() const { return functions->eval_grad_f != nullptr; }
342bool DLProblem::provides_eval_g() const { return functions->eval_g != nullptr; }
344bool DLProblem::provides_eval_jac_g() const { return functions->eval_jac_g != nullptr; }
346bool DLProblem::provides_eval_grad_gi() const { return functions->eval_grad_gi != nullptr; }
348bool DLProblem::provides_eval_hess_L() const { return functions->eval_hess_L != nullptr; }
351bool DLProblem::provides_eval_hess_ψ() const { return functions->eval_hess_ψ != nullptr; }
354bool DLProblem::provides_eval_f_g() const { return functions->eval_f_g != nullptr; }
356bool DLProblem::provides_eval_grad_L() const { return functions->eval_grad_L != nullptr; }
357bool DLProblem::provides_eval_ψ() const { return functions->eval_ψ != nullptr; }
358bool DLProblem::provides_eval_grad_ψ() const { return functions->eval_grad_ψ != nullptr; }
361bool DLProblem::provides_get_box_D() const { return functions->eval_proj_diff_g == nullptr; }
363// clang-format on
364
365#if ALPAQA_WITH_OCP
366
368 const std::string &function_name,
370 if (so_filename.empty())
371 throw std::invalid_argument("Invalid problem filename");
372 handle = load_lib(so_filename);
373 try {
375 handle.get(), function_name + "_version");
376 check_abi_version(version_func());
377 } catch (const function_load_error &) {
378 std::cerr << "Warning: problem " << so_filename
379 << " does not provide a function to query the ABI version, "
380 "alpaqa_dl_abi_version_t "
381 << function_name << "_version(void)\n";
382 }
383 auto *register_func =
385 handle.get(), function_name);
386 auto r = register_func(user_param);
387 // Avoid leaking if we throw (or if std::shared_ptr constructor throws)
388 std::unique_ptr<void, void (*)(void *)> unique_inst{r.instance, r.cleanup};
389 std::unique_ptr<alpaqa_function_dict_t> unique_extra{r.extra_functions};
390 std::unique_ptr<alpaqa_exception_ptr_t> unique_exception{r.exception};
391 check_abi_version(r.abi_version);
392 // Check exception thrown by plugin
393 if (unique_exception) {
394 // Here we're facing an interesting problem: the exception we throw
395 // might propagate upwards to a point where this instance is destroyed.
396 // This would cause the shared module to be closed using dlclose.
397 // However, the exception is still stored somewhere in the memory of
398 // that module, causing a segmentation fault when accessed.
399 // To get around this issue, we need to ensure that the shared module
400 // is not closed. Here we simply leak it by storing a shared_ptr to it
401 // in a global variable.
402 leak_lib(handle);
403 std::rethrow_exception(unique_exception->exc);
404 }
405 if (!functions)
406 throw std::logic_error("alpaqa::dl::DLControlProblem::DLControlProblem:"
407 " plugin did not return any functions");
408 // Store data returned by plugin
409 instance = std::shared_ptr<void>{std::move(unique_inst)};
410 functions = r.functions;
411 extra_funcs = std::shared_ptr<function_dict_t>{std::move(unique_extra)};
412}
413
414// clang-format off
415auto DLControlProblem::get_U(Box &U) const -> void { return functions->get_U(instance.get(), U.lowerbound.data(), U.upperbound.data()); }
416auto DLControlProblem::get_D(Box &D) const -> void { return functions->get_D(instance.get(), D.lowerbound.data(), D.upperbound.data()); }
417auto DLControlProblem::get_D_N(Box &D) const -> void { return functions->get_D_N(instance.get(), D.lowerbound.data(), D.upperbound.data()); }
418auto DLControlProblem::get_x_init(rvec x_init) const -> void { return functions->get_x_init(instance.get(), x_init.data()); }
419auto DLControlProblem::eval_f(index_t timestep, crvec x, crvec u, rvec fxu) const -> void { return functions->eval_f(instance.get(), timestep, x.data(), u.data(), fxu.data()); }
420auto DLControlProblem::eval_jac_f(index_t timestep, crvec x, crvec u, rmat J_fxu) const -> void { return functions->eval_jac_f(instance.get(), timestep, x.data(), u.data(), J_fxu.data()); }
421auto DLControlProblem::eval_grad_f_prod(index_t timestep, crvec x, crvec u, crvec p, rvec grad_fxu_p) const -> void { return functions->eval_grad_f_prod(instance.get(), timestep, x.data(), u.data(), p.data(), grad_fxu_p.data()); }
422auto DLControlProblem::eval_h(index_t timestep, crvec x, crvec u, rvec h) const -> void { return functions->eval_h(instance.get(), timestep, x.data(), u.data(), h.data()); }
423auto DLControlProblem::eval_h_N(crvec x, rvec h) const -> void { return functions->eval_h_N(instance.get(), x.data(), h.data()); }
424auto DLControlProblem::eval_l(index_t timestep, crvec h) const -> real_t { return functions->eval_l(instance.get(), timestep, h.data()); }
425auto DLControlProblem::eval_l_N(crvec h) const -> real_t { return functions->eval_l_N(instance.get(), h.data()); }
426auto DLControlProblem::eval_qr(index_t timestep, crvec xu, crvec h, rvec qr) const -> void { return functions->eval_qr(instance.get(), timestep, xu.data(), h.data(), qr.data()); }
427auto DLControlProblem::eval_q_N(crvec x, crvec h, rvec q) const -> void { return functions->eval_q_N(instance.get(), x.data(), h.data(), q.data()); }
428auto DLControlProblem::eval_add_Q(index_t timestep, crvec xu, crvec h, rmat Q) const -> void { return functions->eval_add_Q(instance.get(), timestep, xu.data(), h.data(), Q.data()); }
429auto DLControlProblem::eval_add_Q_N(crvec x, crvec h, rmat Q) const -> void { return functions->eval_add_Q_N(instance.get(), x.data(), h.data(), Q.data()); }
430auto DLControlProblem::eval_add_R_masked(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat R, rvec work) const -> void { return functions->eval_add_R_masked(instance.get(), timestep, xu.data(), h.data(), mask.data(), R.data(), work.data()); }
431auto DLControlProblem::eval_add_S_masked(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat S, rvec work) const -> void { return functions->eval_add_S_masked(instance.get(), timestep, xu.data(), h.data(), mask.data(), S.data(), work.data()); }
432auto DLControlProblem::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 -> void { return functions->eval_add_R_prod_masked(instance.get(), timestep, xu.data(), h.data(), mask_J.data(), mask_K.data(), v.data(), out.data(), work.data()); }
433auto DLControlProblem::eval_add_S_prod_masked(index_t timestep, crvec xu, crvec h, crindexvec mask_K, crvec v, rvec out, rvec work) const -> void { return functions->eval_add_S_prod_masked(instance.get(), timestep, xu.data(), h.data(), mask_K.data(), v.data(), out.data(), work.data()); }
436auto DLControlProblem::eval_constr(index_t timestep, crvec x, rvec c) const -> void { return functions->eval_constr(instance.get(), timestep, x.data(), c.data()); }
437auto DLControlProblem::eval_constr_N(crvec x, rvec c) const -> void { return functions->eval_constr_N(instance.get(), x.data(), c.data()); }
438auto DLControlProblem::eval_grad_constr_prod(index_t timestep, crvec x, crvec p, rvec grad_cx_p) const -> void { return functions->eval_grad_constr_prod(instance.get(), timestep, x.data(), p.data(), grad_cx_p.data()); }
439auto DLControlProblem::eval_grad_constr_prod_N(crvec x, crvec p, rvec grad_cx_p) const -> void { return functions->eval_grad_constr_prod_N(instance.get(), x.data(), p.data(), grad_cx_p.data()); }
440auto DLControlProblem::eval_add_gn_hess_constr(index_t timestep, crvec x, crvec M, rmat out) const -> void { return functions->eval_add_gn_hess_constr(instance.get(), timestep, x.data(), M.data(), out.data()); }
441auto DLControlProblem::eval_add_gn_hess_constr_N(crvec x, crvec M, rmat out) const -> void { return functions->eval_add_gn_hess_constr_N(instance.get(), x.data(), M.data(), out.data()); }
442
443bool DLControlProblem::provides_get_D() const { return functions->get_D != nullptr; }
444bool DLControlProblem::provides_get_D_N() const { return functions->get_D_N != nullptr; }
456// clang-format on
457
458#endif
459
460} // namespace alpaqa::dl
Implements common problem functions for minimization problems with box constraints.
Box C
Constraints of the decision variables, .
index_t eval_inactive_indices_res_lna(real_t γ, crvec x, crvec grad_ψ, rindexvec J) const
void eval_proj_diff_g(crvec z, rvec p) const
bool provides_get_box_C() const
Only supported if the ℓ₁-regularization term is zero.
length_t m
Number of constraints, dimension of g(x) and z.
length_t n
Number of decision variables, dimension of x.
void eval_proj_multipliers(rvec y, real_t M) const
real_t eval_prox_grad_step(real_t γ, crvec x, crvec grad_ψ, rvec x̂, rvec p) const
vec l1_reg
(1-norm) regularization parameter.
void eval_add_S_masked(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat S, rvec work) const
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,...
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
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.
DLControlProblem(const std::filesystem::path &so_filename, const std::string &function_name="register_alpaqa_control_problem", alpaqa_register_arg_t user_param={})
Load a problem from a shared library.
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
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_proj_multipliers(rvec y, real_t M) 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_proj_diff_g(crvec z, rvec e) 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
bool provides_eval_f() const
index_t eval_inactive_indices_res_lna(real_t γ, crvec x, crvec grad_ψ, rindexvec J) 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
DLProblem(const std::filesystem::path &so_filename, const std::string &function_name="register_alpaqa_problem", alpaqa_register_arg_t user_param={})
Load a problem from a shared library.
bool provides_eval_f_grad_f() const
bool provides_eval_grad_f() const
bool provides_eval_grad_gi() const
std::filesystem::path file
Path to the shared module file.
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
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
bool provides_get_box_D() 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
std::string get_name() const
#define USING_ALPAQA_CONFIG(Conf)
Definition config.hpp:77
#define ALPAQA_DL_ABI_VERSION
Definition dl-problem.h:8
@ alpaqa_register_arg_strings
The alpaqa_register_arg_t::data pointer points to a dynamic C++ std::span of std::string_view.
Definition dl-problem.h:56
@ alpaqa_register_arg_std_any
The alpaqa_register_arg_t::data pointer points to a C++ std::any object.
Definition dl-problem.h:51
User-provided argument that is passed to the problem registration functions.
Definition dl-problem.h:65
std::string format_abi_version(uint64_t version)
std::list< std::shared_ptr< void > > leaked_modules
F * load_func(void *handle, const std::string &name)
Sparsity< Conf > convert_sparsity(alpaqa_sparsity_t sp)
void leak_lib(std::shared_ptr< void > handle)
Symmetry
Describes the symmetry of matrices.
Definition sparsity.hpp:12
Dense matrix structure.
Definition sparsity.hpp:21
typename Conf::rmat rmat
Definition config.hpp:96
typename Conf::real_t real_t
Definition config.hpp:86
typename Conf::rindexvec rindexvec
Definition config.hpp:106
typename Conf::index_t index_t
Definition config.hpp:104
typename Conf::length_t length_t
Definition config.hpp:103
constexpr const auto inf
Definition config.hpp:112
typename Conf::rvec rvec
Definition config.hpp:91
typename Conf::crvec crvec
Definition config.hpp:92
typename Conf::crindexvec crindexvec
Definition config.hpp:107
std::shared_ptr< void > load_lib(const char *so_filename)
Sparse coordinate list structure (COO).
Definition sparsity.hpp:56
Sparse compressed-column structure (CCS or CSC).
Definition sparsity.hpp:29
Stores any of the supported sparsity patterns.
Definition sparsity.hpp:106
void(* eval_add_gn_hess_constr)(void *instance, alpaqa_index_t timestep, const alpaqa_real_t *x, const alpaqa_real_t *M, alpaqa_real_t *out)
Definition dl-problem.h:604
alpaqa_length_t(* get_S_work_size)(void *instance)
Definition dl-problem.h:582
void(* eval_grad_constr_prod_N)(void *instance, const alpaqa_real_t *x, const alpaqa_real_t *p, alpaqa_real_t *grad_cx_p)
Definition dl-problem.h:599
void(* get_D)(void *instance, alpaqa_real_t *lb, alpaqa_real_t *ub)
Definition dl-problem.h:476
void(* eval_grad_constr_prod)(void *instance, alpaqa_index_t timestep, const alpaqa_real_t *x, const alpaqa_real_t *p, alpaqa_real_t *grad_cx_p)
Definition dl-problem.h:593
void(* eval_add_R_prod_masked)(void *instance, alpaqa_index_t timestep, const alpaqa_real_t *xu, const alpaqa_real_t *h, const alpaqa_index_t *mask_J, const alpaqa_index_t *mask_K, const alpaqa_real_t *v, alpaqa_real_t *out, alpaqa_real_t *work)
Definition dl-problem.h:561
void(* eval_add_gn_hess_constr_N)(void *instance, const alpaqa_real_t *x, const alpaqa_real_t *M, alpaqa_real_t *out)
Definition dl-problem.h:610
alpaqa_length_t(* get_R_work_size)(void *instance)
Definition dl-problem.h:580
void(* get_D_N)(void *instance, alpaqa_real_t *lb, alpaqa_real_t *ub)
Definition dl-problem.h:480
void(* eval_constr)(void *instance, alpaqa_index_t timestep, const alpaqa_real_t *x, alpaqa_real_t *c)
Definition dl-problem.h:584
void(* eval_add_Q_N)(void *instance, const alpaqa_real_t *x, const alpaqa_real_t *h, alpaqa_real_t *Q)
Definition dl-problem.h:540
void(* eval_add_S_prod_masked)(void *instance, alpaqa_index_t timestep, const alpaqa_real_t *xu, const alpaqa_real_t *h, const alpaqa_index_t *mask_K, const alpaqa_real_t *v, alpaqa_real_t *out, alpaqa_real_t *work)
Definition dl-problem.h:571
void(* eval_constr_N)(void *instance, const alpaqa_real_t *x, alpaqa_real_t *c)
Definition dl-problem.h:589
void(* eval_grad_f)(void *instance, const alpaqa_real_t *x, alpaqa_real_t *grad_fx)
Gradient of the cost function.
Definition dl-problem.h:229
alpaqa_real_t(* eval_ψ)(void *instance, const alpaqa_real_t *x, const alpaqa_real_t *y, const alpaqa_real_t *Σ, const alpaqa_real_t *zl, const alpaqa_real_t *zu, alpaqa_real_t *ŷ)
Augmented Lagrangian.
Definition dl-problem.h:378
void(* eval_hess_ψ)(void *instance, const alpaqa_real_t *x, const alpaqa_real_t *y, const alpaqa_real_t *Σ, alpaqa_real_t scale, const alpaqa_real_t *zl, const alpaqa_real_t *zu, alpaqa_real_t *H_values)
Hessian of the augmented Lagrangian.
Definition dl-problem.h:333
void(* eval_hess_ψ_prod)(void *instance, const alpaqa_real_t *x, const alpaqa_real_t *y, const alpaqa_real_t *Σ, alpaqa_real_t scale, const alpaqa_real_t *zl, const alpaqa_real_t *zu, const alpaqa_real_t *v, alpaqa_real_t *Hv)
Hessian-vector product of the augmented Lagrangian.
Definition dl-problem.h:321
void(* initialize_box_C)(void *instance, alpaqa_real_t *lb, alpaqa_real_t *ub)
Provide the initial values for the bounds of alpaqa::BoxConstrProblem::C, i.e.
Definition dl-problem.h:414
alpaqa_real_t(* eval_prox_grad_step)(void *instance, alpaqa_real_t γ, const alpaqa_real_t *x, const alpaqa_real_t *grad_ψ, alpaqa_real_t *x̂, alpaqa_real_t *p)
Proximal gradient step.
Definition dl-problem.h:263
alpaqa_real_t(* eval_f_g)(void *instance, const alpaqa_real_t *x, alpaqa_real_t *g)
Cost and constraints.
Definition dl-problem.h:355
void(* eval_grad_f_grad_g_prod)(void *instance, const alpaqa_real_t *x, const alpaqa_real_t *y, alpaqa_real_t *grad_f, alpaqa_real_t *grad_gxy)
Gradient of the cost and gradient-vector product of the constraints.
Definition dl-problem.h:361
void(* eval_grad_L)(void *instance, const alpaqa_real_t *x, const alpaqa_real_t *y, alpaqa_real_t *grad_L, alpaqa_real_t *work_n)
Gradient of the Lagrangian.
Definition dl-problem.h:369
alpaqa_real_t(* eval_f_grad_f)(void *instance, const alpaqa_real_t *x, alpaqa_real_t *grad_fx)
Cost and its gradient.
Definition dl-problem.h:349
alpaqa_real_t(* eval_f)(void *instance, const alpaqa_real_t *x)
Cost function.
Definition dl-problem.h:224
alpaqa_sparsity_t(* get_hess_L_sparsity)(void *instance)
Get the sparsity pattern of the Hessian of the Lagrangian.
Definition dl-problem.h:317
alpaqa_sparsity_t(* get_hess_ψ_sparsity)(void *instance)
Get the sparsity pattern of the Hessian of the augmented Lagrangian.
Definition dl-problem.h:344
alpaqa_length_t m
Number of constraints.
Definition dl-problem.h:216
void(* eval_grad_ψ)(void *instance, const alpaqa_real_t *x, const alpaqa_real_t *y, const alpaqa_real_t *Σ, const alpaqa_real_t *zl, const alpaqa_real_t *zu, alpaqa_real_t *grad_ψ, alpaqa_real_t *work_n, alpaqa_real_t *work_m)
Gradient of the augmented Lagrangian.
Definition dl-problem.h:388
alpaqa_length_t n
Number of decision variables.
Definition dl-problem.h:213
void(* eval_grad_gi)(void *instance, const alpaqa_real_t *x, alpaqa_index_t i, alpaqa_real_t *grad_gi)
Gradient of specific constraint function.
Definition dl-problem.h:293
const char * name
Name of the problem.
Definition dl-problem.h:219
void(* initialize_l1_reg)(void *instance, alpaqa_real_t *lambda, alpaqa_length_t *size)
Provide the initial values for alpaqa::BoxConstrProblem::l1_reg, the ℓ₁-regularization factor.
Definition dl-problem.h:430
alpaqa_index_t(* eval_inactive_indices_res_lna)(void *instance, alpaqa_real_t γ, const alpaqa_real_t *x, const alpaqa_real_t *grad_ψ, alpaqa_index_t *J)
Active indices for proximal operator.
Definition dl-problem.h:274
void(* eval_hess_L_prod)(void *instance, const alpaqa_real_t *x, const alpaqa_real_t *y, alpaqa_real_t scale, const alpaqa_real_t *v, alpaqa_real_t *Hv)
Hessian-vector product of the Lagrangian.
Definition dl-problem.h:300
void(* eval_g)(void *instance, const alpaqa_real_t *x, alpaqa_real_t *gx)
Constraints function.
Definition dl-problem.h:235
void(* eval_proj_diff_g)(void *instance, const alpaqa_real_t *z, alpaqa_real_t *e)
Difference between point and its projection onto the general constraint set D.
Definition dl-problem.h:250
alpaqa_sparsity_t(* get_jac_g_sparsity)(void *instance)
Get the sparsity pattern of the Jacobian of the constraints function.
Definition dl-problem.h:289
void(* initialize_box_D)(void *instance, alpaqa_real_t *lb, alpaqa_real_t *ub)
Provide the initial values for the bounds of alpaqa::BoxConstrProblem::D, i.e.
Definition dl-problem.h:420
void(* eval_jac_g)(void *instance, const alpaqa_real_t *x, alpaqa_real_t *J_values)
Jacobian of the constraints function.
Definition dl-problem.h:283
alpaqa_real_t(* eval_ψ_grad_ψ)(void *instance, const alpaqa_real_t *x, const alpaqa_real_t *y, const alpaqa_real_t *Σ, const alpaqa_real_t *zl, const alpaqa_real_t *zu, alpaqa_real_t *grad_ψ, alpaqa_real_t *work_n, alpaqa_real_t *work_m)
Augmented Lagrangian and its gradient.
Definition dl-problem.h:400
void(* eval_hess_L)(void *instance, const alpaqa_real_t *x, const alpaqa_real_t *y, alpaqa_real_t scale, alpaqa_real_t *H_values)
Hessian of the Lagrangian.
Definition dl-problem.h:309
void(* eval_grad_g_prod)(void *instance, const alpaqa_real_t *x, const alpaqa_real_t *y, alpaqa_real_t *grad_gxy)
Gradient-vector product of the constraints function.
Definition dl-problem.h:241
Sparsity of matrices.
Definition dl-problem.h:187