fatrop_conic_interface.cpp
1 /*
2  * This file is part of CasADi.
3  *
4  * CasADi -- A symbolic framework for dynamic optimization.
5  * Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl,
6  * KU Leuven. All rights reserved.
7  * Copyright (C) 2011-2014 Greg Horn
8  *
9  * CasADi is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 3 of the License, or (at your option) any later version.
13  *
14  * CasADi is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with CasADi; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 #include "fatrop_conic_interface.hpp"
26 #include <numeric>
27 #include <cstring>
28 
29 #include <fatrop_conic_runtime_str.h>
30 
31 
32 namespace casadi {
33 
34  extern "C"
35  int CASADI_CONIC_FATROP_EXPORT
36  casadi_register_conic_fatrop(Conic::Plugin* plugin) {
37  plugin->creator = FatropConicInterface::creator;
38  plugin->name = "fatrop";
39  plugin->doc = FatropConicInterface::meta_doc.c_str();
40  plugin->version = CASADI_VERSION;
41  plugin->options = &FatropConicInterface::options_;
42  return 0;
43  }
44 
45  extern "C"
46  void CASADI_CONIC_FATROP_EXPORT casadi_load_conic_fatrop() {
48  }
49 
51  const std::map<std::string, Sparsity>& st)
52  : Conic(name, st) {
53  }
54 
56  clear_mem();
57  }
58 
60  = {{&Conic::options_},
61  {{"N",
62  {OT_INT,
63  "OCP horizon"}},
64  {"nx",
65  {OT_INTVECTOR,
66  "Number of states, length N+1"}},
67  {"nu",
68  {OT_INTVECTOR,
69  "Number of controls, length N"}},
70  {"ng",
71  {OT_INTVECTOR,
72  "Number of non-dynamic constraints, length N+1"}},
73  {"structure_detection",
74  {OT_STRING,
75  "NONE | auto | manual"}},
76  {"fatrop",
77  {OT_DICT,
78  "Options to be passed to fatrop"}}}
79  };
80 
81  void FatropConicInterface::init(const Dict& opts) {
82  Conic::init(opts);
83 
84  casadi_int struct_cnt=0;
86 
87  // Read options
88  for (auto&& op : opts) {
89  if (op.first=="N") {
90  N_ = op.second;
91  struct_cnt++;
92  } else if (op.first=="nx") {
93  nxs_ = op.second;
94  struct_cnt++;
95  } else if (op.first=="nu") {
96  nus_ = op.second;
97  struct_cnt++;
98  } else if (op.first=="ng") {
99  ngs_ = op.second;
100  struct_cnt++;
101  } else if (op.first=="structure_detection") {
102  std::string v = op.second;
103  if (v=="auto") {
105  } else if (v=="manual") {
107  } else if (v=="none") {
109  } else {
110  casadi_error("Unknown option for structure_detection: '" + v + "'.");
111  }
112  }
113  }
114 
116  casadi_assert(struct_cnt==4,
117  "You must set all of N, nx, nu, ng.");
119  N_ = 0;
120 
121  }
122 
123  if (struct_cnt>0) {
124  casadi_assert(structure_detection_ == STRUCTURE_MANUAL,
125  "You must set structure_detection to 'manual' if you set N, nx, nu, ng.");
126  }
127 
128 
129  const std::vector<int>& nx = nxs_;
130  const std::vector<int>& ng = ngs_;
131  const std::vector<int>& nu = nus_;
132 
133  Sparsity lamg_csp_, lam_ulsp_, lam_uusp_, lam_xlsp_, lam_xusp_, lam_clsp_;
134 
136  /* General strategy: look for the xk+1 diagonal part in A
137  */
138 
139  // Find the right-most column for each row in A -> A_skyline
140  // Find the second-to-right-most column -> A_skyline2
141  // Find the left-most column -> A_bottomline
142  Sparsity AT = A_.T();
143  std::vector<casadi_int> A_skyline;
144  std::vector<casadi_int> A_skyline2;
145  std::vector<casadi_int> A_bottomline;
146  for (casadi_int i=0;i<AT.size2();++i) {
147  casadi_int pivot = AT.colind()[i+1];
148  A_bottomline.push_back(AT.row()[AT.colind()[i]]);
149  if (pivot>AT.colind()[i]) {
150  A_skyline.push_back(AT.row()[pivot-1]);
151  if (pivot>AT.colind()[i]+1) {
152  A_skyline2.push_back(AT.row()[pivot-2]);
153  } else {
154  A_skyline2.push_back(-1);
155  }
156  } else {
157  A_skyline.push_back(-1);
158  A_skyline2.push_back(-1);
159  }
160  }
161 
162  /*
163  Loop over the right-most columns of A:
164  they form the diagonal part due to xk+1 in gap constraints.
165  detect when the diagonal pattern is broken -> new stage
166  */
167  casadi_int pivot = 0; // Current right-most element
168  casadi_int start_pivot = pivot; // First right-most element that started the stage
169  casadi_int cg = 0; // Counter for non-gap-closing constraints
170  for (casadi_int i=0;i<na_;++i) { // Loop over all rows
171  bool commit = false; // Set true to jump to the stage
172  if (A_skyline[i]>pivot+1) { // Jump to a diagonal in the future
173  nus_.push_back(A_skyline[i]-pivot-1); // Size of jump equals number of states
174  commit = true;
175  } else if (A_skyline[i]==pivot+1) { // Walking the diagonal
176  if (A_skyline2[i]<start_pivot) { // Free of below-diagonal entries?
177  pivot++;
178  } else {
179  nus_.push_back(0); // We cannot but conclude that we arrived at a new stage
180  commit = true;
181  }
182  } else { // non-gap-closing constraint detected
183  cg++;
184  }
185 
186  if (commit) {
187  nxs_.push_back(pivot-start_pivot+1);
188  ngs_.push_back(cg); cg=0;
189  start_pivot = A_skyline[i];
190  pivot = A_skyline[i];
191  }
192  }
193  nxs_.push_back(pivot-start_pivot+1);
194 
195  // Correction for k==0
196  nxs_[0] = A_skyline[0];
197  nus_[0] = 0;
198  ngs_.erase(ngs_.begin());
199  casadi_int cN=0;
200  for (casadi_int i=na_-1;i>=0;--i) {
201  if (A_bottomline[i]<start_pivot) break;
202  cN++;
203  }
204  ngs_.push_back(cg-cN);
205  ngs_.push_back(cN);
206 
207  N_ = nus_.size();
208  uout() << "nus" << nus_.size() << "nxs" << nxs_.size() << std::endl;
209  nus_.push_back(0);
210 
211  if (N_>1) {
212  if (nus_[0]==0 && nxs_[1]+nus_[1]==nxs_[0]) {
213  nxs_[0] = nxs_[1];
214  nus_[0] = nus_[1];
215  }
216  }
217  }
218 
219  if (verbose_) {
220  casadi_message("Using structure: N " + str(N_) + ", nx " + str(nx) + ", "
221  "nu " + str(nu) + ", ng " + str(ng) + ".");
222  }
223 
224  /* Disassemble A input into:
225  A B I
226  C D
227  A B I
228  C D
229  C
230  */
231  casadi_int offset_r = 0, offset_c = 0;
232  for (casadi_int k=0;k<N_;++k) { // Loop over blocks
233  AB_blocks.push_back({offset_r, offset_c, nx[k+1], nx[k]+nu[k]});
234  CD_blocks.push_back({offset_r+nx[k+1], offset_c, ng[k], nx[k]+nu[k]});
235  offset_c+= nx[k]+nu[k];
236  if (k+1<N_)
237  I_blocks.push_back({offset_r, offset_c, nx[k+1], nx[k+1]});
238  // TODO(jgillis) actually use these
239  // test5.py versus tesst6.py
240  // test5 changes behaviour when piping stdout to file -> memory corruption
241  // logs are ever so slightly different
242  else
243  I_blocks.push_back({offset_r, offset_c, nx[k+1], nx[k+1]});
244  offset_r+= nx[k+1]+ng[k];
245  }
246  CD_blocks.push_back({offset_r, offset_c, ng[N_], nx[N_]});
247 
248  casadi_int offset = 0;
249  AB_offsets_.push_back(0);
250  for (auto e : AB_blocks) {
251  offset += e.rows*e.cols;
252  AB_offsets_.push_back(offset);
253  }
254  offset = 0;
255  CD_offsets_.push_back(0);
256  for (auto e : CD_blocks) {
257  offset += e.rows*e.cols;
258  CD_offsets_.push_back(offset);
259  }
260 
263  Isp_ = blocksparsity(na_, nx_, I_blocks, true);
264 
265  Sparsity total = ABsp_ + CDsp_ + Isp_;
266 
267  casadi_assert((A_ + total).nnz() == total.nnz(),
268  "HPIPM: specified structure of A does not correspond to what the interface can handle. "
269  "Structure is: N " + str(N_) + ", nx " + str(nx) + ", nu " + str(nu) + ", "
270  "ng " + str(ng) + ".");
271  casadi_assert_dev(total.nnz() == ABsp_.nnz() + CDsp_.nnz() + Isp_.nnz());
272 
273  /* Disassemble H input into:
274  Q S'
275  S R
276  Q S'
277  S R
278 
279  Multiply by 2
280  */
281  offset = 0;
282  for (casadi_int k=0;k<N_+1;++k) { // Loop over blocks
283  RSQ_blocks.push_back({offset, offset, nx[k]+nu[k], nx[k]+nu[k]});
284  offset+= nx[k]+nu[k];
285  }
287 
288  offset = 0;
289  RSQ_offsets_.push_back(0);
290  for (auto e : RSQ_blocks) {
291  offset += e.rows*e.cols;
292  RSQ_offsets_.push_back(offset);
293  }
295 
296  // Allocate memory
297  casadi_int sz_arg, sz_res, sz_w, sz_iw;
298  casadi_fatrop_conic_work(&p_, &sz_arg, &sz_res, &sz_iw, &sz_w);
299 
300  alloc_arg(sz_arg, true);
301  alloc_res(sz_res, true);
302  alloc_iw(sz_iw, true);
303  alloc_w(sz_w, true);
304  }
305 
306  void FatropConicInterface::set_temp(void* mem, const double** arg, double** res,
307  casadi_int* iw, double* w) const {
308 
309  }
310 
311  std::vector<casadi_int> fatrop_blocks_pack(const std::vector<casadi_ocp_block>& blocks) {
312  size_t N = blocks.size();
313  std::vector<casadi_int> ret(4*N);
314  casadi_int* r = get_ptr(ret);
315  for (casadi_int i=0;i<N;++i) {
316  *r++ = blocks[i].offset_r;
317  *r++ = blocks[i].offset_c;
318  *r++ = blocks[i].rows;
319  *r++ = blocks[i].cols;
320  }
321  return ret;
322  }
323 
325  p_.qp = &p_qp_;
326  p_.nx = get_ptr(nxs_);
327  p_.nu = get_ptr(nus_);
328  p_.ABsp = ABsp_;
330  p_.CDsp = CDsp_;
332  p_.RSQsp = RSQsp_;
334  p_.AB = get_ptr(AB_blocks);
335  p_.CD = get_ptr(CD_blocks);
337  p_.N = N_;
338  casadi_fatrop_conic_setup(&p_);
339  }
340 
341  int FatropConicInterface::init_mem(void* mem) const {
342  if (Conic::init_mem(mem)) return 1;
343  auto m = static_cast<FatropConicMemory*>(mem);
344 
345  m->add_stat("preprocessing");
346  m->add_stat("solver");
347  m->add_stat("postprocessing");
348  return 0;
349  }
350 
352  void FatropConicInterface::set_work(void* mem, const double**& arg, double**& res,
353  casadi_int*& iw, double*& w) const {
354 
355  auto m = static_cast<FatropConicMemory*>(mem);
356 
357  Conic::set_work(mem, arg, res, iw, w);
358 
359  m->d.prob = &p_;
360  m->d.qp = &m->d_qp;
361 
362  //casadi_qp_data<double>* d_qp = m->d.qp;
363 
364  casadi_fatrop_conic_set_work(&m->d, &arg, &res, &iw, &w);
365  }
366 
367 
369  Dict stats = Conic::get_stats(mem);
370  auto m = static_cast<FatropConicMemory*>(mem);
371 
372  stats["return_status"] = m->d.return_status;
373  stats["iter_count"] = m->d.iter_count;
374  return stats;
375  }
376 
378  }
379 
381  }
382 
383  Sparsity FatropConicInterface::blocksparsity(casadi_int rows, casadi_int cols,
384  const std::vector<casadi_ocp_block>& blocks, bool eye) {
385  DM r(rows, cols);
386  for (auto && b : blocks) {
387  if (eye) {
388  r(range(b.offset_r, b.offset_r+b.rows),
389  range(b.offset_c, b.offset_c+b.cols)) = DM::eye(b.rows);
390  casadi_assert_dev(b.rows==b.cols);
391  } else {
392  r(range(b.offset_r, b.offset_r+b.rows),
393  range(b.offset_c, b.offset_c+b.cols)) = DM::zeros(b.rows, b.cols);
394  }
395  }
396  return r.sparsity();
397  }
398  void FatropConicInterface::blockptr(std::vector<double *>& vs, std::vector<double>& v,
399  const std::vector<casadi_ocp_block>& blocks, bool eye) {
400  casadi_int N = blocks.size();
401  vs.resize(N);
402  casadi_int offset=0;
403  for (casadi_int k=0;k<N;++k) {
404  vs[k] = get_ptr(v)+offset;
405  if (eye) {
406  casadi_assert_dev(blocks[k].rows==blocks[k].cols);
407  offset+=blocks[k].rows;
408  } else {
409  offset+=blocks[k].rows*blocks[k].cols;
410  }
411  }
412  }
413 
415  s.version("FatropConicInterface", 1);
416  }
417 
420 
421  s.version("FatropConicInterface", 1);
422  }
423 
424  typedef struct FatropUserData {
425  const FatropConicInterface* solver;
426  FatropConicMemory* mem;
427  } FatropUserData;
428 
429  fatrop_int get_nx(const fatrop_int k, void* user_data) {
430  FatropUserData* data = static_cast<FatropUserData*>(user_data);
431  const auto& solver = *data->solver;
432  if (k==solver.nxs_.size()) return solver.nxs_[k-1];
433  return solver.nxs_[k];
434  }
435 
436  fatrop_int get_nu(const fatrop_int k, void* user_data) {
437  FatropUserData* data = static_cast<FatropUserData*>(user_data);
438  const auto& solver = *data->solver;
439  return solver.nus_[k];
440  }
441 
442  fatrop_int get_ng(const fatrop_int k, void* user_data) {
443  FatropUserData* data = static_cast<FatropUserData*>(user_data);
444  auto d = &data->mem->d;
445  int ret;
446  fatrop_int n_a_eq = d->a_eq_idx[k+1]-d->a_eq_idx[k];
447  fatrop_int n_x_eq = d->x_eq_idx[k+1]-d->x_eq_idx[k];
448 
449  ret = n_a_eq+n_x_eq;
450  return ret;
451  }
452 
453  fatrop_int get_n_stage_params(const fatrop_int k, void* user_data) {
454  return 0;
455  }
456 
457  fatrop_int get_n_global_params(void* user_data) {
458  return 0;
459  }
460 
461  fatrop_int get_default_stage_params(double *stage_params, const fatrop_int k, void* user_data) {
462  return 0;
463  }
464 
465  fatrop_int get_default_global_params(double *global_params, void* user_data) {
466  return 0;
467  }
468 
469  fatrop_int get_ng_ineq(const fatrop_int k, void* user_data) {
470  FatropUserData* data = static_cast<FatropUserData*>(user_data);
471  auto d = &data->mem->d;
472  fatrop_int n_a_ineq = d->a_ineq_idx[k+1]-d->a_ineq_idx[k];
473  fatrop_int n_x_ineq = d->x_ineq_idx[k+1]-d->x_ineq_idx[k];
474  return n_a_ineq+n_x_ineq;
475  }
476 
477  fatrop_int get_horizon_length(void* user_data) {
478  FatropUserData* data = static_cast<FatropUserData*>(user_data);
479  return data->solver->N_+1;
480  }
481 
482  fatrop_int eval_BAbt(const double *states_kp1, const double *inputs_k,
483  const double *states_k, const double *stage_params_k,
484  const double *global_params, MAT *res, const fatrop_int k, void* user_data) {
485  FatropUserData* data = static_cast<FatropUserData*>(user_data);
486  auto m = data->mem;
487  double one = 1.0;
488  auto d = &m->d;
489  auto p = d->prob;
490  casadi_qp_data<double>* d_qp = d->qp;
491  blasfeo_pack_tran_dmat(p->nx[k+1], p->nx[k],
492  d->AB+p->AB_offsets[k], p->nx[k+1], res, p->nu[k], 0);
493  blasfeo_pack_tran_dmat(p->nx[k+1], p->nu[k],
494  d->AB+p->AB_offsets[k]+p->nx[k]*p->nx[k+1], p->nx[k+1], res, 0, 0);
495  blasfeo_pack_dmat(1, p->nx[k+1], const_cast<double*>(d_qp->lba+p->AB[k].offset_r),
496  1, res, p->nx[k]+p->nu[k], 0);
497 
498  blasfeo_dvec v, r;
499  blasfeo_allocate_dvec(p->nx[k]+p->nu[k]+1, &v);
500  blasfeo_allocate_dvec(p->nx[k+1], &r);
501  // Fill v with [u;x;1]
502  blasfeo_pack_dvec(p->nu[k], const_cast<double*>(inputs_k), 1, &v, 0);
503  blasfeo_pack_dvec(p->nx[k], const_cast<double*>(states_k), 1, &v, p->nu[k]);
504  blasfeo_pack_dvec(1, &one, 1, &v, p->nu[k]+p->nx[k]);
505 
506  blasfeo_dgemv_t(p->nx[k]+p->nu[k]+1, p->nx[k+1], 1.0, res, 0, 0,
507  &v, 0,
508  0.0, &r, 0,
509  &r, 0);
510 
511  std::vector<double> mem(p->nx[k+1]);
512  blasfeo_unpack_dvec(p->nx[k+1], &r, 0, get_ptr(mem), 1);
513 
514  if (states_kp1) {
515  for (int i=0;i<p->nx[k+1];++i) {
516  mem[i] -= states_kp1[i];
517  }
518  }
519 
520  blasfeo_pack_dmat(1, p->nx[k+1], get_ptr(mem), 1, res, p->nx[k]+p->nu[k], 0);
521 
522  blasfeo_free_dvec(&v);
523  blasfeo_free_dvec(&r);
524 
525  return 0;
526  }
527 
528 
529  fatrop_int eval_Ggt(
530  const double *inputs_k,
531  const double *states_k,
532  const double *stage_params_k,
533  const double *global_params,
534  MAT *res,
535  const fatrop_int k, void* user_data) {
536  FatropUserData* data = static_cast<FatropUserData*>(user_data);
537  auto m = data->mem;
538 casadi_int i, column;
539  double one = 1;
540  auto d = &m->d;
541  auto p = d->prob;
542  casadi_qp_data<double>* d_qp = d->qp;
543 
544  int n_a_eq = d->a_eq_idx[k+1]-d->a_eq_idx[k];
545  int n_x_eq = d->x_eq_idx[k+1]-d->x_eq_idx[k];
546  int ng_eq = n_a_eq+n_x_eq;
547 
548  blasfeo_dgese(p->nx[k]+p->nu[k]+1, ng_eq, 0.0, res, 0, 0);
549 
550  column = 0;
551  for (i=d->a_eq_idx[k];i<d->a_eq_idx[k+1];++i) {
552  blasfeo_pack_tran_dmat(1, p->nx[k],
553  d->CD+p->CD_offsets[k]+(d->a_eq[i]-p->CD[k].offset_r),
554  p->CD[k].rows, res, p->nu[k], column);
555  blasfeo_pack_tran_dmat(1, p->nu[k],
556  d->CD+p->CD_offsets[k]+(d->a_eq[i]-p->CD[k].offset_r)+p->nx[k]*p->CD[k].rows,
557  p->CD[k].rows, res, 0, column);
558  double v = -d_qp->lba[d->a_eq[i]];
559  blasfeo_pack_tran_dmat(1, 1, &v, 1, res, p->nx[k]+p->nu[k], column);
560  column++;
561  }
562  for (i=d->x_eq_idx[k];i<d->x_eq_idx[k+1];++i) {
563  int j = d->x_eq[i]-p->CD[k].offset_c;
564  if (j>=p->nx[k]) {
565  j -= p->nx[k];
566  } else {
567  j += p->nu[k];
568  }
569  blasfeo_pack_tran_dmat(1, 1, &one, 1, res, j, column);
570  double v = -d_qp->lbx[d->x_eq[i]];
571  blasfeo_pack_tran_dmat(1, 1, &v, 1, res, p->nx[k]+p->nu[k], column);
572  column++;
573  }
574 
575  // Second part
576  blasfeo_dvec v, r;
577  blasfeo_allocate_dvec(p->nx[k]+p->nu[k]+1, &v);
578  blasfeo_allocate_dvec(ng_eq, &r);
579  // Fill v with [u;x;1]
580  blasfeo_pack_dvec(p->nu[k], const_cast<double*>(inputs_k), 1, &v, 0);
581  blasfeo_pack_dvec(p->nx[k], const_cast<double*>(states_k), 1, &v, p->nu[k]);
582  blasfeo_pack_dvec(1, &one, 1, &v, p->nu[k]+p->nx[k]);
583 
584  blasfeo_dgemv_t(p->nx[k]+p->nu[k]+1, ng_eq, 1.0, res, 0, 0,
585  &v, 0,
586  0.0, &r, 0,
587  &r, 0);
588 
589  std::vector<double> mem(ng_eq);
590  blasfeo_unpack_dvec(ng_eq, &r, 0, get_ptr(mem), 1);
591 
592  blasfeo_pack_dmat(1, ng_eq, get_ptr(mem), 1, res, p->nx[k]+p->nu[k], 0);
593 
594  blasfeo_free_dvec(&v);
595  blasfeo_free_dvec(&r);
596 
597  return 0;
598  }
599 
600  fatrop_int eval_Ggt_ineq(
601  const double *inputs_k,
602  const double *states_k,
603  const double *stage_params_k,
604  const double *global_params,
605  MAT *res,
606  const fatrop_int k, void* user_data) {
607  FatropUserData* data = static_cast<FatropUserData*>(user_data);
608  auto m = data->mem;
609  casadi_int i, column;
610  double one = 1;
611  double zero = 0;
612  auto d = &m->d;
613  auto p = d->prob;
614  //casadi_qp_data<double>* d_qp = d->qp;
615 
616  int n_a_ineq = d->a_ineq_idx[k+1]-d->a_ineq_idx[k];
617  int n_x_ineq = d->x_ineq_idx[k+1]-d->x_ineq_idx[k];
618  int ng_ineq = n_a_ineq+n_x_ineq;
619 
620  blasfeo_dgese(p->nx[k]+p->nu[k]+1, ng_ineq, 0.0, res, 0, 0);
621 
622  column = 0;
623  for (i=d->a_ineq_idx[k];i<d->a_ineq_idx[k+1];++i) {
624  blasfeo_pack_tran_dmat(1, p->nx[k],
625  d->CD+p->CD_offsets[k]+(d->a_ineq[i]-p->CD[k].offset_r),
626  p->CD[k].rows, res, p->nu[k], column);
627  blasfeo_pack_tran_dmat(1, p->nu[k],
628  d->CD+p->CD_offsets[k]+(d->a_ineq[i]-p->CD[k].offset_r)+p->nx[k]*p->CD[k].rows,
629  p->CD[k].rows, res, 0, column);
630  blasfeo_pack_tran_dmat(1, 1, &zero, 1, res, p->nx[k]+p->nu[k], column);
631  column++;
632  }
633  for (i=d->x_ineq_idx[k];i<d->x_ineq_idx[k+1];++i) {
634  int j = d->x_ineq[i]-p->CD[k].offset_c;
635  if (j>=p->nx[k]) {
636  j -= p->nx[k];
637  } else {
638  j += p->nu[k];
639  }
640  blasfeo_pack_tran_dmat(1, 1, &one, 1, res, j, column);
641  blasfeo_pack_tran_dmat(1, 1, &zero, 1, res, p->nx[k]+p->nu[k], column);
642  column++;
643  }
644 
645  // Second part
646  blasfeo_dvec v, r;
647  blasfeo_allocate_dvec(p->nx[k]+p->nu[k]+1, &v);
648  blasfeo_allocate_dvec(ng_ineq, &r);
649  // Fill v with [u;x;1]
650  blasfeo_pack_dvec(p->nu[k], const_cast<double*>(inputs_k), 1, &v, 0);
651  blasfeo_pack_dvec(p->nx[k], const_cast<double*>(states_k), 1, &v, p->nu[k]);
652  blasfeo_pack_dvec(1, &zero, 1, &v, p->nu[k]+p->nx[k]);
653 
654  blasfeo_dgemv_t(p->nx[k]+p->nu[k]+1, ng_ineq, 1.0, res, 0, 0,
655  &v, 0,
656  0.0, &r, 0,
657  &r, 0);
658  std::vector<double> mem(ng_ineq);
659  blasfeo_unpack_dvec(ng_ineq, &r, 0, get_ptr(mem), 1);
660 
661  blasfeo_pack_dmat(1, ng_ineq, get_ptr(mem), 1, res, p->nx[k]+p->nu[k], 0);
662 
663  blasfeo_free_dvec(&v);
664  blasfeo_free_dvec(&r);
665 
666  return 0;
667  }
668 
669  fatrop_int eval_RSQrqt(
670  const double *objective_scale,
671  const double *inputs_k,
672  const double *states_k,
673  const double *lam_dyn_k,
674  const double *lam_eq_k,
675  const double *lam_eq_ineq_k,
676  const double *stage_params_k,
677  const double *global_params,
678  MAT *res,
679  const fatrop_int k, void* user_data) {
680  FatropUserData* data = static_cast<FatropUserData*>(user_data);
681  auto m = data->mem;
682  const auto& solver = *data->solver;
683  casadi_assert_dev(*objective_scale==1);
684 
685  auto d = &m->d;
686  auto p = d->prob;
687  casadi_qp_data<double>* d_qp = d->qp;
688  int n = p->nx[k]+p->nu[k];
689  blasfeo_pack_dmat(p->nx[k], p->nx[k],
690  d->RSQ+p->RSQ_offsets[k], n, res, p->nu[k], p->nu[k]);
691  blasfeo_pack_dmat(p->nu[k], p->nu[k],
692  d->RSQ+p->RSQ_offsets[k]+p->nx[k]*n+p->nx[k], n, res, 0, 0);
693  blasfeo_pack_dmat(p->nu[k], p->nx[k],
694  d->RSQ+p->RSQ_offsets[k]+p->nx[k], n, res, 0, p->nu[k]);
695  blasfeo_pack_dmat(p->nx[k], p->nu[k],
696  d->RSQ+p->RSQ_offsets[k]+p->nx[k]*n, n, res, p->nu[k], 0);
697 
698  blasfeo_pack_dmat(1, p->nx[k], const_cast<double*>(d_qp->g+p->RSQ[k].offset_r),
699  1, res, p->nu[k]+p->nx[k], p->nu[k]);
700  blasfeo_pack_dmat(1, p->nu[k], const_cast<double*>(d_qp->g+p->RSQ[k].offset_r+p->nx[k]),
701  1, res, p->nu[k]+p->nx[k], 0);
702 
703  blasfeo_dvec r, v;
704  blasfeo_allocate_dvec(n, &v);
705  blasfeo_allocate_dvec(p->nx[k]+p->nu[k], &r);
706  // Fill v with [u;x]
707  blasfeo_pack_dvec(p->nu[k], const_cast<double*>(inputs_k), 1, &v, 0);
708  blasfeo_pack_dvec(p->nx[k], const_cast<double*>(states_k), 1, &v, p->nu[k]);
709 
710  blasfeo_pack_dvec(p->nx[k], const_cast<double*>(d_qp->g+p->RSQ[k].offset_r),
711  1, &r, p->nu[k]);
712  blasfeo_pack_dvec(p->nu[k], const_cast<double*>(d_qp->g+p->RSQ[k].offset_r+p->nx[k]),
713  1, &r, 0);
714 
715  blasfeo_dgemv_n(n, n, 1.0, res, 0, 0,
716  &v, 0,
717  1.0, &r, 0,
718  &r, 0);
719 
720  int n_a_eq = d->a_eq_idx[k+1]-d->a_eq_idx[k];
721  int n_x_eq = d->x_eq_idx[k+1]-d->x_eq_idx[k];
722  int ng_eq = n_a_eq+n_x_eq;
723  int n_a_ineq = d->a_ineq_idx[k+1]-d->a_ineq_idx[k];
724  int n_x_ineq = d->x_ineq_idx[k+1]-d->x_ineq_idx[k];
725  int ng_ineq = n_a_ineq+n_x_ineq;
726 
727  bool last_k = k==solver.N_;
728 
729  blasfeo_dvec lam_dyn, lam_g, lam_g_ineq;
730  blasfeo_dmat BAbtk, Ggtk, Ggt_ineqk;
731  if (!last_k)
732  blasfeo_allocate_dvec(p->nx[k+1], &lam_dyn);
733  blasfeo_allocate_dvec(ng_eq, &lam_g);
734  blasfeo_allocate_dvec(ng_ineq, &lam_g_ineq);
735  if (!last_k)
736  blasfeo_allocate_dmat(p->nx[k]+p->nu[k]+1, p->nx[k+1], &BAbtk);
737  blasfeo_allocate_dmat(p->nx[k]+p->nu[k]+1, ng_eq, &Ggtk);
738  blasfeo_allocate_dmat(p->nx[k]+p->nu[k]+1, ng_ineq, &Ggt_ineqk);
739 
740  if (!last_k)
741  eval_BAbt(0, inputs_k, states_k, stage_params_k, global_params, &BAbtk, k, user_data);
742  eval_Ggt(inputs_k, states_k, stage_params_k, global_params, &Ggtk, k, user_data);
743  eval_Ggt_ineq(inputs_k, states_k, stage_params_k, global_params, &Ggt_ineqk, k, user_data);
744 
745  if (!last_k)
746  blasfeo_pack_dvec(p->nx[k+1], const_cast<double*>(lam_dyn_k), 1, &lam_dyn, 0);
747  blasfeo_pack_dvec(ng_eq, const_cast<double*>(lam_eq_k), 1, &lam_g, 0);
748  blasfeo_pack_dvec(ng_ineq, const_cast<double*>(lam_eq_ineq_k), 1, &lam_g_ineq, 0);
749 
750  if (!last_k)
751  blasfeo_dgemv_n(p->nx[k]+p->nu[k], p->nx[k+1], 1.0, &BAbtk, 0, 0,
752  &lam_dyn, 0,
753  1.0, &r, 0,
754  &r, 0);
755 
756  blasfeo_dgemv_n(p->nx[k]+p->nu[k], ng_eq, 1.0, &Ggtk, 0, 0,
757  &lam_g, 0,
758  1.0, &r, 0,
759  &r, 0);
760 
761  blasfeo_dgemv_n(p->nx[k]+p->nu[k], ng_ineq, 1.0, &Ggt_ineqk, 0, 0,
762  &lam_g_ineq, 0,
763  1.0, &r, 0,
764  &r, 0);
765 
766  std::vector<double> mem(p->nx[k]+p->nu[k]);
767  blasfeo_unpack_dvec(p->nx[k]+p->nu[k], &r, 0, get_ptr(mem), 1);
768 
769  blasfeo_pack_dmat(1, p->nx[k]+p->nu[k], const_cast<double*>(get_ptr(mem)),
770  1, res, p->nu[k]+p->nx[k], 0);
771 
772 
773  if (!last_k)
774  blasfeo_free_dmat(&BAbtk);
775  blasfeo_free_dmat(&Ggtk);
776  blasfeo_free_dmat(&Ggt_ineqk);
777  blasfeo_free_dvec(&r);
778  if (!last_k)
779  blasfeo_free_dvec(&lam_dyn);
780  blasfeo_free_dvec(&lam_g);
781  blasfeo_free_dvec(&lam_g_ineq);
782  blasfeo_free_dvec(&v);
783 
784  return 0;
785  }
786 
787  fatrop_int eval_b(
788  const double *states_kp1,
789  const double *inputs_k,
790  const double *states_k,
791  const double *stage_params_k,
792  const double *global_params,
793  double *res,
794  const fatrop_int k, void* user_data) {
795  FatropUserData* data = static_cast<FatropUserData*>(user_data);
796  auto m = data->mem;
797  auto d = &m->d;
798  auto p = d->prob;
799 
800  blasfeo_dmat BAbtk;
801  blasfeo_allocate_dmat(p->nx[k]+p->nu[k]+1, p->nx[k+1], &BAbtk);
802  eval_BAbt(states_kp1, inputs_k, states_k, stage_params_k, global_params, &BAbtk, k, user_data);
803  blasfeo_unpack_dmat(1, p->nx[k+1], &BAbtk, p->nx[k]+p->nu[k], 0, res, 1);
804  blasfeo_free_dmat(&BAbtk);
805 
806  return 0;
807 
808  }
809 
810  fatrop_int eval_g(
811  const double *states_k,
812  const double *inputs_k,
813  const double *stage_params_k,
814  const double *global_params,
815  double *res,
816  const fatrop_int k, void* user_data) {
817  FatropUserData* data = static_cast<FatropUserData*>(user_data);
818 
819  auto m = data->mem;
820  auto d = &m->d;
821  auto p = d->prob;
822 
823  int n_a_eq = d->a_eq_idx[k+1]-d->a_eq_idx[k];
824  int n_x_eq = d->x_eq_idx[k+1]-d->x_eq_idx[k];
825  int ng_eq = n_a_eq+n_x_eq;
826 
827  blasfeo_dmat Ggtk;
828  blasfeo_allocate_dmat(p->nx[k]+p->nu[k]+1, ng_eq, &Ggtk);
829  eval_Ggt(states_k, inputs_k, stage_params_k, global_params, &Ggtk, k, user_data);
830  blasfeo_unpack_dmat(1, ng_eq, &Ggtk, p->nx[k]+p->nu[k], 0, res, 1);
831  blasfeo_free_dmat(&Ggtk);
832 
833  return 0;
834  }
835 
836  fatrop_int eval_gineq(
837  const double *states_k,
838  const double *inputs_k,
839  const double *stage_params_k,
840  const double *global_params,
841  double *res,
842  const fatrop_int k, void* user_data) {
843  FatropUserData* data = static_cast<FatropUserData*>(user_data);
844  auto m = data->mem;
845  auto d = &m->d;
846  auto p = d->prob;
847 
848  int n_a_ineq = d->a_ineq_idx[k+1]-d->a_ineq_idx[k];
849  int n_x_ineq = d->x_ineq_idx[k+1]-d->x_ineq_idx[k];
850  int ng_ineq = n_a_ineq+n_x_ineq;
851 
852 
853  blasfeo_dmat Ggtk;
854  blasfeo_allocate_dmat(p->nx[k]+p->nu[k]+1, ng_ineq, &Ggtk);
855  eval_Ggt_ineq(states_k, inputs_k, stage_params_k, global_params, &Ggtk, k, user_data);
856  blasfeo_unpack_dmat(1, ng_ineq, &Ggtk, p->nx[k]+p->nu[k], 0, res, 1);
857  blasfeo_free_dmat(&Ggtk);
858 
859  return 0;
860  }
861 
862  fatrop_int eval_rq(
863  const double *objective_scale,
864  const double *inputs_k,
865  const double *states_k,
866  const double *stage_params_k,
867  const double *global_params,
868  double *res,
869  const fatrop_int k, void* user_data) {
870  FatropUserData* data = static_cast<FatropUserData*>(user_data);
871  auto m = data->mem;
872  *res = 0.0;
873  casadi_assert_dev(*objective_scale==1);
874  auto d = &m->d;
875  auto p = d->prob;
876  casadi_qp_data<double>* d_qp = d->qp;
877  blasfeo_dmat RSQrqtk;
878 
879  int n = p->nx[k]+p->nu[k];
880 
881  blasfeo_dvec v, r;
882  blasfeo_allocate_dmat(n, n, &RSQrqtk);
883  blasfeo_allocate_dvec(n, &v);
884  blasfeo_allocate_dvec(n, &r);
885  blasfeo_pack_dmat(p->nx[k], p->nx[k], d->RSQ+p->RSQ_offsets[k],
886  n, &RSQrqtk, p->nu[k], p->nu[k]);
887  blasfeo_pack_dmat(p->nu[k], p->nu[k], d->RSQ+p->RSQ_offsets[k]+p->nx[k]*n+p->nx[k],
888  n, &RSQrqtk, 0, 0);
889  blasfeo_pack_dmat(p->nu[k], p->nx[k], d->RSQ+p->RSQ_offsets[k]+p->nx[k],
890  n, &RSQrqtk, 0, p->nu[k]);
891  blasfeo_pack_dmat(p->nx[k], p->nu[k], d->RSQ+p->RSQ_offsets[k]+p->nx[k]*n,
892  n, &RSQrqtk, p->nu[k], 0);
893 
894  // Fill v with [u;x]
895  blasfeo_pack_dvec(p->nu[k], const_cast<double*>(inputs_k), 1, &v, 0);
896  blasfeo_pack_dvec(p->nx[k], const_cast<double*>(states_k), 1, &v, p->nu[k]);
897 
898  blasfeo_pack_dvec(p->nx[k], const_cast<double*>(d_qp->g+p->RSQ[k].offset_r), 1, &r, p->nu[k]);
899  blasfeo_pack_dvec(p->nu[k], const_cast<double*>(d_qp->g+p->RSQ[k].offset_r+p->nx[k]), 1, &r, 0);
900 
901  blasfeo_dgemv_n(n, n, 1.0, &RSQrqtk, 0, 0,
902  &v, 0,
903  1.0, &r, 0,
904  &r, 0);
905 
906  blasfeo_unpack_dvec(n, &r, 0, res, 1);
907 
908  blasfeo_free_dmat(&RSQrqtk);
909  blasfeo_free_dvec(&v);
910  blasfeo_free_dvec(&r);
911 
912  return 0;
913  }
914 
915  fatrop_int eval_L(
916  const double *objective_scale,
917  const double *inputs_k,
918  const double *states_k,
919  const double *stage_params_k,
920  const double *global_params,
921  double *res,
922  const fatrop_int k, void* user_data) {
923  FatropUserData* data = static_cast<FatropUserData*>(user_data);
924  auto m = data->mem;
925  *res = 0.0;
926  casadi_assert_dev(*objective_scale==1);
927  auto d = &m->d;
928  auto p = d->prob;
929  casadi_qp_data<double>* d_qp = d->qp;
930  blasfeo_dmat RSQrqtk;
931 
932  int n = p->nx[k]+p->nu[k];
933 
934  blasfeo_dvec v, r;
935  blasfeo_allocate_dmat(n, n, &RSQrqtk);
936  blasfeo_allocate_dvec(n, &v);
937  blasfeo_allocate_dvec(n, &r);
938  blasfeo_pack_dmat(p->nx[k], p->nx[k], d->RSQ+p->RSQ_offsets[k],
939  n, &RSQrqtk, p->nu[k], p->nu[k]);
940  blasfeo_pack_dmat(p->nu[k], p->nu[k], d->RSQ+p->RSQ_offsets[k]+p->nx[k]*n+p->nx[k],
941  n, &RSQrqtk, 0, 0);
942  blasfeo_pack_dmat(p->nu[k], p->nx[k], d->RSQ+p->RSQ_offsets[k]+p->nx[k],
943  n, &RSQrqtk, 0, p->nu[k]);
944  blasfeo_pack_dmat(p->nx[k], p->nu[k], d->RSQ+p->RSQ_offsets[k]+p->nx[k]*n,
945  n, &RSQrqtk, p->nu[k], 0);
946 
947  // Fill v with [u;x]
948  blasfeo_pack_dvec(p->nu[k], const_cast<double*>(inputs_k), 1, &v, 0);
949  blasfeo_pack_dvec(p->nx[k], const_cast<double*>(states_k), 1, &v, p->nu[k]);
950 
951  blasfeo_dgemv_n(n, n, 1.0, &RSQrqtk, 0, 0,
952  &v, 0,
953  0.0, &r, 0,
954  &r, 0);
955 
956  double obj = 0.5*blasfeo_ddot(n, &v, 0, &r, 0);
957 
958  blasfeo_pack_dvec(p->nx[k], const_cast<double*>(d_qp->g+p->RSQ[k].offset_r),
959  1, &r, p->nu[k]);
960  blasfeo_pack_dvec(p->nu[k], const_cast<double*>(d_qp->g+p->RSQ[k].offset_r+p->nx[k]),
961  1, &r, 0);
962 
963  obj += blasfeo_ddot(n, &v, 0, &r, 0);
964 
965  blasfeo_free_dmat(&RSQrqtk);
966  blasfeo_free_dvec(&v);
967  blasfeo_free_dvec(&r);
968  *res = obj;
969 
970  return 0;
971 
972  }
973 
974  fatrop_int get_bounds(double *lower, double *upper, const fatrop_int k, void* user_data) {
975  FatropUserData* data = static_cast<FatropUserData*>(user_data);
976  auto m = data->mem;
977  auto d = &m->d;
978  //auto p = d->prob;
979  casadi_qp_data<double>* d_qp = d->qp;
980  int i=0;
981  int column = 0;
982  for (i=d->a_ineq_idx[k];i<d->a_ineq_idx[k+1];++i) {
983  lower[column] = d_qp->lba[d->a_ineq[i]];
984  upper[column] = d_qp->uba[d->a_ineq[i]];
985  column++;
986  }
987  //int offset = d->a_ineq_idx[k+1]-d->a_ineq_idx[k];
988  for (i=d->x_ineq_idx[k];i<d->x_ineq_idx[k+1];++i) {
989  lower[column] = d_qp->lbx[d->x_ineq[i]];
990  upper[column] = d_qp->ubx[d->x_ineq[i]];
991  column++;
992  }
993 
994  //fatrop_int n_a_ineq = d->a_ineq_idx[k+1]-d->a_ineq_idx[k];
995  //fatrop_int n_x_ineq = d->x_ineq_idx[k+1]-d->x_ineq_idx[k];
996  //fatrop_int ng_ineq = n_a_ineq+n_x_ineq;
997 
998  return 0;
999  }
1000 
1001  fatrop_int get_initial_xk(double *xk, const fatrop_int k, void* user_data) {
1002  FatropUserData* data = static_cast<FatropUserData*>(user_data);
1003  auto m = data->mem;
1004  auto d = &m->d;
1005  auto p = d->prob;
1006  casadi_qp_data<double>* d_qp = d->qp;
1007  casadi_copy(d_qp->x0+p->CD[k].offset_c, p->nx[k], xk);
1008 
1009  return 0;
1010  }
1011 
1012  fatrop_int get_initial_uk(double *uk, const fatrop_int k, void* user_data) {
1013  FatropUserData* data = static_cast<FatropUserData*>(user_data);
1014  auto m = data->mem;
1015  auto d = &m->d;
1016  auto p = d->prob;
1017  casadi_qp_data<double>* d_qp = d->qp;
1018  casadi_copy(d_qp->x0+p->CD[k].offset_c+p->nx[k], p->nu[k], uk);
1019  return 0;
1020  }
1021 
1022  void dummy_signal(void* user_data) {
1023 
1024  }
1025 
1026  fatrop_int full_eval_lag_hess(double objective_scale,
1027  const double* primal_data, const double* lam_data,
1028  const double* stageparams_p, const double* globalparams_p,
1029  MAT * RSQrqt_p, const FatropOcpCDims* s, void* user_data) {
1030  return 0;
1031  }
1032 
1033  fatrop_int full_eval_constr_jac(const double* primal_data,
1034  const double* stageparams_p, const double* globalparams_p,
1035  MAT* BAbt_p, MAT* Ggt_p, MAT* Ggt_ineq_p, const FatropOcpCDims* s, void* user_data) {
1036  return 0;
1037  }
1038 
1039  fatrop_int full_eval_contr_viol(const double* primal_data,
1040  const double* stageparams_p, const double* globalparams_p,
1041  double* cv_p, const FatropOcpCDims* s, void* user_data) {
1042  return 0;
1043  }
1044 
1045  fatrop_int full_eval_obj_grad(double objective_scale, const double* primal_data,
1046  const double* stageparams_p, const double* globalparams_p,
1047  double* grad_p, const FatropOcpCDims* s, void* user_data) {
1048  return 0;
1049  }
1050 
1051  fatrop_int full_eval_obj(double objective_scale, const double* primal_data,
1052  const double* stageparams_p, const double* globalparams_p,
1053  double* res, const FatropOcpCDims* s, void* user_data) {
1054  return 0;
1055  }
1056 
1057 
1059  solve(const double** arg, double** res, casadi_int* iw, double* w, void* mem) const {
1060  auto m = static_cast<FatropConicMemory*>(mem);
1061 
1062 
1063  casadi_fatrop_conic_solve(&m->d, arg, res, iw, w);
1064 
1065  // Statistics
1066  m->fstats.at("solver").tic();
1067 
1068  FatropOcpCInterface ocp_interface;
1069  ocp_interface.get_nx = get_nx;
1070  ocp_interface.get_nu = get_nu;
1071  ocp_interface.get_ng = get_ng;
1072  ocp_interface.get_n_stage_params = get_n_stage_params;
1073  ocp_interface.get_n_global_params = get_n_global_params;
1074  ocp_interface.get_default_stage_params = get_default_stage_params;
1075  ocp_interface.get_default_global_params = get_default_global_params;
1076  ocp_interface.get_ng_ineq = get_ng_ineq;
1077  ocp_interface.get_horizon_length = get_horizon_length;
1078  ocp_interface.eval_BAbt = eval_BAbt;
1079  ocp_interface.eval_Ggt = eval_Ggt;
1080  ocp_interface.eval_Ggt_ineq = eval_Ggt_ineq;
1081  ocp_interface.eval_RSQrqt = eval_RSQrqt;
1082  ocp_interface.eval_b = eval_b;
1083  ocp_interface.eval_g = eval_g;
1084  ocp_interface.eval_gineq = eval_gineq;
1085  ocp_interface.eval_rq = eval_rq;
1086  ocp_interface.eval_L = eval_L;
1087  ocp_interface.get_bounds = get_bounds;
1088  ocp_interface.get_initial_xk = get_initial_xk;
1089  ocp_interface.get_initial_uk = get_initial_uk;
1090  ocp_interface.full_eval_lag_hess = full_eval_lag_hess;
1091  ocp_interface.full_eval_constr_jac = full_eval_constr_jac;
1092  ocp_interface.full_eval_contr_viol = full_eval_contr_viol;
1093  ocp_interface.full_eval_obj_grad = full_eval_obj_grad;
1094  ocp_interface.full_eval_obj = full_eval_obj;
1095 
1096  FatropUserData user_data;
1097  user_data.solver = this;
1098  user_data.mem = static_cast<FatropConicMemory*>(mem);
1099 
1100  ocp_interface.user_data = &user_data;
1101 
1102  uout() << "ocp_interface" << ocp_interface.get_horizon_length << std::endl;
1103 
1104 
1105  FatropOcpCSolver* s = fatrop_ocp_c_create(&ocp_interface, 0, 0);
1106  fatrop_ocp_c_set_option_bool(s, "accept_every_trial_step", false);
1107 
1108  int ret = fatrop_ocp_c_solve(s);
1109 
1110  uout() << "ret" << ret << std::endl;
1111 
1112  if (ret) {
1113  m->d_qp.success = false;
1114  m->d.return_status = "failed";
1115  return 0;
1116  }
1117 
1118  // u0 x0 u1 u2 ...
1119  const blasfeo_dvec* primal = fatrop_ocp_c_get_primal(s);
1120  // eq, dynamic, ineq
1121  const blasfeo_dvec* dual = fatrop_ocp_c_get_dual(s);
1122 
1123  auto d = &m->d;
1124  auto p = d->prob;
1125  casadi_qp_data<double>* d_qp = d->qp;
1126 
1127  // Unpack primal solution
1128  casadi_int offset_fatrop = 0;
1129  casadi_int offset_casadi = 0;
1130  for (int k=0;k<N_+1;++k) {
1131  blasfeo_unpack_dvec(p->nu[k], const_cast<blasfeo_dvec*>(primal),
1132  offset_fatrop, d_qp->x+offset_casadi+p->nx[k], 1);
1133  offset_fatrop += p->nu[k];
1134  blasfeo_unpack_dvec(p->nx[k], const_cast<blasfeo_dvec*>(primal),
1135  offset_fatrop, d_qp->x+offset_casadi, 1);
1136  offset_fatrop += p->nx[k];
1137  offset_casadi += p->nx[k]+p->nu[k];
1138  }
1139 
1140  blasfeo_print_dvec(offset_casadi, const_cast<blasfeo_dvec*>(primal), 0);
1141 
1142  m->d_qp.success = true;
1143  m->d_qp.unified_return_status = SOLVER_RET_SUCCESS;
1144  m->d.return_status = "solved";
1145 
1146  std::vector<double> dualv(nx_+na_);
1147  blasfeo_unpack_dvec(nx_+na_, const_cast<blasfeo_dvec*>(dual), 0, get_ptr(dualv), 1);
1148 
1149  // Unpack dual solution
1150  offset_fatrop = 0;
1151  // Inequalities
1152  for (int k=0;k<N_+1;++k) {
1153  for (casadi_int i=d->a_eq_idx[k];i<d->a_eq_idx[k+1];++i) {
1154  d_qp->lam_a[d->a_eq[i]] = dualv[offset_fatrop++];
1155  }
1156  for (casadi_int i=d->x_eq_idx[k];i<d->x_eq_idx[k+1];++i) {
1157  d_qp->lam_x[d->x_eq[i]] = dualv[offset_fatrop++];
1158  }
1159  }
1160  // Dynamics
1161  for (int k=0;k<N_;++k) {
1162  for (casadi_int i=0;i<p->nx[k];++i) {
1163  d_qp->lam_a[AB_blocks[k].offset_r+i] = -dualv[offset_fatrop++];
1164  }
1165  }
1166  // Inequalities
1167  for (int k=0;k<N_+1;++k) {
1168  for (casadi_int i=d->a_ineq_idx[k];i<d->a_ineq_idx[k+1];++i) {
1169  d_qp->lam_a[d->a_ineq[i]] = dualv[offset_fatrop++];
1170  }
1171  for (casadi_int i=d->x_ineq_idx[k];i<d->x_ineq_idx[k+1];++i) {
1172  d_qp->lam_x[d->x_ineq[i]] = dualv[offset_fatrop++];
1173  }
1174  }
1175  //const fatrop::FatropVecBF& primal = app.last_solution_primal();
1176  //const fatrop::FatropVecBF& dual = app.last_solution_dual();
1177 
1178  //primal.vec_;
1179 
1180  m->fstats.at("solver").toc();
1181 
1182  //fatrop::FatropStats stats = app.get_stats();
1183 
1184  // success
1185  // fail
1186 
1187  fatrop_ocp_c_destroy(s);
1188 
1189  return 0;
1190  }
1191 
1192 } // namespace casadi
Internal class.
Definition: conic_impl.hpp:44
static const Options options_
Options.
Definition: conic_impl.hpp:83
casadi_int nx_
Number of decision variables.
Definition: conic_impl.hpp:169
int init_mem(void *mem) const override
Initalize memory block.
Definition: conic.cpp:451
casadi_int na_
The number of constraints (counting both equality and inequality) == A.size1()
Definition: conic_impl.hpp:172
void init(const Dict &opts) override
Initialize.
Definition: conic.cpp:412
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
Definition: conic.cpp:738
void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const override
Set the (persistent) work vectors.
Definition: conic.cpp:458
Dict get_stats(void *mem) const override
Get all statistics.
Definition: conic.cpp:711
casadi_qp_prob< double > p_qp_
Definition: conic_impl.hpp:47
Helper class for Serialization.
void version(const std::string &name, int v)
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_
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_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)
General sparsity class.
Definition: sparsity.hpp:106
Sparsity T() const
Transpose the matrix.
Definition: sparsity.cpp:394
casadi_int nnz() const
Get the number of (structural) non-zeros.
Definition: sparsity.cpp:148
casadi_int size2() const
Get the number of columns.
Definition: sparsity.cpp:128
const casadi_int * row() const
Get a reference to row-vector,.
Definition: sparsity.cpp:164
const casadi_int * colind() const
Get a reference to the colindex of all column element (see class description)
Definition: sparsity.cpp:168
The casadi namespace.
Definition: archiver.cpp:28
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)
@ OT_INTVECTOR
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)
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)
std::ostream & uout()
fatrop_int get_n_stage_params(const fatrop_int k, void *user_data)
@ SOLVER_RET_SUCCESS
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
Options metadata for a class.
Definition: options.hpp:40
void add_stat(const std::string &s)
const casadi_qp_prob< T1 > * qp
const T1 * lba
Definition: casadi_qp.hpp:64
const T1 * lbx
Definition: casadi_qp.hpp:64
const T1 * uba
Definition: casadi_qp.hpp:64
const T1 * ubx
Definition: casadi_qp.hpp:64
const T1 * x0
Definition: casadi_qp.hpp:64
const T1 * g
Definition: casadi_qp.hpp:64