proxsuite 0.7.2
The Advanced Proximal Optimization Toolbox
 
Loading...
Searching...
No Matches
random_qp_problems.hpp
Go to the documentation of this file.
1#ifndef PROXSUITE_PROXQP_UTILS_RANDOM_QP_PROBLEMS_HPP
2#define PROXSUITE_PROXQP_UTILS_RANDOM_QP_PROBLEMS_HPP
3
4#include <Eigen/Core>
5#include <Eigen/SparseCore>
6#include <Eigen/Cholesky>
7#include <Eigen/Eigenvalues>
8#include <Eigen/QR>
9#include <utility>
13#include <map>
14#include <random>
15
16namespace proxsuite {
17namespace proxqp {
18namespace utils {
19
20using c_int = long long;
21using c_float = double;
22
23namespace proxqp = proxsuite::proxqp;
24
25template<typename T, proxqp::Layout L>
26using Mat =
27 Eigen::Matrix<T,
28 Eigen::Dynamic,
29 Eigen::Dynamic,
30 (L == proxqp::colmajor) ? Eigen::ColMajor : Eigen::RowMajor>;
31template<typename T>
32using Vec = Eigen::Matrix<T, Eigen::Dynamic, 1>;
33
34template<typename Scalar>
35using SparseMat = Eigen::SparseMatrix<Scalar, Eigen::ColMajor, c_int>;
36
37using namespace proxqp;
65namespace rand {
66
67using proxqp::u32;
68using proxqp::u64;
69
70#ifdef _MSC_VER
71/* Using the MSCV compiler on Windows causes problems because the type uint128
72is not available. Therefore, we use a random number generator from the stdlib
73instead of our custom Lehmer random number generator. The necessary lehmer
74functions used in in our code are remplaced with calls to the stdlib.*/
75std::mt19937 gen(1234);
76std::uniform_real_distribution<> uniform_dist(0.0, 1.0);
77std::normal_distribution<double> normal_dist;
78using u128 = u64;
79inline auto
80uniform_rand() -> double
81{
82 double output = double(uniform_dist(gen));
83 return output;
84}
85inline auto
87{
88 static u64 output = gen();
89 return output;
90}
91
92inline void
93set_seed(u64 seed)
94{
95 gen.seed(seed);
96}
97
98inline auto
99normal_rand() -> double
100{
101 return normal_dist(gen);
102}
103#else
104using u128 = __uint128_t;
105
106constexpr u128 lehmer64_constant(0xda942042e4dd58b5);
107inline auto
109{
110 static u128 g_lehmer64_state = lehmer64_constant * lehmer64_constant;
111 return g_lehmer64_state;
112}
113
114inline auto
116{ // [0, 2^64)
118 return u64(lehmer_global() >> u128(64U));
119}
120
121inline void
123{
124 lehmer_global() = u128(seed) + 1;
125 lehmer64();
126 lehmer64();
127}
128
129inline auto
130uniform_rand() -> double
131{ // [0, 2^53]
132 u64 a = lehmer64() / (1U << 11U);
133 return double(a) / double(u64(1) << 53U);
134}
135inline auto
136normal_rand() -> double
137{
138 static const double pi2 = std::atan(static_cast<double>(1)) * 8;
139
140 double u1 = uniform_rand();
141 double u2 = uniform_rand();
142
143 double ln = std::log(u1);
144 double sqrt = std::sqrt(-2 * ln);
145
146 return sqrt * std::cos(pi2 * u2);
147}
148#endif
149
150template<typename Scalar>
151auto
153{
154 auto v = Vec<Scalar>(nrows);
155
156 for (isize i = 0; i < nrows; ++i) {
157 v(i) = Scalar(rand::normal_rand());
158 }
159
160 return v;
161}
162template<typename Scalar>
163auto
165{
166 auto v = Mat<Scalar, colmajor>(nrows, ncols);
167
168 for (isize i = 0; i < nrows; ++i) {
169 for (isize j = 0; j < ncols; ++j) {
170 v(i, j) = Scalar(rand::normal_rand());
171 }
172 }
173
174 return v;
175}
176
177namespace detail {
178template<typename Scalar>
179auto
181{
182 auto mat = rand::matrix_rand<Scalar>(n, n);
183 auto qr = mat.householderQr();
184 Mat<Scalar, colmajor> q = qr.householderQ();
185 return q;
186}
187using Input = std::pair<u128, isize>;
188} // namespace detail
189
190template<typename Scalar>
191auto
193{
194
195 static auto cache = std::map<detail::Input, Mat<Scalar, colmajor>>{};
196 auto input = detail::Input{ lehmer_global(), n };
197 auto it = cache.find(input);
198 if (it == cache.end()) {
199 auto res = cache.insert({
200 input,
202 });
203 it = res.first;
204 }
205 return (*it).second;
206}
207
208template<typename Scalar>
209auto
211{
212 auto const& q = rand::orthonormal_rand<Scalar>(n);
213 auto d = Vec<Scalar>(n);
214
215 {
216 using std::exp;
217 using std::log;
218 Scalar diff = log(cond);
219 for (isize i = 0; i < n; ++i) {
220 d(i) = exp(Scalar(i) / Scalar(n) * diff);
221 }
222 }
223
224 return q * d.asDiagonal() * q.transpose();
225}
226
227template<typename Scalar>
228auto
229sparse_positive_definite_rand(isize n, Scalar cond, Scalar p)
231{
232 auto H = SparseMat<Scalar>(n, n);
233
234 for (isize i = 0; i < n; ++i) {
235 auto random = Scalar(rand::normal_rand());
236 H.insert(i, i) = random;
237 }
238
239 for (isize i = 0; i < n; ++i) {
240 for (isize j = i + 1; j < n; ++j) {
241 auto urandom = rand::uniform_rand();
242 if (urandom < p / 2) {
243 auto random = Scalar(rand::normal_rand());
244 H.insert(i, j) = random;
245 }
246 }
247 }
248
249 Mat<Scalar, colmajor> H_dense = H.toDense();
250 Vec<Scalar> eigh =
251 H_dense.template selfadjointView<Eigen::Upper>().eigenvalues();
252
253 Scalar min = eigh.minCoeff();
254 Scalar max = eigh.maxCoeff();
255
256 // new_min = min + rho
257 // new_max = max + rho
258 //
259 // (max + rho)/(min + rho) = cond
260 // 1 + (max - min) / (min + rho) = cond
261 // (max - min) / (min + rho) = cond - 1
262 // min + rho = (max - min) / (cond - 1)
263 // rho = (max - min)/(cond - 1) - min
264 Scalar rho = (max - min) / (cond - 1) - min;
265 if (max == min) {
266 rho += 1;
267 }
268
269 for (isize i = 0; i < n; ++i) {
270 H.coeffRef(i, i) += rho;
271 }
272
273 H.makeCompressed();
274 return H;
275}
276
277template<typename Scalar>
278auto
281{
282 auto H = SparseMat<Scalar>(n, n);
283
284 H.setZero();
285
286 for (isize i = 0; i < n; ++i) {
287 for (isize j = i + 1; j < n; ++j) {
288 auto urandom = rand::uniform_rand();
289 if (urandom < p) {
290 auto random = Scalar(rand::normal_rand());
291 H.insert(i, j) = random;
292 }
293 }
294 }
295 Mat<Scalar, colmajor> H_dense = H.toDense();
296 Vec<Scalar> eigh =
297 H_dense.template selfadjointView<Eigen::Upper>().eigenvalues();
298 Scalar min = eigh.minCoeff();
299 for (isize i = 0; i < n; ++i) {
300 H.coeffRef(i, i) += (rho + abs(min));
301 }
302
303 H.makeCompressed();
304 return H;
305}
306
307template<typename Scalar>
308auto
311{
312 auto H = Mat<Scalar, colmajor>(n, n);
313 H.setZero();
314
315 for (isize i = 0; i < n; ++i) {
316 for (isize j = 0; j < n; ++j) {
317 auto urandom = rand::uniform_rand();
318 if (urandom < p / 2) {
319 auto random = Scalar(rand::normal_rand());
320 H(i, j) = random;
321 }
322 }
323 }
324
325 H = ((H + H.transpose()) * 0.5)
326 .eval(); // safe no aliasing :
327 // https://eigen.tuxfamily.org/dox/group__TopicAliasing.html
328 // H.array() /= 2.;
329 Vec<Scalar> eigh = H.template selfadjointView<Eigen::Upper>().eigenvalues();
330 Scalar min = eigh.minCoeff();
331 H.diagonal().array() += (rho + abs(min));
332
333 return H;
334}
335
336template<typename Scalar>
337auto
339{
340 auto A = SparseMat<Scalar>(nrows, ncols);
341
342 for (isize i = 0; i < nrows; ++i) {
343 for (isize j = 0; j < ncols; ++j) {
344 if (rand::uniform_rand() < p) {
345 A.insert(i, j) = Scalar(rand::normal_rand());
346 }
347 }
348 }
349 A.makeCompressed();
350 return A;
351}
352
353template<typename Scalar>
354auto
357{
358 auto A = Mat<Scalar, colmajor>(nrows, ncols);
359 A.setZero();
360 for (isize i = 0; i < nrows; ++i) {
361 for (isize j = 0; j < ncols; ++j) {
362 if (rand::uniform_rand() < p) {
363 A(i, j) = Scalar(rand::normal_rand());
364 }
365 }
366 }
367 return A;
368}
369
370} // namespace rand
371using proxqp::usize;
372
373namespace osqp {
374auto
376auto
378} // namespace osqp
379
380template<typename T>
381auto
383 Mat<T, proxqp::colmajor> const& lhs,
385{
386 return lhs.operator*(rhs);
387}
388template<typename To, typename From>
389auto
391{
392 return from.template cast<To>();
393}
397
398template<typename MatLhs, typename MatRhs, typename T = typename MatLhs::Scalar>
399auto
400matmul(MatLhs const& a, MatRhs const& b) -> Mat<T, proxqp::colmajor>
401{
402 using Upscaled = typename std::
403 conditional<std::is_floating_point<T>::value, long double, T>::type;
404
406 Mat<T, proxqp::colmajor>(a).template cast<Upscaled>(),
407 Mat<T, proxqp::colmajor>(b).template cast<Upscaled>()));
408}
409
410template<typename MatLhs,
411 typename MatMid,
412 typename MatRhs,
413 typename T = typename MatLhs::Scalar>
414auto
415matmul3(MatLhs const& a, MatMid const& b, MatRhs const& c)
417{
418 return matmul(matmul(a, b), c);
419}
420
421VEG_TAG(from_data, FromData);
422
424{
426 EigenNoAlloc(EigenNoAlloc const&) = delete;
427 auto operator=(EigenNoAlloc&&) -> EigenNoAlloc& = delete;
428 auto operator=(EigenNoAlloc const&) -> EigenNoAlloc& = delete;
429
430#if defined(EIGEN_RUNTIME_NO_MALLOC)
431 EigenNoAlloc() noexcept { Eigen::internal::set_is_malloc_allowed(false); }
432 ~EigenNoAlloc() noexcept { Eigen::internal::set_is_malloc_allowed(true); }
433#else
434 EigenNoAlloc() = default;
435#endif
436};
437
438template<typename Scalar>
441 Scalar sparsity_factor,
442 Scalar strong_convexity_factor = Scalar(1e-2))
443{
444
447 dim, strong_convexity_factor, sparsity_factor);
457 model.H = H;
458 model.g = g;
459 return model;
460}
461
462template<typename Scalar>
465 proxqp::isize n_eq,
466 proxqp::isize n_in,
467 Scalar sparsity_factor,
468 Scalar strong_convexity_factor = Scalar(1e-2))
469{
470
473 dim, strong_convexity_factor, sparsity_factor);
476 rand::sparse_matrix_rand_not_compressed<Scalar>(n_eq, dim, sparsity_factor);
478 rand::sparse_matrix_rand_not_compressed<Scalar>(n_in, dim, sparsity_factor);
479
481 auto delta = Vec<Scalar>(n_in);
482
483 for (proxqp::isize i = 0; i < n_in; ++i) {
484 delta(i) = rand::uniform_rand();
485 }
486
487 Vec<Scalar> u = C * x_sol + delta;
488 Vec<Scalar> b = A * x_sol;
489 Vec<Scalar> l(n_in);
490 l.setZero();
491 l.array() -= 1.e20;
492
493 proxsuite::proxqp::dense::Model<Scalar> model(dim, n_eq, n_in);
494 model.H = H;
495 model.g = g;
496 model.A = A;
497 model.b = b;
498 model.C = C;
499 model.u = u;
500 model.l = l;
501 return model;
502}
503
504template<typename Scalar>
507 proxqp::isize n_eq,
508 proxqp::isize n_in,
509 Scalar sparsity_factor)
510{
511
514 dim, Scalar(0), sparsity_factor);
516 rand::sparse_matrix_rand_not_compressed<Scalar>(n_eq, dim, sparsity_factor);
518 rand::sparse_matrix_rand_not_compressed<Scalar>(n_in, dim, sparsity_factor);
519
523 auto delta = Vec<Scalar>(n_in);
524
525 for (proxqp::isize i = 0; i < n_in; ++i) {
526 delta(i) = rand::uniform_rand();
527 }
528 auto Cx = C * x_sol;
529 Vec<Scalar> u = Cx + delta;
530 Vec<Scalar> b = A * x_sol;
531 Vec<Scalar> l = Cx - delta;
532 Vec<Scalar> g = -(H * x_sol + C.transpose() * z_sol + A.transpose() * y_sol);
533
534 proxsuite::proxqp::dense::Model<Scalar> model(dim, n_eq, n_in);
535 model.H = H;
536 model.g = g;
537 model.A = A;
538 model.b = b;
539 model.C = C;
540 model.u = u;
541 model.l = l;
542 return model;
543}
544
545template<typename Scalar>
548 proxqp::isize n_eq,
549 proxqp::isize n_in,
550 Scalar sparsity_factor,
551 Scalar strong_convexity_factor = Scalar(1e-2))
552{
553
556 dim, strong_convexity_factor, sparsity_factor);
559 rand::sparse_matrix_rand_not_compressed<Scalar>(n_eq, dim, sparsity_factor);
561
563 auto delta = Vec<Scalar>(2 * n_in);
564
565 for (proxqp::isize i = 0; i < 2 * n_in; ++i) {
566 delta(i) = rand::uniform_rand();
567 }
568 Vec<Scalar> b = A * x_sol;
569
570 auto C_ =
571 rand::sparse_matrix_rand_not_compressed<Scalar>(n_in, dim, sparsity_factor);
572 C.setZero();
573 C.block(0, 0, n_in, dim) = C_;
574 C.block(n_in, 0, n_in, dim) = C_;
575 Vec<Scalar> u = C * x_sol + delta;
576 Vec<Scalar> l(2 * n_in);
577 l.setZero();
578 l.array() -= 1.e20;
579
580 proxsuite::proxqp::dense::Model<Scalar> model(dim, n_eq, n_in);
581 model.H = H;
582 model.g = g;
583 model.A = A;
584 model.b = b;
585 model.C = C;
586 model.u = u;
587 model.l = l;
588 return model;
589}
590
591template<typename Scalar>
594 proxqp::isize n_eq,
595 proxqp::isize n_in,
596 Scalar sparsity_factor,
597 Scalar strong_convexity_factor = Scalar(1e-2))
598{
599
602 dim, strong_convexity_factor, sparsity_factor);
605 rand::sparse_matrix_rand_not_compressed<Scalar>(n_eq, dim, sparsity_factor);
607
609 auto delta = Vec<Scalar>(n_in);
610
611 for (proxqp::isize i = 0; i < n_in; ++i) {
612 delta(i) = rand::uniform_rand();
613 }
614 Vec<Scalar> b = A * x_sol;
615 C.setZero();
616 C.diagonal().array() += 1;
617 Vec<Scalar> u = x_sol + delta;
618 Vec<Scalar> l = x_sol - delta;
619 proxsuite::proxqp::dense::Model<Scalar> model(dim, n_eq, n_in);
620 model.H = H;
621 model.g = g;
622 model.A = A;
623 model.b = b;
624 model.C = C;
625 model.u = u;
626 model.l = l;
627 return model;
628}
629
630template<typename Scalar>
633 proxqp::isize n_eq,
634 proxqp::isize n_in,
635 Scalar sparsity_factor,
636 Scalar strong_convexity_factor = Scalar(1e-2))
637{
638
640 dim, strong_convexity_factor, sparsity_factor);
643 rand::sparse_matrix_rand<Scalar>(n_eq, dim, sparsity_factor);
645 rand::sparse_matrix_rand<Scalar>(n_in, dim, sparsity_factor);
646
648 auto delta = Vec<Scalar>(n_in);
649
650 for (proxqp::isize i = 0; i < n_in; ++i) {
651 delta(i) = rand::uniform_rand();
652 }
653
654 Vec<Scalar> u = C * x_sol + delta;
655 Vec<Scalar> b = A * x_sol;
656 Vec<Scalar> l(n_in);
657 l.setZero();
658 l.array() -= 1.e20;
659
660 proxsuite::proxqp::sparse::SparseModel<Scalar> res{ H, g, A, b, C, u, l };
661 return res;
662}
663
664} // namespace utils
665} // namespace proxqp
666} // namespace proxsuite
667
668#endif /* end of include guard PROXSUITE_PROXQP_UTILS_RANDOM_QP_PROBLEMS_HPP \
669 */
#define LDLT_EXPLICIT_TPL_DECL(NParams,...)
Definition views.hpp:58
#define VEG_TAG(Name, Type)
Definition macros.hpp:550
decltype(sizeof(0)) usize
Definition macros.hpp:702
std::uint64_t u64
Definition typedefs.hpp:46
std::uint32_t u32
Definition typedefs.hpp:48
_detail::_meta::make_signed< usize >::Type isize
Definition typedefs.hpp:43
void ldlt_compute(Eigen::LDLT< T > &out, T const &mat)
void llt_compute(Eigen::LLT< T > &out, T const &mat)
auto to_sparse_sym(Mat< c_float, colmajor > const &mat) -> SparseMat< c_float >
auto to_sparse(Mat< c_float, colmajor > const &mat) -> SparseMat< c_float >
auto orthonormal_rand_impl(isize n) -> Mat< Scalar, colmajor >
auto orthonormal_rand(isize n) -> Mat< Scalar, colmajor > const &
auto sparse_matrix_rand_not_compressed(isize nrows, isize ncols, Scalar p) -> Mat< Scalar, colmajor >
auto sparse_positive_definite_rand_compressed(isize n, Scalar rho, Scalar p) -> SparseMat< Scalar >
auto matrix_rand(isize nrows, isize ncols) -> Mat< Scalar, colmajor >
auto sparse_positive_definite_rand(isize n, Scalar cond, Scalar p) -> SparseMat< Scalar >
auto positive_definite_rand(isize n, Scalar cond) -> Mat< Scalar, colmajor >
auto vector_rand(isize nrows) -> Vec< Scalar >
auto sparse_positive_definite_rand_not_compressed(isize n, Scalar rho, Scalar p) -> Mat< Scalar, colmajor >
constexpr u128 lehmer64_constant(0xda942042e4dd58b5)
auto sparse_matrix_rand(isize nrows, isize ncols, Scalar p) -> SparseMat< Scalar >
Eigen::Matrix< T, Eigen::Dynamic, 1 > Vec
proxsuite::proxqp::dense::Model< Scalar > dense_strongly_convex_qp(proxqp::isize dim, proxqp::isize n_eq, proxqp::isize n_in, Scalar sparsity_factor, Scalar strong_convexity_factor=Scalar(1e-2))
proxsuite::proxqp::dense::Model< Scalar > dense_box_constrained_qp(proxqp::isize dim, proxqp::isize n_eq, proxqp::isize n_in, Scalar sparsity_factor, Scalar strong_convexity_factor=Scalar(1e-2))
proxsuite::proxqp::dense::Model< Scalar > dense_degenerate_qp(proxqp::isize dim, proxqp::isize n_eq, proxqp::isize n_in, Scalar sparsity_factor, Scalar strong_convexity_factor=Scalar(1e-2))
Eigen::SparseMatrix< Scalar, Eigen::ColMajor, c_int > SparseMat
proxsuite::proxqp::dense::Model< Scalar > dense_unconstrained_qp(proxqp::isize dim, Scalar sparsity_factor, Scalar strong_convexity_factor=Scalar(1e-2))
auto matmul3(MatLhs const &a, MatMid const &b, MatRhs const &c) -> Mat< T, proxqp::colmajor >
auto mat_cast(Mat< From, proxqp::colmajor > const &from) -> Mat< To, proxqp::colmajor >
auto matmul_impl(Mat< T, proxqp::colmajor > const &lhs, Mat< T, proxqp::colmajor > const &rhs) -> Mat< T, proxqp::colmajor >
proxsuite::proxqp::sparse::SparseModel< Scalar > sparse_strongly_convex_qp(proxqp::isize dim, proxqp::isize n_eq, proxqp::isize n_in, Scalar sparsity_factor, Scalar strong_convexity_factor=Scalar(1e-2))
proxsuite::proxqp::dense::Model< Scalar > dense_not_strongly_convex_qp(proxqp::isize dim, proxqp::isize n_eq, proxqp::isize n_in, Scalar sparsity_factor)
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic,(L==proxqp::colmajor) ? Eigen::ColMajor :Eigen::RowMajor > Mat
auto matmul(MatLhs const &a, MatRhs const &b) -> Mat< T, proxqp::colmajor >
constexpr Layout colmajor
Definition views.hpp:244
This class stores the model of the QP problem.
Definition model.hpp:24
EigenNoAlloc(EigenNoAlloc const &)=delete
auto operator=(EigenNoAlloc const &) -> EigenNoAlloc &=delete
EigenNoAlloc(EigenNoAlloc &&)=delete
auto operator=(EigenNoAlloc &&) -> EigenNoAlloc &=delete