26 #include "qpoases_interface.hpp"
29 #define ALLOW_QPROBLEMB true
30 #define ALLOW_ALL_OPTIONS
35 int CASADI_CONIC_QPOASES_EXPORT
38 plugin->name =
"qpoases";
40 plugin->version = CASADI_VERSION;
52 const std::map<std::string, Sparsity>& st)
55 static bool first_call =
true;
74 "Formulate the QP using sparse matrices. [false]"}},
77 "Use Schur Complement Approach [false]"}},
80 "Type of Hessian - see qpOASES documentation "
81 "[UNKNOWN|posdef|semidef|indef|zero|identity]]"}},
84 "Maximal number of Schur updates [75]"}},
87 "Linear solver plugin"}},
90 "The maximum number of working set recalculations to be performed during "
91 "the initial homotopy. Default is 5(nx + nc)"}},
94 "The maximum allowed CPU time in seconds for the whole initialisation"
95 " (and the actually required one on output). Disabled if unset."}},
98 "Defines the amount of text output during QP solution, see Section 5.7"}},
101 "Enables ramping."}},
104 "Enables the use of far bounds."}},
105 {
"enableFlippingBounds",
107 "Enables the use of flipping bounds."}},
108 {
"enableRegularisation",
110 "Enables automatic Hessian regularisation."}},
111 {
"enableFullLITests",
113 "Enables condition-hardened (but more expensive) LI test."}},
116 "Enables nonzero curvature tests."}},
117 {
"enableDriftCorrection",
119 "Specifies the frequency of drift corrections: 0: turns them off."}},
120 {
"enableCholeskyRefactorisation",
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."}},
126 "Specifies whether equalities should be treated as always active "
127 "(True) or not (False)"}},
128 {
"terminationTolerance",
130 "Relative termination tolerance to stop homotopy."}},
133 "If upper and lower bounds differ less than this tolerance, they are regarded "
134 "equal, i.e. as equality constraint."}},
137 "Initial relaxation of bounds to start homotopy and initial value for far bounds."}},
140 "Numerator tolerance for ratio tests."}},
143 "Denominator tolerance for ratio tests."}},
146 "Maximum allowed jump in primal variables in nonzero curvature tests."}},
149 "Maximum allowed jump in dual variables in linear independence tests."}},
152 "Start value for ramping strategy."}},
155 "Final value for ramping strategy."}},
158 "Initial size for far bounds."}},
161 "Factor to grow far bounds."}},
162 {
"initialStatusBounds",
164 "Initial status of bounds at first iteration."}},
167 "Tolerance of squared Cholesky diagonal factor which triggers flipping bound."}},
168 {
"numRegularisationSteps",
170 "Maximum number of successive regularisation steps."}},
171 {
"epsRegularisation",
173 "Scaling factor of identity matrix used for Hessian regularisation."}},
174 {
"numRefinementSteps",
176 "Maximum number of iterative refinement steps."}},
179 "Early termination tolerance for iterative refinement."}},
182 "Tolerance for linear independence tests."}},
185 "Tolerance for nonzero curvature tests."}},
186 {
"enableInertiaCorrection",
188 "Should working set be repaired when negative curvature is discovered during hotstart."}}
198 hess_ = qpOASES::HessianType::HST_UNKNOWN;
206 for (
auto&& op : opts) {
207 if (op.first==
"sparse") {
209 }
else if (op.first==
"schur") {
211 }
else if (op.first==
"hessian_type") {
212 std::string h = op.second;
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;
226 casadi_error(
"Unknown Hessian type \"" + h +
"\"");
228 }
else if (op.first==
"max_schur") {
230 }
else if (op.first==
"linsol_plugin") {
232 }
else if (op.first==
"nWSR") {
234 }
else if (op.first==
"CPUtime") {
236 }
else if (op.first==
"printLevel") {
238 }
else if (op.first==
"enableRamping") {
240 }
else if (op.first==
"enableFarBounds") {
242 }
else if (op.first==
"enableFlippingBounds") {
244 }
else if (op.first==
"enableRegularisation") {
246 }
else if (op.first==
"enableFullLITests") {
248 }
else if (op.first==
"enableNZCTests") {
250 }
else if (op.first==
"enableDriftCorrection") {
252 }
else if (op.first==
"enableCholeskyRefactorisation") {
253 ops_.enableCholeskyRefactorisation = op.second;
254 }
else if (op.first==
"enableEqualities") {
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") {
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") {
301 casadi_error(
"With no linear constraints, qpOASES fails in sparse mode: "
302 "https://github.com/casadi/casadi/issues/2358");
335 m->qp =
new qpOASES::QProblemB(
nx_,
hess_);
341 m->qp->setOptions(
ops_);
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);
355 solve(
const double** arg,
double** res, casadi_int* iw,
double* w,
void* mem)
const {
358 m->
fstats.at(
"preprocessing").tic();
361 m->return_status = -1;
366 double *cputime_ptr = cputime<=0 ? nullptr : &cputime;
369 double* g=w; w +=
nx_;
371 double* lb=w; w +=
nx_;
373 double* ub=w; w +=
nx_;
375 double* lbA=w; w +=
na_;
377 double* ubA=w; w +=
na_;
388 double* h=w; w +=
H_.
nnz();
393 m->h->createDiagInfo();
398 double* a=w; w +=
A_.
nnz();
404 m->fstats.at(
"preprocessing").toc();
405 m->fstats.at(
"solver").tic();
408 if (m->called_once) {
409 flag = m->sqp->hotstart(m->h, g, m->a, lb, ub, lbA, ubA, nWSR, cputime_ptr);
411 flag = m->sqp->init(m->h, g, m->a, lb, ub, lbA, ubA, nWSR, cputime_ptr);
413 m->fstats.at(
"solver").toc();
417 double* h=w; w +=
nx_*
nx_;
421 double* a = w; w +=
nx_*
na_;
424 m->fstats.at(
"preprocessing").toc();
425 m->fstats.at(
"solver").tic();
428 if (m->called_once) {
432 flag = m->qp->init(h, g, lb, ub, nWSR, cputime_ptr);
434 flag = m->qp->init(h, g, lb, ub, nWSR, cputime_ptr);
437 if (m->called_once) {
438 flag = m->sqp->hotstart(h, g, a, lb, ub, lbA, ubA, nWSR, cputime_ptr);
440 flag = m->sqp->init(h, g, a, lb, ub, lbA, ubA, nWSR, cputime_ptr);
443 m->fstats.at(
"solver").toc();
447 m->called_once =
true;
449 m->fstats.at(
"postprocessing").tic();
451 m->return_status = flag;
452 m->d_qp.success = flag==qpOASES::SUCCESSFUL_RETURN;
454 if (flag == qpOASES::RET_MAX_NWSR_REACHED) {
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) {
468 m->d_qp.iter_count = nWSR;
480 double* dual=w; w +=
nx_+
na_;
481 m->qp->getDualSolution(dual);
487 m->fstats.at(
"postprocessing").toc();
489 return m->d_qp.unified_return_status;
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.";
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.";
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.";
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.";
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.";
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.";
750 case qpOASES::RET_UNABLE_TO_ANALYSE_QPROBLEM:
751 return "Unable to analyse (S)QProblem(B) object";
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.";
768 std::stringstream ss;
769 ss <<
"Unknown error flag: " << flag <<
". Consult qpOASES documentation.";
775 case qpOASES::BT_TRUE:
return true;
776 case qpOASES::BT_FALSE:
return false;
778 casadi_error(
"not_implemented");
782 return b ? qpOASES::BT_TRUE : qpOASES::BT_FALSE;
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";
794 casadi_error(
"not_implemented");
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;
809 casadi_error(
"No such qpOASES::SubjectToStatus: " + 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";
822 casadi_error(
"not_implemented");
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;
839 casadi_error(
"No such qpOASES::PrintLevel: " + b);
856 qpoases_init(
void* mem,
int dim,
int nnz,
const int* row,
const int* col) {
857 casadi_assert_dev(mem!=
nullptr);
864 for (casadi_int k=0; k<nnz; ++k) {
866 m->
row.push_back(row[k]-1);
867 m->
col.push_back(col[k]-1);
870 if (row[k]!=col[k]) {
871 m->
row.push_back(col[k]-1);
872 m->
col.push_back(row[k]-1);
882 m->
nz.resize(sp.
nnz());
891 casadi_assert_dev(mem!=
nullptr);
895 for (
int i=0; i<m->
nz.size(); ++i) m->
nz[i] = vals[m->
lin_map[i]];
904 qpoases_nfact(
void* mem,
const double* vals,
int* neig,
int* rank) {
905 casadi_assert_dev(mem!=
nullptr);
909 for (casadi_int i=0; i<m->
nz.size(); ++i) m->
nz[i] = vals[m->
lin_map[i]];
924 casadi_assert_dev(mem!=
nullptr);
941 s.
version(
"QpoasesInterface", 1);
945 s.
unpack(
"QpoasesInterface::hess", hess);
946 hess_ =
static_cast<qpOASES::HessianType
>(hess);
952 casadi_int print_level;
953 s.
unpack(
"QpoasesInterface::ops::printLevel", print_level);
956 s.
unpack(
"QpoasesInterface::ops::enableRamping", enableRamping);
960 bool enableFarBounds;
961 s.
unpack(
"QpoasesInterface::ops::enableFarBounds", enableFarBounds);
965 bool enableFlippingBounds;
966 s.
unpack(
"QpoasesInterface::ops::enableFlippingBounds", enableFlippingBounds);
970 bool enableRegularisation;
971 s.
unpack(
"QpoasesInterface::ops::enableRegularisation", enableRegularisation);
975 bool enableFullLITests;
976 s.
unpack(
"QpoasesInterface::ops::enableFullLITests", enableFullLITests);
981 s.
unpack(
"QpoasesInterface::ops::enableNZCTests", enableNZCTests);
985 s.
unpack(
"QpoasesInterface::ops::enableDriftCorrection",
ops_.enableDriftCorrection);
986 s.
unpack(
"QpoasesInterface::ops::enableCholeskyRefactorisation",
987 ops_.enableCholeskyRefactorisation);
990 bool enableEqualities;
991 s.
unpack(
"QpoasesInterface::ops::enableEqualities", enableEqualities);
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);
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);
1022 s.
version(
"QpoasesInterface", 1);
1025 s.
pack(
"QpoasesInterface::hess",
static_cast<casadi_int
>(
hess_));
1030 s.
pack(
"QpoasesInterface::ops::printLevel",
static_cast<casadi_int
>(
ops_.printLevel));
1032 s.
pack(
"QpoasesInterface::ops::enableFarBounds",
1034 s.
pack(
"QpoasesInterface::ops::enableFlippingBounds",
1036 s.
pack(
"QpoasesInterface::ops::enableRegularisation",
1038 s.
pack(
"QpoasesInterface::ops::enableFullLITests",
1041 s.
pack(
"QpoasesInterface::ops::enableDriftCorrection",
ops_.enableDriftCorrection);
1042 s.
pack(
"QpoasesInterface::ops::enableCholeskyRefactorisation",
1043 ops_.enableCholeskyRefactorisation);
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",
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",
static const Options options_
Options.
casadi_int nx_
Number of decision variables.
int init_mem(void *mem) const override
Initalize memory block.
casadi_int na_
The number of constraints (counting both equality and inequality) == A.size1()
Sparsity H_
Problem structure.
void init(const Dict &opts) override
Initialize.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
Dict get_stats(void *mem) const override
Get all statistics.
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.
casadi_int rank(const DM &A) const
Matrix rank.
void nfact(const DM &A) const
Numeric factorization of the linear system.
DM solve(const DM &A, const DM &B, bool tr=false) const
void sfact(const DM &A) const
Symbolic factorization of the linear system, e.g. selecting pivots.
casadi_int neig(const DM &A) const
Number of negative eigenvalues.
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.
std::string linsol_plugin_
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.
casadi_int size1() const
Get the number of rows.
casadi_int nnz() const
Get the number of (structural) non-zeros.
casadi_int size2() const
Get the number of columns.
const casadi_int * row() const
Get a reference to row-vector,.
const casadi_int * colind() const
Get a reference to the colindex of all column element (see class description)
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 *.
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)
@ CONIC_A
The matrix A: sparse, (nc x n) - product with x must be dense.
@ CONIC_G
The vector g: dense, (n x 1)
@ CONIC_LBA
dense, (nc x 1)
@ CONIC_UBX
dense, (n x 1)
@ CONIC_LBX
dense, (n x 1)
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.
@ CONIC_X
The primal solution.
@ CONIC_LAM_A
The dual solution corresponding to linear bounds.
@ CONIC_COST
The optimal cost.
@ CONIC_LAM_X
The dual solution corresponding to simple bounds.
Options metadata for a class.
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< casadi_int > col
qpOASES::SymSparseMat * h
~QpoasesMemory()
Destructor.
std::vector< casadi_int > row
std::string linsol_plugin
qpOASES::SparseMatrix * a
QpoasesMemory()
Constructor.