80 qpwork.primal_residual_in_scaled_up_plus_alphaCdx =
81 qpwork.primal_residual_in_scaled_up + qpwork.Cdx * alpha;
82 qpwork.primal_residual_in_scaled_low_plus_alphaCdx =
83 qpresults.si + qpwork.Cdx * alpha;
85 T a(qpwork.dw_aug.head(qpmodel.dim).dot(qpwork.Hdx) +
86 qpresults.info.mu_eq_inv * (qpwork.Adx).squaredNorm() +
88 qpwork.dw_aug.head(qpmodel.dim)
92 qpwork.err.segment(qpmodel.dim, qpmodel.n_eq) =
94 qpwork.dw_aug.segment(qpmodel.dim, qpmodel.n_eq) * qpresults.info.mu_eq;
96 qpwork.err.segment(qpmodel.dim, qpmodel.n_eq).squaredNorm() *
100 qpwork.err.head(qpmodel.dim) =
101 qpresults.info.rho * (qpresults.x - qpwork.x_prev) + qpwork.g_scaled;
102 T b(qpresults.x.dot(qpwork.Hdx) +
103 (qpwork.err.head(qpmodel.dim)).dot(qpwork.dw_aug.head(qpmodel.dim)) +
104 qpresults.info.mu_eq_inv *
107 qpresults.y * qpresults.info.mu_eq));
112 qpwork.rhs.segment(qpmodel.dim, qpmodel.n_eq) = qpresults.se;
113 b += qpresults.info.mu_eq_inv *
114 qpwork.err.segment(qpmodel.dim, qpmodel.n_eq)
115 .dot(qpwork.rhs.segment(
122 qpwork.err.tail(n_constraints) =
123 ((qpwork.primal_residual_in_scaled_up_plus_alphaCdx.array() > T(0.)) ||
124 (qpwork.primal_residual_in_scaled_low_plus_alphaCdx.array() < T(0.)))
126 Eigen::Matrix<T, Eigen::Dynamic, 1>::Zero(n_constraints));
128 a += qpresults.info.mu_in_inv * qpwork.err.tail(n_constraints).squaredNorm() /
129 qpsettings.alpha_gpdal;
133 a += qpresults.info.mu_in * (1. - qpsettings.alpha_gpdal) *
134 qpwork.dw_aug.tail(n_constraints).squaredNorm();
138 qpwork.active_part_z =
139 (qpwork.primal_residual_in_scaled_up_plus_alphaCdx.array() > T(0.))
140 .select(qpwork.primal_residual_in_scaled_up,
141 Eigen::Matrix<T, Eigen::Dynamic, 1>::Zero(n_constraints)) +
142 (qpwork.primal_residual_in_scaled_low_plus_alphaCdx.array() < T(0.))
143 .select(qpresults.si,
144 Eigen::Matrix<T, Eigen::Dynamic, 1>::Zero(n_constraints));
147 qpresults.info.mu_in_inv *
148 qpwork.active_part_z.dot(qpwork.err.tail(n_constraints)) /
149 qpsettings.alpha_gpdal;
159 b += qpresults.info.mu_in * (1. - qpsettings.alpha_gpdal) *
160 qpwork.dw_aug.tail(n_constraints).dot(qpresults.z);
208 qpwork.primal_residual_in_scaled_up_plus_alphaCdx =
209 qpwork.primal_residual_in_scaled_up + qpwork.Cdx * alpha;
210 qpwork.primal_residual_in_scaled_low_plus_alphaCdx =
211 qpresults.si + qpwork.Cdx * alpha;
213 T a(qpwork.dw_aug.head(qpmodel.dim).dot(qpwork.Hdx) +
214 qpresults.info.mu_eq_inv * (qpwork.Adx).squaredNorm() +
216 qpwork.dw_aug.head(qpmodel.dim)
220 qpwork.err.segment(qpmodel.dim, qpmodel.n_eq) =
222 qpwork.dw_aug.segment(qpmodel.dim, qpmodel.n_eq) * qpresults.info.mu_eq;
223 a += qpwork.err.segment(qpmodel.dim, qpmodel.n_eq).squaredNorm() *
224 qpresults.info.mu_eq_inv *
228 qpwork.err.head(qpmodel.dim) =
229 qpresults.info.rho * (qpresults.x - qpwork.x_prev) + qpwork.g_scaled;
239 T b(qpresults.x.dot(qpwork.Hdx) +
240 (qpwork.err.head(qpmodel.dim)).dot(qpwork.dw_aug.head(qpmodel.dim)) +
241 qpresults.info.mu_eq_inv *
244 qpresults.y * qpresults.info.mu_eq));
248 qpwork.rhs.segment(qpmodel.dim, qpmodel.n_eq) = qpresults.se;
249 b += qpresults.info.nu * qpresults.info.mu_eq_inv *
250 qpwork.err.segment(qpmodel.dim, qpmodel.n_eq)
251 .dot(qpwork.rhs.segment(
258 qpwork.err.tail(n_constraints) =
259 ((qpwork.primal_residual_in_scaled_up_plus_alphaCdx.array() > T(0.)) ||
260 (qpwork.primal_residual_in_scaled_low_plus_alphaCdx.array() < T(0.)))
262 Eigen::Matrix<T, Eigen::Dynamic, 1>::Zero(n_constraints));
264 a += qpresults.info.mu_in_inv *
265 qpwork.err.tail(n_constraints)
272 qpwork.active_part_z =
273 (qpwork.primal_residual_in_scaled_up_plus_alphaCdx.array() > T(0.))
274 .select(qpwork.primal_residual_in_scaled_up,
275 Eigen::Matrix<T, Eigen::Dynamic, 1>::Zero(n_constraints)) +
276 (qpwork.primal_residual_in_scaled_low_plus_alphaCdx.array() < T(0.))
277 .select(qpresults.si,
278 Eigen::Matrix<T, Eigen::Dynamic, 1>::Zero(n_constraints));
280 b += qpresults.info.mu_in_inv *
281 qpwork.active_part_z.dot(qpwork.err.tail(
288 qpwork.err.tail(n_constraints) -=
289 qpwork.dw_aug.tail(n_constraints) * qpresults.info.mu_in;
291 qpwork.active_part_z -= qpresults.z * qpresults.info.mu_in;
296 a += qpresults.info.nu * qpresults.info.mu_in_inv *
297 qpwork.err.tail(n_constraints).squaredNorm();
303 b += qpresults.info.nu * qpresults.info.mu_in_inv *
304 qpwork.err.tail(n_constraints).dot(qpwork.active_part_z);
326 const isize n_constraints)
367 const T machine_eps = std::numeric_limits<T>::epsilon();
378 for (isize i = 0; i < n_constraints; i++) {
380 if (qpwork.
Cdx(i) != 0.) {
383 if (alpha_ > machine_eps) {
384 qpwork.
alphas.push(alpha_);
386 alpha_ = -qpresults.
si(i) / (qpwork.
Cdx(i) + machine_eps);
387 if (alpha_ > machine_eps) {
388 qpwork.
alphas.push(alpha_);
393 isize n_alpha = qpwork.
alphas.len();
397 std::sort(qpwork.
alphas.ptr_mut(), qpwork.
alphas.ptr_mut() + n_alpha);
398 isize new_len = std::unique(
400 qpwork.
alphas.ptr_mut() + n_alpha) -
402 qpwork.
alphas.resize(new_len);
404 n_alpha = qpwork.
alphas.len();
409 qpmodel, qpresults, qpwork, qpsettings, n_constraints, T(0));
410 qpwork.
alpha = -res.b / res.a;
414 qpmodel, qpresults, qpwork, n_constraints, T(0));
415 qpwork.
alpha = -res.b / res.a;
421 auto infty = std::numeric_limits<T>::infinity();
424 T alpha_last_neg = 0;
425 T first_pos_grad = 0;
426 T alpha_first_pos = infty;
427 for (isize i = 0; i < n_alpha; ++i) {
428 alpha_ = qpwork.
alphas[i];
450 qpmodel, qpresults, qpwork, qpsettings, n_constraints, alpha_)
455 qpmodel, qpresults, qpwork, n_constraints, alpha_)
461 alpha_last_neg = alpha_;
465 alpha_first_pos = alpha_;
477 if (alpha_last_neg == T(0)) {
491 qpmodel, qpresults, qpwork, n_constraints, alpha_last_neg)
496 if (alpha_first_pos == infty) {
510 2 * alpha_last_neg + 1);
515 qpwork.
alpha = -b / a;
519 qpmodel, qpresults, qpwork, n_constraints, 2 * alpha_last_neg + 1);
524 qpwork.
alpha = -b / a;
534 qpwork.
alpha = std::abs(alpha_last_neg -
535 last_neg_grad * (alpha_first_pos - alpha_last_neg) /
536 (first_pos_grad - last_neg_grad));
554 const isize n_constraints,
605 isize n_c_f = qpwork.
n_c;
614 auto _planned_to_delete = stack.make_new_for_overwrite(
616 isize* planned_to_delete = _planned_to_delete.ptr_mut();
617 isize planned_to_delete_count = 0;
619 for (isize i = 0; i < n_constraints; i++) {
624 planned_to_delete[planned_to_delete_count] =
626 ++planned_to_delete_count;
628 for (isize j = 0; j < n_constraints; j++) {
638 std::sort(planned_to_delete, planned_to_delete + planned_to_delete_count);
639 switch (dense_backend) {
641 qpwork.
ldl.delete_at(planned_to_delete, planned_to_delete_count, stack);
659 T, new_cols, qpmodel.
dim, planned_to_delete_count, stack);
660 qpwork.
dw_aug.head(planned_to_delete_count).setOnes();
661 T mu_in_inv_neg(-qpresults.
info.mu_in_inv);
662 qpwork.
dw_aug.head(planned_to_delete_count).array() *= mu_in_inv_neg;
663 for (isize i = 0; i < planned_to_delete_count; ++i) {
664 isize index = planned_to_delete[i] - (qpmodel.
dim + qpmodel.
n_eq);
665 auto col = new_cols.col(i);
666 if (index >= qpmodel.
n_in) {
675 qpwork.
ldl.rank_r_update(
676 new_cols, qpwork.
dw_aug.head(planned_to_delete_count), stack);
681 if (planned_to_delete_count > 0) {
688 auto _planned_to_add = stack.make_new_for_overwrite(
690 auto planned_to_add = _planned_to_add.ptr_mut();
692 isize planned_to_add_count = 0;
693 T mu_in_neg(-qpresults.
info.mu_in);
696 for (isize i = 0; i < n_constraints; i++) {
700 planned_to_add[planned_to_add_count] = i;
701 ++planned_to_add_count;
703 for (isize j = 0; j < n_constraints; j++) {
715 switch (dense_backend) {
717 isize n = qpmodel.
dim;
718 isize n_eq = qpmodel.
n_eq;
720 T, new_cols, n + n_eq + n_c_f, planned_to_add_count, stack);
722 for (isize k = 0; k < planned_to_add_count; ++k) {
723 isize index = planned_to_add[k];
724 auto col = new_cols.col(k);
725 if (index >= qpmodel.
n_in) {
726 col.head(n).setZero();
730 col.head(n) = (qpwork.
C_scaled.row(index));
732 col.tail(n_eq + n_c_f).setZero();
733 col[n + n_eq + n_c + k] = mu_in_neg;
735 qpwork.
ldl.insert_block_at(n + n_eq + n_c, new_cols, stack);
754 T, new_cols, qpmodel.
dim, planned_to_add_count, stack);
755 qpwork.
dw_aug.head(planned_to_add_count).setOnes();
756 qpwork.
dw_aug.head(planned_to_add_count).array() *=
757 qpresults.
info.mu_in_inv;
758 for (isize i = 0; i < planned_to_add_count; ++i) {
759 isize index = planned_to_add[i];
760 auto col = new_cols.col(i);
761 if (index >= qpmodel.
n_in) {
767 col.head(qpmodel.
dim) = qpwork.
C_scaled.row(index);
770 qpwork.
ldl.rank_r_update(
771 new_cols, qpwork.
dw_aug.head(planned_to_add_count), stack);
779 if (planned_to_add_count > 0) {