qpoases_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, Kobe Bergmans
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 
26 #include "qpoases_interface.hpp"
27 
28 // Bug in qpOASES?
29 #define ALLOW_QPROBLEMB true
30 #define ALLOW_ALL_OPTIONS
31 
32 namespace casadi {
33 
34  extern "C"
35  int CASADI_CONIC_QPOASES_EXPORT
36  casadi_register_conic_qpoases(Conic::Plugin* plugin) {
37  plugin->creator = QpoasesInterface::creator;
38  plugin->name = "qpoases";
39  plugin->doc = QpoasesInterface::meta_doc.c_str();
40  plugin->version = CASADI_VERSION;
41  plugin->options = &QpoasesInterface::options_;
42  plugin->deserialize = &QpoasesInterface::deserialize;
43  return 0;
44  }
45 
46  extern "C"
47  void CASADI_CONIC_QPOASES_EXPORT casadi_load_conic_qpoases() {
49  }
50 
51  QpoasesInterface::QpoasesInterface(const std::string& name,
52  const std::map<std::string, Sparsity>& st)
53  : Conic(name, st) {
54  // Redirect output to CasADi
55  static bool first_call = true;
56  if (first_call) {
57  qpOASES::setPrintf(qpoases_printf);
58  first_call = false;
59  }
60  }
61 
62  void QpoasesInterface::qpoases_printf(const char* s) {
63  uout() << s;
64  }
65 
67  clear_mem();
68  }
69 
71  = {{&Conic::options_},
72  {{"sparse",
73  {OT_BOOL,
74  "Formulate the QP using sparse matrices. [false]"}},
75  {"schur",
76  {OT_BOOL,
77  "Use Schur Complement Approach [false]"}},
78  {"hessian_type",
79  {OT_STRING,
80  "Type of Hessian - see qpOASES documentation "
81  "[UNKNOWN|posdef|semidef|indef|zero|identity]]"}},
82  {"max_schur",
83  {OT_INT,
84  "Maximal number of Schur updates [75]"}},
85  {"linsol_plugin",
86  {OT_STRING,
87  "Linear solver plugin"}},
88  {"nWSR",
89  {OT_INT,
90  "The maximum number of working set recalculations to be performed during "
91  "the initial homotopy. Default is 5(nx + nc)"}},
92  {"CPUtime",
93  {OT_DOUBLE,
94  "The maximum allowed CPU time in seconds for the whole initialisation"
95  " (and the actually required one on output). Disabled if unset."}},
96  {"printLevel",
97  {OT_STRING,
98  "Defines the amount of text output during QP solution, see Section 5.7"}},
99  {"enableRamping",
100  {OT_BOOL,
101  "Enables ramping."}},
102  {"enableFarBounds",
103  {OT_BOOL,
104  "Enables the use of far bounds."}},
105  {"enableFlippingBounds",
106  {OT_BOOL,
107  "Enables the use of flipping bounds."}},
108  {"enableRegularisation",
109  {OT_BOOL,
110  "Enables automatic Hessian regularisation."}},
111  {"enableFullLITests",
112  {OT_BOOL,
113  "Enables condition-hardened (but more expensive) LI test."}},
114  {"enableNZCTests",
115  {OT_BOOL,
116  "Enables nonzero curvature tests."}},
117  {"enableDriftCorrection",
118  {OT_INT,
119  "Specifies the frequency of drift corrections: 0: turns them off."}},
120  {"enableCholeskyRefactorisation",
121  {OT_INT,
122  "Specifies the frequency of a full re-factorisation of projected "
123  "Hessian matrix: 0: turns them off, 1: uses them at each iteration etc."}},
124  {"enableEqualities",
125  {OT_BOOL,
126  "Specifies whether equalities should be treated as always active "
127  "(True) or not (False)"}},
128  {"terminationTolerance",
129  {OT_DOUBLE,
130  "Relative termination tolerance to stop homotopy."}},
131  {"boundTolerance",
132  {OT_DOUBLE,
133  "If upper and lower bounds differ less than this tolerance, they are regarded "
134  "equal, i.e. as equality constraint."}},
135  {"boundRelaxation",
136  {OT_DOUBLE,
137  "Initial relaxation of bounds to start homotopy and initial value for far bounds."}},
138  {"epsNum",
139  {OT_DOUBLE,
140  "Numerator tolerance for ratio tests."}},
141  {"epsDen",
142  {OT_DOUBLE,
143  "Denominator tolerance for ratio tests."}},
144  {"maxPrimalJump",
145  {OT_DOUBLE,
146  "Maximum allowed jump in primal variables in nonzero curvature tests."}},
147  {"maxDualJump",
148  {OT_DOUBLE,
149  "Maximum allowed jump in dual variables in linear independence tests."}},
150  {"initialRamping",
151  {OT_DOUBLE,
152  "Start value for ramping strategy."}},
153  {"finalRamping",
154  {OT_DOUBLE,
155  "Final value for ramping strategy."}},
156  {"initialFarBounds",
157  {OT_DOUBLE,
158  "Initial size for far bounds."}},
159  {"growFarBounds",
160  {OT_DOUBLE,
161  "Factor to grow far bounds."}},
162  {"initialStatusBounds",
163  {OT_STRING,
164  "Initial status of bounds at first iteration."}},
165  {"epsFlipping",
166  {OT_DOUBLE,
167  "Tolerance of squared Cholesky diagonal factor which triggers flipping bound."}},
168  {"numRegularisationSteps",
169  {OT_INT,
170  "Maximum number of successive regularisation steps."}},
171  {"epsRegularisation",
172  {OT_DOUBLE,
173  "Scaling factor of identity matrix used for Hessian regularisation."}},
174  {"numRefinementSteps",
175  {OT_INT,
176  "Maximum number of iterative refinement steps."}},
177  {"epsIterRef",
178  {OT_DOUBLE,
179  "Early termination tolerance for iterative refinement."}},
180  {"epsLITests",
181  {OT_DOUBLE,
182  "Tolerance for linear independence tests."}},
183  {"epsNZCTests",
184  {OT_DOUBLE,
185  "Tolerance for nonzero curvature tests."}},
186  {"enableInertiaCorrection",
187  {OT_BOOL,
188  "Should working set be repaired when negative curvature is discovered during hotstart."}}
189  }
190  };
191 
192  void QpoasesInterface::init(const Dict& opts) {
193  Conic::init(opts);
194 
195  // Default options
196  sparse_ = false;
197  schur_ = false;
198  hess_ = qpOASES::HessianType::HST_UNKNOWN;
199  max_schur_ = 75;
200  max_nWSR_ = 5 *(nx_ + na_);
201  max_cputime_ = -1;
202  ops_.setToDefault();
203  linsol_plugin_ = "ma27";
204 
205  // Read options
206  for (auto&& op : opts) {
207  if (op.first=="sparse") {
208  sparse_ = op.second;
209  } else if (op.first=="schur") {
210  schur_= op.second;
211  } else if (op.first=="hessian_type") {
212  std::string h = op.second;
213  if (h=="unknown") {
214  hess_ = qpOASES::HessianType::HST_UNKNOWN;
215  } else if (h=="posdef") {
216  hess_ = qpOASES::HessianType::HST_POSDEF;
217  } else if (h=="semidef") {
218  hess_ = qpOASES::HessianType::HST_SEMIDEF;
219  } else if (h=="indef") {
220  hess_ = qpOASES::HessianType::HST_INDEF;
221  } else if (h=="zero") {
222  hess_ = qpOASES::HessianType::HST_ZERO;
223  } else if (h=="identity") {
224  hess_ = qpOASES::HessianType::HST_IDENTITY;
225  } else {
226  casadi_error("Unknown Hessian type \"" + h + "\"");
227  }
228  } else if (op.first=="max_schur") {
229  max_schur_ = op.second;
230  } else if (op.first=="linsol_plugin") {
231  linsol_plugin_ = std::string(op.second);
232  } else if (op.first=="nWSR") {
233  max_nWSR_ = op.second;
234  } else if (op.first=="CPUtime") {
235  max_cputime_ = op.second;
236  } else if (op.first=="printLevel") {
237  ops_.printLevel = to_PrintLevel(op.second);
238  } else if (op.first=="enableRamping") {
239  ops_.enableRamping = to_BooleanType(op.second);
240  } else if (op.first=="enableFarBounds") {
241  ops_.enableFarBounds = to_BooleanType(op.second);
242  } else if (op.first=="enableFlippingBounds") {
243  ops_.enableFlippingBounds = to_BooleanType(op.second);
244  } else if (op.first=="enableRegularisation") {
245  ops_.enableRegularisation = to_BooleanType(op.second);
246  } else if (op.first=="enableFullLITests") {
247  ops_.enableFullLITests = to_BooleanType(op.second);
248  } else if (op.first=="enableNZCTests") {
249  ops_.enableNZCTests = to_BooleanType(op.second);
250  } else if (op.first=="enableDriftCorrection") {
251  ops_.enableRegularisation = to_BooleanType(op.second);
252  } else if (op.first=="enableCholeskyRefactorisation") {
253  ops_.enableCholeskyRefactorisation = op.second;
254  } else if (op.first=="enableEqualities") {
255  ops_.enableEqualities = to_BooleanType(op.second);
256  } else if (op.first=="terminationTolerance") {
257  ops_.terminationTolerance = op.second;
258  } else if (op.first=="boundTolerance") {
259  ops_.boundTolerance = op.second;
260  } else if (op.first=="boundRelaxation") {
261  ops_.boundRelaxation = op.second;
262  } else if (op.first=="epsNum") {
263  ops_.epsNum = op.second;
264  } else if (op.first=="epsDen") {
265  ops_.epsDen = op.second;
266  } else if (op.first=="maxPrimalJump") {
267  ops_.maxPrimalJump = op.second;
268  } else if (op.first=="maxDualJump") {
269  ops_.maxDualJump = op.second;
270  } else if (op.first=="initialRamping") {
271  ops_.initialRamping = op.second;
272  } else if (op.first=="finalRamping") {
273  ops_.finalRamping = op.second;
274  } else if (op.first=="initialFarBounds") {
275  ops_.initialFarBounds = op.second;
276  } else if (op.first=="growFarBounds") {
277  ops_.growFarBounds = op.second;
278  } else if (op.first=="initialStatusBounds") {
279  ops_.initialStatusBounds = to_SubjectToStatus(op.second);
280  } else if (op.first=="epsFlipping") {
281  ops_.epsFlipping = op.second;
282  } else if (op.first=="numRegularisationSteps") {
283  ops_.numRegularisationSteps = op.second;
284  } else if (op.first=="epsRegularisation") {
285  ops_.epsRegularisation = op.second;
286  } else if (op.first=="numRefinementSteps") {
287  ops_.numRefinementSteps = op.second;
288  } else if (op.first=="epsIterRef") {
289  ops_.epsIterRef = op.second;
290  } else if (op.first=="epsLITests") {
291  ops_.epsLITests = op.second;
292  } else if (op.first=="epsNZCTests") {
293  ops_.epsNZCTests = op.second;
294  } else if (op.first=="enableInertiaCorrection") {
295  ops_.enableInertiaCorrection = to_BooleanType(op.second);
296  }
297  }
298 
299  // Bug #2358
300  if (sparse_ && na_ == 0) {
301  casadi_error("With no linear constraints, qpOASES fails in sparse mode: "
302  "https://github.com/casadi/casadi/issues/2358");
303  }
304 
305  // Allocate work vectors
306  if (sparse_) {
307  alloc_w(nnz_in(CONIC_H), true); // h
308  alloc_w(nnz_in(CONIC_A), true); // a
309  } else {
310  alloc_w(nx_*nx_, true); // h
311  alloc_w(nx_*na_, true); // a
312  }
313  alloc_w(nx_, true); // g
314  alloc_w(nx_, true); // lbx
315  alloc_w(nx_, true); // ubx
316  alloc_w(na_, true); // lba
317  alloc_w(na_, true); // uba
318  alloc_w(nx_+na_, true); // dual
319  }
320 
321  int QpoasesInterface::init_mem(void* mem) const {
322  if (Conic::init_mem(mem)) return 1;
323  auto m = static_cast<QpoasesMemory*>(mem);
324  m->called_once = false;
325 
326  // Linear solver, if any
327  m->linsol_plugin = linsol_plugin_;
328 
329  // Create qpOASES instance
330  delete m->qp;
331  if (schur_) {
332  m->sqp = new qpOASES::SQProblemSchur(nx_, na_, hess_, max_schur_,
334  } else if (na_==0) {
335  m->qp = new qpOASES::QProblemB(nx_, hess_);
336  } else {
337  m->sqp = new qpOASES::SQProblem(nx_, na_, hess_);
338  }
339 
340  // Pass to qpOASES
341  m->qp->setOptions(ops_);
342 
343  m->add_stat("preprocessing");
344  m->add_stat("solver");
345  m->add_stat("postprocessing");
346  m->h_row.resize(H_.nnz());
347  m->h_colind.resize(H_.size2()+1);
348  m->a_row.resize(A_.nnz());
349  m->a_colind.resize(A_.size2()+1);
350 
351  return 0;
352  }
353 
355  solve(const double** arg, double** res, casadi_int* iw, double* w, void* mem) const {
356  auto m = static_cast<QpoasesMemory*>(mem);
357 
358  m->fstats.at("preprocessing").tic();
359 
360  // Problem has not been solved at this point
361  m->return_status = -1;
362 
363  // Maxiumum number of working set changes
364  int nWSR = max_nWSR_;
365  double cputime = max_cputime_;
366  double *cputime_ptr = cputime<=0 ? nullptr : &cputime;
367 
368  // Get the arguments to call qpOASES with
369  double* g=w; w += nx_;
370  casadi_copy(arg[CONIC_G], nx_, g);
371  double* lb=w; w += nx_;
372  casadi_copy(arg[CONIC_LBX], nx_, lb);
373  double* ub=w; w += nx_;
374  casadi_copy(arg[CONIC_UBX], nx_, ub);
375  double* lbA=w; w += na_;
376  casadi_copy(arg[CONIC_LBA], na_, lbA);
377  double* ubA=w; w += na_;
378  casadi_copy(arg[CONIC_UBA], na_, ubA);
379 
380  // Return flag
381  casadi_int flag;
382 
383  // Sparse or dense mode?
384  if (sparse_) {
385  // Get quadratic term
386  copy_vector(H_.colind(), m->h_colind);
387  copy_vector(H_.row(), m->h_row);
388  double* h=w; w += H_.nnz();
389  casadi_copy(arg[CONIC_H], H_.nnz(), h);
390  delete m->h;
391  m->h = new qpOASES::SymSparseMat(H_.size1(), H_.size2(),
392  get_ptr(m->h_row), get_ptr(m->h_colind), h);
393  m->h->createDiagInfo();
394 
395  // Get linear term
396  copy_vector(A_.colind(), m->a_colind);
397  copy_vector(A_.row(), m->a_row);
398  double* a=w; w += A_.nnz();
399  casadi_copy(arg[CONIC_A], A_.nnz(), a);
400  delete m->a;
401  m->a = new qpOASES::SparseMatrix(A_.size1(), A_.size2(),
402  get_ptr(m->a_row), get_ptr(m->a_colind), a);
403 
404  m->fstats.at("preprocessing").toc();
405  m->fstats.at("solver").tic();
406 
407  // Solve sparse
408  if (m->called_once) {
409  flag = m->sqp->hotstart(m->h, g, m->a, lb, ub, lbA, ubA, nWSR, cputime_ptr);
410  } else {
411  flag = m->sqp->init(m->h, g, m->a, lb, ub, lbA, ubA, nWSR, cputime_ptr);
412  }
413  m->fstats.at("solver").toc();
414 
415  } else {
416  // Get quadratic term
417  double* h=w; w += nx_*nx_;
418  casadi_densify(arg[CONIC_H], H_, h, false);
419 
420  // Get linear term
421  double* a = w; w += nx_*na_;
422  casadi_densify(arg[CONIC_A], A_, a, true);
423 
424  m->fstats.at("preprocessing").toc();
425  m->fstats.at("solver").tic();
426  // Solve dense
427  if (na_==0) {
428  if (m->called_once) {
429  // Broken?
430  //flag = m->qp->hotstart(g, lb, ub, nWSR, cputime_ptr);
431  m->qp->reset();
432  flag = m->qp->init(h, g, lb, ub, nWSR, cputime_ptr);
433  } else {
434  flag = m->qp->init(h, g, lb, ub, nWSR, cputime_ptr);
435  }
436  } else {
437  if (m->called_once) {
438  flag = m->sqp->hotstart(h, g, a, lb, ub, lbA, ubA, nWSR, cputime_ptr);
439  } else {
440  flag = m->sqp->init(h, g, a, lb, ub, lbA, ubA, nWSR, cputime_ptr);
441  }
442  }
443  m->fstats.at("solver").toc();
444  }
445 
446  // Solver is "warm" now
447  m->called_once = true;
448 
449  m->fstats.at("postprocessing").tic();
450 
451  m->return_status = flag;
452  m->d_qp.success = flag==qpOASES::SUCCESSFUL_RETURN;
453  if (m->d_qp.success) m->d_qp.unified_return_status = SOLVER_RET_SUCCESS;
454  if (flag == qpOASES::RET_MAX_NWSR_REACHED) {
455  m->d_qp.unified_return_status = SOLVER_RET_LIMITED;
456  }
457 
458  if (flag==qpOASES::RET_INIT_FAILED_INFEASIBILITY
459  || flag == qpOASES::RET_QP_INFEASIBLE
460  || flag == qpOASES::RET_HOTSTART_STOPPED_INFEASIBILITY
461  || flag == qpOASES::RET_ADDCONSTRAINT_FAILED_INFEASIBILITY
462  || flag == qpOASES::RET_ADDBOUND_FAILED_INFEASIBILITY
463  || flag == qpOASES::RET_ENSURELI_FAILED_NOINDEX
464  || flag == qpOASES::RET_ENSURELI_FAILED_CYCLING) {
465  m->d_qp.unified_return_status = SOLVER_RET_INFEASIBLE;
466  }
467 
468  m->d_qp.iter_count = nWSR;
469 
470  if (verbose_) casadi_message("qpOASES return status: " + getErrorMessage(m->return_status));
471 
472  // Get optimal cost
473  if (res[CONIC_COST]) *res[CONIC_COST] = m->qp->getObjVal();
474 
475  // Get the primal solution
476  if (res[CONIC_X]) m->qp->getPrimalSolution(res[CONIC_X]);
477 
478  // Get the dual solution
479  if (res[CONIC_LAM_X] || res[CONIC_LAM_A]) {
480  double* dual=w; w += nx_+na_;
481  m->qp->getDualSolution(dual);
482  casadi_scal(nx_+na_, -1., dual);
483  casadi_copy(dual, nx_, res[CONIC_LAM_X]);
484  casadi_copy(dual+nx_, na_, res[CONIC_LAM_A]);
485  }
486 
487  m->fstats.at("postprocessing").toc();
488 
489  return m->d_qp.unified_return_status;
490  }
491 
492  std::string QpoasesInterface::getErrorMessage(casadi_int flag) {
493  switch (flag) {
494  case qpOASES::SUCCESSFUL_RETURN:
495  return "Successful return.";
496  case qpOASES::RET_DIV_BY_ZERO:
497  return "Division by zero.";
498  case qpOASES::RET_INDEX_OUT_OF_BOUNDS:
499  return "Index out of bounds.";
500  case qpOASES::RET_INVALID_ARGUMENTS:
501  return "At least one of the arguments is invalid.";
502  case qpOASES::RET_ERROR_UNDEFINED:
503  return "Error number undefined.";
504  case qpOASES::RET_WARNING_UNDEFINED:
505  return "Warning number undefined.";
506  case qpOASES::RET_INFO_UNDEFINED:
507  return "Info number undefined.";
508  case qpOASES::RET_EWI_UNDEFINED:
509  return "Error/warning/info number undefined.";
510  case qpOASES::RET_AVAILABLE_WITH_LINUX_ONLY:
511  return "This function is available under Linux only.";
512  case qpOASES::RET_UNKNOWN_BUG:
513  return "The error occured is not yet known.";
514  case qpOASES::RET_PRINTLEVEL_CHANGED:
515  return "Print level changed.";
516  case qpOASES::RET_NOT_YET_IMPLEMENTED:
517  return "Requested function is not yet implemented in this version of qpOASES.";
518  // Indexlist
519  case qpOASES::RET_INDEXLIST_MUST_BE_REORDERD:
520  return "Index list has to be reordered.";
521  case qpOASES::RET_INDEXLIST_EXCEEDS_MAX_LENGTH:
522  return "Index list exceeds its maximal physical length.";
523  case qpOASES::RET_INDEXLIST_CORRUPTED:
524  return "Index list corrupted.";
525  case qpOASES::RET_INDEXLIST_OUTOFBOUNDS:
526  return "Physical index is out of bounds.";
527  case qpOASES::RET_INDEXLIST_ADD_FAILED:
528  return "Adding indices from another index set failed.";
529  case qpOASES::RET_INDEXLIST_INTERSECT_FAILED:
530  return "Intersection with another index set failed.";
531  // SubjectTo / Bounds / Constraints
532  case qpOASES::RET_INDEX_ALREADY_OF_DESIRED_STATUS:
533  return "Index is already of desired status.";
534  case qpOASES::RET_ADDINDEX_FAILED:
535  return "Adding index to index set failed.";
536  case qpOASES::RET_REMOVEINDEX_FAILED:
537  return "Removing index from index set failed.";
538  case qpOASES::RET_SWAPINDEX_FAILED:
539  return "Cannot swap between different indexsets.";
540  case qpOASES::RET_NOTHING_TO_DO:
541  return "Nothing to do.";
542  case qpOASES::RET_SETUP_BOUND_FAILED:
543  return "Setting up bound index failed.";
544  case qpOASES::RET_SETUP_CONSTRAINT_FAILED:
545  return "Setting up constraint index failed.";
546  case qpOASES::RET_MOVING_BOUND_FAILED:
547  return "Moving bound between index sets failed.";
548  case qpOASES::RET_MOVING_CONSTRAINT_FAILED:
549  return "Moving constraint between index sets failed.";
550  case qpOASES::RET_SHIFTING_FAILED:
551  return "Shifting of bounds/constraints failed.";
552  case qpOASES::RET_ROTATING_FAILED:
553  return "Rotating of bounds/constraints failed.";
554  // QProblem
555  case qpOASES::RET_QPOBJECT_NOT_SETUP:
556  return "The QP object has not been setup correctly, use another constructor.";
557  case qpOASES::RET_QP_ALREADY_INITIALISED:
558  return "QProblem has already been initialized.";
559  case qpOASES::RET_NO_INIT_WITH_STANDARD_SOLVER:
560  return "Initialisation via extern QP solver is not yet implemented.";
561  case qpOASES::RET_RESET_FAILED:
562  return "Reset failed.";
563  case qpOASES::RET_INIT_FAILED:
564  return "Initialisation failed.";
565  case qpOASES::RET_INIT_FAILED_TQ:
566  return "Initialisation failed due to TQ factorisation.";
567  case qpOASES::RET_INIT_FAILED_CHOLESKY:
568  return "Initialisation failed due to Cholesky decomposition.";
569  case qpOASES::RET_INIT_FAILED_HOTSTART:
570  return "Initialisation failed! QP could not be solved!";
571  case qpOASES::RET_INIT_FAILED_INFEASIBILITY:
572  return "Initial QP could not be solved due to infeasibility!";
573  case qpOASES::RET_INIT_FAILED_UNBOUNDEDNESS:
574  return "Initial QP could not be solved due to unboundedness!";
575  case qpOASES::RET_INIT_SUCCESSFUL:
576  return "Initialisation done.";
577  case qpOASES::RET_OBTAINING_WORKINGSET_FAILED:
578  return "Failed to obtain working set for auxiliary QP.";
579  case qpOASES::RET_SETUP_WORKINGSET_FAILED:
580  return "Failed to setup working set for auxiliary QP.";
581  case qpOASES::RET_SETUP_AUXILIARYQP_FAILED:
582  return "Failed to setup auxiliary QP for initialized homotopy.";
583  case qpOASES::RET_NO_EXTERN_SOLVER:
584  return "No extern QP solver available.";
585  case qpOASES::RET_QP_UNBOUNDED:
586  return "QP is unbounded.";
587  case qpOASES::RET_QP_INFEASIBLE:
588  return "QP is infeasible.";
589  case qpOASES::RET_QP_NOT_SOLVED:
590  return "Problems occured while solving QP with standard solver.";
591  case qpOASES::RET_QP_SOLVED:
592  return "QP successfully solved.";
593  case qpOASES::RET_UNABLE_TO_SOLVE_QP:
594  return "Problems occured while solving QP.";
595  case qpOASES::RET_INITIALISATION_STARTED:
596  return "Starting problem initialisation.";
597  case qpOASES::RET_HOTSTART_FAILED:
598  return "Unable to perform homotopy due to internal error.";
599  case qpOASES::RET_HOTSTART_FAILED_TO_INIT:
600  return "Unable to initialise problem.";
601  case qpOASES::RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED:
602  return "Unable to perform homotopy as previous QP is not solved.";
603  case qpOASES::RET_ITERATION_STARTED:
604  return "Iteration...";
605  case qpOASES::RET_SHIFT_DETERMINATION_FAILED:
606  return "Determination of shift of the QP data failed.";
607  case qpOASES::RET_STEPDIRECTION_DETERMINATION_FAILED:
608  return "Determination of step direction failed.";
609  case qpOASES::RET_STEPLENGTH_DETERMINATION_FAILED:
610  return "Determination of step direction failed.";
611  case qpOASES::RET_OPTIMAL_SOLUTION_FOUND:
612  return "Optimal solution of neighbouring QP found.";
613  case qpOASES::RET_HOMOTOPY_STEP_FAILED:
614  return "Unable to perform homotopy step.";
615  case qpOASES::RET_HOTSTART_STOPPED_INFEASIBILITY:
616  return "Premature homotopy termination because QP is infeasible.";
617  case qpOASES::RET_HOTSTART_STOPPED_UNBOUNDEDNESS:
618  return "Premature homotopy termination because QP is unbounded.";
619  case qpOASES::RET_WORKINGSET_UPDATE_FAILED:
620  return "Unable to update working sets according to initial guesses.";
621  case qpOASES::RET_MAX_NWSR_REACHED:
622  return "Maximum number of working set recalculations performed.";
623  case qpOASES::RET_CONSTRAINTS_NOT_SPECIFIED:
624  return "Problem does comprise constraints! "
625  "You also have to specify new constraints' bounds.";
626  case qpOASES::RET_INVALID_FACTORISATION_FLAG:
627  return "Invalid factorisation flag.";
628  case qpOASES::RET_UNABLE_TO_SAVE_QPDATA:
629  return "Unable to save QP data.";
630  case qpOASES::RET_STEPDIRECTION_FAILED_TQ:
631  return "Abnormal termination due to TQ factorisation.";
632  case qpOASES::RET_STEPDIRECTION_FAILED_CHOLESKY:
633  return "Abnormal termination due to Cholesky factorisation.";
634  case qpOASES::RET_CYCLING_DETECTED:
635  return "Cycling detected.";
636  case qpOASES::RET_CYCLING_NOT_RESOLVED:
637  return "Cycling cannot be resolved, QP probably infeasible.";
638  case qpOASES::RET_CYCLING_RESOLVED:
639  return "Cycling probably resolved.";
640  case qpOASES::RET_STEPSIZE:
641  return "For displaying performed stepsize.";
642  case qpOASES::RET_STEPSIZE_NONPOSITIVE:
643  return "For displaying non-positive stepsize.";
644  case qpOASES::RET_SETUPSUBJECTTOTYPE_FAILED:
645  return "Setup of SubjectToTypes failed.";
646  case qpOASES::RET_ADDCONSTRAINT_FAILED:
647  return "Addition of constraint to working set failed.";
648  case qpOASES::RET_ADDCONSTRAINT_FAILED_INFEASIBILITY:
649  return "Addition of constraint to working set failed (due to QP infeasibility).";
650  case qpOASES::RET_ADDBOUND_FAILED:
651  return "Addition of bound to working set failed.";
652  case qpOASES::RET_ADDBOUND_FAILED_INFEASIBILITY:
653  return "Addition of bound to working set failed (due to QP infeasibility).";
654  case qpOASES::RET_REMOVECONSTRAINT_FAILED:
655  return "Removal of constraint from working set failed.";
656  case qpOASES::RET_REMOVEBOUND_FAILED:
657  return "Removal of bound from working set failed.";
658  case qpOASES::RET_REMOVE_FROM_ACTIVESET:
659  return "Removing from active set...";
660  case qpOASES::RET_ADD_TO_ACTIVESET:
661  return "Adding to active set...";
662  case qpOASES::RET_REMOVE_FROM_ACTIVESET_FAILED:
663  return "Removing from active set failed.";
664  case qpOASES::RET_ADD_TO_ACTIVESET_FAILED:
665  return "Adding to active set failed.";
666  case qpOASES::RET_CONSTRAINT_ALREADY_ACTIVE:
667  return "Constraint is already active.";
668  case qpOASES::RET_ALL_CONSTRAINTS_ACTIVE:
669  return "All constraints are active, no further constraint can be added.";
670  case qpOASES::RET_LINEARLY_DEPENDENT:
671  return "New bound/constraint is linearly dependent.";
672  case qpOASES::RET_LINEARLY_INDEPENDENT:
673  return "New bound/constraint is linearly independent.";
674  case qpOASES::RET_LI_RESOLVED:
675  return "Linear indepence of active contraint matrix successfully resolved.";
676  case qpOASES::RET_ENSURELI_FAILED:
677  return "Failed to ensure linear indepence of active contraint matrix.";
678  case qpOASES::RET_ENSURELI_FAILED_TQ:
679  return "Abnormal termination due to TQ factorisation.";
680  case qpOASES::RET_ENSURELI_FAILED_NOINDEX:
681  return "QP is infeasible.";
682  case qpOASES::RET_ENSURELI_FAILED_CYCLING:
683  return "QP is infeasible.";
684  case qpOASES::RET_BOUND_ALREADY_ACTIVE:
685  return "Bound is already active.";
686  case qpOASES::RET_ALL_BOUNDS_ACTIVE:
687  return "All bounds are active, no further bound can be added.";
688  case qpOASES::RET_CONSTRAINT_NOT_ACTIVE:
689  return "Constraint is not active.";
690  case qpOASES::RET_BOUND_NOT_ACTIVE:
691  return "Bound is not active.";
692  case qpOASES::RET_HESSIAN_NOT_SPD:
693  return "Projected Hessian matrix not positive definite.";
694  case qpOASES::RET_HESSIAN_INDEFINITE:
695  return "Hessian matrix is indefinite.";
696  case qpOASES::RET_MATRIX_SHIFT_FAILED:
697  return "Unable to update matrices or to transform vectors.";
698  case qpOASES::RET_MATRIX_FACTORISATION_FAILED:
699  return "Unable to calculate new matrix factorisations.";
700  case qpOASES::RET_PRINT_ITERATION_FAILED:
701  return "Unable to print information on current iteration.";
702  case qpOASES::RET_NO_GLOBAL_MESSAGE_OUTPUTFILE:
703  return "No global message output file initialized.";
704  case qpOASES::RET_DISABLECONSTRAINTS_FAILED:
705  return "Unable to disbable constraints.";
706  case qpOASES::RET_ENABLECONSTRAINTS_FAILED:
707  return "Unable to enbable constraints.";
708  case qpOASES::RET_ALREADY_ENABLED:
709  return "Bound or constraint is already enabled.";
710  case qpOASES::RET_ALREADY_DISABLED:
711  return "Bound or constraint is already disabled.";
712  case qpOASES::RET_NO_HESSIAN_SPECIFIED:
713  return "No Hessian matrix has been specified.";
714  case qpOASES::RET_USING_REGULARISATION:
715  return "Using regularisation as Hessian matrix is not positive definite.";
716  case qpOASES::RET_EPS_MUST_BE_POSITVE:
717  return "Eps for regularisation must be sufficiently positive.";
718  case qpOASES::RET_REGSTEPS_MUST_BE_POSITVE:
719  return "Maximum number of regularisation steps must be non-negative.";
720  case qpOASES::RET_HESSIAN_ALREADY_REGULARISED:
721  return "Hessian has been already regularised.";
722  case qpOASES::RET_CANNOT_REGULARISE_IDENTITY:
723  return "Identity Hessian matrix cannot be regularised.";
724  case qpOASES::RET_NO_REGSTEP_NWSR:
725  return "No additional regularisation step could be performed due to limits.";
726  case qpOASES::RET_FEWER_REGSTEPS_NWSR:
727  return "Fewer additional regularisation steps have been performed due to limits.";
728  case qpOASES::RET_CHOLESKY_OF_ZERO_HESSIAN:
729  return "Cholesky decomposition of (unregularised) zero Hessian matrix.";
730  case qpOASES::RET_CONSTRAINTS_ARE_NOT_SCALED:
731  return "When defining __MANY_CONSTRAINTS__, l1 norm of each "
732  "constraint must be not greater than one.";
733  case qpOASES::RET_ERROR_IN_CONSTRAINTPRODUCT:
734  return "Error in user-defined constraint product function.";
735  // SQProblem
736  case qpOASES::RET_UPDATEMATRICES_FAILED:
737  return "Unable to update QP matrices.";
738  case qpOASES::RET_UPDATEMATRICES_FAILED_AS_QP_NOT_SOLVED:
739  return "Unable to update matrices as previous QP is not solved.";
740  // Utils
741  case qpOASES::RET_UNABLE_TO_OPEN_FILE:
742  return "Unable to open file.";
743  case qpOASES::RET_UNABLE_TO_WRITE_FILE:
744  return "Unable to write into file.";
745  case qpOASES::RET_UNABLE_TO_READ_FILE:
746  return "Unable to read from file.";
747  case qpOASES::RET_FILEDATA_INCONSISTENT:
748  return "File contains inconsistent data.";
749  // SolutionAnalysis
750  case qpOASES::RET_UNABLE_TO_ANALYSE_QPROBLEM:
751  return "Unable to analyse (S)QProblem(B) object";
752  // Benchmark
753  case qpOASES::RET_NWSR_SET_TO_ONE:
754  return "Maximum number of working set changes was set to 1.";
755  case qpOASES::RET_BENCHMARK_ABORTED:
756  return "Benchmark aborted.";
757  case qpOASES::RET_UNABLE_TO_READ_BENCHMARK:
758  return "Unable to read benchmark data.";
759  case qpOASES::RET_INITIAL_QP_SOLVED:
760  return "Initial QP solved.";
761  case qpOASES::RET_QP_SOLUTION_STARTED:
762  return "Solving QP...";
763  case qpOASES::RET_BENCHMARK_SUCCESSFUL:
764  return "Benchmark terminated successfully.";
765  }
766 
767  // Default error message
768  std::stringstream ss;
769  ss << "Unknown error flag: " << flag << ". Consult qpOASES documentation.";
770  return ss.str();
771  }
772 
773  bool QpoasesInterface::from_BooleanType(qpOASES::BooleanType b) {
774  switch (b) {
775  case qpOASES::BT_TRUE: return true;
776  case qpOASES::BT_FALSE: return false;
777  }
778  casadi_error("not_implemented");
779  }
780 
781  qpOASES::BooleanType QpoasesInterface::to_BooleanType(bool b) {
782  return b ? qpOASES::BT_TRUE : qpOASES::BT_FALSE;
783  }
784 
785  std::string QpoasesInterface::from_SubjectToStatus(qpOASES::SubjectToStatus b) {
786  switch (b) {
787  case qpOASES::ST_INACTIVE: return "inactive";
788  case qpOASES::ST_LOWER: return "lower";
789  case qpOASES::ST_UPPER: return "upper";
790  case qpOASES::ST_INFEASIBLE_LOWER: return "infeasible_lower";
791  case qpOASES::ST_INFEASIBLE_UPPER: return "infeasible_upper";
792  case qpOASES::ST_UNDEFINED: return "undefined";
793  }
794  casadi_error("not_implemented");
795  }
796 
797  qpOASES::SubjectToStatus QpoasesInterface::to_SubjectToStatus(std::string b) {
798  if (b == "inactive") {
799  return qpOASES::ST_INACTIVE;
800  } else if (b == "lower") {
801  return qpOASES::ST_LOWER;
802  } else if (b == "infeasible_lower") {
803  return qpOASES::ST_INFEASIBLE_LOWER;
804  } else if (b == "infeasible_upper") {
805  return qpOASES::ST_INFEASIBLE_UPPER;
806  } else if (b == "undefined") {
807  return qpOASES::ST_UNDEFINED;
808  } else {
809  casadi_error("No such qpOASES::SubjectToStatus: " + b);
810  }
811  }
812 
813  std::string QpoasesInterface::from_PrintLevel(qpOASES::PrintLevel b) {
814  switch (b) {
815  case qpOASES::PL_TABULAR: return "tabular";
816  case qpOASES::PL_NONE: return "none";
817  case qpOASES::PL_LOW: return "low";
818  case qpOASES::PL_MEDIUM: return "medium";
819  case qpOASES::PL_HIGH: return "high";
820  case qpOASES::PL_DEBUG_ITER: return "debug_iter";
821  }
822  casadi_error("not_implemented");
823  }
824 
825  qpOASES::PrintLevel QpoasesInterface::to_PrintLevel(std::string b) {
826  if (b == "tabular") {
827  return qpOASES::PL_TABULAR;
828  } else if (b == "none") {
829  return qpOASES::PL_NONE;
830  } else if (b == "low") {
831  return qpOASES::PL_LOW;
832  } else if (b == "medium") {
833  return qpOASES::PL_MEDIUM;
834  } else if (b == "high") {
835  return qpOASES::PL_HIGH;
836  } else if (b == "debug_iter") {
837  return qpOASES::PL_DEBUG_ITER;
838  } else {
839  casadi_error("No such qpOASES::PrintLevel: " + b);
840  }
841  }
842 
844  this->qp = nullptr;
845  this->h = nullptr;
846  this->a = nullptr;
847  }
848 
850  delete this->qp;
851  delete this->h;
852  delete this->a;
853  }
854 
856  qpoases_init(void* mem, int dim, int nnz, const int* row, const int* col) {
857  casadi_assert_dev(mem!=nullptr);
858  QpoasesMemory* m = static_cast<QpoasesMemory*>(mem);
859 
860  // Get sparsity pattern in sparse triplet format
861  m->row.clear();
862  m->col.clear();
863  m->nz_map.clear();
864  for (casadi_int k=0; k<nnz; ++k) {
865  // Add upper(?) triangular part (and diagonal)
866  m->row.push_back(row[k]-1);
867  m->col.push_back(col[k]-1);
868  m->nz_map.push_back(k);
869  // Add lower(?) triangular part
870  if (row[k]!=col[k]) {
871  m->row.push_back(col[k]-1);
872  m->col.push_back(row[k]-1);
873  m->nz_map.push_back(k);
874  }
875  }
876 
877  // Create sparsity pattern: TODO(@jaeandersson) No memory allocation
878  Sparsity sp = Sparsity::triplet(dim, dim, m->row, m->col, m->lin_map, false);
879  for (casadi_int& e : m->lin_map) e = m->nz_map[e];
880 
881  // Allocate memory for nonzeros
882  m->nz.resize(sp.nnz());
883 
884  // Create linear solver
885  m->linsol = Linsol("linsol", m->linsol_plugin, sp);
886 
887  return 0;
888  }
889 
890  int QpoasesInterface::qpoases_sfact(void* mem, const double* vals) {
891  casadi_assert_dev(mem!=nullptr);
892  QpoasesMemory* m = static_cast<QpoasesMemory*>(mem);
893 
894  // Get nonzero elements (entire elements)
895  for (int i=0; i<m->nz.size(); ++i) m->nz[i] = vals[m->lin_map[i]];
896 
897  // Pass to linear solver
898  m->linsol.sfact(get_ptr(m->nz));
899 
900  return 0;
901  }
902 
904  qpoases_nfact(void* mem, const double* vals, int* neig, int* rank) {
905  casadi_assert_dev(mem!=nullptr);
906  QpoasesMemory* m = static_cast<QpoasesMemory*>(mem);
907 
908  // Get nonzero elements (entire elements)
909  for (casadi_int i=0; i<m->nz.size(); ++i) m->nz[i] = vals[m->lin_map[i]];
910 
911  // Pass to linear solver
912  m->linsol.nfact(get_ptr(m->nz));
913 
914  // Number of negative eigenvalues
915  if (neig) *neig = m->linsol.neig(get_ptr(m->nz));
916 
917  // Rank of the matrix
918  if (rank) *rank = m->linsol.rank(get_ptr(m->nz));
919 
920  return 0;
921  }
922 
923  int QpoasesInterface::qpoases_solve(void* mem, int nrhs, double* rhs) {
924  casadi_assert_dev(mem!=nullptr);
925  QpoasesMemory* m = static_cast<QpoasesMemory*>(mem);
926 
927  // Pass to linear solver
928  m->linsol.solve(get_ptr(m->nz), rhs, nrhs);
929 
930  return 0;
931  }
932 
934  Dict stats = Conic::get_stats(mem);
935  auto m = static_cast<QpoasesMemory*>(mem);
936  stats["return_status"] = getErrorMessage(m->return_status);
937  return stats;
938  }
939 
941  s.version("QpoasesInterface", 1);
942  s.unpack("QpoasesInterface::max_nWSR", max_nWSR_);
943  s.unpack("QpoasesInterface::max_cputime", max_cputime_);
944  casadi_int hess;
945  s.unpack("QpoasesInterface::hess", hess);
946  hess_ = static_cast<qpOASES::HessianType>(hess);
947  s.unpack("QpoasesInterface::sparse", sparse_);
948  s.unpack("QpoasesInterface::schur", schur_);
949  s.unpack("QpoasesInterface::max_schur", max_schur_);
950  s.unpack("QpoasesInterface::linsol_plugin", linsol_plugin_);
951  ops_.setToDefault();
952  casadi_int print_level;
953  s.unpack("QpoasesInterface::ops::printLevel", print_level);
954 
955  bool enableRamping;
956  s.unpack("QpoasesInterface::ops::enableRamping", enableRamping);
957  ops_.enableRamping = to_BooleanType(enableRamping);
958 
959 
960  bool enableFarBounds;
961  s.unpack("QpoasesInterface::ops::enableFarBounds", enableFarBounds);
962  ops_.enableFarBounds = to_BooleanType(enableFarBounds);
963 
964 
965  bool enableFlippingBounds;
966  s.unpack("QpoasesInterface::ops::enableFlippingBounds", enableFlippingBounds);
967  ops_.enableFlippingBounds = to_BooleanType(enableFlippingBounds);
968 
969 
970  bool enableRegularisation;
971  s.unpack("QpoasesInterface::ops::enableRegularisation", enableRegularisation);
972  ops_.enableRegularisation = to_BooleanType(enableRegularisation);
973 
974 
975  bool enableFullLITests;
976  s.unpack("QpoasesInterface::ops::enableFullLITests", enableFullLITests);
977  ops_.enableFullLITests = to_BooleanType(enableFullLITests);
978 
979 
980  bool enableNZCTests;
981  s.unpack("QpoasesInterface::ops::enableNZCTests", enableNZCTests);
982  ops_.enableNZCTests = to_BooleanType(enableNZCTests);
983 
984 
985  s.unpack("QpoasesInterface::ops::enableDriftCorrection", ops_.enableDriftCorrection);
986  s.unpack("QpoasesInterface::ops::enableCholeskyRefactorisation",
987  ops_.enableCholeskyRefactorisation);
988 
989 
990  bool enableEqualities;
991  s.unpack("QpoasesInterface::ops::enableEqualities", enableEqualities);
992  ops_.enableEqualities = to_BooleanType(enableEqualities);
993 
994  s.unpack("QpoasesInterface::ops::terminationTolerance", ops_.terminationTolerance);
995  s.unpack("QpoasesInterface::ops::boundTolerance", ops_.boundTolerance);
996  s.unpack("QpoasesInterface::ops::boundRelaxation", ops_.boundRelaxation);
997  s.unpack("QpoasesInterface::ops::epsNum", ops_.epsNum);
998  s.unpack("QpoasesInterface::ops::epsDen", ops_.epsDen);
999  s.unpack("QpoasesInterface::ops::maxPrimalJump", ops_.maxPrimalJump);
1000  s.unpack("QpoasesInterface::ops::maxDualJump", ops_.maxDualJump);
1001  s.unpack("QpoasesInterface::ops::initialRamping", ops_.initialRamping);
1002  s.unpack("QpoasesInterface::ops::finalRamping", ops_.finalRamping);
1003  s.unpack("QpoasesInterface::ops::initialFarBounds", ops_.initialFarBounds);
1004  s.unpack("QpoasesInterface::ops::growFarBounds", ops_.growFarBounds);
1005  std::string initialStatusBounds;
1006  s.unpack("QpoasesInterface::ops::initialStatusBounds", initialStatusBounds);
1007  ops_.initialStatusBounds = to_SubjectToStatus(initialStatusBounds);
1008  s.unpack("QpoasesInterface::ops::epsFlipping", ops_.epsFlipping);
1009  s.unpack("QpoasesInterface::ops::numRegularisationSteps", ops_.numRegularisationSteps);
1010  s.unpack("QpoasesInterface::ops::epsRegularisation", ops_.epsRegularisation);
1011  s.unpack("QpoasesInterface::ops::numRefinementSteps", ops_.numRefinementSteps);
1012  s.unpack("QpoasesInterface::ops::epsIterRef", ops_.epsIterRef);
1013  s.unpack("QpoasesInterface::ops::epsLITests", ops_.epsLITests);
1014  s.unpack("QpoasesInterface::ops::epsNZCTests", ops_.epsNZCTests);
1015  bool enableInertiaCorrection;
1016  s.unpack("QpoasesInterface::ops::enableInertiaCorrection", enableInertiaCorrection);
1017  ops_.enableInertiaCorrection = to_BooleanType(enableInertiaCorrection);
1018  }
1019 
1022  s.version("QpoasesInterface", 1);
1023  s.pack("QpoasesInterface::max_nWSR", max_nWSR_);
1024  s.pack("QpoasesInterface::max_cputime", max_cputime_);
1025  s.pack("QpoasesInterface::hess", static_cast<casadi_int>(hess_));
1026  s.pack("QpoasesInterface::sparse", sparse_);
1027  s.pack("QpoasesInterface::schur", schur_);
1028  s.pack("QpoasesInterface::max_schur", max_schur_);
1029  s.pack("QpoasesInterface::linsol_plugin", linsol_plugin_);
1030  s.pack("QpoasesInterface::ops::printLevel", static_cast<casadi_int>(ops_.printLevel));
1031  s.pack("QpoasesInterface::ops::enableRamping", from_BooleanType(ops_.enableRamping));
1032  s.pack("QpoasesInterface::ops::enableFarBounds",
1033  from_BooleanType(ops_.enableFarBounds));
1034  s.pack("QpoasesInterface::ops::enableFlippingBounds",
1035  from_BooleanType(ops_.enableFlippingBounds));
1036  s.pack("QpoasesInterface::ops::enableRegularisation",
1037  from_BooleanType(ops_.enableRegularisation));
1038  s.pack("QpoasesInterface::ops::enableFullLITests",
1039  from_BooleanType(ops_.enableFullLITests));
1040  s.pack("QpoasesInterface::ops::enableNZCTests", from_BooleanType(ops_.enableNZCTests));
1041  s.pack("QpoasesInterface::ops::enableDriftCorrection", ops_.enableDriftCorrection);
1042  s.pack("QpoasesInterface::ops::enableCholeskyRefactorisation",
1043  ops_.enableCholeskyRefactorisation);
1044  s.pack("QpoasesInterface::ops::enableEqualities", from_BooleanType(ops_.enableEqualities));
1045  s.pack("QpoasesInterface::ops::terminationTolerance", ops_.terminationTolerance);
1046  s.pack("QpoasesInterface::ops::boundTolerance", ops_.boundTolerance);
1047  s.pack("QpoasesInterface::ops::boundRelaxation", ops_.boundRelaxation);
1048  s.pack("QpoasesInterface::ops::epsNum", ops_.epsNum);
1049  s.pack("QpoasesInterface::ops::epsDen", ops_.epsDen);
1050  s.pack("QpoasesInterface::ops::maxPrimalJump", ops_.maxPrimalJump);
1051  s.pack("QpoasesInterface::ops::maxDualJump", ops_.maxDualJump);
1052  s.pack("QpoasesInterface::ops::initialRamping", ops_.initialRamping);
1053  s.pack("QpoasesInterface::ops::finalRamping", ops_.finalRamping);
1054  s.pack("QpoasesInterface::ops::initialFarBounds", ops_.initialFarBounds);
1055  s.pack("QpoasesInterface::ops::growFarBounds", ops_.growFarBounds);
1056  s.pack("QpoasesInterface::ops::initialStatusBounds",
1057  from_SubjectToStatus(ops_.initialStatusBounds));
1058  s.pack("QpoasesInterface::ops::epsFlipping", ops_.epsFlipping);
1059  s.pack("QpoasesInterface::ops::numRegularisationSteps", ops_.numRegularisationSteps);
1060  s.pack("QpoasesInterface::ops::epsRegularisation", ops_.epsRegularisation);
1061  s.pack("QpoasesInterface::ops::numRefinementSteps", ops_.numRefinementSteps);
1062  s.pack("QpoasesInterface::ops::epsIterRef", ops_.epsIterRef);
1063  s.pack("QpoasesInterface::ops::epsLITests", ops_.epsLITests);
1064  s.pack("QpoasesInterface::ops::epsNZCTests", ops_.epsNZCTests);
1065  s.pack("QpoasesInterface::ops::enableInertiaCorrection",
1066  from_BooleanType(ops_.enableInertiaCorrection));
1067 
1068  }
1069 
1070 } // 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
Sparsity H_
Problem structure.
Definition: conic_impl.hpp:166
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
Dict get_stats(void *mem) const override
Get all statistics.
Definition: conic.cpp:711
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
void version(const std::string &name, int v)
casadi_int nnz_in() const
Number of input/output nonzeros.
void alloc_w(size_t sz_w, bool persistent=false)
Ensure required length of w field.
Linear solver.
Definition: linsol.hpp:55
casadi_int rank(const DM &A) const
Matrix rank.
Definition: linsol.cpp:177
void nfact(const DM &A) const
Numeric factorization of the linear system.
Definition: linsol.cpp:127
DM solve(const DM &A, const DM &B, bool tr=false) const
Definition: linsol.cpp:73
void sfact(const DM &A) const
Symbolic factorization of the linear system, e.g. selecting pivots.
Definition: linsol.cpp:105
casadi_int neig(const DM &A) const
Number of negative eigenvalues.
Definition: linsol.cpp:166
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)
static int qpoases_init(void *mem, int dim, int nnz, const int *row, const int *col)
qpOASES linear solver initialization
static std::string from_SubjectToStatus(qpOASES::SubjectToStatus b)
static int qpoases_solve(void *mem, int nrhs, double *rhs)
qpOASES linear solver solve
static std::string getErrorMessage(casadi_int flag)
Get qpOASES error message.
static const Options options_
Options.
static const std::string meta_doc
A documentation string.
static int qpoases_sfact(void *mem, const double *vals)
qpOASES linear solver symbolical factorization
static Conic * creator(const std::string &name, const std::map< std::string, Sparsity > &st)
Create a new QP Solver.
static void qpoases_printf(const char *s)
qpOases printing function
Dict get_stats(void *mem) const override
Get all statistics.
static qpOASES::SubjectToStatus to_SubjectToStatus(std::string b)
void init(const Dict &opts) override
Initialize.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into MX.
QpoasesInterface()
Constructor.
static std::string from_PrintLevel(qpOASES::PrintLevel b)
static int qpoases_nfact(void *mem, const double *vals, int *neig, int *rank)
qpOASES linear solver numerical factorization
int init_mem(void *mem) const override
Initalize memory block.
static qpOASES::PrintLevel to_PrintLevel(std::string b)
int solve(const double **arg, double **res, casadi_int *iw, double *w, void *mem) const override
Evaluate numerically.
~QpoasesInterface() override
Destructor.
qpOASES::HessianType hess_
static qpOASES::BooleanType to_BooleanType(bool b)
static bool from_BooleanType(qpOASES::BooleanType b)
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
Helper class for Serialization.
void version(const std::string &name, int v)
void pack(const Sparsity &e)
Serializes an object to the output stream.
General sparsity class.
Definition: sparsity.hpp:106
casadi_int size1() const
Get the number of rows.
Definition: sparsity.cpp:124
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
static Sparsity triplet(casadi_int nrow, casadi_int ncol, const std::vector< casadi_int > &row, const std::vector< casadi_int > &col, std::vector< casadi_int > &mapping, bool invert_mapping)
Create a sparsity pattern given the nonzeros in sparse triplet form *.
Definition: sparsity.cpp:1127
The casadi namespace.
Definition: archiver.cpp:28
int CASADI_CONIC_QPOASES_EXPORT casadi_register_conic_qpoases(Conic::Plugin *plugin)
void copy_vector(const std::vector< S > &s, std::vector< D > &d)
@ CONIC_UBA
dense, (nc x 1)
Definition: conic.hpp:181
@ CONIC_A
The matrix A: sparse, (nc x n) - product with x must be dense.
Definition: conic.hpp:177
@ CONIC_G
The vector g: dense, (n x 1)
Definition: conic.hpp:175
@ CONIC_LBA
dense, (nc x 1)
Definition: conic.hpp:179
@ CONIC_UBX
dense, (n x 1)
Definition: conic.hpp:185
@ CONIC_H
Definition: conic.hpp:173
@ CONIC_LBX
dense, (n x 1)
Definition: conic.hpp:183
void casadi_copy(const T1 *x, casadi_int n, T1 *y)
COPY: y <-x.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
void casadi_densify(const T1 *x, const casadi_int *sp_x, T2 *y, casadi_int tr)
Convert sparse to dense.
void CASADI_CONIC_QPOASES_EXPORT casadi_load_conic_qpoases()
void casadi_scal(casadi_int n, T1 alpha, T1 *x)
SCAL: x <- alpha*x.
T * get_ptr(std::vector< T > &v)
Get a pointer to the data contained in the vector.
std::ostream & uout()
@ SOLVER_RET_INFEASIBLE
@ SOLVER_RET_LIMITED
@ SOLVER_RET_SUCCESS
@ CONIC_X
The primal solution.
Definition: conic.hpp:201
@ CONIC_LAM_A
The dual solution corresponding to linear bounds.
Definition: conic.hpp:205
@ CONIC_COST
The optimal cost.
Definition: conic.hpp:203
@ CONIC_LAM_X
The dual solution corresponding to simple bounds.
Definition: conic.hpp:207
Options metadata for a class.
Definition: options.hpp:40
std::map< std::string, FStats > fstats
bool called_once
Has qpOASES been called once?
std::vector< casadi_int > nz_map
std::vector< casadi_int > lin_map
std::vector< double > nz
std::vector< casadi_int > col
qpOASES::SymSparseMat * h
std::vector< casadi_int > row
qpOASES::QProblemB * qp
qpOASES::SparseMatrix * a