25 #include "fatrop_conic_interface.hpp"
29 #include <fatrop_conic_runtime_str.h>
35 int CASADI_CONIC_FATROP_EXPORT
38 plugin->name =
"fatrop";
40 plugin->version = CASADI_VERSION;
51 const std::map<std::string, Sparsity>& st)
66 "Number of states, length N+1"}},
69 "Number of controls, length N"}},
72 "Number of non-dynamic constraints, length N+1"}},
73 {
"structure_detection",
75 "NONE | auto | manual"}},
78 "Options to be passed to fatrop"}}}
84 casadi_int struct_cnt=0;
88 for (
auto&& op : opts) {
92 }
else if (op.first==
"nx") {
95 }
else if (op.first==
"nu") {
98 }
else if (op.first==
"ng") {
101 }
else if (op.first==
"structure_detection") {
102 std::string v = op.second;
105 }
else if (v==
"manual") {
107 }
else if (v==
"none") {
110 casadi_error(
"Unknown option for structure_detection: '" + v +
"'.");
116 casadi_assert(struct_cnt==4,
117 "You must set all of N, nx, nu, ng.");
120 nxs_ = {
static_cast<int>(
nx_)};
122 ngs_ = {
static_cast<int>(
na_)};
127 "You must set structure_detection to 'manual' if you set N, nx, nu, ng.");
131 const std::vector<int>& nx =
nxs_;
132 const std::vector<int>& ng =
ngs_;
133 const std::vector<int>& nu =
nus_;
135 Sparsity lamg_csp_, lam_ulsp_, lam_uusp_, lam_xlsp_, lam_xusp_, lam_clsp_;
145 std::vector<casadi_int> A_skyline;
146 std::vector<casadi_int> A_skyline2;
147 std::vector<casadi_int> A_bottomline;
148 for (casadi_int i=0;i<AT.
size2();++i) {
149 casadi_int pivot = AT.
colind()[i+1];
150 A_bottomline.push_back(AT.
row()[AT.
colind()[i]]);
151 if (pivot>AT.
colind()[i]) {
152 A_skyline.push_back(AT.
row()[pivot-1]);
153 if (pivot>AT.
colind()[i]+1) {
154 A_skyline2.push_back(AT.
row()[pivot-2]);
156 A_skyline2.push_back(-1);
159 A_skyline.push_back(-1);
160 A_skyline2.push_back(-1);
169 casadi_int pivot = 0;
170 casadi_int start_pivot = pivot;
172 for (casadi_int i=0;i<
na_;++i) {
174 if (A_skyline[i]>pivot+1) {
175 nus_.push_back(A_skyline[i]-pivot-1);
177 }
else if (A_skyline[i]==pivot+1) {
178 if (A_skyline2[i]<start_pivot) {
189 nxs_.push_back(pivot-start_pivot+1);
190 ngs_.push_back(cg); cg=0;
191 start_pivot = A_skyline[i];
192 pivot = A_skyline[i];
195 nxs_.push_back(pivot-start_pivot+1);
198 nxs_[0] = A_skyline[0];
202 for (casadi_int i=
na_-1;i>=0;--i) {
203 if (A_bottomline[i]<start_pivot)
break;
206 ngs_.push_back(cg-cN);
210 uout() <<
"nus" <<
nus_.size() <<
"nxs" <<
nxs_.size() << std::endl;
222 casadi_message(
"Using structure: N " +
str(
N_) +
", nx " +
str(nx) +
", "
223 "nu " +
str(nu) +
", ng " +
str(ng) +
".");
233 casadi_int offset_r = 0, offset_c = 0;
234 for (casadi_int k=0;k<
N_;++k) {
235 AB_blocks.push_back({offset_r, offset_c, nx[k+1], nx[k]+nu[k]});
236 CD_blocks.push_back({offset_r+nx[k+1], offset_c, ng[k], nx[k]+nu[k]});
237 offset_c+= nx[k]+nu[k];
239 I_blocks.push_back({offset_r, offset_c, nx[k+1], nx[k+1]});
245 I_blocks.push_back({offset_r, offset_c, nx[k+1], nx[k+1]});
246 offset_r+= nx[k+1]+ng[k];
250 casadi_int offset = 0;
253 offset += e.rows*e.cols;
259 offset += e.rows*e.cols;
269 casadi_assert((
A_ + total).nnz() == total.
nnz(),
270 "HPIPM: specified structure of A does not correspond to what the interface can handle. "
271 "Structure is: N " +
str(
N_) +
", nx " +
str(nx) +
", nu " +
str(nu) +
", "
272 "ng " +
str(ng) +
".");
284 for (casadi_int k=0;k<
N_+1;++k) {
285 RSQ_blocks.push_back({offset, offset, nx[k]+nu[k], nx[k]+nu[k]});
286 offset+= nx[k]+nu[k];
293 offset += e.rows*e.cols;
309 casadi_int* iw,
double* w)
const {
314 size_t N = blocks.size();
315 std::vector<casadi_int> ret(4*N);
317 for (casadi_int i=0;i<N;++i) {
318 *r++ = blocks[i].offset_r;
319 *r++ = blocks[i].offset_c;
320 *r++ = blocks[i].rows;
321 *r++ = blocks[i].cols;
340 casadi_fatrop_conic_setup(&
p_);
348 m->add_stat(
"solver");
349 m->add_stat(
"postprocessing");
355 casadi_int*& iw,
double*& w)
const {
366 casadi_fatrop_conic_set_work(&m->d, &arg, &res, &iw, &w);
375 stats[
"iter_count"] = m->d.iter_count;
386 const std::vector<casadi_ocp_block>& blocks,
bool eye) {
388 for (
auto && b : blocks) {
390 r(
range(b.offset_r, b.offset_r+b.rows),
391 range(b.offset_c, b.offset_c+b.cols)) =
DM::eye(b.rows);
392 casadi_assert_dev(b.rows==b.cols);
394 r(
range(b.offset_r, b.offset_r+b.rows),
395 range(b.offset_c, b.offset_c+b.cols)) =
DM::zeros(b.rows, b.cols);
401 const std::vector<casadi_ocp_block>& blocks,
bool eye) {
402 casadi_int N = blocks.size();
405 for (casadi_int k=0;k<N;++k) {
408 casadi_assert_dev(blocks[k].rows==blocks[k].cols);
409 offset+=blocks[k].rows;
411 offset+=blocks[k].rows*blocks[k].cols;
417 s.
version(
"FatropConicInterface", 1);
423 s.
version(
"FatropConicInterface", 1);
426 typedef struct FatropUserData {
431 fatrop_int
get_nx(
const fatrop_int k,
void* user_data) {
432 FatropUserData* data =
static_cast<FatropUserData*
>(user_data);
433 const auto& solver = *data->solver;
434 if (k==solver.nxs_.size())
return solver.nxs_[k-1];
435 return solver.nxs_[k];
438 fatrop_int
get_nu(
const fatrop_int k,
void* user_data) {
439 FatropUserData* data =
static_cast<FatropUserData*
>(user_data);
440 const auto& solver = *data->solver;
441 return solver.nus_[k];
444 fatrop_int
get_ng(
const fatrop_int k,
void* user_data) {
445 FatropUserData* data =
static_cast<FatropUserData*
>(user_data);
446 auto d = &data->mem->d;
448 fatrop_int n_a_eq = d->a_eq_idx[k+1]-d->a_eq_idx[k];
449 fatrop_int n_x_eq = d->x_eq_idx[k+1]-d->x_eq_idx[k];
472 FatropUserData* data =
static_cast<FatropUserData*
>(user_data);
473 auto d = &data->mem->d;
474 fatrop_int n_a_ineq = d->a_ineq_idx[k+1]-d->a_ineq_idx[k];
475 fatrop_int n_x_ineq = d->x_ineq_idx[k+1]-d->x_ineq_idx[k];
476 return n_a_ineq+n_x_ineq;
480 FatropUserData* data =
static_cast<FatropUserData*
>(user_data);
481 return data->solver->N_+1;
484 fatrop_int
eval_BAbt(
const double *states_kp1,
const double *inputs_k,
485 const double *states_k,
const double *stage_params_k,
486 const double *global_params, MAT *res,
const fatrop_int k,
void* user_data) {
487 FatropUserData* data =
static_cast<FatropUserData*
>(user_data);
493 blasfeo_pack_tran_dmat(p->nx[k+1], p->nx[k],
494 d->AB+p->AB_offsets[k], p->nx[k+1], res, p->nu[k], 0);
495 blasfeo_pack_tran_dmat(p->nx[k+1], p->nu[k],
496 d->AB+p->AB_offsets[k]+p->nx[k]*p->nx[k+1], p->nx[k+1], res, 0, 0);
497 blasfeo_pack_dmat(1, p->nx[k+1],
const_cast<double*
>(d_qp->
lba+p->AB[k].offset_r),
498 1, res, p->nx[k]+p->nu[k], 0);
501 blasfeo_allocate_dvec(p->nx[k]+p->nu[k]+1, &v);
502 blasfeo_allocate_dvec(p->nx[k+1], &r);
504 blasfeo_pack_dvec(p->nu[k],
const_cast<double*
>(inputs_k), 1, &v, 0);
505 blasfeo_pack_dvec(p->nx[k],
const_cast<double*
>(states_k), 1, &v, p->nu[k]);
506 blasfeo_pack_dvec(1, &one, 1, &v, p->nu[k]+p->nx[k]);
508 blasfeo_dgemv_t(p->nx[k]+p->nu[k]+1, p->nx[k+1], 1.0, res, 0, 0,
513 std::vector<double> mem(p->nx[k+1]);
514 blasfeo_unpack_dvec(p->nx[k+1], &r, 0,
get_ptr(mem), 1);
517 for (
int i=0;i<p->nx[k+1];++i) {
518 mem[i] -= states_kp1[i];
522 blasfeo_pack_dmat(1, p->nx[k+1],
get_ptr(mem), 1, res, p->nx[k]+p->nu[k], 0);
524 blasfeo_free_dvec(&v);
525 blasfeo_free_dvec(&r);
532 const double *inputs_k,
533 const double *states_k,
534 const double *stage_params_k,
535 const double *global_params,
537 const fatrop_int k,
void* user_data) {
538 FatropUserData* data =
static_cast<FatropUserData*
>(user_data);
540 casadi_int i, column;
546 int n_a_eq = d->a_eq_idx[k+1]-d->a_eq_idx[k];
547 int n_x_eq = d->x_eq_idx[k+1]-d->x_eq_idx[k];
548 int ng_eq = n_a_eq+n_x_eq;
550 blasfeo_dgese(p->nx[k]+p->nu[k]+1, ng_eq, 0.0, res, 0, 0);
553 for (i=d->a_eq_idx[k];i<d->a_eq_idx[k+1];++i) {
554 blasfeo_pack_tran_dmat(1, p->nx[k],
555 d->CD+p->CD_offsets[k]+(d->a_eq[i]-p->CD[k].offset_r),
556 p->CD[k].rows, res, p->nu[k], column);
557 blasfeo_pack_tran_dmat(1, p->nu[k],
558 d->CD+p->CD_offsets[k]+(d->a_eq[i]-p->CD[k].offset_r)+p->nx[k]*p->CD[k].rows,
559 p->CD[k].rows, res, 0, column);
560 double v = -d_qp->
lba[d->a_eq[i]];
561 blasfeo_pack_tran_dmat(1, 1, &v, 1, res, p->nx[k]+p->nu[k], column);
564 for (i=d->x_eq_idx[k];i<d->x_eq_idx[k+1];++i) {
565 int j = d->x_eq[i]-p->CD[k].offset_c;
571 blasfeo_pack_tran_dmat(1, 1, &one, 1, res, j, column);
572 double v = -d_qp->
lbx[d->x_eq[i]];
573 blasfeo_pack_tran_dmat(1, 1, &v, 1, res, p->nx[k]+p->nu[k], column);
579 blasfeo_allocate_dvec(p->nx[k]+p->nu[k]+1, &v);
580 blasfeo_allocate_dvec(ng_eq, &r);
582 blasfeo_pack_dvec(p->nu[k],
const_cast<double*
>(inputs_k), 1, &v, 0);
583 blasfeo_pack_dvec(p->nx[k],
const_cast<double*
>(states_k), 1, &v, p->nu[k]);
584 blasfeo_pack_dvec(1, &one, 1, &v, p->nu[k]+p->nx[k]);
586 blasfeo_dgemv_t(p->nx[k]+p->nu[k]+1, ng_eq, 1.0, res, 0, 0,
591 std::vector<double> mem(ng_eq);
592 blasfeo_unpack_dvec(ng_eq, &r, 0,
get_ptr(mem), 1);
594 blasfeo_pack_dmat(1, ng_eq,
get_ptr(mem), 1, res, p->nx[k]+p->nu[k], 0);
596 blasfeo_free_dvec(&v);
597 blasfeo_free_dvec(&r);
603 const double *inputs_k,
604 const double *states_k,
605 const double *stage_params_k,
606 const double *global_params,
608 const fatrop_int k,
void* user_data) {
609 FatropUserData* data =
static_cast<FatropUserData*
>(user_data);
611 casadi_int i, column;
618 int n_a_ineq = d->a_ineq_idx[k+1]-d->a_ineq_idx[k];
619 int n_x_ineq = d->x_ineq_idx[k+1]-d->x_ineq_idx[k];
620 int ng_ineq = n_a_ineq+n_x_ineq;
622 blasfeo_dgese(p->nx[k]+p->nu[k]+1, ng_ineq, 0.0, res, 0, 0);
625 for (i=d->a_ineq_idx[k];i<d->a_ineq_idx[k+1];++i) {
626 blasfeo_pack_tran_dmat(1, p->nx[k],
627 d->CD+p->CD_offsets[k]+(d->a_ineq[i]-p->CD[k].offset_r),
628 p->CD[k].rows, res, p->nu[k], column);
629 blasfeo_pack_tran_dmat(1, p->nu[k],
630 d->CD+p->CD_offsets[k]+(d->a_ineq[i]-p->CD[k].offset_r)+p->nx[k]*p->CD[k].rows,
631 p->CD[k].rows, res, 0, column);
632 blasfeo_pack_tran_dmat(1, 1, &zero, 1, res, p->nx[k]+p->nu[k], column);
635 for (i=d->x_ineq_idx[k];i<d->x_ineq_idx[k+1];++i) {
636 int j = d->x_ineq[i]-p->CD[k].offset_c;
642 blasfeo_pack_tran_dmat(1, 1, &one, 1, res, j, column);
643 blasfeo_pack_tran_dmat(1, 1, &zero, 1, res, p->nx[k]+p->nu[k], column);
649 blasfeo_allocate_dvec(p->nx[k]+p->nu[k]+1, &v);
650 blasfeo_allocate_dvec(ng_ineq, &r);
652 blasfeo_pack_dvec(p->nu[k],
const_cast<double*
>(inputs_k), 1, &v, 0);
653 blasfeo_pack_dvec(p->nx[k],
const_cast<double*
>(states_k), 1, &v, p->nu[k]);
654 blasfeo_pack_dvec(1, &zero, 1, &v, p->nu[k]+p->nx[k]);
656 blasfeo_dgemv_t(p->nx[k]+p->nu[k]+1, ng_ineq, 1.0, res, 0, 0,
660 std::vector<double> mem(ng_ineq);
661 blasfeo_unpack_dvec(ng_ineq, &r, 0,
get_ptr(mem), 1);
663 blasfeo_pack_dmat(1, ng_ineq,
get_ptr(mem), 1, res, p->nx[k]+p->nu[k], 0);
665 blasfeo_free_dvec(&v);
666 blasfeo_free_dvec(&r);
672 const double *objective_scale,
673 const double *inputs_k,
674 const double *states_k,
675 const double *lam_dyn_k,
676 const double *lam_eq_k,
677 const double *lam_eq_ineq_k,
678 const double *stage_params_k,
679 const double *global_params,
681 const fatrop_int k,
void* user_data) {
682 FatropUserData* data =
static_cast<FatropUserData*
>(user_data);
684 const auto& solver = *data->solver;
685 casadi_assert_dev(*objective_scale==1);
690 int n = p->nx[k]+p->nu[k];
691 blasfeo_pack_dmat(p->nx[k], p->nx[k],
692 d->RSQ+p->RSQ_offsets[k], n, res, p->nu[k], p->nu[k]);
693 blasfeo_pack_dmat(p->nu[k], p->nu[k],
694 d->RSQ+p->RSQ_offsets[k]+p->nx[k]*n+p->nx[k], n, res, 0, 0);
695 blasfeo_pack_dmat(p->nu[k], p->nx[k],
696 d->RSQ+p->RSQ_offsets[k]+p->nx[k], n, res, 0, p->nu[k]);
697 blasfeo_pack_dmat(p->nx[k], p->nu[k],
698 d->RSQ+p->RSQ_offsets[k]+p->nx[k]*n, n, res, p->nu[k], 0);
700 blasfeo_pack_dmat(1, p->nx[k],
const_cast<double*
>(d_qp->
g+p->RSQ[k].offset_r),
701 1, res, p->nu[k]+p->nx[k], p->nu[k]);
702 blasfeo_pack_dmat(1, p->nu[k],
const_cast<double*
>(d_qp->
g+p->RSQ[k].offset_r+p->nx[k]),
703 1, res, p->nu[k]+p->nx[k], 0);
706 blasfeo_allocate_dvec(n, &v);
707 blasfeo_allocate_dvec(p->nx[k]+p->nu[k], &r);
709 blasfeo_pack_dvec(p->nu[k],
const_cast<double*
>(inputs_k), 1, &v, 0);
710 blasfeo_pack_dvec(p->nx[k],
const_cast<double*
>(states_k), 1, &v, p->nu[k]);
712 blasfeo_pack_dvec(p->nx[k],
const_cast<double*
>(d_qp->
g+p->RSQ[k].offset_r),
714 blasfeo_pack_dvec(p->nu[k],
const_cast<double*
>(d_qp->
g+p->RSQ[k].offset_r+p->nx[k]),
717 blasfeo_dgemv_n(n, n, 1.0, res, 0, 0,
722 int n_a_eq = d->a_eq_idx[k+1]-d->a_eq_idx[k];
723 int n_x_eq = d->x_eq_idx[k+1]-d->x_eq_idx[k];
724 int ng_eq = n_a_eq+n_x_eq;
725 int n_a_ineq = d->a_ineq_idx[k+1]-d->a_ineq_idx[k];
726 int n_x_ineq = d->x_ineq_idx[k+1]-d->x_ineq_idx[k];
727 int ng_ineq = n_a_ineq+n_x_ineq;
729 bool last_k = k==solver.N_;
731 blasfeo_dvec lam_dyn, lam_g, lam_g_ineq;
732 blasfeo_dmat BAbtk, Ggtk, Ggt_ineqk;
734 blasfeo_allocate_dvec(p->nx[k+1], &lam_dyn);
735 blasfeo_allocate_dvec(ng_eq, &lam_g);
736 blasfeo_allocate_dvec(ng_ineq, &lam_g_ineq);
738 blasfeo_allocate_dmat(p->nx[k]+p->nu[k]+1, p->nx[k+1], &BAbtk);
739 blasfeo_allocate_dmat(p->nx[k]+p->nu[k]+1, ng_eq, &Ggtk);
740 blasfeo_allocate_dmat(p->nx[k]+p->nu[k]+1, ng_ineq, &Ggt_ineqk);
743 eval_BAbt(0, inputs_k, states_k, stage_params_k, global_params, &BAbtk, k, user_data);
744 eval_Ggt(inputs_k, states_k, stage_params_k, global_params, &Ggtk, k, user_data);
745 eval_Ggt_ineq(inputs_k, states_k, stage_params_k, global_params, &Ggt_ineqk, k, user_data);
748 blasfeo_pack_dvec(p->nx[k+1],
const_cast<double*
>(lam_dyn_k), 1, &lam_dyn, 0);
749 blasfeo_pack_dvec(ng_eq,
const_cast<double*
>(lam_eq_k), 1, &lam_g, 0);
750 blasfeo_pack_dvec(ng_ineq,
const_cast<double*
>(lam_eq_ineq_k), 1, &lam_g_ineq, 0);
753 blasfeo_dgemv_n(p->nx[k]+p->nu[k], p->nx[k+1], 1.0, &BAbtk, 0, 0,
758 blasfeo_dgemv_n(p->nx[k]+p->nu[k], ng_eq, 1.0, &Ggtk, 0, 0,
763 blasfeo_dgemv_n(p->nx[k]+p->nu[k], ng_ineq, 1.0, &Ggt_ineqk, 0, 0,
768 std::vector<double> mem(p->nx[k]+p->nu[k]);
769 blasfeo_unpack_dvec(p->nx[k]+p->nu[k], &r, 0,
get_ptr(mem), 1);
771 blasfeo_pack_dmat(1, p->nx[k]+p->nu[k],
const_cast<double*
>(
get_ptr(mem)),
772 1, res, p->nu[k]+p->nx[k], 0);
776 blasfeo_free_dmat(&BAbtk);
777 blasfeo_free_dmat(&Ggtk);
778 blasfeo_free_dmat(&Ggt_ineqk);
779 blasfeo_free_dvec(&r);
781 blasfeo_free_dvec(&lam_dyn);
782 blasfeo_free_dvec(&lam_g);
783 blasfeo_free_dvec(&lam_g_ineq);
784 blasfeo_free_dvec(&v);
790 const double *states_kp1,
791 const double *inputs_k,
792 const double *states_k,
793 const double *stage_params_k,
794 const double *global_params,
796 const fatrop_int k,
void* user_data) {
797 FatropUserData* data =
static_cast<FatropUserData*
>(user_data);
803 blasfeo_allocate_dmat(p->nx[k]+p->nu[k]+1, p->nx[k+1], &BAbtk);
804 eval_BAbt(states_kp1, inputs_k, states_k, stage_params_k, global_params, &BAbtk, k, user_data);
805 blasfeo_unpack_dmat(1, p->nx[k+1], &BAbtk, p->nx[k]+p->nu[k], 0, res, 1);
806 blasfeo_free_dmat(&BAbtk);
813 const double *states_k,
814 const double *inputs_k,
815 const double *stage_params_k,
816 const double *global_params,
818 const fatrop_int k,
void* user_data) {
819 FatropUserData* data =
static_cast<FatropUserData*
>(user_data);
825 int n_a_eq = d->a_eq_idx[k+1]-d->a_eq_idx[k];
826 int n_x_eq = d->x_eq_idx[k+1]-d->x_eq_idx[k];
827 int ng_eq = n_a_eq+n_x_eq;
830 blasfeo_allocate_dmat(p->nx[k]+p->nu[k]+1, ng_eq, &Ggtk);
831 eval_Ggt(states_k, inputs_k, stage_params_k, global_params, &Ggtk, k, user_data);
832 blasfeo_unpack_dmat(1, ng_eq, &Ggtk, p->nx[k]+p->nu[k], 0, res, 1);
833 blasfeo_free_dmat(&Ggtk);
839 const double *states_k,
840 const double *inputs_k,
841 const double *stage_params_k,
842 const double *global_params,
844 const fatrop_int k,
void* user_data) {
845 FatropUserData* data =
static_cast<FatropUserData*
>(user_data);
850 int n_a_ineq = d->a_ineq_idx[k+1]-d->a_ineq_idx[k];
851 int n_x_ineq = d->x_ineq_idx[k+1]-d->x_ineq_idx[k];
852 int ng_ineq = n_a_ineq+n_x_ineq;
856 blasfeo_allocate_dmat(p->nx[k]+p->nu[k]+1, ng_ineq, &Ggtk);
857 eval_Ggt_ineq(states_k, inputs_k, stage_params_k, global_params, &Ggtk, k, user_data);
858 blasfeo_unpack_dmat(1, ng_ineq, &Ggtk, p->nx[k]+p->nu[k], 0, res, 1);
859 blasfeo_free_dmat(&Ggtk);
865 const double *objective_scale,
866 const double *inputs_k,
867 const double *states_k,
868 const double *stage_params_k,
869 const double *global_params,
871 const fatrop_int k,
void* user_data) {
872 FatropUserData* data =
static_cast<FatropUserData*
>(user_data);
875 casadi_assert_dev(*objective_scale==1);
879 blasfeo_dmat RSQrqtk;
881 int n = p->nx[k]+p->nu[k];
884 blasfeo_allocate_dmat(n, n, &RSQrqtk);
885 blasfeo_allocate_dvec(n, &v);
886 blasfeo_allocate_dvec(n, &r);
887 blasfeo_pack_dmat(p->nx[k], p->nx[k], d->RSQ+p->RSQ_offsets[k],
888 n, &RSQrqtk, p->nu[k], p->nu[k]);
889 blasfeo_pack_dmat(p->nu[k], p->nu[k], d->RSQ+p->RSQ_offsets[k]+p->nx[k]*n+p->nx[k],
891 blasfeo_pack_dmat(p->nu[k], p->nx[k], d->RSQ+p->RSQ_offsets[k]+p->nx[k],
892 n, &RSQrqtk, 0, p->nu[k]);
893 blasfeo_pack_dmat(p->nx[k], p->nu[k], d->RSQ+p->RSQ_offsets[k]+p->nx[k]*n,
894 n, &RSQrqtk, p->nu[k], 0);
897 blasfeo_pack_dvec(p->nu[k],
const_cast<double*
>(inputs_k), 1, &v, 0);
898 blasfeo_pack_dvec(p->nx[k],
const_cast<double*
>(states_k), 1, &v, p->nu[k]);
900 blasfeo_pack_dvec(p->nx[k],
const_cast<double*
>(d_qp->
g+p->RSQ[k].offset_r), 1, &r, p->nu[k]);
901 blasfeo_pack_dvec(p->nu[k],
const_cast<double*
>(d_qp->
g+p->RSQ[k].offset_r+p->nx[k]), 1, &r, 0);
903 blasfeo_dgemv_n(n, n, 1.0, &RSQrqtk, 0, 0,
908 blasfeo_unpack_dvec(n, &r, 0, res, 1);
910 blasfeo_free_dmat(&RSQrqtk);
911 blasfeo_free_dvec(&v);
912 blasfeo_free_dvec(&r);
918 const double *objective_scale,
919 const double *inputs_k,
920 const double *states_k,
921 const double *stage_params_k,
922 const double *global_params,
924 const fatrop_int k,
void* user_data) {
925 FatropUserData* data =
static_cast<FatropUserData*
>(user_data);
928 casadi_assert_dev(*objective_scale==1);
932 blasfeo_dmat RSQrqtk;
934 int n = p->nx[k]+p->nu[k];
937 blasfeo_allocate_dmat(n, n, &RSQrqtk);
938 blasfeo_allocate_dvec(n, &v);
939 blasfeo_allocate_dvec(n, &r);
940 blasfeo_pack_dmat(p->nx[k], p->nx[k], d->RSQ+p->RSQ_offsets[k],
941 n, &RSQrqtk, p->nu[k], p->nu[k]);
942 blasfeo_pack_dmat(p->nu[k], p->nu[k], d->RSQ+p->RSQ_offsets[k]+p->nx[k]*n+p->nx[k],
944 blasfeo_pack_dmat(p->nu[k], p->nx[k], d->RSQ+p->RSQ_offsets[k]+p->nx[k],
945 n, &RSQrqtk, 0, p->nu[k]);
946 blasfeo_pack_dmat(p->nx[k], p->nu[k], d->RSQ+p->RSQ_offsets[k]+p->nx[k]*n,
947 n, &RSQrqtk, p->nu[k], 0);
950 blasfeo_pack_dvec(p->nu[k],
const_cast<double*
>(inputs_k), 1, &v, 0);
951 blasfeo_pack_dvec(p->nx[k],
const_cast<double*
>(states_k), 1, &v, p->nu[k]);
953 blasfeo_dgemv_n(n, n, 1.0, &RSQrqtk, 0, 0,
960 blasfeo_pack_dvec(p->nx[k],
const_cast<double*
>(d_qp->
g+p->RSQ[k].offset_r),
962 blasfeo_pack_dvec(p->nu[k],
const_cast<double*
>(d_qp->
g+p->RSQ[k].offset_r+p->nx[k]),
967 blasfeo_free_dmat(&RSQrqtk);
968 blasfeo_free_dvec(&v);
969 blasfeo_free_dvec(&r);
976 fatrop_int
get_bounds(
double *lower,
double *upper,
const fatrop_int k,
void* user_data) {
977 FatropUserData* data =
static_cast<FatropUserData*
>(user_data);
984 for (i=d->a_ineq_idx[k];i<d->a_ineq_idx[k+1];++i) {
985 lower[column] = d_qp->
lba[d->a_ineq[i]];
986 upper[column] = d_qp->
uba[d->a_ineq[i]];
990 for (i=d->x_ineq_idx[k];i<d->x_ineq_idx[k+1];++i) {
991 lower[column] = d_qp->
lbx[d->x_ineq[i]];
992 upper[column] = d_qp->
ubx[d->x_ineq[i]];
1004 FatropUserData* data =
static_cast<FatropUserData*
>(user_data);
1015 FatropUserData* data =
static_cast<FatropUserData*
>(user_data);
1020 casadi_copy(d_qp->
x0+p->CD[k].offset_c+p->nx[k], p->nu[k], uk);
1029 const double* primal_data,
const double* lam_data,
1030 const double* stageparams_p,
const double* globalparams_p,
1031 MAT * RSQrqt_p,
const FatropOcpCDims* s,
void* user_data) {
1036 const double* stageparams_p,
const double* globalparams_p,
1037 MAT* BAbt_p, MAT* Ggt_p, MAT* Ggt_ineq_p,
const FatropOcpCDims* s,
void* user_data) {
1042 const double* stageparams_p,
const double* globalparams_p,
1043 double* cv_p,
const FatropOcpCDims* s,
void* user_data) {
1048 const double* stageparams_p,
const double* globalparams_p,
1049 double* grad_p,
const FatropOcpCDims* s,
void* user_data) {
1054 const double* stageparams_p,
const double* globalparams_p,
1055 double* res,
const FatropOcpCDims* s,
void* user_data) {
1061 solve(
const double** arg,
double** res, casadi_int* iw,
double* w,
void* mem)
const {
1065 casadi_fatrop_conic_solve(&m->d, arg, res, iw, w);
1068 m->fstats.at(
"solver").tic();
1070 FatropOcpCInterface ocp_interface;
1071 ocp_interface.get_nx =
get_nx;
1072 ocp_interface.get_nu =
get_nu;
1073 ocp_interface.get_ng =
get_ng;
1084 ocp_interface.eval_b =
eval_b;
1085 ocp_interface.eval_g =
eval_g;
1087 ocp_interface.eval_rq =
eval_rq;
1088 ocp_interface.eval_L =
eval_L;
1098 FatropUserData user_data;
1099 user_data.solver =
this;
1102 ocp_interface.user_data = &user_data;
1104 uout() <<
"ocp_interface" << ocp_interface.get_horizon_length << std::endl;
1107 FatropOcpCSolver* s = fatrop_ocp_c_create(&ocp_interface, 0, 0);
1109 int ret = fatrop_ocp_c_solve(s);
1111 uout() <<
"ret" << ret << std::endl;
1114 m->d_qp.success =
false;
1115 m->d.return_status =
"failed";
1120 const blasfeo_dvec* primal = fatrop_ocp_c_get_primal(s);
1122 const blasfeo_dvec* dual = fatrop_ocp_c_get_dual(s);
1129 casadi_int offset_fatrop = 0;
1130 casadi_int offset_casadi = 0;
1131 for (
int k=0;k<
N_+1;++k) {
1132 blasfeo_unpack_dvec(p->nu[k],
const_cast<blasfeo_dvec*
>(primal),
1133 offset_fatrop, d_qp->
x+offset_casadi+p->nx[k], 1);
1134 offset_fatrop += p->nu[k];
1135 blasfeo_unpack_dvec(p->nx[k],
const_cast<blasfeo_dvec*
>(primal),
1136 offset_fatrop, d_qp->
x+offset_casadi, 1);
1137 offset_fatrop += p->nx[k];
1138 offset_casadi += p->nx[k]+p->nu[k];
1141 blasfeo_print_dvec(offset_casadi,
const_cast<blasfeo_dvec*
>(primal), 0);
1143 m->d_qp.success =
true;
1145 m->d.return_status =
"solved";
1147 std::vector<double> dualv(
nx_+
na_);
1148 blasfeo_unpack_dvec(
nx_+
na_,
const_cast<blasfeo_dvec*
>(dual), 0,
get_ptr(dualv), 1);
1153 for (
int k=0;k<
N_+1;++k) {
1154 for (casadi_int i=d->a_eq_idx[k];i<d->a_eq_idx[k+1];++i) {
1155 d_qp->
lam_a[d->a_eq[i]] = dualv[offset_fatrop++];
1157 for (casadi_int i=d->x_eq_idx[k];i<d->x_eq_idx[k+1];++i) {
1158 d_qp->
lam_x[d->x_eq[i]] = dualv[offset_fatrop++];
1162 for (
int k=0;k<
N_;++k) {
1163 for (casadi_int i=0;i<p->nx[k];++i) {
1168 for (
int k=0;k<
N_+1;++k) {
1169 for (casadi_int i=d->a_ineq_idx[k];i<d->a_ineq_idx[k+1];++i) {
1170 d_qp->
lam_a[d->a_ineq[i]] = dualv[offset_fatrop++];
1172 for (casadi_int i=d->x_ineq_idx[k];i<d->x_ineq_idx[k+1];++i) {
1173 d_qp->
lam_x[d->x_ineq[i]] = dualv[offset_fatrop++];
1181 m->fstats.at(
"solver").toc();
1188 fatrop_ocp_c_destroy(s);
static const Options options_
Options.
casadi_int nx_
Number of decision variables.
int init_mem(void *mem) const override
Initalize memory block.
casadi_int na_
The number of constraints (counting both equality and inequality) == A.size1()
void init(const Dict &opts) override
Initialize.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const override
Set the (persistent) work vectors.
Dict get_stats(void *mem) const override
Get all statistics.
casadi_qp_prob< double > p_qp_
Helper class for Serialization.
void version(const std::string &name, int v)
'fatrop' plugin for Conic
FatropConicInterface()
Constructor.
static const std::string meta_doc
A documentation string.
std::vector< casadi_ocp_block > CD_blocks
std::vector< casadi_ocp_block > AB_blocks
std::vector< casadi_int > CD_offsets_
int solve(const double **arg, double **res, casadi_int *iw, double *w, void *mem) const override
Evaluate numerically.
casadi_fatrop_conic_prob< double > p_
structure_detection structure_detection_
std::vector< casadi_int > AB_offsets_
void init(const Dict &opts) override
Initialize.
Dict get_stats(void *mem) const override
Get all statistics.
static Sparsity blocksparsity(casadi_int rows, casadi_int cols, const std::vector< casadi_ocp_block > &blocks, bool eye=false)
static const Options options_
Options.
~FatropConicInterface() override
Destructor.
static Conic * creator(const std::string &name, const std::map< std::string, Sparsity > &st)
Create a new QP Solver.
void set_fatrop_conic_prob()
void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const override
Set the (persistent) work vectors.
std::vector< casadi_ocp_block > RSQ_blocks
static void blockptr(std::vector< double * > &vs, std::vector< double > &v, const std::vector< casadi_ocp_block > &blocks, bool eye=false)
void set_temp(void *mem, const double **arg, double **res, casadi_int *iw, double *w) const override
Set the (temporary) work vectors.
int init_mem(void *mem) const override
Initalize memory block.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
std::vector< casadi_int > RSQ_offsets_
std::vector< casadi_ocp_block > I_blocks
void alloc_iw(size_t sz_iw, bool persistent=false)
Ensure required length of iw field.
void alloc_res(size_t sz_res, bool persistent=false)
Ensure required length of res field.
void alloc_arg(size_t sz_arg, bool persistent=false)
Ensure required length of arg field.
size_t sz_res() const
Get required length of res field.
size_t sz_w() const
Get required length of w field.
void alloc_w(size_t sz_w, bool persistent=false)
Ensure required length of w field.
size_t sz_arg() const
Get required length of arg field.
size_t sz_iw() const
Get required length of iw field.
static MatType zeros(casadi_int nrow=1, casadi_int ncol=1)
Create a dense matrix or a matrix with specified sparsity with all entries zero.
const Sparsity & sparsity() const
Const access the sparsity - reference to data member.
static Matrix< double > eye(casadi_int n)
create an n-by-n identity matrix
static void registerPlugin(const Plugin &plugin, bool needs_lock=true)
Register an integrator in the factory.
bool verbose_
Verbose printout.
void clear_mem()
Clear all memory (called from destructor)
Helper class for Serialization.
void version(const std::string &name, int v)
Sparsity T() const
Transpose the matrix.
casadi_int nnz() const
Get the number of (structural) non-zeros.
casadi_int size2() const
Get the number of columns.
const casadi_int * row() const
Get a reference to row-vector,.
const casadi_int * colind() const
Get a reference to the colindex of all column element (see class description)
void CASADI_CONIC_FATROP_EXPORT casadi_load_conic_fatrop()
void dummy_signal(void *user_data)
std::vector< casadi_int > range(casadi_int start, casadi_int stop, casadi_int step, casadi_int len)
Range function.
fatrop_int get_initial_uk(double *uk, const fatrop_int k, void *user_data)
fatrop_int get_horizon_length(void *user_data)
std::vector< casadi_int > fatrop_blocks_pack(const std::vector< casadi_ocp_block > &blocks)
fatrop_int full_eval_constr_jac(const double *primal_data, const double *stageparams_p, const double *globalparams_p, MAT *BAbt_p, MAT *Ggt_p, MAT *Ggt_ineq_p, const FatropOcpCDims *s, void *user_data)
fatrop_int get_nu(const fatrop_int k, void *user_data)
fatrop_int get_ng_ineq(const fatrop_int k, void *user_data)
fatrop_int eval_BAbt(const double *states_kp1, const double *inputs_k, const double *states_k, const double *stage_params_k, const double *global_params, MAT *res, const fatrop_int k, void *user_data)
fatrop_int get_n_global_params(void *user_data)
void casadi_copy(const T1 *x, casadi_int n, T1 *y)
COPY: y <-x.
fatrop_int full_eval_lag_hess(double objective_scale, const double *primal_data, const double *lam_data, const double *stageparams_p, const double *globalparams_p, MAT *RSQrqt_p, const FatropOcpCDims *s, void *user_data)
fatrop_int eval_RSQrqt(const double *objective_scale, const double *inputs_k, const double *states_k, const double *lam_dyn_k, const double *lam_eq_k, const double *lam_eq_ineq_k, const double *stage_params_k, const double *global_params, MAT *res, const fatrop_int k, void *user_data)
fatrop_int eval_Ggt(const double *inputs_k, const double *states_k, const double *stage_params_k, const double *global_params, MAT *res, const fatrop_int k, void *user_data)
fatrop_int eval_gineq(const double *states_k, const double *inputs_k, const double *stage_params_k, const double *global_params, double *res, const fatrop_int k, void *user_data)
fatrop_int eval_L(const double *objective_scale, const double *inputs_k, const double *states_k, const double *stage_params_k, const double *global_params, double *res, const fatrop_int k, void *user_data)
std::string str(const T &v)
String representation, any type.
fatrop_int full_eval_obj(double objective_scale, const double *primal_data, const double *stageparams_p, const double *globalparams_p, double *res, const FatropOcpCDims *s, void *user_data)
fatrop_int get_ng(const fatrop_int k, void *user_data)
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
fatrop_int full_eval_contr_viol(const double *primal_data, const double *stageparams_p, const double *globalparams_p, double *cv_p, const FatropOcpCDims *s, void *user_data)
fatrop_int eval_Ggt_ineq(const double *inputs_k, const double *states_k, const double *stage_params_k, const double *global_params, MAT *res, const fatrop_int k, void *user_data)
fatrop_int eval_b(const double *states_kp1, const double *inputs_k, const double *states_k, const double *stage_params_k, const double *global_params, double *res, const fatrop_int k, void *user_data)
fatrop_int full_eval_obj_grad(double objective_scale, const double *primal_data, const double *stageparams_p, const double *globalparams_p, double *grad_p, const FatropOcpCDims *s, void *user_data)
int CASADI_CONIC_FATROP_EXPORT casadi_register_conic_fatrop(Conic::Plugin *plugin)
fatrop_int eval_rq(const double *objective_scale, const double *inputs_k, const double *states_k, const double *stage_params_k, const double *global_params, double *res, const fatrop_int k, void *user_data)
static double blasfeo_ddot(casadi_int n, const double *x, const double *y)
T * get_ptr(std::vector< T > &v)
Get a pointer to the data contained in the vector.
fatrop_int get_nx(const fatrop_int k, void *user_data)
fatrop_int eval_g(const double *states_k, const double *inputs_k, const double *stage_params_k, const double *global_params, double *res, const fatrop_int k, void *user_data)
fatrop_int get_default_global_params(double *global_params, void *user_data)
fatrop_int get_n_stage_params(const fatrop_int k, void *user_data)
fatrop_int get_initial_xk(double *xk, const fatrop_int k, void *user_data)
fatrop_int get_default_stage_params(double *stage_params, const fatrop_int k, void *user_data)
fatrop_int get_bounds(double *lower, double *upper, const fatrop_int k, void *user_data)
casadi_fatrop_conic_data< double > d
FatropConicMemory()
Constructor.
~FatropConicMemory()
Destructor.
Options metadata for a class.
void add_stat(const std::string &s)
const char * return_status
const casadi_int * AB_offsets
const casadi_int * RSQ_offsets
const casadi_int * CD_offsets
const casadi_qp_prob< T1 > * qp