26 #include "blocksqp.hpp"
27 #include "casadi/core/casadi_misc.hpp"
28 #include "casadi/core/conic.hpp"
33 int CASADI_NLPSOL_BLOCKSQP_EXPORT
36 plugin->name =
"blocksqp";
38 plugin->version = CASADI_VERSION;
62 "The QP solver to be used by the SQP method"}},
65 "Options to be passed to the QP solver"}},
68 "The linear solver to be used by the QP method"}},
71 "Print solver header at startup"}},
74 "Print SQP iterations"}},
77 "Values smaller than this are regarded as numerically zero"}},
80 "Optimality tolerance"}},
83 "Nonlinear feasibility tolerance"}},
86 "Use qpOASES Schur compliment approach"}},
89 "Enable globalization"}},
92 "Use feasibility restoration phase"}},
95 "Maximum number of steps in line search"}},
96 {
"max_consec_reduced_steps",
98 "Maximum number of consecutive reduced steps"}},
99 {
"max_consec_skipped_updates",
101 "Maximum number of consecutive skipped updates"}},
104 "Maximum number of SQP iterations"}},
107 "Use warmstarting"}},
110 "Use warmstarting"}},
113 "Maximum number of QP iterations per SQP iteration"}},
116 "Blockwise Hessian approximation?"}},
119 "Scaling strategy for Hessian approximation"}},
122 "If indefinite update is used, the type of fallback strategy"}},
125 "Maximum number of time in seconds per QP solve per SQP iteration"}},
128 "Initial Hessian guess: diagonal matrix diag(iniHessDiag)"}},
131 "Epsilon for COL scaling strategy"}},
134 "tau1 for COL scaling strategy"}},
137 "tau2 for COL scaling strategy"}},
140 "Activate Powell damping for BFGS"}},
143 "Damping factor for BFGS Powell modification"}},
146 "Type of Hessian approximation"}},
149 "If indefinite update is used, the type of fallback strategy"}},
152 "Full or limited memory"}},
155 "Memory size for L-BFGS updates"}},
156 {
"which_second_derv",
158 "For which block should second derivatives be provided by the user"}},
159 {
"skip_first_globalization",
161 "No globalization strategy in first iteration"}},
164 "Convexification strategy"}},
167 "How many additional QPs may be solved for convexification per iteration?"}},
170 "Maximum number of SOC line search iterations"}},
173 "Filter line search parameter, cf. IPOPT paper"}},
176 "Filter line search parameter, cf. IPOPT paper"}},
179 "Filter line search parameter, cf. IPOPT paper"}},
182 "Filter line search parameter, cf. IPOPT paper"}},
185 "Filter line search parameter, cf. IPOPT paper"}},
188 "Filter line search parameter, cf. IPOPT paper"}},
191 "Filter line search parameter, cf. IPOPT paper"}},
194 "Filter line search parameter, cf. IPOPT paper"}},
197 "Filter line search parameter, cf. IPOPT paper"}},
200 "Filter line search parameter, cf. IPOPT paper"}},
203 "Filter line search parameter, cf. IPOPT paper"}},
206 "Filter line search parameter, cf. IPOPT paper"}},
209 "Filter line search parameter, cf. IPOPT paper"}},
212 "Filter line search parameter, cf. IPOPT paper"}},
215 "Lower bound on objective function [-inf]"}},
218 "Upper bound on objective function [inf]"}},
221 "Feasibility restoration phase parameter"}},
224 "Feasibility restoration phase parameter"}},
225 {
"print_maxit_reached",
227 "Print error when maximum number of SQP iterations reached"}}
294 for (
auto&& op : opts) {
295 if (op.first==
"qpsol") {
297 casadi_warning(
"Option 'qpsol' currently not supported, ignored");
298 }
else if (op.first==
"qpsol_options") {
300 casadi_warning(
"Option 'qpsol_options' currently not supported, ignored");
301 }
else if (op.first==
"linsol") {
303 }
else if (op.first==
"print_header") {
305 }
else if (op.first==
"print_iteration") {
307 }
else if (op.first==
"eps") {
309 }
else if (op.first==
"opttol") {
311 }
else if (op.first==
"nlinfeastol") {
313 }
else if (op.first==
"schur") {
315 }
else if (op.first==
"globalization") {
317 }
else if (op.first==
"restore_feas") {
319 }
else if (op.first==
"max_line_search") {
321 }
else if (op.first==
"max_consec_reduced_steps") {
323 }
else if (op.first==
"max_consec_skipped_updates") {
325 }
else if (op.first==
"max_iter") {
327 }
else if (op.first==
"warmstart") {
329 }
else if (op.first==
"qp_init") {
331 }
else if (op.first==
"max_it_qp") {
333 }
else if (op.first==
"block_hess") {
335 }
else if (op.first==
"hess_scaling") {
337 }
else if (op.first==
"fallback_scaling") {
339 }
else if (op.first==
"max_time_qp") {
341 }
else if (op.first==
"ini_hess_diag") {
343 }
else if (op.first==
"col_eps") {
345 }
else if (op.first==
"col_tau1") {
347 }
else if (op.first==
"col_tau2") {
349 }
else if (op.first==
"hess_damp") {
351 }
else if (op.first==
"hess_damp_fac") {
353 }
else if (op.first==
"hess_update") {
355 }
else if (op.first==
"fallback_update") {
357 }
else if (op.first==
"hess_lim_mem") {
359 }
else if (op.first==
"hess_memsize") {
361 }
else if (op.first==
"which_second_derv") {
363 }
else if (op.first==
"skip_first_globalization") {
365 }
else if (op.first==
"conv_strategy") {
367 }
else if (op.first==
"max_conv_qp") {
369 }
else if (op.first==
"max_soc_iter") {
371 }
else if (op.first==
"gamma_theta") {
373 }
else if (op.first==
"gamma_f") {
375 }
else if (op.first==
"kappa_soc") {
377 }
else if (op.first==
"kappa_f") {
379 }
else if (op.first==
"theta_max") {
381 }
else if (op.first==
"theta_min") {
383 }
else if (op.first==
"delta") {
385 }
else if (op.first==
"s_theta") {
387 }
else if (op.first==
"s_f") {
389 }
else if (op.first==
"kappa_minus") {
391 }
else if (op.first==
"kappa_plus") {
393 }
else if (op.first==
"kappa_plus_max") {
395 }
else if (op.first==
"delta_h0") {
397 }
else if (op.first==
"eta") {
399 }
else if (op.first==
"obj_lo") {
401 }
else if (op.first==
"obj_up") {
403 }
else if (op.first==
"rho") {
405 }
else if (op.first==
"zeta") {
407 }
else if (op.first==
"print_maxit_reached") {
422 print(
"***WARNING: SR1 update only works with qpOASES Schur complement version. "
423 "Using BFGS updates instead.\n");
432 std::vector<MX> resv;
433 std::vector<MX> argv = nlp.
mx_in();
439 MX d = fmin(1.0, 1.0/abs(p)) * (argv.at(0) - p);
441 MX g_rp = nlp(argv).at(1) - s;
450 solver_options[
"globalization"] =
true;
451 solver_options[
"which_second_derv"] = 0;
452 solver_options[
"restore_feas"] =
false;
453 solver_options[
"hess_update"] = 2;
454 solver_options[
"hess_lim_mem"] = 1;
455 solver_options[
"hess_scaling"] = 2;
456 solver_options[
"opttol"] =
opttol_;
458 solver_options[
"max_iter"] = 1;
459 solver_options[
"print_time"] =
false;
460 solver_options[
"print_header"] =
false;
461 solver_options[
"print_iteration"] =
false;
462 solver_options[
"print_maxit_reached"] =
false;
471 {
"f",
"g",
"grad:f:x",
"jac:g:x"});
472 Asp_ = gf_jg.sparsity_out(
"jac_g_x");
484 {
"x",
"p",
"lam:f",
"lam:g"}, {
"grad:gamma:x"},
485 {{
"gamma", {
"f",
"g"}}});
494 const casadi_int* row =
Hsp_.
row();
499 casadi_int next=ind+1;
500 while (ind<next && ind<
nx_) {
501 for (casadi_int k=colind[ind]; k<colind[ind+1]; ++k) next = std::max(next, 1+row[k]);
513 casadi_int max_size = 0;
515 for (casadi_int i=0; i<
nblocks_; ++i) {
517 max_size = std::max(max_size,
dim_[i]);
522 {
"triu:hess:gamma:x:x"}, {{
"gamma", {
"f",
"g"}}});
583 casadi_int*& iw,
double*& w)
const {
591 m->lam_xk = w; w +=
nx_;
592 m->lam_gk = w; w +=
ng_;
594 m->grad_fk = w; w +=
nx_;
595 m->grad_lagk = w; w +=
nx_;
596 m->lam_qp = w; w +=
nx_+
ng_;
598 m->delta_norm_old = w; w +=
nblocks_;
600 m->delta_gamma_old = w; w +=
nblocks_;
602 m->trial_xk = w; w +=
nx_;
603 m->lbx_qp = w; w +=
nx_;
604 m->ubx_qp = w; w +=
nx_;
605 m->lba_qp = w; w +=
ng_;
606 m->uba_qp = w; w +=
ng_;
607 m->jac_times_dxk = w; w +=
ng_;
611 m->hess_lag = w; w +=
nnz_H_;
612 m->hessIndRow =
reinterpret_cast<int*
>(iw); iw +=
nnz_H_ + (
nx_+1) +
nx_;
613 m->noUpdateCounter = iw; iw +=
nblocks_;
617 for (casadi_int b=0; b<
nblocks_; b++) {
618 m->hess1[b] = w; w +=
dim_[b]*
dim_[b];
624 for (casadi_int b=0; b<
nblocks_; b++) {
625 m->hess2[b] = w; w +=
dim_[b]*
dim_[b];
636 auto d_nlp = &m->
d_nlp;
641 std::vector<casadi_int> blocks =
blocks_;
649 m->qpIterations2 = 0;
654 m->averageSizingFactor = 0.0;
657 m->nRestHeurCalls = 0;
658 m->nRestPhaseCalls = 0;
660 m->nTotalUpdates = 0;
661 m->nTotalSkippedUpdates = 0;
663 casadi_int maxblocksize = 1;
665 for (casadi_int k=0; k<
nblocks_+1; k++) {
684 m->qp =
new qpOASES::SQProblemSchur(
nx_,
ng_, qpOASES::HST_UNKNOWN, 50,
691 m->qp =
new qpOASES::SQProblem(
nx_,
ng_);
726 d_nlp->objective = m->obj;
741 casadi_int it, infoQP = 0;
742 bool skipLineSearch =
false;
743 bool hasConverged =
false;
745 if (warmStart == 0 || m->
itCount == 0) {
769 print(
"\n***CONVERGENCE ACHIEVED!***\n");
779 for (it=0; it<maxIt; it++) {
786 print(
"***WARNING: Maximum number of QP iterations exceeded.***\n");
787 }
else if (infoQP == 2 || infoQP > 3) {
789 print(
"***WARNING: QP error. Solve again with identity matrix.***\n");
794 print(
"***WARNING: QP error. Stop.***\n");
799 }
else if (infoQP == 3) {
802 skipLineSearch =
true;
806 print(
"***WARNING: QP infeasible. Trying to reduce constraint violation ...");
810 print(
"Success.***\n");
812 print(
"Failure.***\n");
819 print(
"***Start feasibility restoration phase.***\n");
826 print(
"***WARNING: QP error. Stop.\n");
835 print(
"***WARNING: Constraint or objective could "
836 "not be evaluated at new point. Stop.***\n");
856 print(
"***WARNING: Steplength too short. "
857 "Trying to reduce constraint violation...");
863 print(
"Success.***\n");
865 print(
"***WARNING: Failed.***\n");
874 print(
"***WARNING: Steplength too short. "
875 "Trying to find a new step with identity Hessian.***\n");
884 print(
"***WARNING: Steplength too short. "
885 "Start feasibility restoration phase.***\n");
894 print(
"***WARNING: Line search error. Stop.***\n");
915 if (hasConverged && m->
steptype < 2) {
939 skipLineSearch =
false;
954 const double* lam_x,
const double* lam_g,
955 const double* grad_f,
const double *jacNz,
956 double* grad_lag, casadi_int flag)
const {
961 }
else if (flag == 1) {
969 const casadi_int* jacIndRow =
Asp_.
row();
971 for (casadi_int iVar=0; iVar<
nx_; iVar++) {
972 for (casadi_int iCon=jacIndCol[iVar]; iCon<jacIndCol[iVar+1]; iCon++) {
973 grad_lag[iVar] -= lam_g[jacIndRow[iCon]] * jacNz[iCon];
998 auto d_nlp = &m->
d_nlp;
1013 char hessString1[100];
1014 char hessString2[100];
1015 char globString[100];
1020 strcpy(qpString,
"sparse, Schur complement approach");
1022 strcpy(qpString,
"sparse, reduced Hessian factorization");
1026 strcpy(globString,
"filter line search");
1028 strcpy(globString,
"none (full step)");
1033 strcpy(hessString1,
"block ");
1035 strcpy(hessString1,
"");
1038 strcat(hessString1,
"L-");
1043 strcpy(hessString2, hessString1);
1047 strcat(hessString2,
"Id");
1049 strcat(hessString2,
"SR1");
1051 strcat(hessString2,
"BFGS");
1053 strcat(hessString2,
"Finite differences");
1058 strcat(hessString2,
", SP");
1060 strcat(hessString2,
", OL");
1062 strcat(hessString2,
", mean");
1064 strcat(hessString2,
", selective sizing");
1067 strcpy(hessString2,
"-");
1072 strcat(hessString1,
"Id");
1074 strcat(hessString1,
"SR1");
1076 strcat(hessString1,
"BFGS");
1078 strcat(hessString1,
"Finite differences");
1083 strcat(hessString1,
", SP");
1085 strcat(hessString1,
", OL");
1087 strcat(hessString1,
", mean");
1089 strcat(hessString1,
", selective sizing");
1092 print(
"\n+---------------------------------------------------------------+\n");
1093 print(
"| Starting blockSQP with the following algorithmic settings: |\n");
1094 print(
"+---------------------------------------------------------------+\n");
1095 print(
"| qpOASES flavor | %-34s|\n", qpString);
1096 print(
"| Globalization | %-34s|\n", globString);
1097 print(
"| 1st Hessian approximation | %-34s|\n", hessString1);
1098 print(
"| 2nd Hessian approximation | %-34s|\n", hessString2);
1099 print(
"+---------------------------------------------------------------+\n\n");
1109 const double* lambdaQP,
double alpha, casadi_int nSOCS)
const {
1110 auto d_nlp = &m->
d_nlp;
1118 for (casadi_int k=0; k<
nx_; k++) {
1120 m->
dxk[k] = alpha * deltaXi[k];
1125 for (casadi_int k=0; k<
nx_; k++)
1128 for (casadi_int k=0; k<
ng_; k++)
1133 for (casadi_int k=0; k<
nx_; k++)
1134 m->
lam_xk[k] = (1.0 - alpha)*m->
lam_xk[k] + alpha*lambdaQP[k];
1135 for (casadi_int k=0; k<
ng_; k++)
1147 *alpha = (*alpha) * 0.5;
1152 auto d_nlp = &m->
d_nlp;
1155 for (casadi_int i=0; i<
ng_; i++) {
1156 double lbg = d_nlp->
lbz[i +
nx_];
1157 double ubg = d_nlp->ubz[i +
nx_];
1180 auto d_nlp = &m->
d_nlp;
1182 double objTrial, cNormTrial;
1186 for (casadi_int k=0; k<10; k++) {
1188 for (casadi_int i=0; i<
nx_; i++)
1197 if (
info != 0 || objTrial < obj_lo_ || objTrial >
obj_up_
1198 || !(objTrial == objTrial) || !(cNormTrial == cNormTrial)) {
1199 print(
"info=%i, objTrial=%g\n",
info, objTrial);
1218 auto d_nlp = &m->
d_nlp;
1220 double cNormTrial=0, objTrial, dfTdeltaXi=0;
1229 for (casadi_int i=0; i<
nx_; i++)
1234 for (casadi_int i=0; i<
nx_; i++)
1242 if (
info != 0 || objTrial < obj_lo_ || objTrial >
obj_up_
1243 || !(objTrial == objTrial) || !(cNormTrial == cNormTrial)) {
1269 if (alpha * pow((-dfTdeltaXi),
s_f_)
1272 if (objTrial > m->
obj +
eta_*alpha*dfTdeltaXi) {
1291 || objTrial < m->obj -
gamma_f_ * cNorm) {
1310 if (dfTdeltaXi >= 0) {
1315 }
else if (objTrial <= m->obj +
eta_*alpha*dfTdeltaXi) {
1333 double dfTdeltaXi,
bool swCond, casadi_int it)
const {
1334 auto d_nlp = &m->
d_nlp;
1337 if (it > 0)
return false;
1339 if (cNormTrial < cNorm)
return false;
1341 casadi_int nSOCS = 0;
1342 double cNormTrialSOC, cNormOld, objTrialSOC;
1348 std::vector<double> deltaXiSOC(
nx_, 0.);
1349 std::vector<double> lambdaQPSOC(
nx_+
ng_, 0.);
1363 if (
info != 0)
return false;
1366 for (casadi_int i=0; i<
nx_; i++) {
1367 m->
trial_xk[i] = d_nlp->z[i] + deltaXiSOC[i];
1374 if (
info != 0 || objTrialSOC < obj_lo_ || objTrialSOC >
obj_up_
1375 || !(objTrialSOC == objTrialSOC) || !(cNormTrialSOC == cNormTrialSOC)) {
1388 if (objTrialSOC > m->
obj +
eta_*dfTdeltaXi) {
1395 cNormOld = cNormTrialSOC;
1408 || objTrialSOC < m->obj -
gamma_f_ * cNorm) {
1419 cNormOld = cNormTrialSOC;
1435 auto d_nlp = &m->
d_nlp;
1441 casadi_int ret,
info;
1442 casadi_int maxRestIt = 100;
1443 casadi_int warmStart;
1444 double cNormTrial, objTrial, lStpNorm;
1451 std::vector<double> in_x0(d_nlp->z, d_nlp->z+
nx_);
1454 for (casadi_int i=0; i<
ng_; i++) {
1455 if (m->
gk[i] <= d_nlp->lbz[i+
nx_])
1456 in_x0.push_back(m->
gk[i] - d_nlp->lbz[i+
nx_]);
1457 else if (m->
gk[i] > d_nlp->ubz[i+
nx_])
1458 in_x0.push_back(m->
gk[i] - d_nlp->ubz[i+
nx_]);
1460 in_x0.push_back(0.0);
1464 std::vector<double> in_p(d_nlp->p, d_nlp->p+
np_);
1465 std::vector<double> in_p2(d_nlp->z, d_nlp->z+
nx_);
1466 in_p.insert(in_p.end(), in_p2.begin(), in_p2.end());
1469 std::vector<double> in_lbx(d_nlp->lbz, d_nlp->lbz+
nx_);
1470 std::vector<double> in_ubx(d_nlp->ubz, d_nlp->ubz+
nx_);
1471 for (casadi_int i=0; i<
ng_; i++) {
1472 in_lbx.push_back(-
inf);
1473 in_ubx.push_back(
inf);
1477 std::vector<double> in_lbg(d_nlp->lbz+
nx_, d_nlp->lbz+
nx_+
ng_);
1478 std::vector<double> in_ubg(d_nlp->ubz+
nx_, d_nlp->ubz+
nx_+
ng_);
1480 solver_in[
"x0"] = in_x0;
1481 solver_in[
"p"] = in_p;
1482 solver_in[
"lbx"] = in_lbx;
1483 solver_in[
"ubx"] = in_ubx;
1484 solver_in[
"lbg"] = in_lbg;
1485 solver_in[
"ubg"] = in_ubg;
1509 std::vector<DM> arg_v(n_in);
1510 for (casadi_int i=0; i<arg_v.size(); i++)
1517 for (casadi_int i=0; i<arg_v.size(); i++)
1521 std::vector<DM> res(n_out);
1522 for (casadi_int i=0; i<n_out; i++) {
1533 for (casadi_int i=0; i<n_in; ++i) argp[i] =
get_ptr(arg_v[i]);
1537 for (casadi_int i=0; i<n_out; i++) resp[i] =
get_ptr(res[i]);
1550 for (casadi_int it=0; it<maxRestIt; it++) {
1553 ret = bp->
run(m2, 1, warmStart);
1560 for (casadi_int i=0; i<
nx_; i++)
1567 if (
info != 0 || objTrial < obj_lo_ || objTrial >
obj_up_ ||
1568 !(objTrial == objTrial) || !(cNormTrial == cNormTrial) )
1574 print(
"Found a point acceptable for the filter.\n");
1587 if (ret == 0 || ret == 1) {
1591 for (casadi_int k=0; k<
nx_; k++) {
1592 m->
dxk[k] = d_nlp->z[k];
1599 m->
lam_xk[k] = m2->lam_xk[k];
1600 m->
lam_qp[k] = m2->lam_qp[k];
1602 m->
dxk[k] -= d_nlp->z[k];
1604 for (casadi_int k=0; k<
ng_; k++) {
1608 m->
lam_gk[k] = m2->lam_gk[k];
1624 print(
"The problem seems to be locally infeasible. Infeasibilities minimized.\n");
1637 auto d_nlp = &m->
d_nlp;
1643 for (casadi_int k=0; k<
nx_; k++)
1655 auto d_nlp = &m->
d_nlp;
1656 casadi_int
info = 0;
1657 double objTrial, cNormTrial, trialGradNorm, trialTol;
1660 for (casadi_int i=0; i<
nx_; i++)
1664 std::vector<double> trialConstr(
ng_, 0.);
1668 if (
info != 0 || objTrial < obj_lo_ || objTrial >
obj_up_
1669 || !(objTrial == objTrial) || !(cNormTrial == cNormTrial)) {
1677 std::vector<double> trialGradLagrange(
nx_, 0.);
1680 get_ptr(trialGradLagrange), 0);
1710 for (
auto&& f : m->
filter) {
1713 obj >= f.second -
gamma_f_ * f.first) {
1726 auto iter=m->
filter.begin();
1727 while (iter != m->
filter.end()) {
1728 std::set< std::pair<double, double> >::iterator iterToRemove = iter;
1730 m->
filter.erase(iterToRemove);
1734 m->
filter.insert(initPair);
1743 std::pair<double, double> entry((1-
gamma_theta_)*cNorm,
1750 auto iter=m->
filter.begin();
1751 while (iter != m->
filter.end()) {
1752 if (iter->first > entry.first && iter->second > entry.second) {
1753 auto iterToRemove = iter;
1755 m->
filter.erase(iterToRemove);
1766 for (casadi_int b=0; b<
nblocks_; b++)
1778 casadi_int dim =
dim_[b];
1782 for (casadi_int i=0; i<dim; i++)
1786 if (m->
hess2 !=
nullptr) {
1788 for (casadi_int i=0; i<dim; i++)
1795 for (casadi_int b=0; b<
nblocks_; b++) {
1805 casadi_int dim =
dim_[b];
1836 const double* delta, casadi_int b, casadi_int option)
const {
1837 casadi_int dim =
dim_[b];
1839 double myEps = 1.0e3 *
eps_;
1844 / fmax(
casadi_dot(dim, delta, gamma), myEps);
1845 }
else if (option == 2) {
1848 / fmax(
casadi_dot(dim, delta, delta), myEps);
1849 scale = fmin(scale, 1.0);
1850 }
else if (option == 3) {
1853 / fmax(
casadi_dot(dim, delta, delta), myEps));
1860 scale = fmax(scale, myEps);
1861 for (casadi_int i=0; i<dim; i++)
1862 for (casadi_int j=0; j<dim; j++)
1863 m->
hess[b][i+j*dim] *= scale;
1875 const double* delta, casadi_int b)
const {
1876 casadi_int dim =
dim_[b];
1877 double theta, scale, myEps = 1.0e3 *
eps_;
1878 double deltaNorm, deltaNormOld, deltaGamma, deltaGammaOld, deltaBdelta;
1886 for (casadi_int i=0; i<dim; i++)
1887 for (casadi_int j=0; j<dim; j++)
1888 deltaBdelta += delta[i] * m->
hess[b][i+j*dim] * delta[j];
1897 if (deltaNorm > myEps && deltaNormOld > myEps) {
1898 scale = (1.0 - theta)*deltaGammaOld / deltaNormOld + theta*deltaBdelta / deltaNorm;
1900 scale = ((1.0 - theta)*deltaGammaOld / deltaNormOld + theta*deltaGamma / deltaNorm) / scale;
1906 if (scale < 1.0 && scale > 0.0) {
1909 for (casadi_int i=0; i<dim; i++)
1910 for (casadi_int j=0; j<dim; j++)
1911 m->
hess[b][i+j*dim] *= scale;
1938 for (casadi_int b=0; b<nBlocks; b++) {
1939 casadi_int dim =
dim_[b];
1956 if (hessScaling < 4 && firstIter)
1958 else if (hessScaling == 4)
1962 if (updateType == 1) {
1963 calcSR1(m, smallGamma, smallDelta, b);
1976 calcBFGS(m, smallGamma, smallDelta, b);
1980 }
else if (updateType == 2) {
1981 calcBFGS(m, smallGamma, smallDelta, b);
1997 casadi_int updateType, casadi_int hessScaling)
const {
1999 casadi_int m2, pos, posOldest, posNewest;
2000 casadi_int hessDamped, hessSkipped;
2001 double averageSizingFactor;
2015 for (casadi_int b=0; b<nBlocks; b++) {
2016 casadi_int dim =
dim_[b];
2027 posNewest = (m->
itCount-1) % m2;
2043 double *gammai = smallGamma +
nx_*posNewest;
2044 double *deltai = smallDelta +
nx_*posNewest;
2047 for (casadi_int i=0; i<m2; i++) {
2048 pos = (posOldest+i) % m2;
2051 gammai = smallGamma +
nx_*pos;
2052 deltai = smallDelta +
nx_*pos;
2069 if (updateType == 1) {
2070 calcSR1(m, gammai, deltai, b);
2071 }
else if (updateType == 2) {
2078 if (pos != posNewest) {
2081 if (hessScaling == 4)
2106 for (casadi_int k=0; k<
nblocks_; k++) {
2109 for (casadi_int i=0; i<dim; i++)
2111 m->
hess[k][i + i*dim] = 0.0;
2112 for (casadi_int j=0; j<dim; j++) {
2113 for (casadi_int i=col[j+s]; i<col[j+1+s]; i++) {
2115 if (row[i]-row[col[s]] < j)
2135 const double* delta, casadi_int b)
const {
2136 casadi_int dim =
dim_[b];
2139 double thetaPowell = 0.0;
2147 std::vector<double> gamma2(gamma, gamma+dim);
2149 double *B = m->
hess[b];
2154 std::vector<double> Bdelta(dim, 0.0);
2155 for (casadi_int i=0; i<dim; i++) {
2156 for (casadi_int k=0; k<dim; k++)
2157 Bdelta[i] += B[i+k*dim] * delta[k];
2159 h1 += delta[i] * Bdelta[i];
2168 if (h2 < hess_damp_fac_ * h1 / m->alpha && fabs(h1 - h2) > 1.0e-12) {
2175 for (casadi_int i=0; i<dim; i++) {
2176 gamma2[i] = thetaPowell*gamma2[i] + (1.0 - thetaPowell)*Bdelta[i];
2177 h2 += delta[i] * gamma2[i];
2190 double myEps = 1.0e2 *
eps_;
2191 if (fabs(h1) < myEps || fabs(h2) < myEps) {
2198 for (casadi_int i=0; i<dim; i++)
2199 for (casadi_int j=0; j<dim; j++)
2200 B[i+j*dim] += - Bdelta[i]*Bdelta[j]/h1 + gamma2[i]*gamma2[j]/h2;
2209 const double* delta, casadi_int b)
const {
2210 casadi_int dim =
dim_[b];
2211 double *B = m->
hess[b];
2212 double myEps = 1.0e2 *
eps_;
2218 std::vector<double> gmBdelta(dim);
2219 for (casadi_int i=0; i<dim; i++) {
2220 gmBdelta[i] = gamma[i];
2221 for (casadi_int k=0; k<dim; k++)
2222 gmBdelta[i] -= B[i+k*dim] * delta[k];
2224 h += (gmBdelta[i] * delta[i]);
2235 for (casadi_int i=0; i<dim; i++)
2236 for (casadi_int j=0; j<dim; j++)
2237 B[i+j*dim] += gmBdelta[i]*gmBdelta[j]/h;
2286 double mu = (idx==1) ? 1.0 / (maxQP-1) : idxF / (idxF - 1.0);
2287 double mu1 = 1.0 - mu;
2288 for (casadi_int b=0; b<
nblocks_; b++) {
2289 casadi_int dim =
dim_[b];
2290 for (casadi_int i=0; i<dim; i++) {
2291 for (casadi_int j=0; j<dim; j++) {
2292 m->
hess2[b][i+j*dim] *= mu;
2293 m->
hess2[b][i+j*dim] += mu1 * m->
hess1[b][i+j*dim];
2307 bool matricesChanged)
const {
2308 casadi_int maxQP, l;
2323 if (matricesChanged) {
2330 m->
A =
new qpOASES::SparseMatrix(
ng_,
nx_,
2331 jacIndRow, jacIndCol, m->
jac_g);
2340 qpOASES::Options opts;
2341 if (matricesChanged && maxQP > 1)
2342 opts.enableInertiaCorrection = qpOASES::BT_FALSE;
2344 opts.enableInertiaCorrection = qpOASES::BT_TRUE;
2345 opts.enableEqualities = qpOASES::BT_TRUE;
2346 opts.initialStatusBounds = qpOASES::ST_INACTIVE;
2347 opts.printLevel = qpOASES::PL_NONE;
2348 opts.numRefinementSteps = 2;
2349 opts.epsLITests = 2.2204e-08;
2350 m->
qp->setOptions(opts);
2355 qpOASES::SolutionAnalysis solAna;
2356 qpOASES::returnValue ret = qpOASES::RET_INFO_UNDEFINED;
2361 for (l=0; l<maxQP; l++) {
2373 opts.enableInertiaCorrection = qpOASES::BT_TRUE;
2374 m->
qp->setOptions(opts);
2380 if (matricesChanged) {
2385 m->
H =
new qpOASES::SymSparseMat(
nx_,
nx_,
2388 m->
H->createDiagInfo();
2394 if (matricesChanged) {
2397 if (m->
qp->getStatus() == qpOASES::QPS_HOMOTOPYQPSOLVED ||
2398 m->
qp->getStatus() == qpOASES::QPS_SOLVED) {
2399 ret = m->
qp->hotstart(m->
H, g, m->
A, lb, lu, lbA, luA, maxIt, &cpuTime);
2402 ret = m->
qp->init(m->
H, g, m->
A, lb, lu, lbA, luA, maxIt, &cpuTime,
2405 ret = m->
qp->init(m->
H, g, m->
A, lb, lu, lbA, luA, maxIt, &cpuTime);
2412 ret = m->
qp->hotstart(g, lb, lu, lbA, luA, maxIt, &cpuTime);
2418 if (l < maxQP-1 && matricesChanged) {
2419 if (ret == qpOASES::SUCCESSFUL_RETURN) {
2421 ret = solAna.checkCurvatureOnStronglyActiveConstraints(
2422 dynamic_cast<qpOASES::SQProblemSchur*
>(m->
qp));
2424 ret = solAna.checkCurvatureOnStronglyActiveConstraints(m->
qp);
2428 if (ret == qpOASES::SUCCESSFUL_RETURN) {
2434 if (ret == qpOASES::RET_SETUP_AUXILIARYQP_FAILED)
2452 m->
qp->getPrimalSolution(deltaXi);
2453 m->
qp->getDualSolution(lambdaQP);
2454 m->
qpObj = m->
qp->getObjVal();
2461 if (ret != qpOASES::SUCCESSFUL_RETURN && matricesChanged)
2462 print(
"***WARNING: qpOASES error message: \"%s\"\n",
2463 qpOASES::MessageHandling::getErrorCodeMessage(ret));
2471 double mu = 1.0 / l;
2472 double mu1 = 1.0 - mu;
2474 for (casadi_int b=0; b<nBlocks; b++) {
2475 casadi_int dim =
dim_[b];
2476 for (casadi_int i=0; i<dim; i++) {
2477 for (casadi_int j=0; j<dim; j++) {
2478 m->
hess2[b][i+j*dim] *= mu;
2479 m->
hess2[b][i+j*dim] += mu1 * m->
hess1[b][i+j*dim];
2492 case qpOASES::SUCCESSFUL_RETURN:
2494 case qpOASES::RET_MAX_NWSR_REACHED:
2496 case qpOASES::RET_HESSIAN_NOT_SPD:
2497 case qpOASES::RET_HESSIAN_INDEFINITE:
2498 case qpOASES::RET_INIT_FAILED_UNBOUNDEDNESS:
2499 case qpOASES::RET_QP_UNBOUNDED:
2500 case qpOASES::RET_HOTSTART_STOPPED_UNBOUNDEDNESS:
2502 case qpOASES::RET_INIT_FAILED_INFEASIBILITY:
2503 case qpOASES::RET_QP_INFEASIBLE:
2504 case qpOASES::RET_HOTSTART_STOPPED_INFEASIBILITY:
2517 auto d_nlp = &m->
d_nlp;
2519 for (casadi_int i=0; i<
nx_; i++) {
2520 double lbx = d_nlp->
lbz[i];
2522 m->
lbx_qp[i] = lbx - d_nlp->z[i];
2527 double ubx = d_nlp->ubz[i];
2529 m->
ubx_qp[i] = ubx - d_nlp->z[i];
2536 for (casadi_int i=0; i<
ng_; i++) {
2537 double lbg = d_nlp->lbz[i+
nx_];
2545 double ubg = d_nlp->ubz[i+
nx_];
2567 print(
"%-8s",
" it");
2568 print(
"%-21s",
" qpIt");
2569 print(
"%-9s",
"obj");
2570 print(
"%-11s",
"feas");
2571 print(
"%-7s",
"opt");
2572 print(
"%-11s",
"|lgrd|");
2573 print(
"%-9s",
"|stp|");
2574 print(
"%-10s",
"|lstp|");
2575 print(
"%-8s",
"alpha");
2576 print(
"%-6s",
"nSOCS");
2577 print(
"%-18s",
"sk, da, sca");
2578 print(
"%-6s",
"QPr,mu");
2691 for (casadi_int b=0; b<
nblocks_; b++) {
2692 casadi_int dim =
dim_[b];
2698 for (casadi_int b=0; b<
nblocks_; b++) {
2699 casadi_int dim =
dim_[b];
2714 casadi_int count, colCountTotal, rowOffset;
2719 for (casadi_int b=0; b<
nblocks_; b++) {
2720 casadi_int dim =
dim_[b];
2721 for (casadi_int i=0; i<dim; i++) {
2722 for (casadi_int j=0; j<dim; j++) {
2723 if (fabs(m->
hess[b][i+j*dim]) >
eps_) {
2737 for (casadi_int b=0; b<
nblocks_; b++) {
2738 casadi_int dim =
dim_[b];
2740 for (casadi_int i=0; i<dim; i++) {
2744 for (casadi_int j=0; j<dim; j++) {
2745 if (fabs(m->
hess[b][i+j*dim]) >
eps_) {
2758 for (casadi_int j=0; j<
nx_; j++) {
2765 print(
"***WARNING: Error in convertHessian: %i elements processed, "
2766 "should be %i elements!\n", count, nnz);
2784 double *f,
double *g,
2785 double *grad_f,
double *jac_g)
const {
2786 auto d_nlp = &m->
d_nlp;
2787 m->
arg[0] = d_nlp->z;
2788 m->
arg[1] = d_nlp->p;
2799 auto d_nlp = &m->
d_nlp;
2801 m->
arg[1] = d_nlp->p;
2809 double *exact_hess_lag)
const {
2810 auto d_nlp = &m->
d_nlp;
2811 static std::vector<double> ones;
2813 for (casadi_int i=0; i<
nx_; ++i) ones[i] = 1.0;
2814 static std::vector<double> minus_lam_gk;
2815 minus_lam_gk.resize(
ng_);
2817 for (casadi_int i=0; i<
ng_; ++i) minus_lam_gk[i] = -m->
lam_gk[i];
2818 m->
arg[0] = d_nlp->z;
2819 m->
arg[1] = d_nlp->p;
2822 m->
res[0] = exact_hess_lag;
2842 auto d_nlp = &m->
d_nlp;
'blocksqp' plugin for Nlpsol
void updateDeltaGamma(BlocksqpMemory *m) const
void resetHessian(BlocksqpMemory *m) const
casadi_int conv_strategy_
void reset_sqp(BlocksqpMemory *m) const
Reset variables that any SQP code needs.
void initializeFilter(BlocksqpMemory *m) const
void calcLagrangeGradient(BlocksqpMemory *m, const double *lam_x, const double *lam_g, const double *grad_f, const double *jacNz, double *grad_lag, casadi_int flag) const
Compute gradient of Lagrangian function (sparse version)
static Nlpsol * creator(const std::string &name, const Function &nlp)
Create a new NLP Solver.
casadi_int fallback_update_
casadi_int fallback_scaling_
void printProgress(BlocksqpMemory *m) const
Print one line of output to stdout about the current iteration.
void printInfo(BlocksqpMemory *m) const
Print information about the SQP method.
casadi_int run(BlocksqpMemory *m, casadi_int maxIt, casadi_int warmStart=0) const
Main Loop of SQP method.
void acceptStep(BlocksqpMemory *m, const double *deltaXi, const double *lambdaQP, double alpha, casadi_int nSOCS) const
Set new primal dual iterate.
std::string linsol_plugin_
QP solver for the subproblems.
void sizeHessianCOL(BlocksqpMemory *m, const double *gamma, const double *delta, casadi_int b) const
void sizeInitialHessian(BlocksqpMemory *m, const double *gamma, const double *delta, casadi_int b, casadi_int option) const
int init_mem(void *mem) const override
Initalize memory block.
std::vector< casadi_int > dim_
casadi_int filterLineSearch(BlocksqpMemory *m) const
void reduceStepsize(BlocksqpMemory *m, double *alpha) const
casadi_int feasibilityRestorationHeuristic(BlocksqpMemory *m) const
casadi_int solveQP(BlocksqpMemory *m, double *deltaXi, double *lambdaQP, bool matricesChanged=true) const
bool pairInFilter(BlocksqpMemory *m, double cNorm, double obj) const
void calcInitialHessian(BlocksqpMemory *m) const
void computeNextHessian(BlocksqpMemory *m, casadi_int idx, casadi_int maxQP) const
casadi_int max_consec_skipped_updates_
void reduceSOCStepsize(BlocksqpMemory *m, double *alphaSOC) const
static const Options options_
Options.
void convertHessian(BlocksqpMemory *m) const
Convert *hess to column compressed sparse format.
bool print_maxit_reached_
void calcHessianUpdateLimitedMemory(BlocksqpMemory *m, casadi_int updateType, casadi_int hessScaling) const
casadi_int fullstep(BlocksqpMemory *m) const
No globalization strategy.
void initStats(BlocksqpMemory *m) const
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
static const std::string meta_doc
A documentation string.
double lInfConstraintNorm(BlocksqpMemory *m, const double *xk, const double *g) const
Blocksqp(const std::string &name, const Function &nlp)
void init(const Dict &opts) override
Initialize.
void calcBFGS(BlocksqpMemory *m, const double *gamma, const double *delta, casadi_int b) const
void initIterate(BlocksqpMemory *m) const
Set initial filter, objective function, tolerances etc.
bool secondOrderCorrection(BlocksqpMemory *m, double cNorm, double cNormTrial, double dfTdeltaXi, bool swCond, casadi_int it) const
void augmentFilter(BlocksqpMemory *m, double cNorm, double obj) const
casadi_int evaluate(BlocksqpMemory *m, double *f, double *g, double *grad_f, double *jac_g) const
Evaluate objective and constraints, including derivatives.
void calcHessianUpdateExact(BlocksqpMemory *m) const
casadi_int which_second_derv_
casadi_int max_consec_reduced_steps_
int solve(void *mem) const override
std::vector< casadi_int > blocks_
bool calcOptTol(BlocksqpMemory *m) const
Update optimization tolerance (similar to SNOPT) in current iterate.
casadi_int max_line_search_
void updateStats(BlocksqpMemory *m) const
void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const override
Set the (persistent) work vectors.
void calcSR1(BlocksqpMemory *m, const double *gamma, const double *delta, casadi_int b) const
bool skip_first_globalization_
casadi_int kktErrorReduction(BlocksqpMemory *m) const
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into MX.
void updateStepBounds(BlocksqpMemory *m, bool soc) const
Sparsity exact_hess_lag_sp_
void calcHessianUpdate(BlocksqpMemory *m, casadi_int updateType, casadi_int hessScaling) const
casadi_int feasibilityRestorationPhase(BlocksqpMemory *m) const
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
void version(const std::string &name, int v)
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.
virtual int eval(const double **arg, double **res, casadi_int *iw, double *w, void *mem) const
Evaluate numerically.
virtual Dict info() const
void alloc_w(size_t sz_w, bool persistent=false)
Ensure required length of w field.
size_t sz_res() const
Get required length of res field.
const MX mx_in(casadi_int ind) const
Get symbolic primitives equivalent to the input expressions.
const Sparsity & sparsity_out(casadi_int ind) const
Get sparsity of a given output.
FunctionInternal * get() const
casadi_int size1_in(casadi_int ind) const
Get input dimension.
casadi_int index_in(const std::string &name) const
Find the index for a string describing a particular entry of an input scheme.
const Sparsity sparsity_jac(casadi_int iind, casadi_int oind, bool compact=false, bool symmetric=false) const
const Sparsity & sparsity_in(casadi_int ind) const
Get sparsity of a given input.
size_t sz_iw() const
Get required length of iw field.
casadi_int n_out() const
Get the number of function outputs.
casadi_int n_in() const
Get the number of function inputs.
void * memory(int ind) const
Get memory object.
size_t sz_w() const
Get required length of w field.
size_t sz_arg() const
Get required length of arg field.
casadi_int size1_out(casadi_int ind) const
Get output dimension.
Function factory(const std::string &name, const std::vector< std::string > &s_in, const std::vector< std::string > &s_out, const AuxOut &aux=AuxOut(), const Dict &opts=Dict()) const
double default_in(casadi_int ind) const
Get default input value.
static MX sym(const std::string &name, casadi_int nrow=1, casadi_int ncol=1)
Create an nrow-by-ncol symbolic primitive.
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.
static MX vertcat(const std::vector< MX > &x)
NLP solver storage class.
static const Options options_
Options.
void init(const Dict &opts) override
Initialize.
casadi_int ng_
Number of constraints.
int init_mem(void *mem) const override
Initalize memory block.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
casadi_int np_
Number of parameters.
casadi_int nx_
Number of variables.
void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const override
Set the (persistent) work vectors.
Function oracle_
Oracle: Used to generate other functions.
Function create_function(const Function &oracle, const std::string &fname, const std::vector< std::string > &s_in, const std::vector< std::string > &s_out, const Function::AuxOut &aux=Function::AuxOut(), const Dict &opts=Dict())
int calc_function(OracleMemory *m, const std::string &fcn, const double *const *arg=nullptr, int thread_id=0) const
std::vector< std::string > get_function() const override
Get list of dependency functions.
static void registerPlugin(const Plugin &plugin, bool needs_lock=true)
Register an integrator in the factory.
void print(const char *fmt,...) const
C-style formatted printing during evaluation.
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 int qpoases_solve(void *mem, int nrhs, double *rhs)
qpOASES linear solver solve
static int qpoases_sfact(void *mem, const double *vals)
qpOASES linear solver symbolical factorization
static int qpoases_nfact(void *mem, const double *vals, int *neig, int *rank)
qpOASES linear solver numerical factorization
Helper class for Serialization.
void version(const std::string &name, int v)
void pack(const Sparsity &e)
Serializes an object to the output stream.
static MatType repmat(const MatType &x, casadi_int n, casadi_int m=1)
static Sparsity diag(casadi_int nrow)
Create diagonal sparsity pattern *.
static Sparsity dense(casadi_int nrow, casadi_int ncol=1)
Create a dense rectangular sparsity pattern *.
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)
Function nlpsol(const std::string &name, const std::string &solver, const SXDict &nlp, const Dict &opts)
std::map< std::string, MX > MXDict
T1 casadi_max_viol(casadi_int n, const T1 *x, const T1 *lb, const T1 *ub)
Largest bound violation.
T1 casadi_norm_1(casadi_int n, const T1 *x)
NORM_1: ||x||_1 -> return.
void copy_vector(const std::vector< S > &s, std::vector< D > &d)
void casadi_copy(const T1 *x, casadi_int n, T1 *y)
COPY: y <-x.
void casadi_fill(T1 *x, casadi_int n, T1 alpha)
FILL: x <- alpha.
T1 casadi_norm_2(casadi_int n, const T1 *x)
NORM_2: ||x||_2 -> return.
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
T1 casadi_dot(casadi_int n, const T1 *x, const T1 *y)
Inner product.
T dot(const std::vector< T > &a, const std::vector< T > &b)
void casadi_scal(casadi_int n, T1 alpha, T1 *x)
SCAL: x <- alpha*x.
void CASADI_NLPSOL_BLOCKSQP_EXPORT casadi_load_nlpsol_blocksqp()
int CASADI_NLPSOL_BLOCKSQP_EXPORT casadi_register_nlpsol_blocksqp(Nlpsol::Plugin *plugin)
T * get_ptr(std::vector< T > &v)
Get a pointer to the data contained in the vector.
void casadi_axpy(casadi_int n, T1 alpha, const T1 *x, T1 *y)
AXPY: y <- a*x + y.
T1 casadi_norm_inf(casadi_int n, const T1 *x)
void casadi_mv(const T1 *x, const casadi_int *sp_x, const T1 *y, T1 *z, casadi_int tr)
Sparse matrix-vector multiplication: z <- z + x*y.
std::map< std::string, DM > DMDict
casadi_int reducedStepCount
QpoasesMemory * qpoases_mem
std::vector< int > colind
BlocksqpMemory()
Constructor.
casadi_int nRestHeurCalls
casadi_int nRestPhaseCalls
casadi_int nTotalSkippedUpdates
double averageSizingFactor
casadi_int * noUpdateCounter
std::set< std::pair< double, double > > filter
qpOASES::SymSparseMat * H
~BlocksqpMemory()
Destructor.
UnifiedReturnStatus unified_return_status
casadi_nlpsol_data< double > d_nlp
Options metadata for a class.