Skip to content

topic/osqp: Add the OSQP solver in ProxSuite #399

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 27 commits into
base: devel
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
61b4f29
wrapper.hpp: Refactorize between proxqp and osqp
Lucas-Haubert May 6, 2025
6b07001
solvers/common/utils.hpp: Renamed QPSolver into QPStruct in function …
Lucas-Haubert May 6, 2025
fd7a40f
proxqp/dense/solver.hpp: Factorize the setup in the qp_solve function
Lucas-Haubert May 6, 2025
08a1ab0
proxqp/dense/solver.hpp: Factorize the compute_feasibility function
Lucas-Haubert May 6, 2025
39240ee
proxqp/dense/solver.hpp: Factorize the update_solver_status function
Lucas-Haubert May 6, 2025
8d1b0d8
proxqp/dense/solver: Factorize the print_solver_statistics function
Lucas-Haubert May 7, 2025
b2e3825
proxqp/dense/solver.hpp: Factorize the prepare_next_solve function
Lucas-Haubert May 7, 2025
edb2904
proxqp/dense/solver.hpp: Factorize tje compute_objective function
Lucas-Haubert May 7, 2025
89f0f5d
proxqp/dense/solver/hpp: Factorize the compute_timings function
Lucas-Haubert May 7, 2025
29aa9bd
proxqp/dense/solver.hpp: Factorize the unscale_solver function
Lucas-Haubert May 7, 2025
98fe662
osqp/dense/wrapper.hpp: Fix bug with class constructors and call to q…
Lucas-Haubert May 7, 2025
8b27e7e
osqp::dense: Equality
Lucas-Haubert May 7, 2025
76f5945
osqp::dense: Inequality without polishing and mu update
Lucas-Haubert May 9, 2025
ed42ea2
format: Removed useless commentaries
Lucas-Haubert May 9, 2025
1f7a6fa
Add test osqp_dense_qp_solve: Test on different values of mu_eq and m…
Lucas-Haubert May 9, 2025
9b53147
/test: Inequality without mu update and polishing. Remaining failed t…
Lucas-Haubert May 9, 2025
32dd134
osqp/: mu_update: Code done with time condition transformed into iter…
Lucas-Haubert May 15, 2025
c656ec6
osqp/: polish: Code done and works on simple example. To test and ben…
Lucas-Haubert May 15, 2025
93277bf
osqp/ polish: Implementation strategy regarding unconstrained problem…
Lucas-Haubert May 17, 2025
7b35912
osqp/: Split polish function in several functions
Lucas-Haubert May 18, 2025
d7cad12
osqp/: mu update: fixed bad performances from error in the calculatio…
Lucas-Haubert May 19, 2025
841d01b
osqp/: Polishing: Handled the case where ADMM is solved at initializa…
Lucas-Haubert May 19, 2025
d496734
osqp/: Add function setup_solver_resume_admm to go back to the kkt of…
Lucas-Haubert May 20, 2025
b02ddf0
osqp/: Refrase code for setup solver resume admm
Lucas-Haubert May 20, 2025
65c746e
osqp/: formatting
Lucas-Haubert May 20, 2025
13d2e77
/osqp: Removed memory debug commentaries
Lucas-Haubert May 20, 2025
404b81f
/osqp: Begin work on test_dense_maros_meszaros
Lucas-Haubert May 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions examples/cpp/osqp_initializing_with_none.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <iostream>
#include "proxsuite/osqp/dense/dense.hpp"
#include <proxsuite/proxqp/utils/random_qp_problems.hpp> // used for generating a random convex qp

using namespace proxsuite::proxqp;
using T = double;
namespace pod = proxsuite::osqp::dense;

int
main()
{
dense::isize dim = 10;
dense::isize n_eq(0);
dense::isize n_in(0);
pod::QP<T> qp(dim, n_eq, n_in);
T strong_convexity_factor(0.1);
T sparsity_factor(0.15);
// we generate a qp, so the function used from helpers.hpp is
// in proxqp namespace. The qp is in dense eigen format and
// you can control its sparsity ratio and strong convexity factor.
dense::Model<T> qp_random = utils::dense_strongly_convex_qp(
dim, n_eq, n_in, sparsity_factor, strong_convexity_factor);

qp.settings.default_mu_eq = T(1.E-2);
qp.settings.default_mu_in = T(1.E1);

qp.init(qp_random.H,
qp_random.g,
qp_random.A,
qp_random.b,
qp_random.C,
qp_random.l,
qp_random.u); // initialization with zero shape matrices
// it is equivalent to do qp.init(qp_random.H, qp_random.g,
// nullopt,nullopt,nullopt,nullopt,nullopt);
qp.solve();
// print an optimal solution x,y and z
std::cout << "optimal x: " << qp.results.x << std::endl;
std::cout << "optimal y: " << qp.results.y << std::endl;
std::cout << "optimal z: " << qp.results.z << std::endl;
}
52 changes: 52 additions & 0 deletions examples/cpp/osqp_initializing_with_none_without_api.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include <iostream>
#include "proxsuite/helpers/optional.hpp"
#include "proxsuite/osqp/dense/dense.hpp"
#include <proxsuite/proxqp/utils/random_qp_problems.hpp> // used for generating a random convex qp

using namespace proxsuite;
using T = double;

namespace pp = proxsuite::proxqp;
namespace ppd = proxsuite::proxqp::dense;
namespace pod = proxsuite::osqp::dense;

int
main()
{
ppd::isize dim = 10;
ppd::isize n_eq(0);
ppd::isize n_in(0);
T strong_convexity_factor(0.1);
T sparsity_factor(0.15);
// we generate a qp, so the function used from helpers.hpp is
// in proxqp namespace. The qp is in dense eigen format and
// you can control its sparsity ratio and strong convexity factor.
ppd::Model<T> qp_random = pp::utils::dense_strongly_convex_qp(
dim, n_eq, n_in, sparsity_factor, strong_convexity_factor);

T eps_abs(1.E-5);
T eps_rel(0);
pp::Results<T> results = pod::solve<T>(qp_random.H,
qp_random.g,
qp_random.A,
qp_random.b,
qp_random.C,
qp_random.l,
qp_random.u,
nullopt,
nullopt,
nullopt,
eps_abs,
eps_rel,
nullopt,
T(1.E-2),
T(1.E-1));

// initialization with zero shape matrices
// it is equivalent to do dense::solve<T>(qp_random.H, qp_random.g,
// nullopt,nullopt,nullopt,nullopt,nullopt);
// print an optimal solution x,y and z
std::cout << "optimal x: " << results.x << std::endl;
std::cout << "optimal y: " << results.y << std::endl;
std::cout << "optimal z: " << results.z << std::endl;
}
47 changes: 47 additions & 0 deletions examples/cpp/osqp_overview-simple.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include <iostream>
#include <proxsuite/osqp/dense/dense.hpp>
#include <proxsuite/proxqp/dense/dense.hpp>
#include <proxsuite/proxqp/utils/random_qp_problems.hpp> // used for generating a random convex qp

#include <Eigen/Core>

using namespace proxsuite::osqp;
using T = double;

namespace pp = proxsuite::proxqp;
namespace ppd = proxsuite::proxqp::dense;
namespace pod = proxsuite::osqp::dense;

int
main()
{
T sparsity_factor = 0.15;
ppd::isize dim = 10;
ppd::isize n_eq(dim / 4);
ppd::isize n_in(dim / 4);
T strong_convexity_factor(1.e-2);

ppd::Model<T> qp_random = pp::utils::dense_strongly_convex_qp(
dim, n_eq, n_in, sparsity_factor, strong_convexity_factor);

pod::QP<T> qp(dim, n_eq, n_in);

qp.settings.default_mu_eq = T(1.E-2);
qp.settings.default_mu_in = T(1.E1);

qp.settings.update_mu = true;
qp.settings.polish = true;

qp.init(qp_random.H,
qp_random.g,
qp_random.A,
qp_random.b,
qp_random.C,
qp_random.l,
qp_random.u);
qp.solve();

std::cout << "optimal x: " << qp.results.x << std::endl;
std::cout << "optimal y: " << qp.results.y << std::endl;
std::cout << "optimal z: " << qp.results.z << std::endl;
}
28 changes: 28 additions & 0 deletions include/proxsuite/linalg/dense/ldlt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
#include "proxsuite/linalg/dense/solve.hpp"
#include <proxsuite/linalg/veg/vec.hpp>

#include "proxsuite/proxqp/timings.hpp"
#include <iostream>

namespace proxsuite {
namespace linalg {
namespace dense {
Expand Down Expand Up @@ -718,29 +721,54 @@ struct Ldlt
void factorize(Eigen::Ref<ColMat const> mat /* NOLINT */,
proxsuite::linalg::veg::dynstack::DynStackMut stack)
{
// proxsuite::proxqp::Timer<double> timer;

VEG_ASSERT(mat.rows() == mat.cols());
isize n = mat.rows();
// timer.stop();
// timer.start();
reserve_uninit(n);
// timer.stop();
// std::cout << "Time of reserve_unit: " << timer.elapsed().user <<
// std::endl; // Diff

// timer.start();
perm.resize_for_overwrite(n);
perm_inv.resize_for_overwrite(n);
maybe_sorted_diag.resize_for_overwrite(n);
// timer.stop();
// std::cout << "Time of resize_for_overwrite: " << timer.elapsed().user <<
// std::endl; // Diff

// timer.start();
proxsuite::linalg::dense::_detail::compute_permutation( //
perm.ptr_mut(),
perm_inv.ptr_mut(),
util::diagonal(mat));
// timer.stop();
// std::cout << "Time of compute_permutation: " << timer.elapsed().user <<
// std::endl; // Diff

// timer.start();
{
LDLT_TEMP_MAT_UNINIT(T, work, n, n, stack);
ld_col_mut() = mat;
proxsuite::linalg::dense::_detail::apply_permutation_tri_lower(
ld_col_mut(), work, perm.ptr());
}
// timer.stop();
// std::cout << "Time of apply_permutation_tri_lower: " <<
// timer.elapsed().user << std::endl; // Same timer.start();
for (isize i = 0; i < n; ++i) {
maybe_sorted_diag[i] = ld_col()(i, i);
}
// timer.stop();
// std::cout << "Time of ld_col: " << timer.elapsed().user << std::endl;
// timer.start();
proxsuite::linalg::dense::factorize(ld_col_mut(), stack);
// timer.stop();
// std::cout << "Time of proxsuite::lialg::dense::factorize: " <<
// timer.elapsed().user << std::endl; // Diff
}

/*!
Expand Down
13 changes: 13 additions & 0 deletions include/proxsuite/osqp/dense/dense.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// Copyright (c) 2025 INRIA
//
/**
* @file dense.hpp
*/

#ifndef PROXSUITE_OSQP_DENSE_DENSE_HPP
#define PROXSUITE_OSQP_DENSE_DENSE_HPP

#include "proxsuite/osqp/dense/wrapper.hpp"

#endif /* end of include guard PROXSUITE_OSQP_DENSE_DENSE_HPP */
Loading
Loading