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 <stdexcept>
13#ifndef ALPAQA_WITHOUT_MUTEX
14#include <mutex>
15#endif
16
17#if _WIN32
18#include <windows.h>
19#else
20#include <dlfcn.h>
21#endif
22
23namespace alpaqa::dl {
24
25namespace {
26
27std::string format_abi_version(uint64_t version) {
28 std::string s(16, '0');
29 auto begin = s.data(), end = begin + s.size();
30 auto [ptr, ec] = std::to_chars(begin, end, version, 16);
31 if (ec != std::errc())
32 throw std::logic_error(std::make_error_code(ec).message());
33 std::rotate(begin, ptr, end);
34 return s;
35}
36
37void check_abi_version(uint64_t abi_version) {
38 if (abi_version != ALPAQA_DL_ABI_VERSION) {
39 auto prob_version = format_abi_version(abi_version);
40 auto alpaqa_version = format_abi_version(ALPAQA_DL_ABI_VERSION);
42 "alpaqa::dl::DLProblem::DLProblem: "
43 "Incompatible problem definition (problem ABI version 0x" +
44 prob_version + ", this version of alpaqa supports 0x" +
45 alpaqa_version + ")");
46 }
47}
48#ifndef ALPAQA_WITHOUT_MUTEX
50#endif
51std::list<std::shared_ptr<void>> leaked_modules;
52void leak_lib(std::shared_ptr<void> handle) {
53#ifndef ALPAQA_WITHOUT_MUTEX
54 std::lock_guard lck{leaked_modules_mutex};
55#endif
56 leaked_modules.emplace_back(std::move(handle));
57}
58
59// clang-format off
60template <Config Conf>
63 switch (sp.kind) {
64 using sparsity::Symmetry;
66 return sparsity::Dense{
67 .rows = sp.dense.rows,
68 .cols = sp.dense.cols,
69 .symmetry = static_cast<Symmetry>(sp.dense.symmetry),
70 };
72 using SparseCSC = sparsity::SparseCSC<int, int>;
73 return SparseCSC{
74 .rows = sp.sparse_csc.rows,
75 .cols = sp.sparse_csc.cols,
76 .symmetry = static_cast<Symmetry>(sp.sparse_csc.symmetry),
77 .inner_idx = std::span{sp.sparse_csc.inner_idx, static_cast<size_t>(sp.sparse_csc.nnz)},
78 .outer_ptr = std::span{sp.sparse_csc.outer_ptr, static_cast<size_t>(sp.sparse_csc.cols + 1)},
79 .order = static_cast<typename SparseCSC::Order>(sp.sparse_csc.order),
80 };
82 using SparseCSCl = sparsity::SparseCSC<long, long>;
83 return SparseCSCl{
84 .rows = sp.sparse_csc_l.rows,
85 .cols = sp.sparse_csc_l.cols,
86 .symmetry = static_cast<Symmetry>(sp.sparse_csc_l.symmetry),
87 .inner_idx = std::span{sp.sparse_csc_l.inner_idx, static_cast<size_t>(sp.sparse_csc_l.nnz)},
88 .outer_ptr = std::span{sp.sparse_csc_l.outer_ptr, static_cast<size_t>(sp.sparse_csc_l.cols + 1)},
89 .order = static_cast<typename SparseCSCl::Order>(sp.sparse_csc_l.order),
90 };
92 using SparseCSCll = sparsity::SparseCSC<long long, long long>;
93 return SparseCSCll{
94 .rows = sp.sparse_csc_ll.rows,
95 .cols = sp.sparse_csc_ll.cols,
96 .symmetry = static_cast<Symmetry>(sp.sparse_csc_ll.symmetry),
97 .inner_idx = std::span{sp.sparse_csc_ll.inner_idx, static_cast<size_t>(sp.sparse_csc_ll.nnz)},
98 .outer_ptr = std::span{sp.sparse_csc_ll.outer_ptr, static_cast<size_t>(sp.sparse_csc_ll.cols + 1)},
99 .order = static_cast<typename SparseCSCll::Order>(sp.sparse_csc_ll.order),
100 };
102 using SparseCOO = sparsity::SparseCOO<int>;
103 return SparseCOO{
104 .rows = sp.sparse_coo.rows,
105 .cols = sp.sparse_coo.cols,
106 .symmetry = static_cast<Symmetry>(sp.sparse_coo.symmetry),
107 .row_indices = std::span{sp.sparse_coo.row_indices, static_cast<size_t>(sp.sparse_coo.nnz)},
108 .col_indices = std::span{sp.sparse_coo.col_indices, static_cast<size_t>(sp.sparse_coo.nnz)},
109 .order = static_cast<typename SparseCOO::Order>(sp.sparse_coo.order),
110 .first_index = sp.sparse_coo.first_index,
111 };
113 using SparseCOOl = sparsity::SparseCOO<long>;
114 return SparseCOOl{
115 .rows = sp.sparse_coo_l.rows,
116 .cols = sp.sparse_coo_l.cols,
117 .symmetry = static_cast<Symmetry>(sp.sparse_coo_l.symmetry),
118 .row_indices = std::span{sp.sparse_coo_l.row_indices, static_cast<size_t>(sp.sparse_coo_l.nnz)},
119 .col_indices = std::span{sp.sparse_coo_l.col_indices, static_cast<size_t>(sp.sparse_coo_l.nnz)},
120 .order = static_cast<typename SparseCOOl::Order>(sp.sparse_coo_l.order),
121 .first_index = sp.sparse_coo_l.first_index,
122 };
124 using SparseCOOll = sparsity::SparseCOO<long long>;
125 return SparseCOOll{
126 .rows = sp.sparse_coo_ll.rows,
127 .cols = sp.sparse_coo_ll.cols,
128 .symmetry = static_cast<Symmetry>(sp.sparse_coo_ll.symmetry),
129 .row_indices = std::span{sp.sparse_coo_ll.row_indices, static_cast<size_t>(sp.sparse_coo_ll.nnz)},
130 .col_indices = std::span{sp.sparse_coo_ll.col_indices, static_cast<size_t>(sp.sparse_coo_ll.nnz)},
131 .order = static_cast<typename SparseCOOll::Order>(sp.sparse_coo_ll.order),
132 .first_index = sp.sparse_coo_ll.first_index,
133 };
134 default: throw std::invalid_argument("Invalid sparsity kind");
135 }
136}
137// clang-format on
138
139} // namespace
140
141DLProblem::DLProblem(const std::filesystem::path &so_filename,
142 const std::string &function_name,
143 alpaqa_register_arg_t user_param,
144 DynamicLoadFlags dl_flags)
145 : BoxConstrProblem{0, 0}, file{so_filename} {
146 if (so_filename.empty())
147 throw std::invalid_argument("Invalid problem filename");
148 handle = guanaqo::load_lib(so_filename, dl_flags);
149 try {
150 auto *version_func = reinterpret_cast<alpaqa_dl_abi_version_t (*)()>(
151 guanaqo::load_func(handle.get(), function_name + "_version"));
152 check_abi_version(version_func());
153 } catch (const dynamic_load_error &) {
154 std::cerr << "Warning: problem " << so_filename
155 << " does not provide a function to query the ABI version, "
156 "alpaqa_dl_abi_version_t "
157 << function_name << "_version(void)\n";
158 }
159 auto *register_func =
160 reinterpret_cast<problem_register_t (*)(alpaqa_register_arg_t)>(
161 guanaqo::load_func(handle.get(), function_name));
162 auto r = register_func(user_param);
163 // Avoid leaking if we throw (or if std::shared_ptr constructor throws)
164 std::unique_ptr<void, void (*)(void *)> unique_inst{r.instance, r.cleanup};
165 std::unique_ptr<alpaqa_function_dict_t> unique_extra{r.extra_functions};
166 std::unique_ptr<alpaqa_exception_ptr_t> unique_exception{r.exception};
167 check_abi_version(r.abi_version);
168 // Check exception thrown by plugin
169 if (unique_exception) {
170 // Here we're facing an interesting problem: the exception we throw
171 // might propagate upwards to a point where this instance is destroyed.
172 // This would cause the shared module to be closed using dlclose.
173 // However, the exception is still stored somewhere in the memory of
174 // that module, causing a segmentation fault when accessed.
175 // To get around this issue, we need to ensure that the shared module
176 // is not closed. Here we simply leak it by storing a shared_ptr to it
177 // in a global variable.
178 leak_lib(handle);
179 std::rethrow_exception(unique_exception->exc);
180 }
181 if (!r.functions)
182 throw std::logic_error("alpaqa::dl::DLProblem::DLProblem: plugin did "
183 "not return any functions");
184 // Store data returned by plugin
185 instance = std::shared_ptr<void>{std::move(unique_inst)};
186 functions = r.functions;
187 extra_funcs = std::shared_ptr<function_dict_t>{std::move(unique_extra)};
188
189 num_variables = functions->num_variables;
190 num_constraints = functions->num_constraints;
193 if (functions->initialize_variable_bounds)
194 functions->initialize_variable_bounds(instance.get(),
195 variable_bounds.lower.data(),
196 variable_bounds.upper.data());
197 if (functions->initialize_general_bounds)
198 functions->initialize_general_bounds(instance.get(),
199 general_bounds.lower.data(),
200 general_bounds.upper.data());
201 if (functions->initialize_l1_reg) {
202 length_t nλ = 0;
203 functions->initialize_l1_reg(instance.get(), nullptr, &nλ);
204 if (nλ > 0) {
205 l1_reg.resize(nλ);
206 functions->initialize_l1_reg(instance.get(), l1_reg.data(), &nλ);
207 }
208 }
209}
210
211DLProblem::DLProblem(const std::filesystem::path &so_filename,
212 const std::string &function_name, std::any &user_param,
213 DynamicLoadFlags dl_flags)
214 : DLProblem{so_filename, function_name,
215 alpaqa_register_arg_t{reinterpret_cast<void *>(&user_param),
217 dl_flags} {}
218
219DLProblem::DLProblem(const std::filesystem::path &so_filename,
220 const std::string &function_name,
221 std::span<std::string_view> user_param,
222 DynamicLoadFlags dl_flags)
223 : DLProblem{so_filename, function_name,
224 alpaqa_register_arg_t{reinterpret_cast<void *>(&user_param),
226 dl_flags} {}
227
229 -> void {
230 if (functions->eval_projecting_difference_constraints)
231 return functions->eval_projecting_difference_constraints(
232 instance.get(), z.data(), e.data());
234 z, e);
235}
236
238 if (functions->eval_projection_multipliers)
239 return functions->eval_projection_multipliers(instance.get(), y.data(),
240 M);
242}
243
245 rvec x̂, rvec p) const -> real_t {
246 if (functions->eval_proximal_gradient_step)
247 return functions->eval_proximal_gradient_step(
248 instance.get(), γ, x.data(), grad_ψ.data(), x̂.data(), p.data());
250 x̂, p);
251}
252
254 rindexvec J) const -> index_t {
255 if (functions->eval_inactive_indices_res_lna)
256 return functions->eval_inactive_indices_res_lna(
257 instance.get(), γ, x.data(), grad_ψ.data(), J.data());
259 grad_ψ, J);
260}
261
262auto DLProblem::get_name() const -> std::string {
263 if (functions->name)
264 return functions->name;
265 return file.filename().string();
266}
267
268// clang-format off
269auto DLProblem::eval_objective(crvec x) const -> real_t { return functions->eval_objective(instance.get(), x.data()); }
270auto DLProblem::eval_objective_gradient(crvec x, rvec grad_fx) const -> void { return functions->eval_objective_gradient(instance.get(), x.data(), grad_fx.data()); }
271auto DLProblem::eval_constraints(crvec x, rvec gx) const -> void { return functions->eval_constraints(instance.get(), x.data(), gx.data()); }
272auto DLProblem::eval_constraints_gradient_product(crvec x, crvec y, rvec grad_gxy) const -> void { return functions->eval_constraints_gradient_product(instance.get(), x.data(), y.data(), grad_gxy.data()); }
273auto 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()); }
274auto DLProblem::eval_constraints_jacobian(crvec x, rvec J_values) const -> void { return functions->eval_constraints_jacobian(instance.get(), x.data(), J_values.size() == 0 ? nullptr : J_values.data()); }
275auto DLProblem::get_constraints_jacobian_sparsity() const -> Sparsity { return convert_sparsity<config_t>(functions->get_constraints_jacobian_sparsity(instance.get())); }
276auto DLProblem::eval_lagrangian_hessian_product(crvec x, crvec y, real_t scale, crvec v, rvec Hv) const -> void { return functions->eval_lagrangian_hessian_product(instance.get(), x.data(), y.data(), scale, v.data(), Hv.data()); }
277auto DLProblem::eval_lagrangian_hessian(crvec x, crvec y, real_t scale, rvec H_values) const -> void { return functions->eval_lagrangian_hessian(instance.get(), x.data(), y.data(), scale, H_values.size() == 0 ? nullptr : H_values.data()); }
278auto DLProblem::get_lagrangian_hessian_sparsity() const -> Sparsity { return convert_sparsity<config_t>(functions->get_lagrangian_hessian_sparsity(instance.get())); }
279auto DLProblem::eval_augmented_lagrangian_hessian_product(crvec x, crvec y, crvec Σ, real_t scale, crvec v, rvec Hv) const -> void { return functions->eval_augmented_lagrangian_hessian_product(instance.get(), x.data(), y.data(), Σ.data(), scale, general_bounds.lower.data(), general_bounds.upper.data(), v.data(), Hv.data()); }
280auto DLProblem::eval_augmented_lagrangian_hessian(crvec x, crvec y, crvec Σ, real_t scale, rvec H_values) const -> void { return functions->eval_augmented_lagrangian_hessian(instance.get(), x.data(), y.data(), Σ.data(), scale, general_bounds.lower.data(), general_bounds.upper.data(), H_values.size() == 0 ? nullptr : H_values.data()); }
281auto DLProblem::get_augmented_lagrangian_hessian_sparsity() const -> Sparsity { return convert_sparsity<config_t>(functions->get_augmented_lagrangian_hessian_sparsity(instance.get())); }
282auto DLProblem::eval_objective_and_gradient(crvec x, rvec grad_fx) const -> real_t { return functions->eval_objective_and_gradient(instance.get(), x.data(), grad_fx.data()); }
283auto DLProblem::eval_objective_and_constraints(crvec x, rvec g) const -> real_t { return functions->eval_objective_and_constraints(instance.get(), x.data(), g.data()); }
284auto DLProblem::eval_objective_gradient_and_constraints_gradient_product(crvec x, crvec y, rvec grad_f, rvec grad_gxy) const -> void { return functions->eval_objective_gradient_and_constraints_gradient_product(instance.get(), x.data(), y.data(), grad_f.data(), grad_gxy.data()); }
285auto DLProblem::eval_lagrangian_gradient(crvec x, crvec y, rvec grad_L, rvec work_n) const -> void { return functions->eval_lagrangian_gradient(instance.get(), x.data(), y.data(), grad_L.data(), work_n.data()); }
286auto DLProblem::eval_augmented_lagrangian(crvec x, crvec y, crvec Σ, rvec ŷ) const -> real_t { return functions->eval_augmented_lagrangian(instance.get(), x.data(), y.data(), Σ.data(), general_bounds.lower.data(), general_bounds.upper.data(), ŷ.data()); }
287auto DLProblem::eval_augmented_lagrangian_gradient(crvec x, crvec y, crvec Σ, rvec grad_ψ, rvec work_n, rvec work_m) const -> void { return functions->eval_augmented_lagrangian_gradient(instance.get(), x.data(), y.data(), Σ.data(), general_bounds.lower.data(), general_bounds.upper.data(), grad_ψ.data(), work_n.data(), work_m.data()); }
288auto DLProblem::eval_augmented_lagrangian_and_gradient(crvec x, crvec y, crvec Σ, rvec grad_ψ, rvec work_n, rvec work_m) const -> real_t { return functions->eval_augmented_lagrangian_and_gradient(instance.get(), x.data(), y.data(), Σ.data(), general_bounds.lower.data(), general_bounds.upper.data(), grad_ψ.data(), work_n.data(), work_m.data()); }
289
290bool DLProblem::provides_eval_objective() const { return functions->eval_objective != nullptr; }
291bool DLProblem::provides_eval_objective_gradient() const { return functions->eval_objective_gradient != nullptr; }
292bool DLProblem::provides_eval_constraints() const { return functions->eval_constraints != nullptr; }
293bool DLProblem::provides_eval_constraints_gradient_product() const { return functions->eval_constraints_gradient_product != nullptr; }
294bool DLProblem::provides_eval_constraints_jacobian() const { return functions->eval_constraints_jacobian != nullptr; }
295bool DLProblem::provides_get_constraints_jacobian_sparsity() const { return functions->get_constraints_jacobian_sparsity != nullptr; }
296bool DLProblem::provides_eval_grad_gi() const { return functions->eval_grad_gi != nullptr; }
297bool DLProblem::provides_eval_lagrangian_hessian_product() const { return functions->eval_lagrangian_hessian_product != nullptr; }
298bool DLProblem::provides_eval_lagrangian_hessian() const { return functions->eval_lagrangian_hessian != nullptr; }
299bool DLProblem::provides_get_lagrangian_hessian_sparsity() const { return functions->get_lagrangian_hessian_sparsity != nullptr; }
300bool DLProblem::provides_eval_augmented_lagrangian_hessian_product() const { return functions->eval_augmented_lagrangian_hessian_product != nullptr; }
301bool DLProblem::provides_eval_augmented_lagrangian_hessian() const { return functions->eval_augmented_lagrangian_hessian != nullptr; }
302bool DLProblem::provides_get_augmented_lagrangian_hessian_sparsity() const { return functions->get_augmented_lagrangian_hessian_sparsity != nullptr; }
303bool DLProblem::provides_eval_objective_and_gradient() const { return functions->eval_objective_and_gradient != nullptr; }
304bool DLProblem::provides_eval_objective_and_constraints() const { return functions->eval_objective_and_constraints != nullptr; }
305bool DLProblem::provides_eval_objective_gradient_and_constraints_gradient_product() const { return functions->eval_objective_gradient_and_constraints_gradient_product != nullptr; }
306bool DLProblem::provides_eval_lagrangian_gradient() const { return functions->eval_lagrangian_gradient != nullptr; }
307bool DLProblem::provides_eval_augmented_lagrangian() const { return functions->eval_augmented_lagrangian != nullptr; }
308bool DLProblem::provides_eval_augmented_lagrangian_gradient() const { return functions->eval_augmented_lagrangian_gradient != nullptr; }
309bool DLProblem::provides_eval_augmented_lagrangian_and_gradient() const { return functions->eval_augmented_lagrangian_and_gradient != nullptr; }
310bool DLProblem::provides_get_variable_bounds() const { return functions->eval_proximal_gradient_step == nullptr && BoxConstrProblem::provides_get_variable_bounds(); }
311bool DLProblem::provides_get_general_bounds() const { return functions->eval_projecting_difference_constraints == nullptr; }
312bool DLProblem::provides_eval_inactive_indices_res_lna() const { return functions->eval_proximal_gradient_step == nullptr || functions->eval_inactive_indices_res_lna != nullptr; }
313// clang-format on
314
315#if ALPAQA_WITH_OCP
316
317DLControlProblem::DLControlProblem(const std::filesystem::path &so_filename,
318 const std::string &function_name,
319 alpaqa_register_arg_t user_param,
320 DynamicLoadFlags dl_flags) {
321 if (so_filename.empty())
322 throw std::invalid_argument("Invalid problem filename");
323 handle = guanaqo::load_lib(so_filename, dl_flags);
324 try {
325 auto *version_func = reinterpret_cast<alpaqa_dl_abi_version_t (*)()>(
326 guanaqo::load_func(handle.get(), function_name + "_version"));
327 check_abi_version(version_func());
328 } catch (const dynamic_load_error &) {
329 std::cerr << "Warning: problem " << so_filename
330 << " does not provide a function to query the ABI version, "
331 "alpaqa_dl_abi_version_t "
332 << function_name << "_version(void)\n";
333 }
334 auto *register_func =
336 guanaqo::load_func(handle.get(), function_name));
337 auto r = register_func(user_param);
338 // Avoid leaking if we throw (or if std::shared_ptr constructor throws)
339 std::unique_ptr<void, void (*)(void *)> unique_inst{r.instance, r.cleanup};
340 std::unique_ptr<alpaqa_function_dict_t> unique_extra{r.extra_functions};
341 std::unique_ptr<alpaqa_exception_ptr_t> unique_exception{r.exception};
342 check_abi_version(r.abi_version);
343 // Check exception thrown by plugin
344 if (unique_exception) {
345 // Here we're facing an interesting problem: the exception we throw
346 // might propagate upwards to a point where this instance is destroyed.
347 // This would cause the shared module to be closed using dlclose.
348 // However, the exception is still stored somewhere in the memory of
349 // that module, causing a segmentation fault when accessed.
350 // To get around this issue, we need to ensure that the shared module
351 // is not closed. Here we simply leak it by storing a shared_ptr to it
352 // in a global variable.
353 leak_lib(handle);
354 std::rethrow_exception(unique_exception->exc);
355 }
356 if (!functions)
357 throw std::logic_error("alpaqa::dl::DLControlProblem::DLControlProblem:"
358 " plugin did not return any functions");
359 // Store data returned by plugin
360 instance = std::shared_ptr<void>{std::move(unique_inst)};
361 functions = r.functions;
362 extra_funcs = std::shared_ptr<function_dict_t>{std::move(unique_extra)};
363}
364
365// clang-format off
366auto DLControlProblem::get_U(Box &U) const -> void { return functions->get_U(instance.get(), U.lower.data(), U.upper.data()); }
367auto DLControlProblem::get_D(Box &D) const -> void { return functions->get_D(instance.get(), D.lower.data(), D.upper.data()); }
368auto DLControlProblem::get_D_N(Box &D) const -> void { return functions->get_D_N(instance.get(), D.lower.data(), D.upper.data()); }
369auto DLControlProblem::get_x_init(rvec x_init) const -> void { return functions->get_x_init(instance.get(), x_init.data()); }
370auto 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()); }
371auto 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()); }
372auto 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()); }
373auto 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()); }
374auto DLControlProblem::eval_h_N(crvec x, rvec h) const -> void { return functions->eval_h_N(instance.get(), x.data(), h.data()); }
375auto DLControlProblem::eval_l(index_t timestep, crvec h) const -> real_t { return functions->eval_l(instance.get(), timestep, h.data()); }
376auto DLControlProblem::eval_l_N(crvec h) const -> real_t { return functions->eval_l_N(instance.get(), h.data()); }
377auto 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()); }
378auto 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()); }
379auto 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()); }
380auto 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()); }
381auto 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()); }
382auto 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()); }
383auto 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()); }
384auto 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()); }
385auto DLControlProblem::get_R_work_size() const -> length_t { return functions->get_R_work_size(instance.get()); }
386auto DLControlProblem::get_S_work_size() const -> length_t { return functions->get_S_work_size(instance.get()); }
387auto DLControlProblem::eval_constr(index_t timestep, crvec x, rvec c) const -> void { return functions->eval_constr(instance.get(), timestep, x.data(), c.data()); }
388auto DLControlProblem::eval_constr_N(crvec x, rvec c) const -> void { return functions->eval_constr_N(instance.get(), x.data(), c.data()); }
389auto 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()); }
390auto 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()); }
391auto 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()); }
392auto 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()); }
393
394bool DLControlProblem::provides_get_D() const { return functions->get_D != nullptr; }
395bool DLControlProblem::provides_get_D_N() const { return functions->get_D_N != nullptr; }
396bool DLControlProblem::provides_eval_add_Q_N() const { return functions->eval_add_Q_N != nullptr; }
397bool DLControlProblem::provides_eval_add_R_prod_masked() const { return functions->eval_add_R_prod_masked != nullptr; }
398bool DLControlProblem::provides_eval_add_S_prod_masked() const { return functions->eval_add_S_prod_masked != nullptr; }
399bool DLControlProblem::provides_get_R_work_size() const { return functions->get_R_work_size != nullptr; }
400bool DLControlProblem::provides_get_S_work_size() const { return functions->get_S_work_size != nullptr; }
401bool DLControlProblem::provides_eval_constr() const { return functions->eval_constr != nullptr; }
402bool DLControlProblem::provides_eval_constr_N() const { return functions->eval_constr_N != nullptr; }
403bool DLControlProblem::provides_eval_grad_constr_prod() const { return functions->eval_grad_constr_prod != nullptr; }
404bool DLControlProblem::provides_eval_grad_constr_prod_N() const { return functions->eval_grad_constr_prod_N != nullptr; }
405bool DLControlProblem::provides_eval_add_gn_hess_constr() const { return functions->eval_add_gn_hess_constr != nullptr; }
406bool DLControlProblem::provides_eval_add_gn_hess_constr_N() const { return functions->eval_add_gn_hess_constr_N != nullptr; }
407// clang-format on
408
409#endif
410
411} // namespace alpaqa::dl
index_t eval_inactive_indices_res_lna(real_t γ, crvec x, crvec grad_ψ, rindexvec J) const
void eval_projection_multipliers(rvec y, real_t M) const
BoxConstrProblem(length_t num_variables, length_t num_constraints)
real_t eval_proximal_gradient_step(real_t γ, crvec x, crvec grad_ψ, rvec x̂, rvec p) const
void eval_projecting_difference_constraints(crvec z, rvec p) const
bool provides_get_variable_bounds() const
Only supported if the ℓ₁-regularization term is zero.
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
DLControlProblem(const std::filesystem::path &so_filename, const std::string &function_name="register_alpaqa_control_problem", alpaqa_register_arg_t user_param={}, DynamicLoadFlags dl_flags={})
Load a problem from a shared library.
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
alpaqa::Box< config_t > Box
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.
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
bool provides_eval_constraints_jacobian() const
bool provides_eval_objective() const
void eval_projection_multipliers(rvec y, real_t M) const
void eval_grad_gi(crvec x, index_t i, rvec grad_gi) const
Sparsity get_lagrangian_hessian_sparsity() const
void eval_objective_gradient(crvec x, rvec grad_fx) const
void eval_constraints(crvec x, rvec gx) const
void eval_constraints_gradient_product(crvec x, crvec y, rvec grad_gxy) const
real_t eval_augmented_lagrangian_and_gradient(crvec x, crvec y, crvec Σ, rvec grad_ψ, rvec work_n, rvec work_m) const
bool provides_eval_augmented_lagrangian() const
real_t eval_objective_and_gradient(crvec x, rvec grad_fx) const
bool provides_eval_constraints_gradient_product() const
bool provides_eval_objective_and_gradient() const
bool provides_eval_augmented_lagrangian_and_gradient() const
bool provides_eval_inactive_indices_res_lna() const
void eval_objective_gradient_and_constraints_gradient_product(crvec x, crvec y, rvec grad_f, rvec grad_gxy) const
std::shared_ptr< void > instance
Problem instance created by the registration function, including the deleter to destroy it.
bool provides_eval_objective_gradient_and_constraints_gradient_product() const
bool provides_eval_objective_and_constraints() const
real_t eval_objective(crvec x) const
DLProblem(const std::filesystem::path &so_filename, const std::string &function_name="register_alpaqa_problem", alpaqa_register_arg_t user_param={}, DynamicLoadFlags dl_flags={})
Load a problem from a shared library.
bool provides_get_lagrangian_hessian_sparsity() const
index_t eval_inactive_indices_res_lna(real_t γ, crvec x, crvec grad_ψ, rindexvec J) const
bool provides_eval_lagrangian_hessian_product() const
bool provides_get_constraints_jacobian_sparsity() const
void eval_augmented_lagrangian_hessian(crvec x, crvec y, crvec Σ, real_t scale, rvec H_values) const
void eval_augmented_lagrangian_gradient(crvec x, crvec y, crvec Σ, rvec grad_ψ, rvec work_n, rvec work_m) const
Sparsity get_constraints_jacobian_sparsity() const
bool provides_eval_constraints() const
bool provides_eval_augmented_lagrangian_hessian() const
void eval_lagrangian_gradient(crvec x, crvec y, rvec grad_L, rvec work_n) const
void eval_constraints_jacobian(crvec x, rvec J_values) const
real_t eval_objective_and_constraints(crvec x, rvec g) const
bool provides_eval_augmented_lagrangian_gradient() const
bool provides_get_variable_bounds() const
bool provides_eval_grad_gi() const
std::filesystem::path file
Path to the shared module file.
problem_functions_t * functions
Pointer to the struct of function pointers for evaluating the objective, constraints,...
bool provides_eval_augmented_lagrangian_hessian_product() const
bool provides_get_general_bounds() const
bool provides_eval_lagrangian_hessian() const
std::shared_ptr< void > handle
Handle to the shared module defining the problem.
void eval_lagrangian_hessian_product(crvec x, crvec y, real_t scale, crvec v, rvec Hv) const
ExtraFuncs extra_funcs
Dictionary of extra functions that were registered by the problem.
bool provides_get_augmented_lagrangian_hessian_sparsity() const
Sparsity get_augmented_lagrangian_hessian_sparsity() const
bool provides_eval_objective_gradient() const
real_t eval_augmented_lagrangian(crvec x, crvec y, crvec Σ, rvec ŷ) const
bool provides_eval_lagrangian_gradient() const
void eval_lagrangian_hessian(crvec x, crvec y, real_t scale, rvec H_values) const
void eval_projecting_difference_constraints(crvec z, rvec e) const
void eval_augmented_lagrangian_hessian_product(crvec x, crvec y, crvec Σ, real_t scale, crvec v, rvec Hv) const
std::string get_name() const
real_t eval_proximal_gradient_step(real_t γ, crvec x, crvec grad_ψ, rvec x̂, rvec p) 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 data pointer points to a dynamic C++ std::span of std::string_view.
Definition dl-problem.h:51
@ alpaqa_register_arg_std_any
The data pointer points to a C++ std::any object.
Definition dl-problem.h:46
uint64_t alpaqa_dl_abi_version_t
Definition dl-problem.h:29
User-provided argument that is passed to the problem registration functions.
Definition dl-problem.h:60
std::string format_abi_version(uint64_t version)
std::list< std::shared_ptr< void > > leaked_modules
Sparsity convert_sparsity(alpaqa_sparsity_t sp)
void leak_lib(std::shared_ptr< void > handle)
alpaqa_problem_register_t problem_register_t
Definition dl-problem.h:688
typename Conf::rmat rmat
Definition config.hpp:96
alpaqa_control_problem_register_t control_problem_register_t
Definition dl-problem.h:689
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
typename Conf::rvec rvec
Definition config.hpp:91
typename Conf::crvec crvec
Definition config.hpp:92
typename Conf::crindexvec crindexvec
Definition config.hpp:107
Sparsity of matrices.
Definition dl-problem.h:182
enum alpaqa_sparsity_t::@134212053240032245237223311064313221324035054276 kind