proxsuite 0.6.7
The Advanced Proximal Optimization Toolbox
Loading...
Searching...
No Matches
compute_ECJ.hpp
Go to the documentation of this file.
1//
2// Copyright (c) 2023 INRIA
3//
8#ifndef PROXSUITE_PROXQP_DENSE_COMPUTE_ECJ_HPP
9#define PROXSUITE_PROXQP_DENSE_COMPUTE_ECJ_HPP
11
12namespace proxsuite {
13namespace proxqp {
14namespace dense {
15
29template<typename T>
30void
32 VecRef<T> loss_derivative,
33 T eps = 1.E-4,
34 T rho_new = 1.E-6,
35 T mu_new = 1.E-6)
36{
37 bool check =
38 solved_qp.results.info.status == QPSolverOutput::PROXQP_DUAL_INFEASIBLE;
39 if (check) {
41 true,
42 std::invalid_argument,
43 "the QP problem is not feasible, so computing the derivatives "
44 "is not valid in this setting. Try enabling infeasible solving if "
45 "the problem is only primally infeasible.");
46 } else {
47 solved_qp.model.backward_data.initialize(
48 solved_qp.model.dim, solved_qp.model.n_eq, solved_qp.model.n_in);
49
51 solved_qp.work.CTz.noalias() =
52 solved_qp.model.C * solved_qp.results.x + solved_qp.results.z;
53 solved_qp.work.active_set_up.array() =
54 (solved_qp.work.CTz - solved_qp.model.u).array() >= 0.;
55 solved_qp.work.active_set_low.array() =
56 (solved_qp.work.CTz - solved_qp.model.l).array() <= 0.;
57 solved_qp.work.active_inequalities =
58 solved_qp.work.active_set_up || solved_qp.work.active_set_low;
59 isize numactive_inequalities = solved_qp.work.active_inequalities.count();
60 isize inner_pb_dim =
61 solved_qp.model.dim + solved_qp.model.n_eq + numactive_inequalities;
62 solved_qp.work.rhs.setZero();
63 // work.dw_aug.setZero(); zeroed in active_set_change
64 solved_qp.results.info.rho = rho_new;
65 solved_qp.results.info.mu_eq = mu_new;
66 solved_qp.results.info.mu_in = mu_new;
67
68 // a large amount of constraints might have changed
69 // so in order to avoid to much refactorization later in the
70 // iterative refinement, a factorization from scratch is directly
71 // performed with new mu and rho as well to enable more stability
73 solved_qp.work,
74 solved_qp.model,
75 solved_qp.results,
76 solved_qp.which_dense_backend(),
77 solved_qp.which_hessian_type());
78 solved_qp.work.n_c = 0;
79 for (isize i = 0; i < solved_qp.model.n_in; i++) {
80 solved_qp.work.current_bijection_map(i) = i;
81 solved_qp.work.new_bijection_map(i) = i;
82 }
84 solved_qp.results,
85 solved_qp.which_dense_backend(),
86 solved_qp.model.n_in,
87 solved_qp.work);
88 solved_qp.work.constraints_changed = false; // no refactorization afterwards
89
90 solved_qp.work.rhs = -loss_derivative; // take full derivatives
91 solved_qp.ruiz.scale_dual_residual_in_place(VectorViewMut<T>{
92 from_eigen, solved_qp.work.rhs.head(solved_qp.model.dim) });
93 if (!solved_qp.work.rhs.segment(solved_qp.model.dim, solved_qp.model.n_eq)
94 .isZero()) {
95 solved_qp.work.rhs.segment(solved_qp.model.dim, solved_qp.model.n_eq) =
96 -loss_derivative.segment(solved_qp.model.dim, solved_qp.model.n_eq);
97 solved_qp.ruiz.scale_primal_residual_in_place_eq(
98 VectorViewMut<T>{ from_eigen,
99 solved_qp.work.rhs.segment(solved_qp.model.dim,
100 solved_qp.model.n_eq) });
101 }
102 if (!solved_qp.work.rhs.tail(solved_qp.model.n_in).isZero()) {
103 for (isize i = 0; i < solved_qp.model.n_in; i++) {
104 isize j = solved_qp.work.current_bijection_map(i);
105 if (j < solved_qp.work.n_c) {
106 solved_qp.work.rhs(j + solved_qp.model.dim + solved_qp.model.n_eq) =
107 -loss_derivative(i + solved_qp.model.dim + solved_qp.model.n_eq);
108 }
109 solved_qp.ruiz.scale_primal_residual_in_place_in(VectorViewMut<T>{
110 from_eigen, solved_qp.work.rhs.tail(solved_qp.model.n_in) });
111 }
112 }
114 solved_qp.settings,
115 solved_qp.model,
116 solved_qp.results,
117 solved_qp.work,
118 solved_qp.model.n_in,
119 solved_qp.which_dense_backend(),
120 solved_qp.which_hessian_type(),
121 eps,
122 inner_pb_dim); // /!\ the full rhs is zeroed inside
123 compute_backward_loss_ESG(solved_qp, loss_derivative);
124 }
125}
126
127template<typename T>
128void
130{
131 // use active_part_z as a temporary variable to derive unpermutted dz step
132 solved_qp.work.active_part_z.setZero();
133 for (isize j = 0; j < solved_qp.model.n_in; ++j) {
134 isize i = solved_qp.work.current_bijection_map(j);
135 if (i < solved_qp.work.n_c) {
136 solved_qp.work.active_part_z(j) =
137 solved_qp.work.dw_aug(solved_qp.model.dim + solved_qp.model.n_eq + i);
138 } else {
139 solved_qp.work.active_part_z(j) =
140 loss_derivative(solved_qp.model.dim + solved_qp.model.n_eq + i);
141 }
142 }
143 solved_qp.work.dw_aug.tail(solved_qp.model.n_in) =
144 solved_qp.work.active_part_z;
145 solved_qp.ruiz.unscale_primal_in_place(VectorViewMut<T>{
146 from_eigen, solved_qp.work.dw_aug.head(solved_qp.model.dim) });
147 solved_qp.ruiz.unscale_dual_in_place_eq(VectorViewMut<T>{
148 from_eigen,
149 solved_qp.work.dw_aug.segment(solved_qp.model.dim, solved_qp.model.n_eq) });
150 solved_qp.ruiz.unscale_dual_in_place_in(VectorViewMut<T>{
151 from_eigen, solved_qp.work.dw_aug.tail(solved_qp.model.n_in) });
152
154 solved_qp.model.backward_data.dL_dC.noalias() =
155 solved_qp.work.dw_aug.tail(solved_qp.model.n_in) *
156 solved_qp.results.x.transpose();
157 solved_qp.model.backward_data.dL_dC.noalias() +=
158 solved_qp.results.z *
159 solved_qp.work.dw_aug.head(solved_qp.model.dim).transpose();
160
161 solved_qp.model.backward_data.dL_du =
162 (solved_qp.work.active_set_up)
163 .select(-solved_qp.work.dw_aug.tail(solved_qp.model.n_in),
164 Eigen::Matrix<T, Eigen::Dynamic, 1>::Zero(solved_qp.model.n_in));
165
166 solved_qp.model.backward_data.dL_dl =
167 (solved_qp.work.active_set_low)
168 .select(-solved_qp.work.dw_aug.tail(solved_qp.model.n_in),
169 Eigen::Matrix<T, Eigen::Dynamic, 1>::Zero(solved_qp.model.n_in));
170
171 solved_qp.model.backward_data.dL_dA.noalias() =
172 solved_qp.work.dw_aug.segment(solved_qp.model.dim, solved_qp.model.n_eq) *
173 solved_qp.results.x.transpose();
174 solved_qp.model.backward_data.dL_dA.noalias() +=
175 solved_qp.results.y *
176 solved_qp.work.dw_aug.head(solved_qp.model.dim).transpose();
177
178 solved_qp.model.backward_data.dL_db =
179 -solved_qp.work.dw_aug.segment(solved_qp.model.dim, solved_qp.model.n_eq);
180 solved_qp.model.backward_data.dL_dH.noalias() =
181 0.5 * (solved_qp.work.dw_aug.head(solved_qp.model.dim) *
182 solved_qp.results.x.transpose() +
183 solved_qp.results.x *
184 solved_qp.work.dw_aug.head(solved_qp.model.dim).transpose());
185
186 solved_qp.model.backward_data.dL_dg =
187 solved_qp.work.dw_aug.head(solved_qp.model.dim);
188}
189
190} // namespace dense
191} // namespace proxqp
192} // namespace proxsuite
193
194#endif /* end of include guard PROXSUITE_PROXQP_DENSE_COMPUTE_ECJ_HPP */
#define PROXSUITE_THROW_PRETTY(condition, exception, message)
Definition macros.hpp:18
void active_set_change(const Model< T > &qpmodel, Results< T > &qpresults, const DenseBackend &dense_backend, const isize n_constraints, Workspace< T > &qpwork)
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 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 compute_backward_loss_ESG(dense::QP< T > &solved_qp, VecRef< T > loss_derivative)
void compute_backward(dense::QP< T > &solved_qp, VecRef< T > loss_derivative, T eps=1.E-4, T rho_new=1.E-6, T mu_new=1.E-6)
Eigen::Ref< Vec< T > const > VecRef
Definition fwd.hpp:26
HessianType which_hessian_type() const
Definition wrapper.hpp:336
DenseBackend which_dense_backend() const
Definition wrapper.hpp:335
preconditioner::RuizEquilibration< T > ruiz
Definition wrapper.hpp:129