Skip to content

Commit d3e4e40

Browse files
authored
Merge pull request #139 from fabinsch/topic/fix-cpp-example-update
add is_valid function for dense model and fix example + unittest
2 parents 7151e04 + b3a010f commit d3e4e40

File tree

12 files changed

+55
-87
lines changed

12 files changed

+55
-87
lines changed

bindings/python/src/expose-model.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ exposeDenseModel(pybind11::module_ m)
3131
.def_readonly("dim", &Model<T>::dim)
3232
.def_readonly("n_eq", &Model<T>::n_eq)
3333
.def_readonly("n_in", &Model<T>::n_in)
34-
.def_readonly("n_total", &Model<T>::n_total);
34+
.def_readonly("n_total", &Model<T>::n_total)
35+
.def("is_valid",
36+
&Model<T>::is_valid,
37+
"Check if model is containing valid data.");
3538
}
3639
} // namespace python
3740
} // namespace dense

doc/2-PROXQP_API/2-ProxQP_api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ In this table you have on the three columns from left to right: the name of the
305305
| default_rho | 1.E-6 | Default rho parameter of result class (i.e., for each initial guess, except WARM_START_WITH_PREVIOUS_RESULT, after a new solve or update, the solver initializes rho to this value).
306306
| default_mu_eq | 1.E-3 | Default mu_eq parameter of result class (i.e., for each initial guess, except WARM_START_WITH_PREVIOUS_RESULT, after a new solve or update, the solver initializes mu_eq to this value).
307307
| default_mu_in | 1.E-1 | Default mu_in parameter of result class (i.e., for each initial guess, except WARM_START_WITH_PREVIOUS_RESULT, after a new solve or update, the solver initializes mu_in to this value).
308-
| compute_timings | True | If set to true, timings will be computed by the solver (setup time, solving time, and run time = setup time + solving time).
308+
| compute_timings | False | If set to true, timings will be computed by the solver (setup time, solving time, and run time = setup time + solving time).
309309
| max_iter | 10.000 | Maximal number of authorized outer iterations.
310310
| max_iter_in | 1500 | Maximal number of authorized inner iterations.
311311
| initial_guess | EQUALITY_CONSTRAINED_INITIAL_GUESS | Sets the initial guess option for initilizing x, y and z.

doc/3-ProxQP_solve.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ Different options are available for the solve function. In the table below you h
100100
| rho | 1.E-6 | Proximal step size wrt primal variable.
101101
| VERBOSE | False | If set to true, the solver prints information at each loop.
102102
| compute_preconditioner | True | If set to true, the preconditioner will be derived.
103-
| compute_timings | True | If set to true, timings will be computed by the solver (setup time, solving time, and run time = setup time + solving time).
103+
| compute_timings | False | If set to true, timings will be computed by the solver (setup time, solving time, and run time = setup time + solving time).
104104
| max_iter | 10.000 | Maximal number of authorized outer iterations.
105105
| initial_guess | EQUALITY_CONSTRAINED_INITIAL_GUESS | Sets the initial guess option for initilizing x, y and z.
106106

examples/cpp/solve_without_api.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@ main()
1414
isize n = 10;
1515
isize n_eq(n / 4);
1616
isize n_in(n / 4);
17-
T p = 0.15; // level of sparsity
17+
T p = 0.35; // level of sparsity
1818
T conditioning = 10.0; // conditioning level for H
19-
auto H = utils::rand::sparse_positive_definite_rand(n, conditioning, p);
19+
auto H = utils::rand::sparse_positive_definite_rand(
20+
n, conditioning, p); // upper triangular matrix
2021
Mat H_dense = Mat(H);
22+
H_dense.template triangularView<Eigen::Lower>() = H_dense.transpose();
2123
Vec g = utils::rand::vector_rand<T>(n);
2224
auto A = utils::rand::sparse_matrix_rand<T>(n_eq, n, p);
2325
Mat A_dense = Mat(A);

examples/cpp/update_dense_qp.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ main()
2929
dense::Model<T> qp2 = utils::dense_strongly_convex_qp(
3030
dim, n_eq, n_in, sparsity_factor, strong_convexity_factor);
3131
// re update the model
32-
qp.update(qp2.H, qp2.g, qp2.A, qp2.b, qp2.C, qp2.u, qp2.l);
32+
qp.update(qp2.H, qp2.g, qp2.A, qp2.b, qp2.C, qp2.l, qp2.u);
3333
// solve it
3434
qp.solve();
3535
// print an optimal solution x,y and z

include/proxsuite/proxqp/dense/helpers.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ update(optional<MatRef<T>> H,
264264
if (C != nullopt) {
265265
model.C = C.value();
266266
}
267+
assert(model.is_valid());
267268
}
268269
/*!
269270
* Setups the QP solver model.
@@ -383,6 +384,7 @@ setup( //
383384
qpmodel.l = l.value();
384385
} // else qpmodel.l remains initialized to a matrix with zero elements or zero
385386
// shape
387+
assert(qpmodel.is_valid());
386388

387389
qpwork.H_scaled = qpmodel.H;
388390
qpwork.g_scaled = qpmodel.g;

include/proxsuite/proxqp/dense/model.hpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,40 @@ struct Model
8484
C_sparse, u, l };
8585
return res;
8686
}
87+
88+
bool is_valid()
89+
{
90+
#define PROXSUITE_CHECK_SIZE(size, expected_size) \
91+
if (size != 0) { \
92+
if (!(size == expected_size)) \
93+
return false; \
94+
}
95+
96+
// check that all matrices and vectors of qpmodel have the correct size
97+
// and that H and C have expected properties
98+
PROXSUITE_CHECK_SIZE(g.size(), dim);
99+
PROXSUITE_CHECK_SIZE(b.size(), n_eq);
100+
PROXSUITE_CHECK_SIZE(u.size(), n_in);
101+
PROXSUITE_CHECK_SIZE(l.size(), n_in);
102+
if (H.size()) {
103+
PROXSUITE_CHECK_SIZE(H.rows(), dim);
104+
PROXSUITE_CHECK_SIZE(H.cols(), dim);
105+
if (!H.isApprox(H.transpose(), 0.0))
106+
return false;
107+
}
108+
if (A.size()) {
109+
PROXSUITE_CHECK_SIZE(A.rows(), n_eq);
110+
PROXSUITE_CHECK_SIZE(A.cols(), dim);
111+
}
112+
if (C.size()) {
113+
PROXSUITE_CHECK_SIZE(C.rows(), n_in);
114+
PROXSUITE_CHECK_SIZE(C.cols(), dim);
115+
if (C.isZero())
116+
return false;
117+
}
118+
return true;
119+
#undef PROXSUITE_CHECK_SIZE
120+
}
87121
};
88122
} // namespace dense
89123
} // namespace proxqp

include/proxsuite/proxqp/dense/wrapper.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ solve(
412412
optional<T> mu_in = nullopt,
413413
optional<bool> verbose = nullopt,
414414
bool compute_preconditioner = true,
415-
bool compute_timings = true,
415+
bool compute_timings = false,
416416
optional<isize> max_iter = nullopt,
417417
proxsuite::proxqp::InitialGuessStatus initial_guess =
418418
proxsuite::proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS)
@@ -443,7 +443,7 @@ solve(
443443
Qp.settings.verbose = verbose.value();
444444
}
445445
if (max_iter != nullopt) {
446-
Qp.settings.max_iter = verbose.value();
446+
Qp.settings.max_iter = max_iter.value();
447447
}
448448
Qp.settings.compute_timings = compute_timings;
449449
Qp.init(H, g, A, b, C, l, u, compute_preconditioner, rho, mu_eq, mu_in);

include/proxsuite/proxqp/settings.hpp

Lines changed: 1 addition & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ struct Settings
182182
// once a problem
183183
bool update_preconditioner = true,
184184
bool compute_preconditioner = true,
185-
bool compute_timings = true,
185+
bool compute_timings = false,
186186
isize preconditioner_max_iter = 10,
187187
T preconditioner_accuracy = 1.e-3,
188188
T eps_primal_inf = 1.E-4,
@@ -226,78 +226,6 @@ struct Settings
226226
, sparse_backend(sparse_backend)
227227
{
228228
}
229-
/*
230-
void set(
231-
T alpha_bcl_ = 0.1,
232-
T beta_bcl_ = 0.9,
233-
T refactor_dual_feasibility_threshold_ = 1e-2,
234-
T refactor_rho_threshold_ = 1e-7,
235-
T mu_min_eq_ = 1e-9,
236-
T mu_min_in_ = 1e-8,
237-
T mu_max_eq_inv_ = 1e9,
238-
T mu_max_in_inv_ = 1e8,
239-
T mu_update_factor_ = 0.1,
240-
T mu_update_inv_factor_ = 10,
241-
T cold_reset_mu_eq_ = 1. / 1.1,
242-
T cold_reset_mu_in_ = 1. / 1.1,
243-
T cold_reset_mu_eq_inv_ = 1.1,
244-
T cold_reset_mu_in_inv_ = 1.1,
245-
T eps_abs_ = 1.e-8,
246-
T eps_rel_ = 0,
247-
isize max_iter_ = 10000,
248-
isize max_iter_in_ = 1500,
249-
isize safe_guard_ = 1.E4,
250-
isize nb_iterative_refinement_ = 10,
251-
T eps_refact_ = 1.e-6, // before eps_refact_=1.e-6
252-
bool VERBOSE = false,
253-
InitialGuessStatus initial_guess_ =
254-
InitialGuessStatus::WARM_START_WITH_PREVIOUS_RESULT,
255-
bool update_preconditioner_ = true,
256-
bool compute_preconditioner_ = true,
257-
bool compute_timings_ = true,
258-
isize preconditioner_max_iter_ = 10,
259-
T preconditioner_accuracy_ = 1.e-3,
260-
T eps_primal_inf_ = 1.E-4,
261-
T eps_dual_inf_ = 1.E-4,
262-
bool bcl_update_ = true,
263-
SparseBackend sparse_backend_ = SparseBackend::Automatic
264-
){
265-
alpha_bcl = alpha_bcl_;
266-
beta_bcl = beta_bcl_ ;
267-
refactor_dual_feasibility_threshold = refactor_dual_feasibility_threshold_;
268-
refactor_rho_threshold = refactor_rho_threshold_;
269-
mu_min_eq = mu_min_eq_;
270-
mu_min_in = mu_min_in_;
271-
mu_max_eq_inv = mu_max_eq_inv_;
272-
mu_max_in_inv = mu_max_in_inv_;
273-
mu_update_factor = mu_update_factor_;
274-
mu_update_inv_factor = mu_update_inv_factor_;
275-
cold_reset_mu_eq = cold_reset_mu_eq_;
276-
cold_reset_mu_in = cold_reset_mu_in_;
277-
cold_reset_mu_eq_inv = cold_reset_mu_eq_inv_;
278-
cold_reset_mu_in_inv = cold_reset_mu_in_inv_;
279-
eps_abs = eps_abs_;
280-
eps_rel = eps_rel_;
281-
max_iter = max_iter_;
282-
max_iter_in = max_iter_in_;
283-
safe_guard = safe_guard_;
284-
nb_iterative_refinement = nb_iterative_refinement_;
285-
eps_refact = eps_refact_;
286-
verbose = VERBOSE;
287-
initial_guess = initial_guess_;
288-
update_preconditioner = update_preconditioner_;
289-
compute_preconditioner = compute_preconditioner_;
290-
compute_timings = compute_timings_;
291-
preconditioner_max_iter = preconditioner_max_iter_;
292-
preconditioner_accuracy = preconditioner_accuracy_;
293-
eps_primal_inf = eps_primal_inf_;
294-
eps_dual_inf = eps_dual_inf_;
295-
bcl_update = bcl_update_;
296-
sparse_backend = sparse_backend_;
297-
298-
299-
}
300-
*/
301229
};
302230

303231
} // namespace proxqp

include/proxsuite/proxqp/sparse/wrapper.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,7 @@ solve(
705705
optional<T> mu_in = nullopt,
706706
optional<bool> verbose = nullopt,
707707
bool compute_preconditioner = true,
708-
bool compute_timings = true,
708+
bool compute_timings = false,
709709
optional<isize> max_iter = nullopt,
710710
proxsuite::proxqp::InitialGuessStatus initial_guess =
711711
proxsuite::proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS,
@@ -739,7 +739,7 @@ solve(
739739
Qp.settings.verbose = verbose.value();
740740
}
741741
if (max_iter != nullopt) {
742-
Qp.settings.max_iter = verbose.value();
742+
Qp.settings.max_iter = max_iter.value();
743743
}
744744
Qp.settings.compute_timings = compute_timings;
745745
Qp.settings.sparse_backend = sparse_backend;

0 commit comments

Comments
 (0)