Skip to content

Commit 0920147

Browse files
authored
Merge pull request #100 from fennel-labs/fix_update_dense
Fixed temporaries in update() of dense wrapper
2 parents cf70fd6 + cb9d224 commit 0920147

File tree

6 files changed

+114
-242
lines changed

6 files changed

+114
-242
lines changed

bindings/python/src/expose-qpobject.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,12 @@ exposeQpObjectDense(pybind11::module_ m)
8181
.def(
8282
"update",
8383
static_cast<void (dense::QP<T>::*)(optional<dense::MatRef<T>>,
84-
optional<dense::Vec<T>>,
84+
optional<dense::VecRef<T>>,
8585
optional<dense::MatRef<T>>,
86-
optional<dense::Vec<T>>,
86+
optional<dense::VecRef<T>>,
8787
optional<dense::MatRef<T>>,
88-
optional<dense::Vec<T>>,
89-
optional<dense::Vec<T>>,
88+
optional<dense::VecRef<T>>,
89+
optional<dense::VecRef<T>>,
9090
bool update_preconditioner,
9191
optional<T>,
9292
optional<T>,

examples/cpp/solve_without_api.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
#include <iostream>
22
#include "proxsuite/proxqp/sparse/sparse.hpp" // get the sparse backend of ProxQP
33
#include "proxsuite/proxqp/dense/dense.hpp" // get the dense backend of ProxQP
4-
#include <proxsuite/proxqp/utils/random_qp_problems.hpp> // used for generating a random convex qp
4+
#include "proxsuite/proxqp/utils/random_qp_problems.hpp" // used for generating a random convex qp
55

66
using namespace proxsuite::proxqp;
77
using T = double;
8+
using Mat = dense::Mat<T>;
9+
using Vec = dense::Vec<T>;
810

911
int
1012
main()
@@ -15,13 +17,17 @@ main()
1517
T p = 0.15; // level of sparsity
1618
T conditioning = 10.0; // conditioning level for H
1719
auto H = utils::rand::sparse_positive_definite_rand(n, conditioning, p);
18-
auto g = utils::rand::vector_rand<T>(n);
20+
Mat H_dense = Mat(H);
21+
Vec g = utils::rand::vector_rand<T>(n);
1922
auto A = utils::rand::sparse_matrix_rand<T>(n_eq, n, p);
23+
Mat A_dense = Mat(A);
2024
auto C = utils::rand::sparse_matrix_rand<T>(n_in, n, p);
21-
auto x_sol = utils::rand::vector_rand<T>(n);
22-
auto b = (A * x_sol).eval();
23-
auto l = (C * x_sol).eval();
24-
auto u = (l.array() + 10).matrix().eval();
25+
Mat C_dense = Mat(C);
26+
Vec x_sol = utils::rand::vector_rand<T>(n);
27+
Vec b = A * x_sol;
28+
Vec l = C * x_sol;
29+
Vec u = (l.array() + 10).matrix();
30+
2531
// Solve the problem using the sparse backend
2632
Results<T> results_sparse_solver =
2733
sparse::solve<T, isize>(H, g, A, b, C, l, u);
@@ -32,8 +38,9 @@ main()
3238
std::cout << "optimal z from sparse solver: " << results_sparse_solver.z
3339
<< std::endl;
3440
// Solve the problem using the dense backend
35-
Results<T> results_dense_solver = dense::solve<T>(
36-
dense::Mat<T>(H), g, dense::Mat<T>(A), b, dense::Mat<T>(C), u, l);
41+
Results<T> results_dense_solver =
42+
dense::solve<T>(H_dense, g, A_dense, b, C_dense, l, u);
43+
3744
// print an optimal solution x,y and z
3845
std::cout << "optimal x from dense solver: " << results_dense_solver.x
3946
<< std::endl;

include/proxsuite/helpers/optional.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#ifndef PROXSUITE_HELPERS_OPTIONAL_HPP
99
#define PROXSUITE_HELPERS_OPTIONAL_HPP
1010

11+
#include <proxsuite/fwd.hpp>
12+
1113
#ifdef PROXSUITE_WITH_CPP_17
1214
#include <optional>
1315
#else

include/proxsuite/proxqp/dense/fwd.hpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,16 @@ enum
1919
};
2020
template<typename T>
2121
using SparseMat = Eigen::SparseMatrix<T, 1>;
22-
template<typename T>
23-
using VecRef = Eigen::Ref<Eigen::Matrix<T, DYN, 1> const>;
24-
template<typename T>
25-
using MatRef = Eigen::Ref<Eigen::Matrix<T, DYN, DYN> const>;
26-
template<typename T>
27-
using Mat = Eigen::Matrix<T, DYN, DYN, layout>;
22+
2823
template<typename T>
2924
using Vec = Eigen::Matrix<T, DYN, 1>;
25+
template<typename T>
26+
using VecRef = Eigen::Ref<Vec<T> const>;
27+
28+
template<typename T, int l = layout>
29+
using Mat = Eigen::Matrix<T, DYN, DYN, l>;
30+
template<typename T, int l = layout>
31+
using MatRef = Eigen::Ref<Mat<T, l> const>;
3032

3133
using proxsuite::linalg::veg::isize;
3234

@@ -35,10 +37,10 @@ using VecMap = Eigen::Map<Vec<T> const>;
3537
template<typename T>
3638
using VecMapMut = Eigen::Map<Vec<T>>;
3739

38-
template<typename T>
39-
using MatMap = Eigen::Map<Mat<T> const>;
40-
template<typename T>
41-
using MatMapMut = Eigen::Map<Mat<T>>;
40+
template<typename T, int l = layout>
41+
using MatMap = Eigen::Map<Mat<T, l> const>;
42+
template<typename T, int l = layout>
43+
using MatMapMut = Eigen::Map<Mat<T, l>>;
4244

4345
using VecMapISize = Eigen::Map<Eigen::Matrix<isize, DYN, 1> const>;
4446
using VecISize = Eigen::Matrix<isize, DYN, 1>;

include/proxsuite/proxqp/dense/helpers.hpp

Lines changed: 52 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -161,146 +161,108 @@ initial_guess(Workspace<T>& qpwork,
161161
* @param A equality constraint matrix input defining the QP model.
162162
* @param b equality constraint vector input defining the QP model.
163163
* @param C inequality constraint matrix input defining the QP model.
164-
* @param u upper inequality constraint vector input defining the QP model.
165164
* @param l lower inequality constraint vector input defining the QP model.
165+
* @param u upper inequality constraint vector input defining the QP model.
166166
* @param qpwork solver workspace.
167167
* @param qpsettings solver settings.
168168
* @param qpmodel solver model.
169169
* @param qpresults solver result.
170170
*/
171171

172-
template<typename Mat, typename T>
172+
template<typename T>
173173
void
174-
update(optional<Mat> H_,
175-
optional<Vec<T>> g_,
176-
optional<Mat> A_,
177-
optional<Vec<T>> b_,
178-
optional<Mat> C_,
179-
optional<Vec<T>> u_,
180-
optional<Vec<T>> l_,
174+
update(optional<MatRef<T>> H,
175+
optional<VecRef<T>> g,
176+
optional<MatRef<T>> A,
177+
optional<VecRef<T>> b,
178+
optional<MatRef<T>> C,
179+
optional<VecRef<T>> l,
180+
optional<VecRef<T>> u,
181181
Model<T>& model,
182182
Workspace<T>& work)
183183
{
184184
// check the model is valid
185-
if (g_ != nullopt) {
186-
PROXSUITE_CHECK_ARGUMENT_SIZE(g_.value().rows(),
185+
if (g != nullopt) {
186+
PROXSUITE_CHECK_ARGUMENT_SIZE(g.value().rows(),
187187
model.dim,
188188
"the dimension wrt the primal variable x "
189189
"variable for updating g is not valid.");
190190
}
191-
if (b_ != nullopt) {
192-
PROXSUITE_CHECK_ARGUMENT_SIZE(b_.value().rows(),
191+
if (b != nullopt) {
192+
PROXSUITE_CHECK_ARGUMENT_SIZE(b.value().rows(),
193193
model.n_eq,
194194
"the dimension wrt equality constrained "
195195
"variables for updating b is not valid.");
196196
}
197-
if (u_ != nullopt) {
198-
PROXSUITE_CHECK_ARGUMENT_SIZE(u_.value().rows(),
197+
if (u != nullopt) {
198+
PROXSUITE_CHECK_ARGUMENT_SIZE(u.value().rows(),
199199
model.n_in,
200200
"the dimension wrt inequality constrained "
201201
"variables for updating u is not valid.");
202202
}
203-
if (l_ != nullopt) {
204-
PROXSUITE_CHECK_ARGUMENT_SIZE(l_.value().rows(),
203+
if (l != nullopt) {
204+
PROXSUITE_CHECK_ARGUMENT_SIZE(l.value().rows(),
205205
model.n_in,
206206
"the dimension wrt inequality constrained "
207207
"variables for updating l is not valid.");
208208
}
209-
if (H_ != nullopt) {
209+
if (H != nullopt) {
210210
PROXSUITE_CHECK_ARGUMENT_SIZE(
211-
H_.value().rows(),
211+
H.value().rows(),
212212
model.dim,
213213
"the row dimension for updating H is not valid.");
214214
PROXSUITE_CHECK_ARGUMENT_SIZE(
215-
H_.value().cols(),
215+
H.value().cols(),
216216
model.dim,
217217
"the column dimension for updating H is not valid.");
218218
}
219-
if (A_ != nullopt) {
219+
if (A != nullopt) {
220220
PROXSUITE_CHECK_ARGUMENT_SIZE(
221-
A_.value().rows(),
221+
A.value().rows(),
222222
model.n_eq,
223223
"the row dimension for updating A is not valid.");
224224
PROXSUITE_CHECK_ARGUMENT_SIZE(
225-
A_.value().cols(),
225+
A.value().cols(),
226226
model.dim,
227227
"the column dimension for updating A is not valid.");
228228
}
229-
if (C_ != nullopt) {
229+
if (C != nullopt) {
230230
PROXSUITE_CHECK_ARGUMENT_SIZE(
231-
C_.value().rows(),
231+
C.value().rows(),
232232
model.n_in,
233233
"the row dimension for updating C is not valid.");
234234
PROXSUITE_CHECK_ARGUMENT_SIZE(
235-
C_.value().cols(),
235+
C.value().cols(),
236236
model.dim,
237237
"the column dimension for updating C is not valid.");
238238
}
239+
239240
// update the model
240-
if (g_ != nullopt) {
241-
model.g = g_.value().eval();
241+
if (g != nullopt) {
242+
model.g = g.value().eval();
242243
}
243-
if (b_ != nullopt) {
244-
model.b = b_.value().eval();
244+
if (b != nullopt) {
245+
model.b = b.value().eval();
245246
}
246-
if (u_ != nullopt) {
247-
model.u = u_.value().eval();
247+
if (u != nullopt) {
248+
model.u = u.value().eval();
248249
}
249-
if (l_ != nullopt) {
250-
model.l = l_.value().eval();
250+
if (l != nullopt) {
251+
model.l = l.value().eval();
251252
}
252-
if (H_ != nullopt) {
253-
work.refactorize = true;
254-
if (A_ != nullopt) {
255-
if (C_ != nullopt) {
256-
model.H = Eigen::
257-
Matrix<T, Eigen::Dynamic, Eigen::Dynamic, to_eigen_layout(rowmajor)>(
258-
H_.value());
259-
model.A = Eigen::
260-
Matrix<T, Eigen::Dynamic, Eigen::Dynamic, to_eigen_layout(rowmajor)>(
261-
A_.value());
262-
model.C = Eigen::
263-
Matrix<T, Eigen::Dynamic, Eigen::Dynamic, to_eigen_layout(rowmajor)>(
264-
C_.value());
265-
} else {
266-
model.H = Eigen::
267-
Matrix<T, Eigen::Dynamic, Eigen::Dynamic, to_eigen_layout(rowmajor)>(
268-
H_.value());
269-
model.A = Eigen::
270-
Matrix<T, Eigen::Dynamic, Eigen::Dynamic, to_eigen_layout(rowmajor)>(
271-
A_.value());
272-
}
273-
} else if (C_ != nullopt) {
274-
model.H = Eigen::
275-
Matrix<T, Eigen::Dynamic, Eigen::Dynamic, to_eigen_layout(rowmajor)>(
276-
H_.value());
277-
model.C = Eigen::
278-
Matrix<T, Eigen::Dynamic, Eigen::Dynamic, to_eigen_layout(rowmajor)>(
279-
C_.value());
280-
} else {
281-
model.H = Eigen::
282-
Matrix<T, Eigen::Dynamic, Eigen::Dynamic, to_eigen_layout(rowmajor)>(
283-
H_.value());
284-
}
285-
} else if (A_ != nullopt) {
286-
work.refactorize = true;
287-
if (C_ != nullopt) {
288-
model.A = Eigen::
289-
Matrix<T, Eigen::Dynamic, Eigen::Dynamic, to_eigen_layout(rowmajor)>(
290-
A_.value());
291-
model.C = Eigen::
292-
Matrix<T, Eigen::Dynamic, Eigen::Dynamic, to_eigen_layout(rowmajor)>(
293-
C_.value());
294-
} else {
295-
model.A = Eigen::
296-
Matrix<T, Eigen::Dynamic, Eigen::Dynamic, to_eigen_layout(rowmajor)>(
297-
A_.value());
298-
}
299-
} else if (C_ != nullopt) {
253+
254+
if (H != nullopt || A != nullopt || C != nullopt) {
300255
work.refactorize = true;
301-
model.C = Eigen::
302-
Matrix<T, Eigen::Dynamic, Eigen::Dynamic, to_eigen_layout(rowmajor)>(
303-
C_.value());
256+
}
257+
258+
if (H != nullopt) {
259+
model.H = H.value();
260+
}
261+
if (A != nullopt) {
262+
model.A = A.value();
263+
}
264+
if (C != nullopt) {
265+
model.C = C.value();
304266
}
305267
}
306268
/*!
@@ -311,8 +273,8 @@ update(optional<Mat> H_,
311273
* @param A equality constraint matrix input defining the QP model.
312274
* @param b equality constraint vector input defining the QP model.
313275
* @param C inequality constraint matrix input defining the QP model.
314-
* @param u upper inequality constraint vector input defining the QP model.
315276
* @param l lower inequality constraint vector input defining the QP model.
277+
* @param u upper inequality constraint vector input defining the QP model.
316278
* @param qpwork solver workspace.
317279
* @param qpsettings solver settings.
318280
* @param qpmodel solver model.
@@ -322,14 +284,14 @@ update(optional<Mat> H_,
322284
* preconditioning algorithm, or keeping previous preconditioning variables, or
323285
* using the identity preconditioner (i.e., no preconditioner).
324286
*/
325-
template<typename Mat, typename T>
287+
template<typename T>
326288
void
327289
setup( //
328-
optional<Mat> H,
290+
optional<MatRef<T>> H,
329291
optional<VecRef<T>> g,
330-
optional<Mat> A,
292+
optional<MatRef<T>> A,
331293
optional<VecRef<T>> b,
332-
optional<Mat> C,
294+
optional<MatRef<T>> C,
333295
optional<VecRef<T>> l,
334296
optional<VecRef<T>> u,
335297
Settings<T>& qpsettings,

0 commit comments

Comments
 (0)