11#include <Eigen/Sparse>
12#include <casadi/core/external.hpp>
21namespace fs = std::filesystem;
23namespace casadi_loader {
63 using namespace casadi_loader;
65 casadi::Function
ffun = casadi::external(
"f",
so_name);
66 using namespace std::literals::string_literals;
68 throw std::invalid_argument(
69 "Invalid number of input arguments: got "s +
70 std::to_string(
ffun.n_in()) +
", should be 3.");
71 if (
ffun.n_out() != 1)
72 throw std::invalid_argument(
73 "Invalid number of output arguments: got "s +
74 std::to_string(
ffun.n_in()) +
", should be 1.");
84 casadi::Function
hfun = casadi::external(
"h",
so_name);
85 using namespace std::literals::string_literals;
87 throw std::invalid_argument(
88 "Invalid number of input arguments: got "s +
89 std::to_string(
hfun.n_in()) +
", should be 3.");
90 if (
hfun.n_out() != 1)
91 throw std::invalid_argument(
92 "Invalid number of output arguments: got "s +
93 std::to_string(
hfun.n_in()) +
", should be 1.");
101 casadi::Function
hfun = casadi::external(
"h_N",
so_name);
102 using namespace std::literals::string_literals;
103 if (
hfun.n_in() != 2)
104 throw std::invalid_argument(
105 "Invalid number of input arguments: got "s +
106 std::to_string(
hfun.n_in()) +
", should be 2.");
107 if (
hfun.n_out() != 1)
108 throw std::invalid_argument(
109 "Invalid number of output arguments: got "s +
110 std::to_string(
hfun.n_in()) +
", should be 1.");
117 casadi::Function
cfun = casadi::external(
"c",
so_name);
118 using namespace std::literals::string_literals;
119 if (
cfun.n_in() != 2)
120 throw std::invalid_argument(
121 "Invalid number of input arguments: got "s +
122 std::to_string(
cfun.n_in()) +
", should be 2.");
123 if (
cfun.n_out() != 1)
124 throw std::invalid_argument(
125 "Invalid number of output arguments: got "s +
126 std::to_string(
cfun.n_in()) +
", should be 1.");
133 casadi::Function
cfun = casadi::external(
"c_N",
so_name);
134 using namespace std::literals::string_literals;
135 if (
cfun.n_in() != 2)
136 throw std::invalid_argument(
137 "Invalid number of input arguments: got "s +
138 std::to_string(
cfun.n_in()) +
", should be 2.");
139 if (
cfun.n_out() != 1)
140 throw std::invalid_argument(
141 "Invalid number of output arguments: got "s +
142 std::to_string(
cfun.n_in()) +
", should be 1.");
161 impl = std::make_unique<CasADiControlFunctionsWithParam<Conf>>(
169 .h_N = std::move(h_N),
191 .c_N = std::move(c_N),
199 impl->Q.fun.sparsity_out(0).nnz(),
200 impl->Q_N.fun.sparsity_out(0).nnz(),
201 impl->gn_hess_c.fun.sparsity_out(0).nnz(),
202 impl->gn_hess_c_N.fun.sparsity_out(0).nnz(),
211template <Config Conf>
216 throw std::runtime_error(
"Unable to open bounds file \"" +
224 throw std::runtime_error(
"Unable to read " + std::string(name) +
225 " from bounds file \"" +
227 std::to_string(
line) +
"\": " + e.what());
240template <Config Conf>
243template <Config Conf>
247template <Config Conf>
263 impl->f({x.data(), u.data(), param.data()}, {
fxu.data()});
265template <Config Conf>
272 impl->jac_f({x.data(), u.data(), param.data()}, {
J_fxu.data()});
274template <Config Conf>
282 impl->grad_f_prod({x.data(), u.data(), param.data(), p.data()},
285template <Config Conf>
291 impl->h({x.data(), u.data(), param.data()}, {h.data()});
293template <Config Conf>
297 impl->h_N({x.data(), param.data()}, {h.data()});
299template <Config Conf>
303 impl->l({h.data(), param.data()}, {&l});
306template <Config Conf>
310 impl->l_N({h.data(), param.data()}, {&l});
313template <Config Conf>
316 assert(xu.size() == nx + nu);
318 assert(qr.size() == nx + nu);
319 impl->qr({xu.data(), h.data(), param.data()}, {qr.data()});
321template <Config Conf>
326 impl->q_N({x.data(), h.data(), param.data()}, {q.data()});
328template <Config Conf>
331 assert(xu.size() == nx + nu);
335 impl->Q({xu.data(), h.data(), param.data()}, {work.data()});
336 using spmat = Eigen::SparseMatrix<real_t, Eigen::ColMajor, casadi_int>;
337 using cmspmat = Eigen::Map<const spmat>;
338 auto &&sparse = impl->Q.fun.sparsity_out(0);
339 if (sparse.is_dense())
340 Q +=
cmmat{work.data(), nx, nx};
345 static_cast<length_t>(sparse.nnz()),
351template <Config Conf>
357 impl->Q_N({x.data(), h.data(), param.data()}, {work.data()});
358 auto &&sparse = impl->Q_N.fun.sparsity_out(0);
359 using spmat = Eigen::SparseMatrix<real_t, Eigen::ColMajor, casadi_int>;
360 using cmspmat = Eigen::Map<const spmat>;
361 if (sparse.is_dense())
362 Q +=
cmmat{work.data(), nx, nx};
367 static_cast<length_t>(sparse.nnz()),
374template <Config Conf>
378 auto &&sparse = impl->R.fun.sparsity_out(0);
379 assert(xu.size() == nx + nu);
386 impl->R({xu.data(), h.data(), param.data()}, {work.data()});
387 using spmat = Eigen::SparseMatrix<real_t, Eigen::ColMajor, casadi_int>;
388 using cmspmat = Eigen::Map<const spmat>;
389 if (sparse.is_dense()) {
396 static_cast<length_t>(sparse.nnz()),
405template <Config Conf>
409 auto &&sparse = impl->S.fun.sparsity_out(0);
410 assert(xu.size() == nx + nu);
416 impl->S({xu.data(), h.data(), param.data()}, {work.data()});
417 using spmat = Eigen::SparseMatrix<real_t, Eigen::ColMajor, casadi_int>;
418 using cmspmat = Eigen::Map<const spmat>;
419 using Eigen::indexing::all;
420 if (sparse.is_dense()) {
427 static_cast<length_t>(sparse.nnz()),
436template <Config Conf>
442 auto &&sparse = impl->R.fun.sparsity_out(0);
446 using spmat = Eigen::SparseMatrix<real_t, Eigen::ColMajor, casadi_int>;
447 using cmspmat = Eigen::Map<const spmat>;
448 if (sparse.is_dense()) {
449 auto R =
cmmat{work.data(), nu, nu};
455 static_cast<length_t>(sparse.nnz()),
465template <Config Conf>
470 auto &&sparse = impl->S.fun.sparsity_out(0);
474 using spmat = Eigen::SparseMatrix<real_t, Eigen::ColMajor, casadi_int>;
475 using cmspmat = Eigen::Map<const spmat>;
476 using Eigen::indexing::all;
477 if (sparse.is_dense()) {
478 auto Sᵀ =
cmmat{work.data(), nu, nx}.transpose();
484 static_cast<length_t>(sparse.nnz()),
494template <Config Conf>
496 auto &&sparse = impl->R.fun.sparsity_out(0);
497 return static_cast<length_t>(sparse.nnz());
500template <Config Conf>
502 auto &&sparse = impl->S.fun.sparsity_out(0);
503 return static_cast<length_t>(sparse.nnz());
506template <Config Conf>
512 impl->c({x.data(), param.data()}, {c.data()});
515template <Config Conf>
522 impl->grad_c_prod({x.data(), param.data(), p.data()}, {
grad_cx_p.data()});
525template <Config Conf>
529 auto &&sparse = impl->gn_hess_c.fun.sparsity_out(0);
535 impl->gn_hess_c({x.data(), param.data(),
M.data()}, {work.data()});
536 using spmat = Eigen::SparseMatrix<real_t, Eigen::ColMajor, casadi_int>;
537 using cmspmat = Eigen::Map<const spmat>;
538 if (sparse.is_dense())
544 static_cast<length_t>(sparse.nnz()),
551template <Config Conf>
557 impl->c_N({x.data(), param.data()}, {c.data()});
560template <Config Conf>
566 impl->grad_c_prod_N({x.data(), param.data(), p.data()}, {
grad_cx_p.data()});
569template <Config Conf>
572 auto &&sparse = impl->gn_hess_c.fun.sparsity_out(0);
578 impl->gn_hess_c_N({x.data(), param.data(),
M.data()}, {work.data()});
579 using spmat = Eigen::SparseMatrix<real_t, Eigen::ColMajor, casadi_int>;
580 using cmspmat = Eigen::Map<const spmat>;
581 if (sparse.is_dense())
587 static_cast<length_t>(sparse.nnz()),
void eval_jac_f(index_t timestep, crvec x, crvec u, rmat J_fxu) const
CasADiControlProblem(const std::string &so_name, length_t N)
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
CasADiControlProblem & operator=(const CasADiControlProblem &)
void eval_add_gn_hess_constr_N(crvec x, crvec M, rmat out) const
length_t get_S_work_size() const
void eval_qr(index_t timestep, crvec xu, crvec h, rvec qr) const
void eval_add_S_prod_masked(index_t timestep, crvec xu, crvec h, crindexvec mask_K, crvec v, rvec out, rvec work) const
void eval_constr_N(crvec x, rvec c) const
void load_numerical_data(const std::filesystem::path &filepath, char sep=',')
Load the numerical problem data (bounds and parameters) from a CSV file.
void eval_grad_constr_prod_N(crvec x, crvec p, rvec grad_cx_p) const
void eval_add_R_masked(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat R, rvec work) const
real_t eval_l_N(crvec h) const
real_t eval_l(index_t timestep, crvec h) const
void eval_grad_f_prod(index_t timestep, crvec x, crvec u, crvec p, rvec grad_fxu_p) const
void eval_add_gn_hess_constr(index_t timestep, crvec x, crvec M, rmat out) const
void eval_constr(index_t timestep, crvec x, rvec c) const
void eval_h(index_t timestep, crvec x, crvec u, rvec h) const
util::copyable_unique_ptr< Functions > impl
length_t get_R_work_size() const
void eval_add_S_masked(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat S, rvec work) const
void eval_q_N(crvec x, crvec h, rvec q) const
void eval_add_Q_N(crvec x, crvec h, rmat Q) const
void eval_grad_constr_prod(index_t timestep, crvec x, crvec p, rvec grad_cx_p) const
void eval_add_Q(index_t timestep, crvec xu, crvec h, rmat Q) const
void eval_h_N(crvec x, rvec h) const
Class for evaluating CasADi functions, allocating the necessary workspace storage in advance for allo...
void validate_dimensions(const std::array< casadi_dim, N_in > &dim_in={}, const std::array< casadi_dim, N_out > &dim_out={})
#define USING_ALPAQA_CONFIG(Conf)
std::pair< casadi_int, casadi_int > dim
void read_row(std::istream &is, Eigen::Ref< Eigen::VectorX< float > > v, char sep)
void sparse_matvec_add_masked_rows_cols(const SpMat &R, const CVec &v, Vec &&out, const MaskVec &mask_J, const MaskVec &mask_K)
out += R(mask_J,mask_K) * v(mask_K);
void sparse_add_masked_rows(const SpMat &S_full, Mat &&S, const MaskVec &mask)
S += S_full(mask,:)
void sparse_add_masked(const SpMat &R_full, Mat &&R, const MaskVec &mask)
R += R_full(mask,mask)
void sparse_matvec_add_transpose_masked_rows(const SpMat &S, const CVec &v, Vec &&out, const MaskVec &mask)
out += S(mask,:)ᵀ * v(mask);
typename Conf::cmmat cmmat
typename Conf::real_t real_t
typename Conf::index_t index_t
typename Conf::length_t length_t
typename Conf::crvec crvec
typename Conf::crindexvec crindexvec
CasADiFunctionEvaluator< Conf, 2+WithParam, 1 > qr
CasADiFunctionEvaluator< Conf, 2+WithParam, 1 > jac_f
CasADiFunctionEvaluator< Conf, 2+WithParam, 1 > f
CasADiFunctionEvaluator< Conf, 1+WithParam, 1 > c
CasADiFunctionEvaluator< Conf, 3+WithParam, 1 > grad_f_prod
CasADiFunctionEvaluator< Conf, 2+WithParam, 1 > R
CasADiFunctionEvaluator< Conf, 2+WithParam, 1 > grad_c_prod
CasADiFunctionEvaluator< Conf, 2+WithParam, 1 > q_N
CasADiFunctionEvaluator< Conf, 2+WithParam, 1 > grad_c_prod_N
CasADiFunctionEvaluator< Conf, 1+WithParam, 1 > h_N
CasADiFunctionEvaluator< Conf, 1+WithParam, 1 > l
static constexpr bool WithParam
CasADiFunctionEvaluator< Conf, 2+WithParam, 1 > Q
CasADiFunctionEvaluator< Conf, 2+WithParam, 1 > S
CasADiFunctionEvaluator< Conf, 2+WithParam, 1 > gn_hess_c_N
CasADiFunctionEvaluator< Conf, 2+WithParam, 1 > gn_hess_c
CasADiFunctionEvaluator< Conf, 1+WithParam, 1 > l_N
CasADiFunctionEvaluator< Conf, 2+WithParam, 1 > Q_N
CasADiFunctionEvaluator< Conf, 1+WithParam, 1 > c_N
CasADiFunctionEvaluator< Conf, 2+WithParam, 1 > h