proxsuite 0.6.7
The Advanced Proximal Optimization Toolbox
Loading...
Searching...
No Matches
solver.hpp
Go to the documentation of this file.
1//
2// Copyright (c) 2022-2024 INRIA
3//
8#ifndef PROXSUITE_PROXQP_DENSE_SOLVER_HPP
9#define PROXSUITE_PROXQP_DENSE_SOLVER_HPP
10
11#include "proxsuite/fwd.hpp"
16#include <cmath>
17#include <Eigen/Sparse>
18#include <iostream>
19#include <fstream>
22#include <chrono>
23#include <iomanip>
24
25namespace proxsuite {
26namespace proxqp {
27namespace dense {
28
38template<typename T>
39void
40refactorize(const Model<T>& qpmodel,
41 Results<T>& qpresults,
42 Workspace<T>& qpwork,
43 const isize n_constraints,
44 const DenseBackend& dense_backend,
45 T rho_new)
46{
47
48 if (!qpwork.constraints_changed && rho_new == qpresults.info.rho) {
49 return;
50 }
51
54 };
55 switch (dense_backend) {
57 qpwork.kkt.diagonal().head(qpmodel.dim).array() +=
58 rho_new - qpresults.info.rho;
59 qpwork.kkt.diagonal().segment(qpmodel.dim, qpmodel.n_eq).array() =
60 -qpresults.info.mu_eq;
61 qpwork.ldl.factorize(qpwork.kkt.transpose(), stack);
62
63 isize n = qpmodel.dim;
64 isize n_eq = qpmodel.n_eq;
65 isize n_in = qpmodel.n_in;
66 isize n_c = qpwork.n_c;
67
68 LDLT_TEMP_MAT(T, new_cols, n + n_eq + n_c, n_c, stack);
69 T mu_in_neg(-qpresults.info.mu_in);
70 for (isize i = 0; i < n_constraints; ++i) {
71 isize j = qpwork.current_bijection_map[i];
72 if (j < n_c) {
73 auto col = new_cols.col(j);
74 if (i >= n_in) {
75 // I_scaled = D which is the diagonal matrix
76 // scaling x
77 // col(i-n_in) = ruiz.delta[i-qpmodel.n_in];
78 col(i - n_in) = qpwork.i_scaled[i - qpmodel.n_in];
79 } else {
80 col.head(n) = qpwork.C_scaled.row(i);
81 }
82 col.segment(n, n_eq + n_c).setZero();
83 col(n + n_eq + j) = mu_in_neg;
84 }
85 }
86 qpwork.ldl.insert_block_at(n + n_eq, new_cols, stack);
87 } break;
89 qpwork.kkt.noalias() =
90 qpwork.H_scaled + (qpwork.A_scaled.transpose() * qpwork.A_scaled) *
91 qpresults.info.mu_eq_inv;
92 qpwork.kkt.diagonal().array() += qpresults.info.rho;
93 for (isize i = 0; i < n_constraints; i++) {
94 if (qpwork.active_inequalities(i)) {
95 if (i >= qpmodel.n_in) {
96 // box constraints
97 qpwork.kkt(i - qpmodel.n_in, i - qpmodel.n_in) +=
98 std::pow(qpwork.i_scaled(i - qpmodel.n_in), 2) *
99 qpresults.info.mu_in_inv;
100 } else {
101 // generic ineq constraint
102 qpwork.kkt.noalias() += qpwork.C_scaled.row(i).transpose() *
103 qpwork.C_scaled.row(i) *
104 qpresults.info.mu_in_inv;
105 }
106 }
107 }
108 qpwork.ldl.factorize(qpwork.kkt.transpose(), stack);
109 } break;
111 break;
112 }
113
114 qpwork.constraints_changed = false;
115}
116
128template<typename T>
129void
130mu_update(const Model<T>& qpmodel,
131 Results<T>& qpresults,
132 Workspace<T>& qpwork,
133 isize n_constraints,
134 const DenseBackend& dense_backend,
135 T mu_eq_new,
136 T mu_in_new)
137{
140 };
141
142 isize n = qpmodel.dim;
143 isize n_eq = qpmodel.n_eq;
144 isize n_c = qpwork.n_c;
145
146 if ((n_eq + n_c) == 0) {
147 return;
148 }
149 switch (dense_backend) {
151 LDLT_TEMP_VEC_UNINIT(T, rank_update_alpha, n_eq + n_c, stack);
152
153 rank_update_alpha.head(n_eq).setConstant(qpresults.info.mu_eq -
154 mu_eq_new);
155 rank_update_alpha.tail(n_c).setConstant(qpresults.info.mu_in - mu_in_new);
156
157 {
158 auto _indices = stack.make_new_for_overwrite(
160 isize* indices = _indices.ptr_mut();
161 for (isize k = 0; k < n_eq; ++k) {
162 indices[k] = n + k;
163 }
164 for (isize k = 0; k < n_c; ++k) {
165 indices[n_eq + k] = n + n_eq + k;
166 }
167 qpwork.ldl.diagonal_update_clobber_indices(
168 indices, n_eq + n_c, rank_update_alpha, stack);
169 }
170 } break;
172 // we refactorize there for the moment
175 qpwork.ldl_stack.as_mut(),
176 };
177 // qpwork.kkt.noalias() = qpwork.H_scaled + (qpwork.A_scaled.transpose() *
178 // qpwork.A_scaled) / mu_eq_new; qpwork.kkt.diagonal().array() +=
179 // qpresults.info.rho; for (isize i = 0; i < n_constraints; i++){
180 // if (qpwork.active_inequalities(i)){
181 // if (i >=qpmodel.n_in){
182 // // box constraints
183 // qpwork.kkt(i-qpmodel.n_in,i-qpmodel.n_in) +=
184 // std::pow(qpwork.i_scaled(i-qpmodel.n_in),2) / mu_in_new ;
185 // } else{
186 // // generic ineq constraint
187 // qpwork.kkt.noalias() += qpwork.C_scaled.row(i).transpose() *
188 // qpwork.C_scaled.row(i) / mu_in_new ;
189 // }
190 // }
191 // }
192 // qpwork.ldl.factorize(qpwork.kkt.transpose(), stack);
193
194 // mu update for C_J
195 {
196 LDLT_TEMP_MAT_UNINIT(T, new_cols, qpmodel.dim, qpwork.n_c, stack);
197 qpwork.dw_aug.head(qpmodel.dim).setOnes();
198 T delta_mu(T(1) / mu_in_new - qpresults.info.mu_in_inv);
199 qpwork.dw_aug.head(qpmodel.dim).array() *= delta_mu;
200 for (isize i = 0; i < n_constraints; ++i) {
201 isize j = qpwork.current_bijection_map[i];
202 if (j < n_c) {
203 auto col = new_cols.col(j);
204 if (i >= qpmodel.n_in) {
205 // box constraint
206 col.setZero();
207 col[i - qpmodel.n_in] = qpwork.i_scaled[i - qpmodel.n_in];
208 } else {
209 // generic ineq constraints
210 col = qpwork.C_scaled.row(i);
211 }
212 }
213 }
214 qpwork.ldl.rank_r_update(
215 new_cols, qpwork.dw_aug.head(qpwork.n_c), stack);
216 }
217 // mu update for A
218 {
219 LDLT_TEMP_MAT_UNINIT(T, new_cols, qpmodel.dim, qpmodel.n_eq, stack);
220 qpwork.dw_aug.head(qpmodel.n_eq).setOnes();
221 T delta_mu(1 / mu_eq_new - qpresults.info.mu_eq_inv);
222 qpwork.dw_aug.head(qpmodel.n_eq).array() *= delta_mu;
223 new_cols = qpwork.A_scaled.transpose();
224 qpwork.ldl.rank_r_update(
225 new_cols, qpwork.dw_aug.head(qpmodel.n_eq), stack);
226 }
227 } break;
229 break;
230 }
231 qpwork.constraints_changed = true;
232}
243template<typename T>
244void
246 Results<T>& qpresults,
247 Workspace<T>& qpwork,
248 const isize n_constraints,
249 isize inner_pb_dim,
250 const HessianType& hessian_type)
251{
252 auto& Hdx = qpwork.Hdx;
253 auto& Adx = qpwork.Adx;
254 auto& ATdy = qpwork.CTz;
255 qpwork.err.head(inner_pb_dim) = qpwork.rhs.head(inner_pb_dim);
256 switch (hessian_type) {
258 break;
260 Hdx.noalias() = qpwork.H_scaled.template selfadjointView<Eigen::Lower>() *
261 qpwork.dw_aug.head(qpmodel.dim);
262 qpwork.err.head(qpmodel.dim).noalias() -= Hdx;
263 break;
265#ifndef NDEBUG
266 PROXSUITE_THROW_PRETTY(!qpwork.H_scaled.isDiagonal(),
267 std::invalid_argument,
268 "H is not diagonal.");
269#endif
270 Hdx.array() = qpwork.H_scaled.diagonal().array() *
271 qpwork.dw_aug.head(qpmodel.dim).array();
272 qpwork.err.head(qpmodel.dim).noalias() -= Hdx;
273 break;
274 }
275 qpwork.err.head(qpmodel.dim) -=
276 qpresults.info.rho * qpwork.dw_aug.head(qpmodel.dim);
277
278 // PERF: fuse {A, C}_scaled multiplication operations
279 ATdy.noalias() = qpwork.A_scaled.transpose() *
280 qpwork.dw_aug.segment(qpmodel.dim, qpmodel.n_eq);
281 qpwork.err.head(qpmodel.dim).noalias() -= ATdy;
282 if (n_constraints > qpmodel.n_in) {
283 // there are box constraints
284 qpwork.active_part_z.tail(qpmodel.dim) = qpwork.dw_aug.head(qpmodel.dim);
285 qpwork.active_part_z.tail(qpmodel.dim).array() *= qpwork.i_scaled.array();
286 // ruiz.unscale_primal_in_place(VectorViewMut<T>{from_eigen,qpwork.active_part_z.tail(qpmodel.dim)});
287 }
288 for (isize i = 0; i < n_constraints; i++) {
289 isize j = qpwork.current_bijection_map(i);
290 if (j < qpwork.n_c) {
291 if (i >= qpmodel.n_in) {
292 // I_scaled * dz_box_scaled = unscale_primally(dz_box)
293 qpwork.err(i - qpmodel.n_in) -=
294 // qpwork.dw_aug(qpmodel.dim + qpmodel.n_eq + j) *
295 // ruiz.delta(i-qpmodel.n_in);
296 qpwork.dw_aug(qpmodel.dim + qpmodel.n_eq + j) *
297 qpwork.i_scaled(i - qpmodel.n_in);
298 // I_scaled * dx_scaled = dx_unscaled
299 qpwork.err(qpmodel.dim + qpmodel.n_eq + j) -=
300 (qpwork.active_part_z[i] -
301 qpwork.dw_aug(qpmodel.dim + qpmodel.n_eq + j) *
302 qpresults.info.mu_in);
303 } else {
304 qpwork.err.head(qpmodel.dim).noalias() -=
305 qpwork.dw_aug(qpmodel.dim + qpmodel.n_eq + j) *
306 qpwork.C_scaled.row(i);
307 qpwork.err(qpmodel.dim + qpmodel.n_eq + j) -=
308 (qpwork.C_scaled.row(i).dot(qpwork.dw_aug.head(qpmodel.dim)) -
309 qpwork.dw_aug(qpmodel.dim + qpmodel.n_eq + j) *
310 qpresults.info.mu_in);
311 }
312 }
313 }
314 Adx.noalias() = qpwork.A_scaled * qpwork.dw_aug.head(qpmodel.dim);
315 qpwork.err.segment(qpmodel.dim, qpmodel.n_eq).noalias() -= Adx;
316 qpwork.err.segment(qpmodel.dim, qpmodel.n_eq) +=
317 qpwork.dw_aug.segment(qpmodel.dim, qpmodel.n_eq) * qpresults.info.mu_eq;
318}
319
320template<typename T>
321void
323 const Model<T>& qpmodel,
324 Results<T>& qpresults,
325 Workspace<T>& qpwork,
326 const isize n_constraints,
327 const DenseBackend& dense_backend,
328 isize inner_pb_dim,
330{
331
332 switch (dense_backend) {
334 qpwork.ldl.solve_in_place(dw.head(inner_pb_dim), stack);
335 break;
337 // find dx
338 dw.head(qpmodel.dim).noalias() += qpresults.info.mu_eq_inv *
339 qpwork.A_scaled.transpose() *
340 dw.segment(qpmodel.dim, qpmodel.n_eq);
341 for (isize i = 0; i < n_constraints; i++) {
342 isize j = qpwork.current_bijection_map(i);
343 if (j < qpwork.n_c) {
344 if (i >= qpmodel.n_in) {
345 // box constraints
346 dw(i - qpmodel.n_in) += dw(j + qpmodel.dim + qpmodel.n_eq) *
347 qpwork.i_scaled(i - qpmodel.n_in);
348 } else {
349 // ineq constraints
350 dw.head(qpmodel.dim) +=
351 dw(j + qpmodel.dim + qpmodel.n_eq) * qpwork.C_scaled.row(i);
352 }
353 }
354 }
355 qpwork.ldl.solve_in_place(dw.head(qpmodel.dim), stack);
356 // find dy
357 dw.segment(qpmodel.dim, qpmodel.n_eq) -=
358 qpresults.info.mu_eq_inv * dw.segment(qpmodel.dim, qpmodel.n_eq);
359 dw.segment(qpmodel.dim, qpmodel.n_eq).noalias() +=
360 qpresults.info.mu_eq_inv *
361 (qpwork.A_scaled *
362 dw.head(
363 qpmodel.dim)); //- qpwork.rhs.segment(qpmodel.dim,qpmodel.n_eq));
364 // find dz_J
365 for (isize i = 0; i < n_constraints; i++) {
366 isize j = qpwork.current_bijection_map(i);
367 if (j < qpwork.n_c) {
368 if (i >= qpmodel.n_in) {
369 // box constraints
370 dw(j + qpmodel.dim + qpmodel.n_eq) -=
371 qpresults.info.mu_in_inv * (dw(j + qpmodel.dim + qpmodel.n_eq));
372 dw(j + qpmodel.dim + qpmodel.n_eq) +=
373 qpresults.info.mu_in_inv *
374 (dw(
375 i -
376 qpmodel.n_in)); //- qpwork.rhs(j + qpmodel.dim + qpmodel.n_eq));
377 } else {
378 // ineq constraints
379 dw(j + qpmodel.dim + qpmodel.n_eq) -=
380 qpresults.info.mu_in_inv * (dw(j + qpmodel.dim + qpmodel.n_eq));
381 dw(j + qpmodel.dim + qpmodel.n_eq) +=
382 qpresults.info.mu_in_inv *
383 (qpwork.C_scaled.row(i).dot(dw.head(
384 qpmodel.dim))); //- qpwork.rhs(j + qpmodel.dim + qpmodel.n_eq));
385 }
386 }
387 }
388 break;
390 break;
391 }
392}
393
406template<typename T>
407void
409 const Settings<T>& qpsettings,
410 const Model<T>& qpmodel,
411 Results<T>& qpresults,
412 Workspace<T>& qpwork,
413 const isize n_constraints,
414 const DenseBackend& dense_backend,
415 const HessianType& hessian_type,
416 T eps,
417 isize inner_pb_dim)
418{
419
420 qpwork.err.setZero();
421 i32 it = 0;
422 i32 it_stability = 0;
423
426 };
427 qpwork.dw_aug.head(inner_pb_dim) = qpwork.rhs.head(inner_pb_dim);
429 qpmodel,
430 qpresults,
431 qpwork,
432 n_constraints,
433 dense_backend,
434 inner_pb_dim,
435 stack);
436 iterative_residual<T>(
437 qpmodel, qpresults, qpwork, n_constraints, inner_pb_dim, hessian_type);
438
439 ++it;
440 T preverr = infty_norm(qpwork.err.head(inner_pb_dim));
441 while (infty_norm(qpwork.err.head(inner_pb_dim)) >= eps) {
442
443 if (it >= qpsettings.nb_iterative_refinement) {
444 break;
445 }
446 ++it;
448 qpmodel,
449 qpresults,
450 qpwork,
451 n_constraints,
452 dense_backend,
453 inner_pb_dim,
454 stack);
455 // qpwork.ldl.solve_in_place(qpwork.err.head(inner_pb_dim), stack);
456 qpwork.dw_aug.head(inner_pb_dim) += qpwork.err.head(inner_pb_dim);
457
458 qpwork.err.head(inner_pb_dim).setZero();
459 iterative_residual<T>(
460 qpmodel, qpresults, qpwork, n_constraints, inner_pb_dim, hessian_type);
461
462 if (infty_norm(qpwork.err.head(inner_pb_dim)) > preverr) {
463 it_stability += 1;
464
465 } else {
466 it_stability = 0;
467 }
468 if (it_stability == 2) {
469 break;
470 }
471 preverr = infty_norm(qpwork.err.head(inner_pb_dim));
472 }
473
474 if (infty_norm(qpwork.err.head(inner_pb_dim)) >=
475 std::max(eps, qpsettings.eps_refact)) {
476 refactorize(qpmodel,
477 qpresults,
478 qpwork,
479 n_constraints,
480 dense_backend,
481 qpresults.info.rho);
482 it = 0;
483 it_stability = 0;
484
485 qpwork.dw_aug.head(inner_pb_dim) = qpwork.rhs.head(inner_pb_dim);
487 qpmodel,
488 qpresults,
489 qpwork,
490 n_constraints,
491 dense_backend,
492 inner_pb_dim,
493 stack);
494 // qpwork.ldl.solve_in_place(qpwork.dw_aug.head(inner_pb_dim), stack);
495
496 iterative_residual<T>(
497 qpmodel, qpresults, qpwork, n_constraints, inner_pb_dim, hessian_type);
498
499 preverr = infty_norm(qpwork.err.head(inner_pb_dim));
500 ++it;
501 while (infty_norm(qpwork.err.head(inner_pb_dim)) >= eps) {
502
503 if (it >= qpsettings.nb_iterative_refinement) {
504 break;
505 }
506 ++it;
508 qpmodel,
509 qpresults,
510 qpwork,
511 n_constraints,
512 dense_backend,
513 inner_pb_dim,
514 stack);
515 // qpwork.ldl.solve_in_place(qpwork.err.head(inner_pb_dim), stack);
516 qpwork.dw_aug.head(inner_pb_dim) += qpwork.err.head(inner_pb_dim);
517
518 qpwork.err.head(inner_pb_dim).setZero();
519 iterative_residual<T>(
520 qpmodel, qpresults, qpwork, n_constraints, inner_pb_dim, hessian_type);
521
522 if (infty_norm(qpwork.err.head(inner_pb_dim)) > preverr) {
523 it_stability += 1;
524 } else {
525 it_stability = 0;
526 }
527 if (it_stability == 2) {
528 break;
529 }
530 preverr = infty_norm(qpwork.err.head(inner_pb_dim));
531 }
532 }
533 if (infty_norm(qpwork.err.head(inner_pb_dim)) >= eps && qpsettings.verbose) {
534 // std::cout << "after refact err " << err << std::endl;
535 std::cout << "refact err " << infty_norm(qpwork.err.head(inner_pb_dim))
536 << std::endl;
537 }
538 qpresults.info.iterative_residual = infty_norm(qpwork.err.head(inner_pb_dim));
539
540 qpwork.rhs.head(inner_pb_dim).setZero();
541}
564template<typename T>
565void
566bcl_update(const Settings<T>& qpsettings,
567 Results<T>& qpresults,
568 Workspace<T>& qpwork,
569 T& primal_feasibility_lhs_new,
570 T& bcl_eta_ext,
571 T& bcl_eta_in,
572
573 T bcl_eta_ext_init,
574 T eps_in_min,
575
576 T& new_bcl_mu_in,
577 T& new_bcl_mu_eq,
578 T& new_bcl_mu_in_inv,
579 T& new_bcl_mu_eq_inv
580
581)
582{
583 if (primal_feasibility_lhs_new <= bcl_eta_ext ||
584 qpresults.info.iter > qpsettings.safe_guard) {
585 /* TO PUT IN DEBUG MODE
586 if (qpsettings.verbose) {
587 std::cout << "good step" << std::endl;
588 }
589 */
590 bcl_eta_ext *= pow(qpresults.info.mu_in, qpsettings.beta_bcl);
591 bcl_eta_in = std::max(bcl_eta_in * qpresults.info.mu_in, eps_in_min);
592 } else {
593 /* TO PUT IN DEBUG MODE
594 if (qpsettings.verbose) {
595 std::cout << "bad step" << std::endl;
596 }
597 */
598 qpresults.y = qpwork.y_prev;
599 qpresults.z = qpwork.z_prev;
600
601 new_bcl_mu_in = std::max(qpresults.info.mu_in * qpsettings.mu_update_factor,
602 qpsettings.mu_min_in);
603 new_bcl_mu_eq = std::max(qpresults.info.mu_eq * qpsettings.mu_update_factor,
604 qpsettings.mu_min_eq);
605 new_bcl_mu_in_inv =
606 std::min(qpresults.info.mu_in_inv * qpsettings.mu_update_inv_factor,
607 qpsettings.mu_max_in_inv);
608 new_bcl_mu_eq_inv =
609 std::min(qpresults.info.mu_eq_inv * qpsettings.mu_update_inv_factor,
610 qpsettings.mu_max_eq_inv);
611 bcl_eta_ext = bcl_eta_ext_init * pow(new_bcl_mu_in, qpsettings.alpha_bcl);
612 bcl_eta_in = std::max(new_bcl_mu_in, eps_in_min);
613 }
614}
637template<typename T>
638void
639Martinez_update(const Settings<T>& qpsettings,
640 Results<T>& qpresults,
641 T& primal_feasibility_lhs_new,
642 T& primal_feasibility_lhs_old,
643 T& bcl_eta_in,
644 T eps_in_min,
645
646 T& new_bcl_mu_in,
647 T& new_bcl_mu_eq,
648 T& new_bcl_mu_in_inv,
649 T& new_bcl_mu_eq_inv
650
651)
652{
653 bcl_eta_in = std::max(bcl_eta_in * 0.1, eps_in_min);
654 if (primal_feasibility_lhs_new <= 0.95 * primal_feasibility_lhs_old) {
655 /* TO PUT IN DEBUG MODE
656 if (qpsettings.verbose) {
657 std::cout << "good step" << std::endl;
658 }
659 */
660 } else {
661 /* TO PUT IN DEBUG MODE
662 if (qpsettings.verbose) {
663 std::cout << "bad step" << std::endl;
664 }
665 */
666 new_bcl_mu_in = std::max(qpresults.info.mu_in * qpsettings.mu_update_factor,
667 qpsettings.mu_min_in);
668 new_bcl_mu_eq = std::max(qpresults.info.mu_eq * qpsettings.mu_update_factor,
669 qpsettings.mu_min_eq);
670 new_bcl_mu_in_inv =
671 std::min(qpresults.info.mu_in_inv * qpsettings.mu_update_inv_factor,
672 qpsettings.mu_max_in_inv);
673 new_bcl_mu_eq_inv =
674 std::min(qpresults.info.mu_eq_inv * qpsettings.mu_update_inv_factor,
675 qpsettings.mu_max_eq_inv);
676 }
677}
687template<typename T>
688auto
690 Results<T>& qpresults,
691 Workspace<T>& qpwork,
692 const Settings<T>& qpsettings) -> T
693{
694
695 qpwork.active_part_z =
696 helpers::positive_part(qpwork.primal_residual_in_scaled_up) +
697 helpers::negative_part(qpresults.si);
698 switch (qpsettings.merit_function_type) {
700 qpwork.active_part_z -=
701 qpsettings.alpha_gpdal * qpresults.z *
702 qpresults.info.mu_in; // contains now : [Cx-u+z_prev*mu_in]+
703
704 // qpwork.active_part_z.head(qpmodel.n_in) -=
705 // qpsettings.alpha_gpdal * qpresults.z.head(qpmodel.n_in) *
706 // qpresults.info.mu_in; // contains now : [Cx-u+z_prev*mu_in]+
707 // if (box_constraints){
708 // qpwork.active_part_z.tail(qpmodel.dim) -=
709 // qpsettings.alpha_gpdal * qpresults.z.tail(qpmodel.dim) *
710 // qpresults.info.mu_in; // contains now : [Cx-u+z_prev*mu_in]+
711 // }
712 break;
714 qpwork.active_part_z -=
715 qpresults.z *
716 qpresults.info.mu_in; // contains now : [Cx-u+z_prev*mu_in]+
717 // + [Cx-l+z_prev*mu_in]- - z*mu_in
718 // qpwork.active_part_z.head(qpmodel.n_in) -=
719 // qpresults.z.head(qpmodel.n_in) *
720 // qpresults.info.mu_in; // contains now : [Cx-u+z_prev*mu_in]+
721 // // + [Cx-l+z_prev*mu_in]- - z*mu_in
722 // if (box_constraints){
723 // qpwork.active_part_z.tail(qpmodel.dim) -=
724 // qpresults.z.tail(qpmodel.dim) *
725 // qpresults.info.mu_in; // contains now : [Cx-u+z_prev*mu_in]+
726 // }
727 break;
728 }
729
730 T err = infty_norm(qpwork.active_part_z);
731 qpwork.err.segment(qpmodel.dim, qpmodel.n_eq) = qpresults.se;
732 // qpwork.primal_residual_eq_scaled; // contains now Ax-b-(y-y_prev)/mu
733
734 T prim_eq_e = infty_norm(
735 qpwork.err.segment(qpmodel.dim, qpmodel.n_eq)); // ||Ax-b-(y-y_prev)/mu||
736 err = std::max(err, prim_eq_e);
737 T dual_e =
738 infty_norm(qpwork.dual_residual_scaled); // contains ||Hx + rho(x-xprev) +
739 // g + Aty + Ctz||
740 err = std::max(err, dual_e);
741
742 return err;
743}
754template<typename T>
755void
757 const Model<T>& qpmodel,
758 Results<T>& qpresults,
759 Workspace<T>& qpwork,
760 const bool box_constraints,
761 const isize n_constraints,
762 const DenseBackend& dense_backend,
763 const HessianType& hessian_type,
764 T eps)
765{
766
767 /* MUST BE
768 * dual_residual_scaled = Hx + rho * (x-x_prev) + A.T y + C.T z
769 * primal_residual_eq_scaled = Ax-b+mu_eq (y_prev-y)
770 * primal_residual_in_scaled_up = Cx-u+mu_in(z_prev)
771 * primal_residual_in_scaled_low = Cx-l+mu_in(z_prev)
772 */
773 qpwork.active_set_up.array() =
774 (qpwork.primal_residual_in_scaled_up.array() >= 0);
775 // primal_residual_in_scaled_low = Cx-l+mu_in(z_prev) + mu_in(alpha_gdpal - 1)
776 // * z
777 qpwork.active_set_low.array() = (qpresults.si.array() <= 0);
778 qpwork.active_inequalities = qpwork.active_set_up || qpwork.active_set_low;
779
780 isize numactive_inequalities = qpwork.active_inequalities.count();
781 isize inner_pb_dim = qpmodel.dim + qpmodel.n_eq + numactive_inequalities;
782 qpwork.rhs.setZero();
783 qpwork.dw_aug.setZero();
785 qpmodel, qpresults, dense_backend, n_constraints, qpwork);
786
787 qpwork.rhs.head(qpmodel.dim) = -qpwork.dual_residual_scaled;
788
789 if (box_constraints) {
790 // use active_part_z as tmp variable in order to unscale primarilly z
791 // as I_scaled.T * z_scaled = unscale_primarilly_(z_scaled)
792 qpwork.active_part_z.tail(qpmodel.dim) = qpresults.z.tail(qpmodel.dim);
793 qpwork.active_part_z.tail(qpmodel.dim).array() *= qpwork.i_scaled.array();
794 // ruiz.unscale_primal_in_place(VectorViewMut<T>{from_eigen,qpwork.active_part_z.tail(qpmodel.dim)});
795 }
796
797 qpwork.rhs.segment(qpmodel.dim, qpmodel.n_eq) = -qpresults.se;
798 // -qpwork.primal_residual_eq_scaled;
799 switch (qpsettings.merit_function_type) {
801 for (isize i = 0; i < n_constraints; i++) {
802 isize j = qpwork.current_bijection_map(i);
803 if (j < qpwork.n_c) {
804 if (qpwork.active_set_up(i)) {
805 qpwork.rhs(j + qpmodel.dim + qpmodel.n_eq) =
807 qpresults.z(i) * qpresults.info.mu_in * qpsettings.alpha_gpdal;
808 } else if (qpwork.active_set_low(i)) {
809 qpwork.rhs(j + qpmodel.dim + qpmodel.n_eq) =
810 -qpresults.si(i) +
811 qpresults.z(i) * qpresults.info.mu_in * qpsettings.alpha_gpdal;
812 }
813 } else {
814 // unactive unrelevant columns
815 if (i >= qpmodel.n_in) {
816 qpwork.rhs(i - qpmodel.n_in) += qpwork.active_part_z(i);
817 } else {
818 qpwork.rhs.head(qpmodel.dim) +=
819 qpresults.z(i) * qpwork.C_scaled.row(i);
820 }
821 }
822 }
823 break;
825 for (isize i = 0; i < n_constraints; i++) {
826 isize j = qpwork.current_bijection_map(i);
827 if (j < qpwork.n_c) {
828 if (qpwork.active_set_up(i)) {
829 qpwork.rhs(j + qpmodel.dim + qpmodel.n_eq) =
831 qpresults.z(i) * qpresults.info.mu_in;
832 } else if (qpwork.active_set_low(i)) {
833 qpwork.rhs(j + qpmodel.dim + qpmodel.n_eq) =
834 -qpresults.si(i) + qpresults.z(i) * qpresults.info.mu_in;
835 }
836 } else {
837 if (i >= qpmodel.n_in) {
838 // unactive unrelevant columns
839 qpwork.rhs(i - qpmodel.n_in) += qpwork.active_part_z(i);
840 } else {
841 qpwork.rhs.head(qpmodel.dim) +=
842 qpresults.z(i) * qpwork.C_scaled.row(i);
843 }
844 }
845 }
846 break;
847 }
849 qpsettings,
850 qpmodel,
851 qpresults,
852 qpwork,
853 n_constraints,
854 dense_backend,
855 hessian_type,
856 eps,
857 inner_pb_dim);
858
859 // use active_part_z as a temporary variable to derive unpermutted dz step
860 for (isize j = 0; j < n_constraints; ++j) {
861 isize i = qpwork.current_bijection_map(j);
862 if (i < qpwork.n_c) {
863 qpwork.active_part_z(j) = qpwork.dw_aug(qpmodel.dim + qpmodel.n_eq + i);
864 } else {
865 qpwork.active_part_z(j) = -qpresults.z(j);
866 }
867 }
868 qpwork.dw_aug.tail(n_constraints) = qpwork.active_part_z;
869}
882template<typename T>
883void
885 const Model<T>& qpmodel,
886 Results<T>& qpresults,
887 Workspace<T>& qpwork,
888 const bool box_constraints,
889 const isize n_constraints,
891 const DenseBackend& dense_backend,
892 const HessianType& hessian_type,
893 T eps_int)
894{
895
896 /* MUST CONTAIN IN ENTRY WITH x = x_prev ; y = y_prev ; z = z_prev
897 * dual_residual_scaled = Hx + rho * (x-x_prev) + A.T y + C.T z
898 * primal_residual_eq_scaled = Ax-b+mu_eq (y_prev-y)
899 * primal_residual_in_scaled_up = Cx-u+mu_in(z_prev)
900 * primal_residual_in_scaled_low = Cx-l+mu_in(z_prev)
901 */
902 /* for debug
903 if (qpsettings.verbose) {
904 std::cout << "---- inner iteration inner error alpha ----" <<
905 std::endl;
906 }
907 */
908 T err_in = 1.e6;
909
910 for (i64 iter = 0; iter <= qpsettings.max_iter_in; ++iter) {
911
912 if (iter == qpsettings.max_iter_in) {
913 qpresults.info.iter += qpsettings.max_iter_in + 1;
914 break;
915 }
918 };
919 primal_dual_semi_smooth_newton_step<T>(qpsettings,
920 qpmodel,
921 qpresults,
922 qpwork,
923 box_constraints,
924 n_constraints,
925 dense_backend,
926 hessian_type,
927 eps_int);
928
929 auto& Hdx = qpwork.Hdx;
930 auto& Adx = qpwork.Adx;
931 auto& Cdx = qpwork.Cdx;
932 auto& ATdy = qpwork.CTz;
933 auto dx = qpwork.dw_aug.head(qpmodel.dim);
934 auto dy = qpwork.dw_aug.segment(qpmodel.dim, qpmodel.n_eq);
935 auto dz = qpwork.dw_aug.tail(n_constraints);
936 LDLT_TEMP_VEC(T, CTdz, qpmodel.dim, stack);
937 if (qpmodel.n_in > 0) {
938 Cdx.head(qpmodel.n_in).noalias() = qpwork.C_scaled * dx;
939 CTdz.noalias() = qpwork.C_scaled.transpose() * dz.head(qpmodel.n_in);
940 }
941 if (box_constraints) {
942 // use active_part_z as tmp variable in order to unscale primarilly dz
943 // as I_scaled.T * dz_scaled = unscale_primarilly_(dz_scaled)
944
945 // qpwork.active_part_z.tail(qpmodel.dim) = dz.tail(qpmodel.dim);
946 // ruiz.unscale_primal_in_place(VectorViewMut<T>{from_eigen,qpwork.active_part_z.tail(qpmodel.dim)});
947 // CTdz.noalias() += qpwork.active_part_z.tail(qpmodel.dim);
948 // Cdx.tail(qpmodel.dim) = dx;
949 // // I_scaled * dx_scaled = dx_unscaled
950 // ruiz.unscale_primal_in_place(VectorViewMut<T>{from_eigen,
951 // Cdx.tail(qpmodel.dim)});
952
953 qpwork.active_part_z.tail(qpmodel.dim) = dz.tail(qpmodel.dim);
954 qpwork.active_part_z.tail(qpmodel.dim).array() *= qpwork.i_scaled.array();
955 CTdz.noalias() += qpwork.active_part_z.tail(qpmodel.dim);
956
957 Cdx.tail(qpmodel.dim) = dx;
958 Cdx.tail(qpmodel.dim).array() *= qpwork.i_scaled.array();
959 }
960 switch (qpsettings.merit_function_type) {
962 Cdx.noalias() +=
963 (qpsettings.alpha_gpdal - 1.) * qpresults.info.mu_in * dz;
964 break;
966 break;
967 }
968 if (qpmodel.n_in > 0 || box_constraints) {
970 qpmodel, qpresults, qpwork, qpsettings, n_constraints);
971 }
972 auto alpha = qpwork.alpha;
973 if (infty_norm(alpha * qpwork.dw_aug) < 1.E-11 && iter > 0) {
974 qpresults.info.iter += iter + 1;
975 break;
976 /* to put in debuger mode
977 if (qpsettings.verbose) {
978 std::cout << "infty_norm(alpha_step * dx) "
979 << infty_norm(alpha *
980 qpwork.dw_aug) << std::endl;
981 }
982 */
983 }
984 qpresults.x += alpha * dx;
985
986 // contains now : C(x+alpha dx)-u + z_prev * mu_in
987 qpwork.primal_residual_in_scaled_up += alpha * Cdx;
988
989 // contains now : C(x+alpha dx)-l + z_prev * mu_in
990 qpresults.si += alpha * Cdx;
991
992 // qpwork.primal_residual_eq_scaled +=
993 qpresults.se += alpha * (Adx - qpresults.info.mu_eq * dy);
994 qpresults.y += alpha * dy;
995 qpresults.z += alpha * dz;
996 switch (hessian_type) {
998 qpwork.dual_residual_scaled +=
999 alpha * (qpresults.info.rho * dx + ATdy + CTdz);
1000 break;
1001 case HessianType::Dense:
1002 qpwork.dual_residual_scaled +=
1003 alpha * (qpresults.info.rho * dx + Hdx + ATdy + CTdz);
1004 break;
1006 qpwork.dual_residual_scaled +=
1007 alpha * (qpresults.info.rho * dx + Hdx + ATdy + CTdz);
1008 break;
1009 }
1010
1012 qpmodel, qpresults, qpwork, qpsettings);
1013 /* for debug
1014 if (qpsettings.verbose) {
1015 std::cout << " " << iter << " " <<
1016 std::setprecision(2) << err_in
1017 << " " << alpha <<
1018 std::endl;
1019 }
1020 */
1021 if (qpsettings.verbose) {
1022 std::cout << "\033[1;34m[inner iteration " << iter + 1 << "]\033[0m"
1023 << std::endl;
1024 std::cout << std::scientific << std::setw(2) << std::setprecision(2)
1025 << "| inner residual=" << err_in << " | alpha=" << alpha
1026 << std::endl;
1027 }
1028 if (iter % qpsettings.frequence_infeasibility_check == 0 ||
1029 qpsettings.primal_infeasibility_solving) {
1030 // compute primal and dual infeasibility criteria
1031 bool is_primal_infeasible = global_primal_residual_infeasibility(
1032 VectorViewMut<T>{ from_eigen, ATdy },
1033 VectorViewMut<T>{ from_eigen, CTdz },
1034 VectorViewMut<T>{ from_eigen, dy },
1035 VectorViewMut<T>{ from_eigen, dz },
1036 qpwork,
1037 qpmodel,
1038 qpsettings,
1039 box_constraints,
1040 ruiz);
1041
1042 bool is_dual_infeasible =
1044 VectorViewMut<T>{ from_eigen, Cdx },
1045 VectorViewMut<T>{ from_eigen, Hdx },
1046 VectorViewMut<T>{ from_eigen, dx },
1047 qpwork,
1048 qpsettings,
1049 qpmodel,
1050 box_constraints,
1051 ruiz);
1052 if (is_primal_infeasible) {
1054 if (!qpsettings.primal_infeasibility_solving) {
1055 qpresults.info.iter += iter + 1;
1056 break;
1057 }
1058 } else if (is_dual_infeasible) {
1060 qpresults.info.iter += iter + 1;
1061 break;
1062 }
1063 }
1064 if (err_in <= eps_int) {
1065 qpresults.info.iter += iter + 1;
1066 break;
1067 }
1068 }
1069 /* to put in debuger mode
1070 if (qpsettings.verbose) {
1071 if (err_in > eps_int){
1072 std::cout << " inner loop residual is to high! Its value is equal to "
1073 << err_in << ", while it should be inferior to: " << eps_int << std::endl;
1074 }
1075 }
1076 */
1077}
1088template<typename T>
1089void
1091 const Settings<T>& qpsettings,
1092 const Model<T>& qpmodel,
1093 Results<T>& qpresults,
1094 Workspace<T>& qpwork,
1095 const bool box_constraints,
1096 const DenseBackend& dense_backend,
1097 const HessianType& hessian_type,
1099{
1100 /*** TEST WITH MATRIX FULL OF NAN FOR DEBUG
1101 static constexpr Layout layout = rowmajor;
1102 static constexpr auto DYN = Eigen::Dynamic;
1103 using RowMat = Eigen::Matrix<T, DYN, DYN, Eigen::RowMajor>;
1104 RowMat test(2,2); // test it is full of nan for debug
1105 std::cout << "test " << test << std::endl;
1106 */
1108 isize n_constraints(qpmodel.n_in);
1109 if (box_constraints) {
1110 n_constraints += qpmodel.dim;
1111 }
1112 if (qpsettings.compute_timings) {
1113 qpwork.timer.stop();
1114 qpwork.timer.start();
1115 }
1116 if (qpsettings.verbose) {
1117 dense::print_setup_header(qpsettings,
1118 qpresults,
1119 qpmodel,
1120 box_constraints,
1121 dense_backend,
1122 hessian_type);
1123 }
1124 // std::cout << "qpwork.dirty " << qpwork.dirty << std::endl;
1125 if (qpwork.dirty) { // the following is used when a solve has already been
1126 // executed (and without any intermediary model update)
1127 switch (qpsettings.initial_guess) {
1129 qpwork.cleanup(box_constraints);
1130 qpresults.cleanup(qpsettings);
1131 break;
1132 }
1134 // keep solutions but restart workspace and results
1135 qpwork.cleanup(box_constraints);
1136 qpresults.cold_start(qpsettings);
1138 { proxsuite::proxqp::from_eigen, qpresults.x });
1140 { proxsuite::proxqp::from_eigen, qpresults.y });
1142 { proxsuite::proxqp::from_eigen, qpresults.z.head(qpmodel.n_in) });
1143 if (box_constraints) {
1145 { proxsuite::proxqp::from_eigen, qpresults.z.tail(qpmodel.dim) });
1146 }
1147 break;
1148 }
1150 qpwork.cleanup(box_constraints);
1151 qpresults.cleanup(qpsettings);
1152 break;
1153 }
1155 qpwork.cleanup(box_constraints);
1156 qpresults.cold_start(
1157 qpsettings); // because there was already a solve,
1158 // precond was already computed if set so
1160 { proxsuite::proxqp::from_eigen,
1161 qpresults
1162 .x }); // it contains the value given in entry for warm start
1164 { proxsuite::proxqp::from_eigen, qpresults.y });
1166 { proxsuite::proxqp::from_eigen, qpresults.z.head(qpmodel.n_in) });
1167 if (box_constraints) {
1169 { proxsuite::proxqp::from_eigen, qpresults.z.tail(qpmodel.dim) });
1170 }
1171 break;
1172 }
1174 // keep workspace and results solutions except statistics
1175 // std::cout << "i keep previous solution" << std::endl;
1176 qpresults.cleanup_statistics();
1178 { proxsuite::proxqp::from_eigen, qpresults.x });
1180 { proxsuite::proxqp::from_eigen, qpresults.y });
1182 { proxsuite::proxqp::from_eigen, qpresults.z.head(qpmodel.n_in) });
1183 if (box_constraints) {
1185 { proxsuite::proxqp::from_eigen, qpresults.z.tail(qpmodel.dim) });
1186 }
1187 break;
1188 }
1189 }
1190 if (qpsettings.initial_guess !=
1192 switch (hessian_type) {
1193 case HessianType::Zero:
1194 break;
1195 case HessianType::Dense:
1196 qpwork.H_scaled = qpmodel.H;
1197 break;
1199 qpwork.H_scaled = qpmodel.H;
1200 break;
1201 }
1202 qpwork.g_scaled = qpmodel.g;
1203 qpwork.A_scaled = qpmodel.A;
1204 qpwork.b_scaled = qpmodel.b;
1205 qpwork.C_scaled = qpmodel.C;
1206 qpwork.u_scaled = qpmodel.u;
1207 qpwork.l_scaled = qpmodel.l;
1209 qpwork,
1210 qpsettings,
1211 box_constraints,
1212 hessian_type,
1213 ruiz,
1214 false); // reuse previous equilibration
1216 qpwork, qpmodel, qpresults, dense_backend, hessian_type);
1217 }
1218 switch (qpsettings.initial_guess) {
1221 qpsettings,
1222 qpmodel,
1223 n_constraints,
1224 dense_backend,
1225 hessian_type,
1226 qpresults);
1227 break;
1228 }
1231 qpwork.n_c = 0;
1232 for (isize i = 0; i < n_constraints; i++) {
1233 if (qpresults.z[i] != 0) {
1234 qpwork.active_inequalities[i] = true;
1235 } else {
1236 qpwork.active_inequalities[i] = false;
1237 }
1238 }
1240 qpmodel, qpresults, dense_backend, n_constraints, qpwork);
1241 break;
1242 }
1244 break;
1245 }
1248 qpwork.n_c = 0;
1249 for (isize i = 0; i < n_constraints; i++) {
1250 if (qpresults.z[i] != 0) {
1251 qpwork.active_inequalities[i] = true;
1252 } else {
1253 qpwork.active_inequalities[i] = false;
1254 }
1255 }
1257 qpmodel, qpresults, dense_backend, n_constraints, qpwork);
1258 break;
1259 }
1261 // keep workspace and results solutions except statistics
1262 // std::cout << "i use previous solution" << std::endl;
1263 // meaningful for when one wants to warm start with previous result with
1264 // the same QP model
1265 break;
1266 }
1267 }
1268 } else { // the following is used for a first solve after initializing or
1269 // updating the Qp object
1270 switch (qpsettings.initial_guess) {
1273 qpwork, qpmodel, qpresults, dense_backend, hessian_type);
1275 qpsettings,
1276 qpmodel,
1277 n_constraints,
1278 dense_backend,
1279 hessian_type,
1280 qpresults);
1281 break;
1282 }
1286 { proxsuite::proxqp::from_eigen,
1287 qpresults
1288 .x }); // meaningful for when there is an upate of the model and
1289 // one wants to warm start with previous result
1291 { proxsuite::proxqp::from_eigen, qpresults.y });
1293 { proxsuite::proxqp::from_eigen, qpresults.z.head(qpmodel.n_in) });
1294 if (box_constraints) {
1296 { proxsuite::proxqp::from_eigen, qpresults.z.tail(qpmodel.dim) });
1297 }
1299 qpwork, qpmodel, qpresults, dense_backend, hessian_type);
1300 qpwork.n_c = 0;
1301 for (isize i = 0; i < n_constraints; i++) {
1302 if (qpresults.z[i] != 0) {
1303 qpwork.active_inequalities[i] = true;
1304 } else {
1305 qpwork.active_inequalities[i] = false;
1306 }
1307 }
1309 qpmodel, qpresults, dense_backend, n_constraints, qpwork);
1310 break;
1311 }
1314 qpwork, qpmodel, qpresults, dense_backend, hessian_type);
1315 break;
1316 }
1320 { proxsuite::proxqp::from_eigen, qpresults.x });
1322 { proxsuite::proxqp::from_eigen, qpresults.y });
1324 { proxsuite::proxqp::from_eigen, qpresults.z.head(qpmodel.n_in) });
1325 if (box_constraints) {
1327 { proxsuite::proxqp::from_eigen, qpresults.z.tail(qpmodel.dim) });
1328 }
1330 qpwork, qpmodel, qpresults, dense_backend, hessian_type);
1331 qpwork.n_c = 0;
1332 for (isize i = 0; i < n_constraints; i++) {
1333 if (qpresults.z[i] != 0) {
1334 qpwork.active_inequalities[i] = true;
1335 } else {
1336 qpwork.active_inequalities[i] = false;
1337 }
1338 }
1340 qpmodel, qpresults, dense_backend, n_constraints, qpwork);
1341 break;
1342 }
1344 // std::cout << "i refactorize from previous solution" << std::endl;
1346 { proxsuite::proxqp::from_eigen,
1347 qpresults
1348 .x }); // meaningful for when there is an upate of the model and
1349 // one wants to warm start with previous result
1351 { proxsuite::proxqp::from_eigen, qpresults.y });
1353 { proxsuite::proxqp::from_eigen, qpresults.z.head(qpmodel.n_in) });
1354 if (box_constraints) {
1356 { proxsuite::proxqp::from_eigen, qpresults.z.tail(qpmodel.dim) });
1357 }
1358 if (qpwork.refactorize) { // refactorization only when one of the
1359 // matrices has changed or one proximal
1360 // parameter has changed
1362 qpwork, qpmodel, qpresults, dense_backend, hessian_type);
1363 qpwork.n_c = 0;
1364 for (isize i = 0; i < n_constraints; i++) {
1365 if (qpresults.z[i] != 0) {
1366 qpwork.active_inequalities[i] = true;
1367 } else {
1368 qpwork.active_inequalities[i] = false;
1369 }
1370 }
1372 qpmodel, qpresults, dense_backend, n_constraints, qpwork);
1373 break;
1374 }
1375 }
1376 }
1377 }
1378 T bcl_eta_ext_init = pow(T(0.1), qpsettings.alpha_bcl);
1379 T bcl_eta_ext = bcl_eta_ext_init;
1380 T bcl_eta_in(1);
1381 T eps_in_min = std::min(qpsettings.eps_abs, T(1.E-9));
1382
1383 T primal_feasibility_eq_rhs_0(0);
1384 T primal_feasibility_in_rhs_0(0);
1385 T dual_feasibility_rhs_0(0);
1386 T dual_feasibility_rhs_1(0);
1387 T dual_feasibility_rhs_3(0);
1388 T primal_feasibility_lhs(0);
1389 T primal_feasibility_eq_lhs(0);
1390 T primal_feasibility_in_lhs(0);
1391 T dual_feasibility_lhs(0);
1392
1393 T duality_gap(0);
1394 T rhs_duality_gap(0);
1395 T scaled_eps(qpsettings.eps_abs);
1396
1397 for (i64 iter = 0; iter < qpsettings.max_iter; ++iter) {
1398
1399 // compute primal residual
1400
1401 // PERF: fuse matrix product computations in global_{primal, dual}_residual
1402 global_primal_residual(qpmodel,
1403 qpresults,
1404 qpsettings,
1405 qpwork,
1406 ruiz,
1407 box_constraints,
1408 primal_feasibility_lhs,
1409 primal_feasibility_eq_rhs_0,
1410 primal_feasibility_in_rhs_0,
1411 primal_feasibility_eq_lhs,
1412 primal_feasibility_in_lhs);
1413
1414 global_dual_residual(qpresults,
1415 qpwork,
1416 qpmodel,
1417 box_constraints,
1418 ruiz,
1419 dual_feasibility_lhs,
1420 dual_feasibility_rhs_0,
1421 dual_feasibility_rhs_1,
1422 dual_feasibility_rhs_3,
1423 rhs_duality_gap,
1424 duality_gap,
1425 hessian_type);
1426
1427 qpresults.info.pri_res = primal_feasibility_lhs;
1428 qpresults.info.dua_res = dual_feasibility_lhs;
1429 qpresults.info.duality_gap = duality_gap;
1430
1431 T new_bcl_mu_in(qpresults.info.mu_in);
1432 T new_bcl_mu_eq(qpresults.info.mu_eq);
1433 T new_bcl_mu_in_inv(qpresults.info.mu_in_inv);
1434 T new_bcl_mu_eq_inv(qpresults.info.mu_eq_inv);
1435
1436 T rhs_pri(scaled_eps);
1437 if (qpsettings.eps_rel != 0) {
1438 rhs_pri += qpsettings.eps_rel * std::max(primal_feasibility_eq_rhs_0,
1439 primal_feasibility_in_rhs_0);
1440 }
1441 bool is_primal_feasible = primal_feasibility_lhs <= rhs_pri;
1442
1443 T rhs_dua(qpsettings.eps_abs);
1444 if (qpsettings.eps_rel != 0) {
1445 rhs_dua +=
1446 qpsettings.eps_rel *
1447 std::max(
1448 std::max(dual_feasibility_rhs_3, dual_feasibility_rhs_0),
1449 std::max(dual_feasibility_rhs_1, qpwork.dual_feasibility_rhs_2));
1450 }
1451
1452 bool is_dual_feasible = dual_feasibility_lhs <= rhs_dua;
1453
1454 if (qpsettings.verbose) {
1455
1456 ruiz.unscale_primal_in_place(VectorViewMut<T>{ from_eigen, qpresults.x });
1458 VectorViewMut<T>{ from_eigen, qpresults.y });
1460 VectorViewMut<T>{ from_eigen, qpresults.z.head(qpmodel.n_in) });
1461 if (box_constraints) {
1463 VectorViewMut<T>{ from_eigen, qpresults.z.tail(qpmodel.dim) });
1464 }
1465 {
1466 // EigenAllowAlloc _{};
1467 qpresults.info.objValue = 0;
1468 for (Eigen::Index j = 0; j < qpmodel.dim; ++j) {
1469 qpresults.info.objValue +=
1470 0.5 * (qpresults.x(j) * qpresults.x(j)) * qpmodel.H(j, j);
1471 qpresults.info.objValue +=
1472 qpresults.x(j) * T(qpmodel.H.col(j)
1473 .tail(qpmodel.dim - j - 1)
1474 .dot(qpresults.x.tail(qpmodel.dim - j - 1)));
1475 }
1476 qpresults.info.objValue += (qpmodel.g).dot(qpresults.x);
1477 }
1478 std::cout << "\033[1;32m[outer iteration " << iter + 1 << "]\033[0m"
1479 << std::endl;
1480 std::cout << std::scientific << std::setw(2) << std::setprecision(2)
1481 << "| primal residual=" << qpresults.info.pri_res
1482 << " | dual residual=" << qpresults.info.dua_res
1483 << " | duality gap=" << qpresults.info.duality_gap
1484 << " | mu_in=" << qpresults.info.mu_in
1485 << " | rho=" << qpresults.info.rho << std::endl;
1486 ruiz.scale_primal_in_place(VectorViewMut<T>{ from_eigen, qpresults.x });
1487 ruiz.scale_dual_in_place_eq(VectorViewMut<T>{ from_eigen, qpresults.y });
1489 VectorViewMut<T>{ from_eigen, qpresults.z.head(qpmodel.n_in) });
1490 if (box_constraints) {
1492 VectorViewMut<T>{ from_eigen, qpresults.z.tail(qpmodel.dim) });
1493 }
1494 }
1495 if (is_primal_feasible && is_dual_feasible) {
1496 if (qpsettings.check_duality_gap) {
1497 if (std::fabs(qpresults.info.duality_gap) <=
1498 qpsettings.eps_duality_gap_abs +
1499 qpsettings.eps_duality_gap_rel * rhs_duality_gap) {
1500 if (qpsettings.primal_infeasibility_solving &&
1501 qpresults.info.status ==
1503 qpresults.info.status =
1505 } else {
1506 qpresults.info.status = QPSolverOutput::PROXQP_SOLVED;
1507 }
1508 break;
1509 }
1510 } else {
1511 qpresults.info.status = QPSolverOutput::PROXQP_SOLVED;
1512 break;
1513 }
1514 }
1515 qpresults.info.iter_ext += 1; // We start a new external loop update
1516
1517 qpwork.x_prev = qpresults.x;
1518 qpwork.y_prev = qpresults.y;
1519 qpwork.z_prev = qpresults.z;
1520
1521 // primal dual version from gill and robinson
1522
1524 VectorViewMut<T>{ from_eigen,
1525 qpwork.primal_residual_in_scaled_up.head(
1526 qpmodel.n_in) }); // contains now scaled(Cx)
1527 if (box_constraints) {
1529 VectorViewMut<T>{ from_eigen,
1530 qpwork.primal_residual_in_scaled_up.tail(
1531 qpmodel.dim) }); // contains now scaled(x)
1532 }
1534 qpwork.z_prev *
1535 qpresults.info.mu_in; // contains now scaled(Cx+z_prev*mu_in)
1536 switch (qpsettings.merit_function_type) {
1539 (qpsettings.alpha_gpdal - 1.) * qpresults.info.mu_in * qpresults.z;
1540 break;
1542 break;
1543 }
1544 qpresults.si = qpwork.primal_residual_in_scaled_up;
1545 qpwork.primal_residual_in_scaled_up.head(qpmodel.n_in) -=
1546 qpwork.u_scaled; // contains now scaled(Cx-u+z_prev*mu_in)
1547 qpresults.si.head(qpmodel.n_in) -=
1548 qpwork.l_scaled; // contains now scaled(Cx-l+z_prev*mu_in)
1549 if (box_constraints) {
1550 // qpwork.primal_residual_in_scaled_up.tail(qpmodel.dim) -=
1551 // qpmodel.u_box; // contains now scaled(Cx-u+z_prev*mu_in)
1552 // qpwork.primal_residual_in_scaled_low.tail(qpmodel.dim) -=
1553 // qpmodel.l_box; // contains now scaled(Cx-l+z_prev*mu_in)
1554
1555 qpwork.primal_residual_in_scaled_up.tail(qpmodel.dim) -=
1556 qpwork.u_box_scaled; // contains now scaled(Cx-u+z_prev*mu_in)
1557 qpresults.si.tail(qpmodel.dim) -=
1558 qpwork.l_box_scaled; // contains now scaled(Cx-l+z_prev*mu_in)
1559 }
1560
1562 qpmodel,
1563 qpresults,
1564 qpwork,
1565 box_constraints,
1566 n_constraints,
1567 ruiz,
1568 dense_backend,
1569 hessian_type,
1570 bcl_eta_in);
1571
1572 if ((qpresults.info.status == QPSolverOutput::PROXQP_PRIMAL_INFEASIBLE &&
1573 !qpsettings.primal_infeasibility_solving) ||
1574 qpresults.info.status == QPSolverOutput::PROXQP_DUAL_INFEASIBLE) {
1575 // certificate of infeasibility
1576 qpresults.x = qpwork.dw_aug.head(qpmodel.dim);
1577 qpresults.y = qpwork.dw_aug.segment(qpmodel.dim, qpmodel.n_eq);
1578 qpresults.z = qpwork.dw_aug.tail(n_constraints);
1579 break;
1580 }
1581 if (scaled_eps == qpsettings.eps_abs &&
1582 qpsettings.primal_infeasibility_solving &&
1583 qpresults.info.status == QPSolverOutput::PROXQP_PRIMAL_INFEASIBLE) {
1584 qpwork.rhs.segment(qpmodel.dim, qpmodel.n_eq + qpmodel.n_in)
1585 .setConstant(T(1));
1586 qpwork.rhs.head(qpmodel.dim).noalias() =
1587 qpmodel.A.transpose() * qpwork.rhs.segment(qpmodel.dim, qpmodel.n_eq) +
1588 qpmodel.C.transpose() *
1589 qpwork.rhs.segment(qpmodel.dim + qpmodel.n_eq, qpmodel.n_in);
1590 if (box_constraints) {
1591 qpwork.rhs.head(qpmodel.dim).array() += qpwork.i_scaled.array();
1592 }
1593 scaled_eps =
1594 infty_norm(qpwork.rhs.head(qpmodel.dim)) * qpsettings.eps_abs;
1595 }
1596 T primal_feasibility_lhs_new(primal_feasibility_lhs);
1597
1598 global_primal_residual(qpmodel,
1599 qpresults,
1600 qpsettings,
1601 qpwork,
1602 ruiz,
1603 box_constraints,
1604 primal_feasibility_lhs_new,
1605 primal_feasibility_eq_rhs_0,
1606 primal_feasibility_in_rhs_0,
1607 primal_feasibility_eq_lhs,
1608 primal_feasibility_in_lhs);
1609
1610 is_primal_feasible =
1611 primal_feasibility_lhs_new <=
1612 (scaled_eps + qpsettings.eps_rel * std::max(primal_feasibility_eq_rhs_0,
1613 primal_feasibility_in_rhs_0));
1614 qpresults.info.pri_res = primal_feasibility_lhs_new;
1615 if (is_primal_feasible) {
1616 T dual_feasibility_lhs_new(dual_feasibility_lhs);
1617
1618 global_dual_residual(qpresults,
1619 qpwork,
1620 qpmodel,
1621 box_constraints,
1622 ruiz,
1623 dual_feasibility_lhs_new,
1624 dual_feasibility_rhs_0,
1625 dual_feasibility_rhs_1,
1626 dual_feasibility_rhs_3,
1627 rhs_duality_gap,
1628 duality_gap,
1629 hessian_type);
1630 qpresults.info.dua_res = dual_feasibility_lhs_new;
1631 qpresults.info.duality_gap = duality_gap;
1632
1633 is_dual_feasible =
1634 dual_feasibility_lhs_new <=
1635 (qpsettings.eps_abs +
1636 qpsettings.eps_rel *
1637 std::max(
1638 std::max(dual_feasibility_rhs_3, dual_feasibility_rhs_0),
1639 std::max(dual_feasibility_rhs_1, qpwork.dual_feasibility_rhs_2)));
1640
1641 if (is_dual_feasible) {
1642 if (qpsettings.check_duality_gap) {
1643 if (std::fabs(qpresults.info.duality_gap) <=
1644 qpsettings.eps_duality_gap_abs +
1645 qpsettings.eps_duality_gap_rel * rhs_duality_gap) {
1646 if (qpsettings.primal_infeasibility_solving &&
1647 qpresults.info.status ==
1649 qpresults.info.status =
1651 } else {
1652 qpresults.info.status = QPSolverOutput::PROXQP_SOLVED;
1653 }
1654 }
1655 } else {
1656 if (qpsettings.primal_infeasibility_solving &&
1657 qpresults.info.status ==
1659 qpresults.info.status =
1661 } else {
1662 qpresults.info.status = QPSolverOutput::PROXQP_SOLVED;
1663 }
1664 }
1665 }
1666 }
1667 if (qpsettings.bcl_update) {
1668 bcl_update(qpsettings,
1669 qpresults,
1670 qpwork,
1671 primal_feasibility_lhs_new,
1672 bcl_eta_ext,
1673 bcl_eta_in,
1674 bcl_eta_ext_init,
1675 eps_in_min,
1676
1677 new_bcl_mu_in,
1678 new_bcl_mu_eq,
1679 new_bcl_mu_in_inv,
1680 new_bcl_mu_eq_inv);
1681 } else {
1682 Martinez_update(qpsettings,
1683 qpresults,
1684 primal_feasibility_lhs_new,
1685 primal_feasibility_lhs,
1686 bcl_eta_in,
1687 eps_in_min,
1688 new_bcl_mu_in,
1689 new_bcl_mu_eq,
1690 new_bcl_mu_in_inv,
1691 new_bcl_mu_eq_inv);
1692 }
1693 // COLD RESTART
1694
1695 T dual_feasibility_lhs_new(dual_feasibility_lhs);
1696
1697 global_dual_residual(qpresults,
1698 qpwork,
1699 qpmodel,
1700 box_constraints,
1701 ruiz,
1702 dual_feasibility_lhs_new,
1703 dual_feasibility_rhs_0,
1704 dual_feasibility_rhs_1,
1705 dual_feasibility_rhs_3,
1706 rhs_duality_gap,
1707 duality_gap,
1708 hessian_type);
1709 qpresults.info.dua_res = dual_feasibility_lhs_new;
1710 qpresults.info.duality_gap = duality_gap;
1711
1712 if (primal_feasibility_lhs_new >= primal_feasibility_lhs &&
1713 dual_feasibility_lhs_new >= dual_feasibility_lhs &&
1714 qpresults.info.mu_in <= T(1e-5)) {
1715 /* to put in debuger mode
1716 if (qpsettings.verbose) {
1717 std::cout << "cold restart" << std::endl;
1718 }
1719 */
1720
1721 new_bcl_mu_in = qpsettings.cold_reset_mu_in;
1722 new_bcl_mu_eq = qpsettings.cold_reset_mu_eq;
1723 new_bcl_mu_in_inv = qpsettings.cold_reset_mu_in_inv;
1724 new_bcl_mu_eq_inv = qpsettings.cold_reset_mu_eq_inv;
1725 }
1726
1728
1729 if (qpresults.info.mu_in != new_bcl_mu_in ||
1730 qpresults.info.mu_eq != new_bcl_mu_eq) {
1731 {
1732 ++qpresults.info.mu_updates;
1733 }
1734 mu_update(qpmodel,
1735 qpresults,
1736 qpwork,
1737 n_constraints,
1738 dense_backend,
1739 new_bcl_mu_eq,
1740 new_bcl_mu_in);
1741 }
1742
1743 qpresults.info.mu_eq = new_bcl_mu_eq;
1744 qpresults.info.mu_in = new_bcl_mu_in;
1745 qpresults.info.mu_eq_inv = new_bcl_mu_eq_inv;
1746 qpresults.info.mu_in_inv = new_bcl_mu_in_inv;
1747 }
1748
1749 ruiz.unscale_primal_in_place(VectorViewMut<T>{ from_eigen, qpresults.x });
1750 ruiz.unscale_dual_in_place_eq(VectorViewMut<T>{ from_eigen, qpresults.y });
1752 VectorViewMut<T>{ from_eigen, qpresults.z.head(qpmodel.n_in) });
1753 if (box_constraints) {
1755 VectorViewMut<T>{ from_eigen, qpresults.z.tail(qpmodel.dim) });
1756 }
1757 if (qpsettings.primal_infeasibility_solving &&
1758 qpresults.info.status == QPSolverOutput::PROXQP_PRIMAL_INFEASIBLE) {
1760 VectorViewMut<T>{ from_eigen, qpresults.se });
1762 VectorViewMut<T>{ from_eigen, qpresults.si.head(qpmodel.n_in) });
1763 if (box_constraints) {
1765 VectorViewMut<T>{ from_eigen, qpresults.si.tail(qpmodel.dim) });
1766 }
1767 }
1768
1769 {
1770 // EigenAllowAlloc _{};
1771 qpresults.info.objValue = 0;
1772 for (Eigen::Index j = 0; j < qpmodel.dim; ++j) {
1773 qpresults.info.objValue +=
1774 0.5 * (qpresults.x(j) * qpresults.x(j)) * qpmodel.H(j, j);
1775 qpresults.info.objValue +=
1776 qpresults.x(j) * T(qpmodel.H.col(j)
1777 .tail(qpmodel.dim - j - 1)
1778 .dot(qpresults.x.tail(qpmodel.dim - j - 1)));
1779 }
1780 qpresults.info.objValue += (qpmodel.g).dot(qpresults.x);
1781 }
1782
1783 if (qpsettings.compute_timings) {
1784 qpresults.info.solve_time = qpwork.timer.elapsed().user; // in microseconds
1785 qpresults.info.run_time =
1786 qpresults.info.solve_time + qpresults.info.setup_time;
1787 }
1788
1789 if (qpsettings.verbose) {
1790 std::cout << "-------------------SOLVER STATISTICS-------------------"
1791 << std::endl;
1792 std::cout << "outer iter: " << qpresults.info.iter_ext << std::endl;
1793 std::cout << "total iter: " << qpresults.info.iter << std::endl;
1794 std::cout << "mu updates: " << qpresults.info.mu_updates << std::endl;
1795 std::cout << "rho updates: " << qpresults.info.rho_updates << std::endl;
1796 std::cout << "objective: " << qpresults.info.objValue << std::endl;
1797 switch (qpresults.info.status) {
1799 std::cout << "status: "
1800 << "Solved" << std::endl;
1801 break;
1802 }
1804 std::cout << "status: "
1805 << "Maximum number of iterations reached" << std::endl;
1806 break;
1807 }
1809 std::cout << "status: "
1810 << "Primal infeasible" << std::endl;
1811 break;
1812 }
1814 std::cout << "status: "
1815 << "Dual infeasible" << std::endl;
1816 break;
1817 }
1819 std::cout << "status: "
1820 << "Solved closest primal feasible" << std::endl;
1821 break;
1822 }
1824 std::cout << "status: "
1825 << "Solver not run" << std::endl;
1826 break;
1827 }
1828 }
1829
1830 if (qpsettings.compute_timings)
1831 std::cout << "run time [μs]: " << qpresults.info.solve_time << std::endl;
1832 std::cout << "--------------------------------------------------------"
1833 << std::endl;
1834 }
1835 qpwork.dirty = true;
1836 qpwork.is_initialized = true; // necessary because we call workspace cleanup
1837
1838 assert(!std::isnan(qpresults.info.pri_res));
1839 assert(!std::isnan(qpresults.info.dua_res));
1840 assert(!std::isnan(qpresults.info.duality_gap));
1841
1843}
1844
1845} // namespace dense
1846
1847} // namespace proxqp
1848} // namespace proxsuite
1849
1850#endif /* end of include guard PROXSUITE_PROXQP_DENSE_SOLVER_HPP */
#define LDLT_TEMP_VEC(Type, Name, Rows, Stack)
Definition core.hpp:74
#define LDLT_TEMP_MAT_UNINIT(Type, Name, Rows, Cols, Stack)
Definition core.hpp:81
#define LDLT_TEMP_VEC_UNINIT(Type, Name, Rows, Stack)
Definition core.hpp:76
#define LDLT_TEMP_MAT(Type, Name, Rows, Cols, Stack)
Definition core.hpp:79
#define PROXSUITE_EIGEN_MALLOC_ALLOWED()
Definition fwd.hpp:49
#define PROXSUITE_EIGEN_MALLOC_NOT_ALLOWED()
Definition fwd.hpp:50
#define PROXSUITE_THROW_PRETTY(condition, exception, message)
Definition macros.hpp:18
auto positive_part(T const &expr) PROXSUITE_DEDUCE_RET((expr.array() > 0).select(expr
Returns the positive part of an expression.
auto negative_part(T const &expr) PROXSUITE_DEDUCE_RET((expr.array()< 0).select(expr
Returns the negative part of an expression.
void active_set_change(const Model< T > &qpmodel, Results< T > &qpresults, const DenseBackend &dense_backend, const isize n_constraints, Workspace< T > &qpwork)
void primal_dual_ls(const Model< T > &qpmodel, Results< T > &qpresults, Workspace< T > &qpwork, const Settings< T > &qpsettings, const isize n_constraints)
void setup_factorization(Workspace< T > &qpwork, const Model< T > &qpmodel, Results< T > &qpresults, const DenseBackend &dense_backend, const HessianType &hessian_type)
Definition helpers.hpp:241
void primal_dual_newton_semi_smooth(const Settings< T > &qpsettings, const Model< T > &qpmodel, Results< T > &qpresults, Workspace< T > &qpwork, const bool box_constraints, const isize n_constraints, preconditioner::RuizEquilibration< T > &ruiz, const DenseBackend &dense_backend, const HessianType &hessian_type, T eps_int)
Definition solver.hpp:884
void iterative_solve_with_permut_fact(const Settings< T > &qpsettings, const Model< T > &qpmodel, Results< T > &qpresults, Workspace< T > &qpwork, const isize n_constraints, const DenseBackend &dense_backend, const HessianType &hessian_type, T eps, isize inner_pb_dim)
Definition solver.hpp:408
void setup_equilibration(Workspace< T > &qpwork, const Settings< T > &qpsettings, const bool box_constraints, const HessianType hessian_type, preconditioner::RuizEquilibration< T > &ruiz, bool execute_preconditioner)
Definition helpers.hpp:300
void primal_dual_semi_smooth_newton_step(const Settings< T > &qpsettings, const Model< T > &qpmodel, Results< T > &qpresults, Workspace< T > &qpwork, const bool box_constraints, const isize n_constraints, const DenseBackend &dense_backend, const HessianType &hessian_type, T eps)
Definition solver.hpp:756
void global_dual_residual(Results< T > &qpresults, Workspace< T > &qpwork, const Model< T > &qpmodel, const bool box_constraints, const preconditioner::RuizEquilibration< T > &ruiz, T &dual_feasibility_lhs, T &dual_feasibility_rhs_0, T &dual_feasibility_rhs_1, T &dual_feasibility_rhs_3, T &rhs_duality_gap, T &duality_gap, const HessianType &hessian_type)
Definition utils.hpp:439
bool global_dual_residual_infeasibility(VectorViewMut< T > Adx, VectorViewMut< T > Cdx, VectorViewMut< T > Hdx, VectorViewMut< T > dx, Workspace< T > &qpwork, const Settings< T > &qpsettings, const Model< T > &qpmodel, const bool box_constraints, const preconditioner::RuizEquilibration< T > &ruiz)
Definition utils.hpp:345
void mu_update(const Model< T > &qpmodel, Results< T > &qpresults, Workspace< T > &qpwork, isize n_constraints, const DenseBackend &dense_backend, T mu_eq_new, T mu_in_new)
Definition solver.hpp:130
void Martinez_update(const Settings< T > &qpsettings, Results< T > &qpresults, T &primal_feasibility_lhs_new, T &primal_feasibility_lhs_old, T &bcl_eta_in, T eps_in_min, T &new_bcl_mu_in, T &new_bcl_mu_eq, T &new_bcl_mu_in_inv, T &new_bcl_mu_eq_inv)
Definition solver.hpp:639
bool global_primal_residual_infeasibility(VectorViewMut< T > ATdy, VectorViewMut< T > CTdz, VectorViewMut< T > dy, VectorViewMut< T > dz, Workspace< T > &qpwork, const Model< T > &qpmodel, const Settings< T > &qpsettings, const bool box_constraints, const preconditioner::RuizEquilibration< T > &ruiz)
Definition utils.hpp:271
void bcl_update(const Settings< T > &qpsettings, Results< T > &qpresults, Workspace< T > &qpwork, T &primal_feasibility_lhs_new, T &bcl_eta_ext, T &bcl_eta_in, T bcl_eta_ext_init, T eps_in_min, T &new_bcl_mu_in, T &new_bcl_mu_eq, T &new_bcl_mu_in_inv, T &new_bcl_mu_eq_inv)
Definition solver.hpp:566
void global_primal_residual(const Model< T > &qpmodel, Results< T > &qpresults, const Settings< T > &qpsettings, Workspace< T > &qpwork, const preconditioner::RuizEquilibration< T > &ruiz, const bool box_constraints, T &primal_feasibility_lhs, T &primal_feasibility_eq_rhs_0, T &primal_feasibility_in_rhs_0, T &primal_feasibility_eq_lhs, T &primal_feasibility_in_lhs)
Definition utils.hpp:166
void solve_linear_system(proxsuite::proxqp::dense::Vec< T > &dw, const Model< T > &qpmodel, Results< T > &qpresults, Workspace< T > &qpwork, const isize n_constraints, const DenseBackend &dense_backend, isize inner_pb_dim, proxsuite::linalg::veg::dynstack::DynStackMut &stack)
Definition solver.hpp:322
void qp_solve(const Settings< T > &qpsettings, const Model< T > &qpmodel, Results< T > &qpresults, Workspace< T > &qpwork, const bool box_constraints, const DenseBackend &dense_backend, const HessianType &hessian_type, preconditioner::RuizEquilibration< T > &ruiz)
Definition solver.hpp:1090
void iterative_residual(const Model< T > &qpmodel, Results< T > &qpresults, Workspace< T > &qpwork, const isize n_constraints, isize inner_pb_dim, const HessianType &hessian_type)
Definition solver.hpp:245
Eigen::Matrix< T, DYN, 1 > Vec
Definition fwd.hpp:24
void compute_equality_constrained_initial_guess(Workspace< T > &qpwork, const Settings< T > &qpsettings, const Model< T > &qpmodel, const isize n_constraints, const DenseBackend &dense_backend, const HessianType &hessian_type, Results< T > &qpresults)
Definition helpers.hpp:201
void print_setup_header(const Settings< T > &settings, const Results< T > &results, const Model< T > &model, const bool box_constraints, const DenseBackend &dense_backend, const HessianType &hessian_type)
Definition utils.hpp:33
void refactorize(const Model< T > &qpmodel, Results< T > &qpresults, Workspace< T > &qpwork, const isize n_constraints, const DenseBackend &dense_backend, T rho_new)
Definition solver.hpp:40
auto compute_inner_loop_saddle_point(const Model< T > &qpmodel, Results< T > &qpresults, Workspace< T > &qpwork, const Settings< T > &qpsettings) -> T
Definition solver.hpp:689
VEG_NODISCARD VEG_INLINE auto as_mut() VEG_NOEXCEPT -> SliceMut< T >
Definition vec.hpp:957
This class stores all the results of PROXQP solvers with sparse and dense backends.
Definition results.hpp:68
sparse::Vec< T > z
Definition results.hpp:74
sparse::Vec< T > si
Definition results.hpp:77
void cold_start(optional< Settings< T > > settings=nullopt)
Definition results.hpp:175
void cleanup(optional< Settings< T > > settings=nullopt)
Definition results.hpp:149
sparse::Vec< T > y
Definition results.hpp:73
sparse::Vec< T > se
Definition results.hpp:75
sparse::Vec< T > x
Definition results.hpp:72
This class defines the settings of PROXQP solvers with sparse and dense backends.
Definition settings.hpp:89
MeritFunctionType merit_function_type
Definition settings.hpp:137
InitialGuessStatus initial_guess
Definition settings.hpp:123
This class stores the model of the QP problem.
Definition model.hpp:24
This class defines the workspace of the dense solver.
Definition workspace.hpp:26
proxsuite::linalg::veg::Vec< unsigned char > ldl_stack
Definition workspace.hpp:30
void cleanup(const bool box_constraints)
proxsuite::linalg::dense::Ldlt< T > ldl
Definition workspace.hpp:29
void unscale_primal_in_place(VectorViewMut< T > primal) const
Definition ruiz.hpp:554
void scale_box_dual_in_place_in(VectorViewMut< T > dual) const
Definition ruiz.hpp:580
void unscale_dual_in_place_in(VectorViewMut< T > dual) const
Definition ruiz.hpp:598
void unscale_primal_residual_in_place_in(VectorViewMut< T > primal_in) const
Definition ruiz.hpp:675
void scale_primal_in_place(VectorViewMut< T > primal) const
Definition ruiz.hpp:518
void unscale_dual_in_place_eq(VectorViewMut< T > dual) const
Definition ruiz.hpp:589
void unscale_primal_residual_in_place_eq(VectorViewMut< T > primal_eq) const
Definition ruiz.hpp:667
void scale_dual_in_place_in(VectorViewMut< T > dual) const
Definition ruiz.hpp:545
void scale_primal_residual_in_place_in(VectorViewMut< T > primal_in) const
Definition ruiz.hpp:626
void scale_dual_in_place_eq(VectorViewMut< T > dual) const
Definition ruiz.hpp:536
void scale_box_primal_residual_in_place_in(VectorViewMut< T > primal_in) const
Definition ruiz.hpp:634
void unscale_box_dual_in_place_in(VectorViewMut< T > dual) const
Definition ruiz.hpp:571
void unscale_box_primal_residual_in_place_in(VectorViewMut< T > primal_in) const
Definition ruiz.hpp:683