11#if ALPAQA_WITH_EXTERNAL_CASADI
12#include <casadi/core/external.hpp>
25namespace fs = std::filesystem;
27namespace casadi_loader {
35 std::optional<CasADiFunctionEvaluator<Conf, 2, 1>>
g = std::nullopt;
36 std::optional<CasADiFunctionEvaluator<Conf, 3, 1>>
grad_g_prod =
38 std::optional<CasADiFunctionEvaluator<Conf, 2, 1>>
jac_g = std::nullopt;
39 std::optional<CasADiFunctionEvaluator<Conf, 3, 1>>
grad_L = std::nullopt;
40 std::optional<CasADiFunctionEvaluator<Conf, 5, 1>>
hess_L_prod =
42 std::optional<CasADiFunctionEvaluator<Conf, 4, 1>>
hess_L = std::nullopt;
43 std::optional<CasADiFunctionEvaluator<Conf, 6, 2>>
ψ = std::nullopt;
44 std::optional<CasADiFunctionEvaluator<Conf, 6, 2>>
ψ_grad_ψ = std::nullopt;
45 std::optional<CasADiFunctionEvaluator<Conf, 8, 1>>
hess_ψ_prod =
47 std::optional<CasADiFunctionEvaluator<Conf, 7, 1>>
hess_ψ = std::nullopt;
49 template <
class Loader>
51 {
loader(name) } -> std::same_as<casadi::Function>;
52 {
loader.format_name(name) } -> std::same_as<std::string>;
59 using namespace std::literals::string_literals;
62 "Invalid number of input arguments: got "s +
63 std::to_string(
gfun.n_in()) +
", should be 2.");
66 "Invalid number of output arguments: got "s +
67 std::to_string(
gfun.n_in()) +
", should be 0 or 1.");
68 if (
gfun.size2_in(0) != 1)
70 "First input argument should be a column vector.");
71 if (
gfun.size2_in(1) != 1)
73 "Second input argument should be a column vector.");
74 if (
gfun.n_out() == 1 &&
gfun.size2_out(0) != 1)
76 "First output argument should be a column vector.");
78 if (
gfun.n_out() == 1)
81 if (
gfun.n_out() == 0) {
84 "Function g has no outputs but m != 0");
89 return std::make_optional(std::move(
g));
94 return std::make_unique<CasADiFunctionsWithParam>(
115 loader,
"psi",
dims(
n,
p,
m,
m,
m,
m),
dims(1,
m)),
117 loader,
"psi_grad_psi",
dims(
n,
p,
m,
m,
m,
m),
dims(1,
n)),
119 loader,
"hess_psi_prod",
dims(
n,
p,
m,
m, 1,
m,
m,
n),
132template <Config Conf>
138template <Config Conf>
146 auto operator()(
const std::string &name)
const {
147#if ALPAQA_WITH_EXTERNAL_CASADI
162 this->C = Box<config_t>{impl->n};
163 this->D = Box<config_t>{impl->m};
170template <Config Conf>
173#if ALPAQA_WITH_EXTERNAL_CASADI
176 auto operator()(
const std::string &name)
const {
177 return casadi::Function::deserialize(functions.
functions.at(name));
180 return "SerializedCasADiFunctions['" + name +
"']";
188 this->C = Box<config_t>{impl->n};
189 this->D = Box<config_t>{impl->m};
191 std::ignore = functions;
192 throw std::runtime_error(
193 "This version of alpaqa was compiled without the CasADi C++ library");
197template <Config Conf>
203 auto operator()(
const std::string &name)
const {
207 return "CasADiFunctions['" + name +
"']";
215 this->C = Box<config_t>{impl->n};
216 this->D = Box<config_t>{impl->m};
219template <Config Conf>
221 const std::filesystem::path &
filepath,
char sep) {
225 throw std::runtime_error(
"Unable to open data file \"" +
234 return static_cast<void>(
data_file.get());
238 auto s = csv::read_row_std_vector<real_t>(
data_file, sep);
243 throw std::runtime_error(
"Unable to read " + std::string(name) +
244 " from data file \"" +
filepath.string() +
245 ':' + std::to_string(
line) +
250 auto read_single = [&](std::string_view name,
auto &
v) {
253 throw std::runtime_error(
"Unable to read " + std::string(name) +
254 " from data file \"" +
filepath.string() +
255 ':' + std::to_string(
line) +
'"');
265 read_single(
"penalty_alm_split", this->penalty_alm_split);
270template <Config Conf>
272template <Config Conf>
275template <Config Conf>
287 impl->f({x.data(), param.data()}, {&f});
291template <Config Conf>
294 impl->f_grad_f({x.data(), param.data()}, {&f,
grad_fx.data()});
297template <Config Conf>
300 impl->f_grad_f({x.data(), param.data()}, {&f,
grad_fx.data()});
304template <Config Conf>
309 (*impl->g)({x.data(), param.data()}, {g.data()});
314template <Config Conf>
320 if (impl->grad_g_prod)
321 (*impl->grad_g_prod)({x.data(), param.data(), y.data()}, {
gxy.data()});
326template <Config Conf>
330 impl->grad_ψ({x.data(), param.data(), y.data(), Σ.data(),
331 this->D.lowerbound.data(),
this->D.upperbound.data()},
336 eval_ψ_grad_ψ(x, y, Σ, grad_ψ, work_n, work_m);
340template <Config Conf>
345 throw std::logic_error(
"CasADiProblem::eval_ψ_grad_ψ");
347 (*impl->ψ_grad_ψ)({x.data(), param.data(), y.data(), Σ.data(),
348 this->D.lowerbound.data(), this->D.upperbound.data()},
349 {&ψ, grad_ψ.data()});
353template <Config Conf>
357 throw std::logic_error(
"CasADiProblem::eval_grad_L");
358 (*impl->grad_L)({x.data(), param.data(), y.data()}, {grad_L.data()});
361template <Config Conf>
365 throw std::logic_error(
"CasADiProblem::eval_ψ");
367 (*impl->ψ)({x.data(), param.data(), y.data(), Σ.data(),
368 this->D.lowerbound.data(), this->D.upperbound.data()},
373template <Config Conf>
378template <Config Conf>
382 using map_t =
typename SparseCSC::index_vector_map_t;
385 .cols =
static_cast<index_t>(
sp.size2()),
386 .symmetry = symmetry,
389 .order = SparseCSC::SortedRows,
393template <Config Conf>
400 if (!impl->jac_g.has_value())
402 const auto &
sp = impl->jac_g->fun.sparsity_out(0);
408template <Config Conf>
411 throw std::logic_error(
"CasADiProblem::eval_jac_g");
412 (*impl->jac_g)({x.data(), param.data()}, {
J_values.data()});
415template <Config Conf>
418 if (!impl->hess_L_prod)
419 throw std::logic_error(
"CasADiProblem::eval_ψ");
420 (*impl->hess_L_prod)({x.data(), param.data(), y.data(), &
scale,
v.data()},
424template <Config Conf>
431 if (!impl->hess_L.has_value())
433 const auto &
sp = impl->hess_L->fun.sparsity_out(0);
438template <Config Conf>
442 throw std::logic_error(
"CasADiProblem::eval_hess_L");
443 (*impl->hess_L)({x.data(), param.data(), y.data(), &
scale},
447template <Config Conf>
451 if (!impl->hess_ψ_prod)
452 throw std::logic_error(
"CasADiProblem::eval_hess_ψ_prod");
453 (*impl->hess_ψ_prod)({x.data(), param.data(), y.data(), Σ.data(), &
scale,
454 this->D.lowerbound.data(), this->D.upperbound.data(),
459template <Config Conf>
466 if (!impl->hess_ψ.has_value())
468 const auto &
sp = impl->hess_ψ->fun.sparsity_out(0);
473template <Config Conf>
477 throw std::logic_error(
"CasADiProblem::eval_hess_ψ");
478 (*impl->hess_ψ)({x.data(), param.data(), y.data(), Σ.data(), &
scale,
479 this->D.lowerbound.data(), this->D.upperbound.data()},
483template <Config Conf>
487template <Config Conf>
489 return impl->ψ.has_value();
491template <Config Conf>
493 return impl->ψ_grad_ψ.has_value();
495template <Config Conf>
497 return impl->ψ_grad_ψ.has_value();
499template <Config Conf>
501 return impl->grad_L.has_value();
503template <Config Conf>
505 return impl->jac_g.has_value();
507template <Config Conf>
509 return impl->hess_L_prod.has_value();
511template <Config Conf>
513 return impl->hess_L.has_value();
515template <Config Conf>
517 return impl->hess_ψ_prod.has_value();
519template <Config Conf>
521 return impl->hess_ψ.has_value();
524template <Config Conf>
#define BEGIN_ALPAQA_CASADI_LOADER_NAMESPACE
#define END_ALPAQA_CASADI_LOADER_NAMESPACE
Implements common problem functions for minimization problems with box constraints.
Problem definition for a CasADi problem, loaded from a DLL.
bool provides_eval_hess_L() const
std::string get_name() const
void eval_g(crvec x, rvec g) const
bool provides_eval_hess_ψ_prod() const
bool provides_eval_ψ_grad_ψ() const
void eval_jac_g(crvec x, rvec J_values) const
Sparsity get_jac_g_sparsity() const
Sparsity get_hess_ψ_sparsity() const
bool provides_eval_jac_g() const
void eval_hess_ψ(crvec x, crvec y, crvec Σ, real_t scale, rvec H_values) const
Sparsity get_hess_L_sparsity() const
void load_numerical_data(const std::filesystem::path &filepath, char sep=',')
Load the numerical problem data (bounds and parameters) from a CSV file.
CasADiProblem & operator=(const CasADiProblem &)
void eval_grad_L(crvec x, crvec y, rvec grad_L, rvec work_n) const
real_t eval_ψ(crvec x, crvec y, crvec Σ, rvec ŷ) const
bool provides_eval_hess_L_prod() const
CasADiProblem(const std::string &filename, DynamicLoadFlags dl_flags={})
Load a problem generated by CasADi (with parameters).
real_t eval_f_grad_f(crvec x, rvec grad_fx) const
void eval_grad_g_prod(crvec x, crvec y, rvec grad_gxy) const
void eval_hess_L_prod(crvec x, crvec y, real_t scale, crvec v, rvec Hv) const
bool provides_eval_grad_gi() const
void eval_grad_f(crvec x, rvec grad_fx) const
real_t eval_ψ_grad_ψ(crvec x, crvec y, crvec Σ, rvec grad_ψ, rvec work_n, rvec work_m) const
bool provides_eval_grad_L() const
bool provides_eval_grad_ψ() const
void eval_grad_gi(crvec x, index_t i, rvec grad_i) const
void eval_hess_L(crvec x, crvec y, real_t scale, rvec H_values) const
bool provides_eval_hess_ψ() const
void eval_grad_ψ(crvec x, crvec y, crvec Σ, rvec grad_ψ, rvec work_n, rvec work_m) const
bool provides_eval_ψ() const
void eval_hess_ψ_prod(crvec x, crvec y, crvec Σ, real_t scale, crvec v, rvec Hv) const
Class for evaluating CasADi functions, allocating the necessary workspace storage in advance for allo...
static void validate_dimensions(const casadi::Function &fun, const std::array< casadi_dim, N_in > &dim_in={}, const std::array< casadi_dim, N_out > &dim_out={})
#define USING_ALPAQA_CONFIG(Conf)
auto wrapped_load(Loader &&loader, const char *name, Args &&...args)
std::optional< T > try_load(Loader &&loader, const char *name, Args &&...args)
constexpr auto dims(auto... a)
std::pair< casadi_int, casadi_int > dim
auto wrap_load(Loader &&loader, const char *name, F f)
Function external(const std::string &name, const std::string &bin_name, DynamicLoadFlags dl_flags)
Load the given CasADi function from the given DLL/SO file.
void read_row(std::istream &is, Eigen::Ref< Eigen::VectorX< Eigen::Index > > v, char sep)
auto casadi_to_index(casadi_int i) -> index_t< Conf >
Symmetry
Describes the symmetry of matrices.
@ Unsymmetric
No symmetry.
@ Upper
Symmetric, upper-triangular part is stored.
typename Conf::real_t real_t
typename Conf::index_t index_t
Sparsity< Conf > convert_csc(const auto &sp, sparsity::Symmetry symmetry)
typename Conf::length_t length_t
typename Conf::cmvec cmvec
typename Conf::crvec crvec
std::map< std::string, std::string > functions
std::map< std::string, casadi::Function > functions
Flags to be passed to dlopen.
std::optional< CasADiFunctionEvaluator< Conf, 5, 1 > > hess_L_prod
std::optional< CasADiFunctionEvaluator< Conf, 7, 1 > > hess_ψ
static std::unique_ptr< CasADiFunctionsWithParam > load(Loader &&loader)
std::optional< CasADiFunctionEvaluator< Conf, 6, 2 > > ψ_grad_ψ
std::optional< CasADiFunctionEvaluator< Conf, 4, 1 > > hess_L
CasADiFunctionEvaluator< Conf, 2, 1 > f
std::optional< CasADiFunctionEvaluator< Conf, 8, 1 > > hess_ψ_prod
std::optional< CasADiFunctionEvaluator< Conf, 3, 1 > > grad_L
std::optional< CasADiFunctionEvaluator< Conf, 2, 1 > > jac_g
std::optional< CasADiFunctionEvaluator< Conf, 3, 1 > > grad_g_prod
std::optional< CasADiFunctionEvaluator< Conf, 2, 1 > > g
std::optional< CasADiFunctionEvaluator< Conf, 6, 2 > > ψ
CasADiFunctionEvaluator< Conf, 2, 2 > f_grad_f
Sparse compressed-column structure (CCS or CSC).
Stores any of the supported sparsity patterns.