55 p->
dmin = std::numeric_limits<T1>::min();
56 p->
inf = std::numeric_limits<T1>::infinity();
114 template<
typename T1>
116 casadi_int* sz_iw, casadi_int* sz_w) {
118 casadi_int nnz_a, nnz_kkt, nnz_v, nnz_r;
119 casadi_qp_work(p->
qp, sz_arg, sz_res, sz_iw, sz_w);
121 nnz_a = p->
qp->sp_a[2+p->
qp->sp_a[1]];
126 *sz_w = casadi_max(*sz_w, p->
qp->nz);
127 *sz_iw = casadi_max(*sz_iw, p->
qp->nz);
128 *sz_w = casadi_max(*sz_w, 2*p->
qp->nz);
137 *sz_w += casadi_max(nnz_v+nnz_r, nnz_kkt);
150 template<
typename T1>
152 casadi_int** iw, T1** w) {
153 (void)arg; (void)res;
155 casadi_int nnz_a, nnz_kkt, nnz_v, nnz_r;
158 nnz_a = p->
qp->sp_a[2+p->
qp->sp_a[1]];
162 d->
nz_kkt = *w; *w += nnz_kkt;
163 d->
z = *w; *w += p->
qp->nz;
164 d->
lbz = *w; *w += p->
qp->nz;
165 d->
ubz = *w; *w += p->
qp->nz;
166 d->
lam = *w; *w += p->
qp->nz;
167 d->
dz = *w; *w += p->
qp->nz;
168 d->
dlam = *w; *w += p->
qp->nz;
169 d->
nz_v = *w; *w += casadi_max(nnz_v+nnz_r, nnz_kkt);
170 d->
beta = *w; *w += p->
qp->nz;
171 d->
nz_at = *w; *w += nnz_a;
174 d->
sens = *w; *w += p->
qp->nz;
186 template<
typename T1>
196 for (i=0; i<p->
qp->nz; ++i) {
228 template<
typename T1>
235 for (i=0; i<p->
qp->nz; ++i) {
236 if (d->
z[i] > d->
ubz[i]+d->
pr) {
237 d->
pr = d->
z[i]-d->
ubz[i];
239 }
else if (d->
z[i] < d->
lbz[i]-d->
pr) {
240 d->
pr = d->
lbz[i]-d->
z[i];
247 template<
typename T1>
254 for (i=0; i<p->
qp->nx; ++i) {
266 template<
typename T1>
271 const casadi_int *at_colind, *at_row;
274 at_colind = p->
sp_at + 2;
275 at_row = at_colind + p->
qp->na + 1;
281 for (k=at_colind[i-p->
qp->nx]; k<at_colind[i-p->
qp->nx+1]; ++k) {
282 new_du = fmax(new_du, fabs(d->
infeas[at_row[k]]-d->
nz_at[k]*d->
lam[i]));
285 return new_du <= d->
du;
289 template<
typename T1>
299 for (i = 0; i < p->
qp->nz; ++i) {
301 if (d->
sens[i] == 0.)
continue;
303 if (d->
lam[i] == 0) {
305 s = d->
sens[i] > 0 ? 1 : -1;
314 if (d->
lam[i] > 0. ? d->
sens[i] > 0. : d->
sens[i] < 0.)
continue;
316 if (!casadi_qrqp_du_check(d, i))
continue;
319 if (fabs(d->
sens[i]) > best_sens) {
320 best_sens = fabs(d->
sens[i]);
328 d->
msg =
"Enforced ubz to reduce |du|";
329 }
else if (d->
sign < 0) {
330 d->
msg =
"Enforced lbz to reduce |du|";
332 d->
msg =
"Dropped ubz to reduce |du|";
334 d->
msg =
"Dropped lbz to reduce |du|";
341 template<
typename T1>
344 if (d->
lam[d->
ipr] == 0.) {
348 d->
msg =
"Added lbz to reduce |pr|";
351 d->
msg =
"Added ubz to reduce |pr|";
362 template<
typename T1>
366 const casadi_int *h_colind, *h_row, *a_colind, *a_row, *at_colind, *at_row,
367 *kkt_colind, *kkt_row;
370 a_row = (a_colind = p->
qp->sp_a+2) + p->
qp->nx + 1;
371 at_row = (at_colind = p->
sp_at+2) + p->
qp->na + 1;
372 h_row = (h_colind = p->
qp->sp_h+2) + p->
qp->nx + 1;
373 kkt_row = (kkt_colind = p->
sp_kkt+2) + p->
qp->nz + 1;
375 casadi_clear(d->
w, p->
qp->nz);
377 for (i=0; i<p->
qp->nz; ++i) {
381 for (k=h_colind[i]; k<h_colind[i+1]; ++k) d->
w[h_row[k]] = d->
qp->h[k];
382 for (k=a_colind[i]; k<a_colind[i+1]; ++k) d->
w[p->
qp->nx+a_row[k]] = d->
qp->a[k];
390 for (k=at_colind[i-p->
qp->nx]; k<at_colind[i-p->
qp->nx+1]; ++k) {
391 d->
w[at_row[k]] = d->
nz_at[k];
396 for (k=kkt_colind[i]; k<kkt_colind[i+1]; ++k) {
397 d->
nz_kkt[k] = d->
w[kkt_row[k]];
398 d->
w[kkt_row[k]] = 0;
404 template<
typename T1>
408 const casadi_int *h_colind, *h_row, *a_colind, *a_row, *at_colind, *at_row;
411 a_row = (a_colind = p->
qp->sp_a+2) + p->
qp->nx + 1;
412 at_row = (at_colind = p->
sp_at+2) + p->
qp->na + 1;
413 h_row = (h_colind = p->
qp->sp_h+2) + p->
qp->nx + 1;
415 casadi_clear(kkt_i, p->
qp->nz);
418 for (k=h_colind[i]; k<h_colind[i+1]; ++k) kkt_i[h_row[k]] = d->
qp->h[k];
419 for (k=a_colind[i]; k<a_colind[i+1]; ++k) kkt_i[p->
qp->nx+a_row[k]] = d->
qp->a[k];
421 for (k=at_colind[i-p->
qp->nx]; k<at_colind[i-p->
qp->nx+1]; ++k) {
422 kkt_i[at_row[k]] = -d->
nz_at[k];
430 template<
typename T1>
434 const casadi_int *h_colind, *h_row, *a_colind, *a_row, *at_colind, *at_row;
438 a_row = (a_colind = p->
qp->sp_a + 2) + p->
qp->nx + 1;
439 at_row = (at_colind = p->
sp_at + 2) + p->
qp->na + 1;
440 h_row = (h_colind = p->
qp->sp_h + 2) + p->
qp->nx + 1;
445 for (k=h_colind[i]; k<h_colind[i+1]; ++k) r -= v[h_row[k]] * d->
qp->h[k];
446 for (k=a_colind[i]; k<a_colind[i+1]; ++k) r -= v[p->
qp->nx+a_row[k]] * d->
qp->a[k];
448 for (k=at_colind[i-p->
qp->nx]; k<at_colind[i-p->
qp->nx+1]; ++k) {
449 r += v[at_row[k]] * d->
nz_at[k];
456 template<
typename T1>
460 for (i=0; i<p->
qp->nz; ++i) {
462 r[i] = d->
ubz[i]-d->
z[i];
463 }
else if (d->
lam[i]<0.) {
464 r[i] = d->
lbz[i]-d->
z[i];
465 }
else if (i<p->qp->nx) {
474 template<
typename T1>
481 for (i = 0; i < p->
qp->nz; ++i) {
482 if (d->
dz[i] < -dz_max && d->
lbz[i] - d->
z[i] >= d->
epr) {
486 d->
msg =
"lbz violated with zero step";
488 }
else if (d->
dz[i] > dz_max && d->
z[i] - d->
ubz[i] >= d->
epr) {
492 d->
msg =
"ubz violated with zero step";
500 template<
typename T1>
507 if (casadi_qrqp_zero_blocking(d)) {
512 for (i = 0; i < p->
qp->nz; ++i) {
513 if (d->
dz[i] == 0.)
continue;
515 trial_z = d->
z[i] + d->
tau * d->
dz[i];
516 if (d->
dz[i] < 0 && trial_z < d->lbz[i] - d->
epr) {
521 d->
msg =
"Enforcing lbz";
523 }
else if (d->
dz[i] > 0 && trial_z > d->
ubz[i] + d->
epr) {
528 d->
msg =
"Enforcing ubz";
531 if (d->
tau <= 0)
return;
536 template<
typename T1>
538 casadi_int* ind_list, T1 tau) {
540 casadi_int i, n_tau, loc, next_ind, tmp_ind, j;
541 T1 trial_lam, new_tau, next_tau, tmp_tau;
548 for (i=0; i<p->
qp->nz; ++i) {
549 if (d->
dlam[i]==0.)
continue;
550 if (d->
lam[i]==0.)
continue;
552 trial_lam = d->
lam[i] + tau*d->
dlam[i];
554 if (d->
lam[i]>0 ? trial_lam>=0 : trial_lam<=0)
continue;
556 new_tau = -d->
lam[i]/d->
dlam[i];
558 for (loc=0; loc<n_tau-1; ++loc) {
559 if (new_tau<tau_list[loc])
break;
565 for (j=loc; j<n_tau; ++j) {
566 tmp_tau = tau_list[j];
567 tau_list[j] = next_tau;
569 tmp_ind = ind_list[j];
570 ind_list[j] = next_ind;
578 template<
typename T1>
581 casadi_int i, n_tau, j, k, du_index;
582 T1 tau_k, dtau, new_infeas, tau1, infeas, tinfeas;
583 const casadi_int *at_colind, *at_row;
586 at_row = (at_colind = p->
sp_at+2) + p->
qp->na + 1;
588 n_tau = casadi_qrqp_dual_breakpoints(d, d->
w, d->
iw, d->
tau);
593 for (j=0; j<n_tau; ++j) {
595 dtau = d->
w[j] - tau_k;
597 for (k=0; k<p->
qp->nx; ++k) {
602 if (fabs(tinfeas)<1e-14) {
605 }
else if (tinfeas<0) {
611 new_infeas = infeas + dtau*tinfeas;
613 if (new_infeas > d->
edu) {
615 tau1 = fmax(tau_k, tau_k + (d->
edu - infeas)/tinfeas);
626 if (du_index>=0)
return du_index;
640 for (k=at_colind[i-p->
qp->nx]; k<at_colind[i-p->
qp->nx+1]; ++k) {
650 template<
typename T1>
656 for (i=0; i<p->
qp->nz; ++i) d->
iw[i] = d->
lam[i]>0. ? 1 : d->
lam[i]<0 ? -1 : 0;
658 casadi_axpy(p->
qp->nz, d->
tau, d->
dz, d->
z);
661 for (i=0; i<p->
qp->nz; ++i) {
668 case -1: d->
lam[i] = fmin(d->
lam[i], -p->
dmin);
break;
669 case 1: d->
lam[i] = fmax(d->
lam[i], p->
dmin);
break;
670 case 0: d->
lam[i] = 0.;
break;
676 template<
typename T1>
680 casadi_qrqp_kkt_vector(d, d->
dlam, d->
index);
682 if (d->
sign == 0) casadi_scal(p->
qp->nz, -1., d->
dlam);
687 if (fabs(d->
dlam[d->
index]-1.) >= 1e-12)
return 0;
689 casadi_clear(d->
dz, p->
qp->nz);
694 casadi_scal(p->
qp->nz, 1./sqrt(casadi_dot(p->
qp->nz, d->
dlam, d->
dlam)), d->
dlam);
695 casadi_scal(p->
qp->nz, 1./sqrt(casadi_dot(p->
qp->nz, d->
dz, d->
dz)), d->
dz);
701 template<
typename T1>
719 template<
typename T1>
725 casadi_clear(d->
dlam, p->
qp->nx);
726 casadi_mv(d->
qp->h, p->
qp->sp_h, d->
dz, d->
dlam, 0);
727 casadi_mv(d->
qp->a, p->
qp->sp_a, d->
dz + p->
qp->nx, d->
dlam, 1);
729 casadi_scal(p->
qp->nx, -1., d->
dlam);
731 for (i = 0; i < p->
qp->nx; ++i)
if (d->
lam[i] == 0.) d->
dlam[i] = 0.;
733 casadi_copy(d->
dz+p->
qp->nx, p->
qp->na, d->
dlam + p->
qp->nx);
735 casadi_clear(d->
dz + p->
qp->nx, p->
qp->na);
736 casadi_mv(d->
qp->a, p->
qp->sp_a, d->
dz, d->
dz + p->
qp->nx, 0);
738 for (i = 0; i < p->
qp->nz; ++i)
if (fabs(d->
dz[i]) < 1e-14) d->
dz[i] = 0.;
747 template<
typename T1>
751 for (i=0; i<p->
qp->nz; ++i) {
752 if (d->
lbz[i] - d->
z[i] >= d->
epr) {
754 if (d->
dz[i] < 0 || d->
dlam[i] > 0)
return 1;
755 }
else if (d->
z[i] - d->
ubz[i] >= d->
epr) {
757 if (d->
dz[i] > 0 || d->
dlam[i] < 0)
return 1;
764 template<
typename T1>
768 for (i=0; i<p->
qp->nx; ++i) {
780 template<
typename T1>
784 const casadi_int *at_colind, *at_row;
787 if (fabs(d->
infeas[i]) < d->
edu)
return 1;
789 at_colind = p->
sp_at + 2;
790 at_row = at_colind + p->
qp->na + 1;
793 return (s < 0) == (d->
infeas[i] > 0);
795 for (k=at_colind[i-p->
qp->nx]; k<at_colind[i-p->
qp->nx+1]; ++k) {
796 if (d->
nz_at[k] > 0) {
797 if ((s > 0) == (d->
infeas[at_row[k]] > 0))
return 0;
798 }
else if (d->
nz_at[k] < 0) {
799 if ((s < 0) == (d->
infeas[at_row[k]] > 0))
return 0;
808 template<
typename T1>
812 casadi_int nnz_kkt, nk, k, i, best_k, best_neg, neg;
815 for (i = 0; i < p->
qp->nz; ++i) d->
lincomb[i] = 0;
816 for (k = 0; k < d->
sing; ++k) {
820 for (i = 0; i < p->
qp->nz; ++i)
if (fabs(d->
dlam[i]) >= 1e-12) d->
lincomb[i]++;
834 nk = casadi_qr_singular(
static_cast<T1*
>(0), 0, d->
nz_r, p->
sp_r, p->
pc, 1e-12);
837 best_k = best_neg = -1;
839 for (k=0; k<nk; ++k) {
842 casadi_qr_colcomb(d->
dz, d->
nz_r, p->
sp_r, p->
pc, 1e-12, k);
845 for (i=0; i<p->
qp->nz; ++i) {
846 d->
iw[i] = d->
lincomb[i] && fabs(casadi_qrqp_kkt_dot(d, d->
dz, i)) > 1e-12;
849 casadi_qrqp_expand_step(d);
851 for (neg = 0; neg < 2; ++neg) {
854 casadi_scal(p->
qp->nz, -1., d->
dz);
855 casadi_scal(p->
qp->nz, -1., d->
dlam);
859 if (casadi_qrqp_pr_direction(d))
continue;
861 if (casadi_qrqp_du_direction(d))
continue;
863 for (i=0; i<p->
qp->nz; ++i) {
865 if (!d->
iw[i])
continue;
868 if (d->
z[i] <= d->
ubz[i] && (d->
z[i] >= d->
lbz[i] ?
869 d->
dz[i] < -1e-12 : d->
dz[i] > 1e-12)) {
872 && (tau_test = (d->
lbz[i] - d->
z[i]) / d->
dz[i]) < tau
873 && casadi_qrqp_enforceable(d, i, -1)) {
880 }
else if (d->
z[i] >= d->
lbz[i] && (d->
z[i] <= d->
ubz[i] ?
881 d->
dz[i] > 1e-12 : d->
dz[i] < -1e-12)) {
884 && (tau_test = (d->
ubz[i] - d->
z[i]) / d->
dz[i]) < tau
885 && casadi_qrqp_enforceable(d, i, 1)) {
895 if (d->
lam[i] > 0 ? d->
dlam[i] < -1e-12 : d->
dlam[i] > 1e-12) {
896 if ((tau_test = -d->
lam[i] / d->
dlam[i]) < tau) {
913 casadi_qr_colcomb(d->
dz, d->
nz_r, p->
sp_r, p->
pc, 1e-12, best_k);
914 casadi_qrqp_expand_step(d);
915 if (best_neg) tau *= -1;
916 }
else if (--neg != best_neg) {
921 casadi_scal(p->
qp->nz, tau, d->
dz);
922 casadi_scal(p->
qp->nz, tau, d->
dlam);
928 template<
typename T1>
936 if (d->
sing)
return casadi_qrqp_singular_step(d);
938 casadi_qrqp_kkt_residual(d, d->
dz);
943 casadi_qrqp_expand_step(d);
949 template<
typename T1>
954 casadi_clear(d->
sens, p->
qp->nz);
957 casadi_mv(d->
qp->a, p->
qp->sp_a, d->
sens, d->
sens + p->
qp->nx, 0);
962 template<
typename T1>
969 d->
f = casadi_bilin(d->
qp->h, p->
qp->sp_h, d->
z, d->
z)/2.
970 + casadi_dot(p->
qp->nx, d->
z, d->
qp->g);
972 casadi_clear(d->
z+p->
qp->nx, p->
qp->na);
973 casadi_mv(d->
qp->a, p->
qp->sp_a, d->
z, d->
z+p->
qp->nx, 0);
976 casadi_mv(d->
qp->h, p->
qp->sp_h, d->
z, d->
infeas, 0);
979 for (i=0; i<p->
qp->nx; ++i) {
981 if (d->
lam[i]==0)
continue;
986 d->
lam[i] = r==0 ? p->
dmin : r;
992 d->
lam[i] = r==0 ? -p->
dmin : r;
1007 casadi_qrqp_calc_sens(d, d->
idu);
1011 template<
typename T1>
1014 casadi_int du_index;
1020 casadi_qrqp_primal_blocking(d);
1022 du_index = casadi_qrqp_dual_blocking(d);
1024 casadi_qrqp_take_step(d);
1026 if (du_index >= 0) {
1028 casadi_qrqp_calc_sens(d, du_index);
1030 casadi_qrqp_du_index(d);
1035 template<
typename T1>
1041 if (d->
r_sign != 0 || casadi_qrqp_du_check(d, d->
r_index)) {
1045 d->
msg =
"Enforced ubz for regularity";
1046 }
else if (d->
sign < 0) {
1047 d->
msg =
"Enforced lbz for regularity";
1049 d->
msg =
"Dropped ubz for regularity";
1051 d->
msg =
"Dropped lbz for regularity";
1069 if (d->
index >= 0) {
1075 casadi_qrqp_calc_dependent(d);
1080 template<
typename T1>
1085 casadi_qrqp_calc_dependent(d);
1087 casadi_qrqp_flip(d);
1089 casadi_qrqp_factorize(d);
1093 d->
msg =
"Converged";
1098 d->
msg =
"Max iter";
1101 }
else if (!d->
sing && d->
ipr < 0 && d->
idu < 0) {
1103 d->
msg =
"No primal or dual error";
1113 template<
typename T1>
1120 if (casadi_qrqp_calc_step(d)) {
1121 d->
status = QP_NO_SEARCH_DIR;
1125 casadi_qrqp_linesearch(d);
1131 template<
typename T1>
1133 #ifdef CASADI_SNPRINTF
1136 flag = CASADI_SNPRINTF(buf, buf_sz,
"%5s %5s %9s %9s %5s %9s %5s %9s %5s %9s %4s",
1137 "Iter",
"Sing",
"fk",
"|pr|",
"con",
"|du|",
"var",
1138 "min_R",
"con",
"last_tau",
"Note");
1141 d->
status = QP_PRINTING_ERROR;
1145 if (buf_sz) buf[0] =
'\0';
1152 template<
typename T1>
1153 int casadi_qrqp_print_colcomb(
casadi_qrqp_data<T1>* d,
char* buf,
size_t buf_sz, casadi_int j) {
1154 #ifdef CASADI_SNPRINTF
1155 casadi_int num_size, n_print, i, k, buf_offset, val;
1168 if (buf_sz<=4)
return 1;
1173 n_print = (buf_sz-4)/num_size;
1176 for (b=0;b<buf_sz;++b) buf[b]=
' ';
1179 for (i=0;i<p->
qp->nz;++i) {
1180 if (fabs(d->
dlam[i]) >= 1e-12) {
1182 buf[buf_sz-4] =
'.';
1183 buf[buf_sz-3] =
'.';
1184 buf[buf_sz-2] =
'.';
1185 buf[buf_sz-1] =
'\0';
1189 CASADI_SNPRINTF(buf+buf_offset, num_size,
"%d",
static_cast<int>(i));
1191 for (k=0;k<num_size;++k) {
1192 if (buf[buf_offset+k]==
'\0') buf[buf_offset+k] =
' ';
1194 buf_offset += num_size;
1197 buf[buf_sz-1] =
'\0';
1199 if (buf_sz) buf[0] =
'\0';
1206 template<
typename T1>
1208 #ifdef CASADI_SNPRINTF
1211 flag = CASADI_SNPRINTF(buf, buf_sz,
1212 "%5d %5d %9.2g %9.2g %5d %9.2g %5d %9.2g %5d %9.2g ",
1213 static_cast<int>(d->
iter),
static_cast<int>(d->
sing), d->
f, d->
pr,
1214 static_cast<int>(d->
ipr), d->
du,
static_cast<int>(d->
idu),
1218 d->
status = QP_PRINTING_ERROR;
1227 flag = CASADI_SNPRINTF(buf, buf_sz,
"%s, i=%d", d->
msg,
static_cast<int>(d->
msg_ind));
1229 flag = CASADI_SNPRINTF(buf, buf_sz,
"%s", d->
msg);
1233 d->
status = QP_PRINTING_ERROR;
1238 if (buf_sz) buf[0] =
'\0';
casadi_qp_data< T1 > * qp
casadi_qrqp_flag_t status
const casadi_qrqp_prob< T1 > * prob
const casadi_qp_prob< T1 > * qp
const casadi_int * sp_kkt