.. _program_listing_file__tmp_ws_src_proxsuite_include_proxsuite_proxqp_utils_random_qp_problems.hpp: Program Listing for File random_qp_problems.hpp =============================================== |exhale_lsh| :ref:`Return to documentation for file ` (``/tmp/ws/src/proxsuite/include/proxsuite/proxqp/utils/random_qp_problems.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #ifndef PROXSUITE_PROXQP_UTILS_RANDOM_QP_PROBLEMS_HPP #define PROXSUITE_PROXQP_UTILS_RANDOM_QP_PROBLEMS_HPP #include #include #include #include #include #include #include #include #include #include #include namespace proxsuite { namespace proxqp { namespace utils { using c_int = long long; using c_float = double; namespace proxqp = proxsuite::proxqp; template using Mat = Eigen::Matrix; template using Vec = Eigen::Matrix; template using SparseMat = Eigen::SparseMatrix; using namespace proxqp; namespace eigen { template void llt_compute( // Eigen::LLT& out, T const& mat) { out.compute(mat); } template void ldlt_compute( // Eigen::LDLT& out, T const& mat) { out.compute(mat); } LDLT_EXPLICIT_TPL_DECL(2, llt_compute>); LDLT_EXPLICIT_TPL_DECL(2, ldlt_compute>); LDLT_EXPLICIT_TPL_DECL(2, llt_compute>); LDLT_EXPLICIT_TPL_DECL(2, ldlt_compute>); LDLT_EXPLICIT_TPL_DECL(2, llt_compute>); LDLT_EXPLICIT_TPL_DECL(2, ldlt_compute>); LDLT_EXPLICIT_TPL_DECL(2, llt_compute>); LDLT_EXPLICIT_TPL_DECL(2, ldlt_compute>); } // namespace eigen namespace rand { using proxqp::u32; using proxqp::u64; #ifdef _MSC_VER /* Using the MSCV compiler on Windows causes problems because the type uint128 is not available. Therefore, we use a random number generator from the stdlib instead of our custom Lehmer random number generator. The necessary lehmer functions used in in our code are remplaced with calls to the stdlib.*/ std::mt19937 gen(1234); std::uniform_real_distribution<> uniform_dist(0.0, 1.0); std::normal_distribution normal_dist; using u128 = u64; inline auto uniform_rand() -> double { double output = double(uniform_dist(gen)); return output; } inline auto lehmer_global() -> u128& { static u64 output = gen(); return output; } inline void set_seed(u64 seed) { gen.seed(seed); } inline auto normal_rand() -> double { return normal_dist(gen); } #else using u128 = __uint128_t; constexpr u128 lehmer64_constant(0xda942042e4dd58b5); inline auto lehmer_global() -> u128& { static u128 g_lehmer64_state = lehmer64_constant * lehmer64_constant; return g_lehmer64_state; } inline auto lehmer64() -> u64 { // [0, 2^64) lehmer_global() *= lehmer64_constant; return u64(lehmer_global() >> u128(64U)); } inline void set_seed(u64 seed) { lehmer_global() = u128(seed) + 1; lehmer64(); lehmer64(); } inline auto uniform_rand() -> double { // [0, 2^53] u64 a = lehmer64() / (1U << 11U); return double(a) / double(u64(1) << 53U); } inline auto normal_rand() -> double { static const double pi2 = std::atan(static_cast(1)) * 8; double u1 = uniform_rand(); double u2 = uniform_rand(); double ln = std::log(u1); double sqrt = std::sqrt(-2 * ln); return sqrt * std::cos(pi2 * u2); } #endif template auto vector_rand(isize nrows) -> Vec { auto v = Vec(nrows); for (isize i = 0; i < nrows; ++i) { v(i) = Scalar(rand::normal_rand()); } return v; } template auto matrix_rand(isize nrows, isize ncols) -> Mat { auto v = Mat(nrows, ncols); for (isize i = 0; i < nrows; ++i) { for (isize j = 0; j < ncols; ++j) { v(i, j) = Scalar(rand::normal_rand()); } } return v; } namespace detail { template auto orthonormal_rand_impl(isize n) -> Mat { auto mat = rand::matrix_rand(n, n); auto qr = mat.householderQr(); Mat q = qr.householderQ(); return q; } using Input = std::pair; } // namespace detail template auto orthonormal_rand(isize n) -> Mat const& { static auto cache = std::map>{}; auto input = detail::Input{ lehmer_global(), n }; auto it = cache.find(input); if (it == cache.end()) { auto res = cache.insert({ input, detail::orthonormal_rand_impl(n), }); it = res.first; } return (*it).second; } template auto positive_definite_rand(isize n, Scalar cond) -> Mat { auto const& q = rand::orthonormal_rand(n); auto d = Vec(n); { using std::exp; using std::log; Scalar diff = log(cond); for (isize i = 0; i < n; ++i) { d(i) = exp(Scalar(i) / Scalar(n) * diff); } } return q * d.asDiagonal() * q.transpose(); } template auto sparse_positive_definite_rand(isize n, Scalar cond, Scalar p) -> SparseMat { auto H = SparseMat(n, n); for (isize i = 0; i < n; ++i) { auto random = Scalar(rand::normal_rand()); H.insert(i, i) = random; } for (isize i = 0; i < n; ++i) { for (isize j = i + 1; j < n; ++j) { auto urandom = rand::uniform_rand(); if (urandom < p / 2) { auto random = Scalar(rand::normal_rand()); H.insert(i, j) = random; } } } Mat H_dense = H.toDense(); Vec eigh = H_dense.template selfadjointView().eigenvalues(); Scalar min = eigh.minCoeff(); Scalar max = eigh.maxCoeff(); // new_min = min + rho // new_max = max + rho // // (max + rho)/(min + rho) = cond // 1 + (max - min) / (min + rho) = cond // (max - min) / (min + rho) = cond - 1 // min + rho = (max - min) / (cond - 1) // rho = (max - min)/(cond - 1) - min Scalar rho = (max - min) / (cond - 1) - min; if (max == min) { rho += 1; } for (isize i = 0; i < n; ++i) { H.coeffRef(i, i) += rho; } H.makeCompressed(); return H; } template auto sparse_positive_definite_rand_compressed(isize n, Scalar rho, Scalar p) -> SparseMat { auto H = SparseMat(n, n); H.setZero(); for (isize i = 0; i < n; ++i) { for (isize j = i + 1; j < n; ++j) { auto urandom = rand::uniform_rand(); if (urandom < p) { auto random = Scalar(rand::normal_rand()); H.insert(i, j) = random; } } } Mat H_dense = H.toDense(); Vec eigh = H_dense.template selfadjointView().eigenvalues(); Scalar min = eigh.minCoeff(); for (isize i = 0; i < n; ++i) { H.coeffRef(i, i) += (rho + abs(min)); } H.makeCompressed(); return H; } template auto sparse_positive_definite_rand_not_compressed(isize n, Scalar rho, Scalar p) -> Mat { auto H = Mat(n, n); H.setZero(); for (isize i = 0; i < n; ++i) { for (isize j = 0; j < n; ++j) { auto urandom = rand::uniform_rand(); if (urandom < p / 2) { auto random = Scalar(rand::normal_rand()); H(i, j) = random; } } } H = ((H + H.transpose()) * 0.5) .eval(); // safe no aliasing : // https://eigen.tuxfamily.org/dox/group__TopicAliasing.html // H.array() /= 2.; Vec eigh = H.template selfadjointView().eigenvalues(); Scalar min = eigh.minCoeff(); H.diagonal().array() += (rho + abs(min)); return H; } template auto sparse_matrix_rand(isize nrows, isize ncols, Scalar p) -> SparseMat { auto A = SparseMat(nrows, ncols); for (isize i = 0; i < nrows; ++i) { for (isize j = 0; j < ncols; ++j) { if (rand::uniform_rand() < p) { A.insert(i, j) = Scalar(rand::normal_rand()); } } } A.makeCompressed(); return A; } template auto sparse_matrix_rand_not_compressed(isize nrows, isize ncols, Scalar p) -> Mat { auto A = Mat(nrows, ncols); A.setZero(); for (isize i = 0; i < nrows; ++i) { for (isize j = 0; j < ncols; ++j) { if (rand::uniform_rand() < p) { A(i, j) = Scalar(rand::normal_rand()); } } } return A; } } // namespace rand using proxqp::usize; namespace osqp { auto to_sparse(Mat const& mat) -> SparseMat; auto to_sparse_sym(Mat const& mat) -> SparseMat; } // namespace osqp template auto matmul_impl( // Mat const& lhs, Mat const& rhs) -> Mat { return lhs.operator*(rhs); } template auto mat_cast(Mat const& from) -> Mat { return from.template cast(); } LDLT_EXPLICIT_TPL_DECL(2, matmul_impl); LDLT_EXPLICIT_TPL_DECL(1, mat_cast); LDLT_EXPLICIT_TPL_DECL(1, mat_cast); template auto matmul(MatLhs const& a, MatRhs const& b) -> Mat { using Upscaled = typename std:: conditional::value, long double, T>::type; return mat_cast(matmul_impl( Mat(a).template cast(), Mat(b).template cast())); } template auto matmul3(MatLhs const& a, MatMid const& b, MatRhs const& c) -> Mat { return matmul(matmul(a, b), c); } VEG_TAG(from_data, FromData); struct EigenNoAlloc { EigenNoAlloc(EigenNoAlloc&&) = delete; EigenNoAlloc(EigenNoAlloc const&) = delete; auto operator=(EigenNoAlloc&&) -> EigenNoAlloc& = delete; auto operator=(EigenNoAlloc const&) -> EigenNoAlloc& = delete; #if defined(EIGEN_RUNTIME_NO_MALLOC) EigenNoAlloc() noexcept { Eigen::internal::set_is_malloc_allowed(false); } ~EigenNoAlloc() noexcept { Eigen::internal::set_is_malloc_allowed(true); } #else EigenNoAlloc() = default; #endif }; template proxsuite::proxqp::dense::Model dense_unconstrained_qp(proxqp::isize dim, Scalar sparsity_factor, Scalar strong_convexity_factor = Scalar(1e-2)) { Mat H = rand::sparse_positive_definite_rand_not_compressed( dim, strong_convexity_factor, sparsity_factor); Vec g = rand::vector_rand(dim); Mat A = rand::sparse_matrix_rand_not_compressed(0, dim, sparsity_factor); Vec b = rand::vector_rand(0); Mat C = rand::sparse_matrix_rand_not_compressed(0, dim, sparsity_factor); Vec u = rand::vector_rand(0); Vec l = rand::vector_rand(0); proxsuite::proxqp::dense::Model model(dim, 0, 0); model.H = H; model.g = g; return model; } template proxsuite::proxqp::dense::Model 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)) { Mat H = rand::sparse_positive_definite_rand_not_compressed( dim, strong_convexity_factor, sparsity_factor); Vec g = rand::vector_rand(dim); Mat A = rand::sparse_matrix_rand_not_compressed(n_eq, dim, sparsity_factor); Mat C = rand::sparse_matrix_rand_not_compressed(n_in, dim, sparsity_factor); Vec x_sol = rand::vector_rand(dim); auto delta = Vec(n_in); for (proxqp::isize i = 0; i < n_in; ++i) { delta(i) = rand::uniform_rand(); } Vec u = C * x_sol + delta; Vec b = A * x_sol; Vec l(n_in); l.setZero(); l.array() -= 1.e20; proxsuite::proxqp::dense::Model model(dim, n_eq, n_in); model.H = H; model.g = g; model.A = A; model.b = b; model.C = C; model.u = u; model.l = l; return model; } template proxsuite::proxqp::dense::Model dense_not_strongly_convex_qp(proxqp::isize dim, proxqp::isize n_eq, proxqp::isize n_in, Scalar sparsity_factor) { Mat H = rand::sparse_positive_definite_rand_not_compressed( dim, Scalar(0), sparsity_factor); Mat A = rand::sparse_matrix_rand_not_compressed(n_eq, dim, sparsity_factor); Mat C = rand::sparse_matrix_rand_not_compressed(n_in, dim, sparsity_factor); Vec x_sol = rand::vector_rand(dim); Vec y_sol = rand::vector_rand(n_eq); Vec z_sol = rand::vector_rand(n_in); auto delta = Vec(n_in); for (proxqp::isize i = 0; i < n_in; ++i) { delta(i) = rand::uniform_rand(); } auto Cx = C * x_sol; Vec u = Cx + delta; Vec b = A * x_sol; Vec l = Cx - delta; Vec g = -(H * x_sol + C.transpose() * z_sol + A.transpose() * y_sol); proxsuite::proxqp::dense::Model model(dim, n_eq, n_in); model.H = H; model.g = g; model.A = A; model.b = b; model.C = C; model.u = u; model.l = l; return model; } template proxsuite::proxqp::dense::Model dense_degenerate_qp(proxqp::isize dim, proxqp::isize n_eq, proxqp::isize n_in, Scalar sparsity_factor, Scalar strong_convexity_factor = Scalar(1e-2)) { Mat H = rand::sparse_positive_definite_rand_not_compressed( dim, strong_convexity_factor, sparsity_factor); Vec g = rand::vector_rand(dim); Mat A = rand::sparse_matrix_rand_not_compressed(n_eq, dim, sparsity_factor); Mat C = Mat(2 * n_in, dim); Vec x_sol = rand::vector_rand(dim); auto delta = Vec(2 * n_in); for (proxqp::isize i = 0; i < 2 * n_in; ++i) { delta(i) = rand::uniform_rand(); } Vec b = A * x_sol; auto C_ = rand::sparse_matrix_rand_not_compressed(n_in, dim, sparsity_factor); C.setZero(); C.block(0, 0, n_in, dim) = C_; C.block(n_in, 0, n_in, dim) = C_; Vec u = C * x_sol + delta; Vec l(2 * n_in); l.setZero(); l.array() -= 1.e20; proxsuite::proxqp::dense::Model model(dim, n_eq, n_in); model.H = H; model.g = g; model.A = A; model.b = b; model.C = C; model.u = u; model.l = l; return model; } template proxsuite::proxqp::dense::Model 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)) { Mat H = rand::sparse_positive_definite_rand_not_compressed( dim, strong_convexity_factor, sparsity_factor); Vec g = rand::vector_rand(dim); Mat A = rand::sparse_matrix_rand_not_compressed(n_eq, dim, sparsity_factor); Mat C = Mat(n_in, dim); Vec x_sol = rand::vector_rand(dim); auto delta = Vec(n_in); for (proxqp::isize i = 0; i < n_in; ++i) { delta(i) = rand::uniform_rand(); } Vec b = A * x_sol; C.setZero(); C.diagonal().array() += 1; Vec u = x_sol + delta; Vec l = x_sol - delta; proxsuite::proxqp::dense::Model model(dim, n_eq, n_in); model.H = H; model.g = g; model.A = A; model.b = b; model.C = C; model.u = u; model.l = l; return model; } template proxsuite::proxqp::sparse::SparseModel 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)) { SparseMat H = rand::sparse_positive_definite_rand_compressed( dim, strong_convexity_factor, sparsity_factor); Vec g = rand::vector_rand(dim); SparseMat A = rand::sparse_matrix_rand(n_eq, dim, sparsity_factor); SparseMat C = rand::sparse_matrix_rand(n_in, dim, sparsity_factor); Vec x_sol = rand::vector_rand(dim); auto delta = Vec(n_in); for (proxqp::isize i = 0; i < n_in; ++i) { delta(i) = rand::uniform_rand(); } Vec u = C * x_sol + delta; Vec b = A * x_sol; Vec l(n_in); l.setZero(); l.array() -= 1.e20; proxsuite::proxqp::sparse::SparseModel res{ H, g, A, b, C, u, l }; return res; } } // namespace utils } // namespace proxqp } // namespace proxsuite #endif /* end of include guard PROXSUITE_PROXQP_UTILS_RANDOM_QP_PROBLEMS_HPP \ */