Skip to content

Commit

Permalink
Merge pull request #437 from osqp/im/cap
Browse files Browse the repository at this point in the history
Add function to query capabilities of the current library and abstract linear solver information
  • Loading branch information
vineetbansal committed Jul 26, 2022
2 parents 40959d7 + 5a0ac15 commit b8a13ad
Show file tree
Hide file tree
Showing 12 changed files with 109 additions and 28 deletions.
11 changes: 11 additions & 0 deletions algebra/cuda/algebra_libs.cu
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,24 @@
* limitations under the License.
*/

#include "osqp_api_constants.h"
#include "osqp_api_types.h"
#include "lin_alg.h"
#include "cuda_handler.h"


CUDA_Handle_t *CUDA_handle = OSQP_NULL;

c_int osqp_algebra_linsys_supported(void) {
/* Only has a PCG (indirect) solver */
return OSQP_CAPABILITIY_INDIRECT_SOLVER;
}

enum osqp_linsys_solver_type osqp_algebra_default_linsys(void) {
/* Prefer the PCG solver (it is also the only one available) */
return OSQP_INDIRECT_SOLVER;
}

c_int osqp_algebra_init_libs(c_int device) {
/* This is to prevent a memory leak when multiple OSQP objects are created */
if (CUDA_handle) return 0;
Expand Down
11 changes: 11 additions & 0 deletions algebra/default/algebra_libs.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
#include "osqp_api_constants.h"
#include "osqp_api_types.h"

c_int osqp_algebra_linsys_supported(void) {
/* Only has QDLDL (direct solver) */
return OSQP_CAPABILITIY_DIRECT_SOLVER;
}

enum osqp_linsys_solver_type osqp_algebra_default_linsys(void) {
/* Prefer QDLDL (it is also the only one available) */
return OSQP_DIRECT_SOLVER;
}

c_int osqp_algebra_init_libs(c_int device) {return 0;}

void osqp_algebra_free_libs(void) {return;}
11 changes: 11 additions & 0 deletions algebra/mkl/algebra_libs.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
#include "osqp_configure.h"
#include "osqp_api_constants.h"
#include "osqp_api_types.h"
#include <mkl.h>

c_int osqp_algebra_linsys_supported(void) {
/* Has both Paradiso (direct solver) and a PCG solver (indirect solver) */
return OSQP_CAPABILITIY_DIRECT_SOLVER | OSQP_CAPABILITIY_INDIRECT_SOLVER;
}

enum osqp_linsys_solver_type osqp_algebra_default_linsys(void) {
/* Prefer Pardiso */
return OSQP_DIRECT_SOLVER;
}

c_int osqp_algebra_init_libs(c_int device) {
c_int retval = 0;

Expand Down
15 changes: 15 additions & 0 deletions examples/osqp_demo.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "osqp.h"
#include <stdlib.h>
#include <stdio.h>

int main(void) {

Expand Down Expand Up @@ -41,6 +42,20 @@ int main(void) {
//settings->linsys_solver = OSQP_INDIRECT_SOLVER;
}

c_int cap = osqp_capabilities();

printf("This OSQP library supports:\n");
if(cap & OSQP_CAPABILITIY_DIRECT_SOLVER) {
printf(" A direct linear algebra solver\n");
}
if(cap & OSQP_CAPABILITIY_INDIRECT_SOLVER) {
printf(" An indirect linear algebra solver\n");
}
if(cap & OSQP_CAPABILITIY_CODEGEN) {
printf(" Code generation\n");
}
printf("\n");

/* Setup solver */
exitflag = osqp_setup(&solver, P, q, A, l, u, m, n, settings);

Expand Down
6 changes: 6 additions & 0 deletions include/private/lin_alg.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
extern "C" {
# endif

/* Return which linear system solvers are supported */
c_int osqp_algebra_linsys_supported(void);

/* Return the default linear system the algebra backend prefers */
enum osqp_linsys_solver_type osqp_algebra_default_linsys(void);

/* Initialize libraries that implement algebra. */
c_int osqp_algebra_init_libs(c_int device);

Expand Down
19 changes: 13 additions & 6 deletions include/public/osqp_api_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,19 @@

#include "osqp_configure.h"

/***********************
* Solver capabilities *
***********************/
enum osqp_capabilities {
/* This enum serves as a bit-flag definition, so each capability must be represented by
a different bit in an int variable */
OSQP_CAPABILITIY_DIRECT_SOLVER = 0x01, /* A direct linear solver is present in the algebra */
OSQP_CAPABILITIY_INDIRECT_SOLVER = 0x02, /* An indirect linear solver is present in the algebra */
OSQP_CAPABILITIY_CODEGEN = 0x04, /* Code generation is present */
OSQP_CAPABILITIY_UPDATE_MATRICES = 0x08 /* The problem matrices can be updated */
};


/******************
* Solver Status *
******************/
Expand Down Expand Up @@ -55,12 +68,6 @@ extern const char * OSQP_ERROR_MESSAGE[];
* Solver Parameters and Settings *
**********************************/

#ifdef ALGEBRA_CUDA
# define OSQP_LINSYS_SOLVER (OSQP_INDIRECT_SOLVER)
#else
# define OSQP_LINSYS_SOLVER (OSQP_DIRECT_SOLVER)
#endif

# define OSQP_VERBOSE (1)
# define OSQP_WARM_STARTING (1)
# define OSQP_SCALING (10)
Expand Down
6 changes: 6 additions & 0 deletions include/public/osqp_api_functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ extern "C" {
*/


/**
* Return the capabilities of the OSQP solver.
* @return
*/
OSQP_API c_int osqp_capabilities(void);

/**
* Return OSQP version
* @return OSQP version
Expand Down
18 changes: 7 additions & 11 deletions src/auxil.c
Original file line number Diff line number Diff line change
Expand Up @@ -924,21 +924,17 @@ c_int validate_data(const csc *P,


c_int validate_linsys_solver(c_int linsys_solver) {

#ifdef ALGEBRA_CUDA
if (linsys_solver == OSQP_INDIRECT_SOLVER) {
return 0;
}
#elif defined ALGEBRA_MKL
if ((linsys_solver == OSQP_DIRECT_SOLVER) ||
(linsys_solver == OSQP_INDIRECT_SOLVER)) {
/* Verify the algebra backend supports the requested indirect solver */
if ( (linsys_solver == OSQP_INDIRECT_SOLVER) &&
(osqp_algebra_linsys_supported() & OSQP_CAPABILITIY_INDIRECT_SOLVER) ) {
return 0;
}
#else
if (linsys_solver == OSQP_DIRECT_SOLVER) {

/* Verify the algebra backend supports the requested direct solver */
if ( (linsys_solver == OSQP_DIRECT_SOLVER) &&
(osqp_algebra_linsys_supported() & OSQP_CAPABILITIY_DIRECT_SOLVER) ) {
return 0;
}
#endif

// Invalid solver
return 1;
Expand Down
2 changes: 1 addition & 1 deletion src/codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ static c_int write_settings(FILE *f,
fprintf(f, "/* Define the settings structure */\n");
fprintf(f, "OSQPSettings %ssettings = {\n", prefix);
fprintf(f, " 0,\n"); // device
fprintf(f, " OSQP_LINSYS_SOLVER,\n");
fprintf(f, " OSQP_DIRECT_SOLVER,\n");
fprintf(f, " 0,\n"); // verbose
fprintf(f, " %d,\n", settings->warm_starting);
fprintf(f, " %d,\n", settings->scaling);
Expand Down
29 changes: 23 additions & 6 deletions src/osqp_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "scaling.h"
#include "error.h"
#include "version.h"
#include "lin_alg.h"

#ifdef OSQP_CODEGEN
#include "codegen.h"
Expand All @@ -24,6 +25,22 @@
/**********************
* Main API Functions *
**********************/
c_int osqp_capabilities(void) {
c_int capabilities = 0;

capabilities |= osqp_algebra_linsys_supported();

#if EMBEDDED != 1
capabilities |= OSQP_CAPABILITIY_UPDATE_MATRICES;
#endif

#ifdef OSQP_CODEGEN
capabilities |= OSQP_CAPABILITIY_CODEGEN;
#endif

return capabilities;
}

const char* osqp_version(void) {
return OSQP_VERSION;
}
Expand Down Expand Up @@ -57,12 +74,12 @@ void osqp_get_dimensions(OSQPSolver *solver,

void osqp_set_default_settings(OSQPSettings *settings) {

settings->device = 0; /* device identifier */
settings->linsys_solver = OSQP_LINSYS_SOLVER; /* linear system solver */
settings->verbose = OSQP_VERBOSE; /* print output */
settings->warm_starting = OSQP_WARM_STARTING; /* warm starting */
settings->scaling = OSQP_SCALING; /* heuristic problem scaling */
settings->polishing = OSQP_POLISHING; /* ADMM solution polish: 1 */
settings->device = 0; /* device identifier */
settings->linsys_solver = osqp_algebra_default_linsys(); /* linear system solver */
settings->verbose = OSQP_VERBOSE; /* print output */
settings->warm_starting = OSQP_WARM_STARTING; /* warm starting */
settings->scaling = OSQP_SCALING; /* heuristic problem scaling */
settings->polishing = OSQP_POLISHING; /* ADMM solution polish: 1 */

settings->rho = (c_float)OSQP_RHO; /* ADMM step */
settings->rho_is_vec = OSQP_RHO_IS_VEC; /* defines whether rho is scalar or vector*/
Expand Down
6 changes: 3 additions & 3 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ find_package(Python)
if(NOT PYTHON_FOUND)
message(
FATAL_ERROR
"You need python installed to generate unittests. If you do not want to compile the unittests pass -DBUILD_TESTING=OFF to cmake."
"You need python installed to generate unittests."
)
endif()

find_python_module(numpy)
if(NOT NUMPY_FOUND)
message(
FATAL_ERROR
"You need numpy python module installed to generate unittests. If you do not want to compile the unittests pass -DBUILD_TESTING=OFF to cmake."
"You need numpy python module installed to generate unittests."
)
endif()

Expand All @@ -23,7 +23,7 @@ find_python_module(scipy)
if((NOT SCIPY_FOUND) OR (SCIPY_VERSION VERSION_LESS 0.17.0))
message(
FATAL_ERROR
"You need scipy python module installed to generate unittests. If you do not want to compile the unittests pass -DBUILD_TESTING=OFF to cmake."
"You need scipy python module installed to generate unittests."
)
endif()

Expand Down
3 changes: 2 additions & 1 deletion tests/solve_linsys/test_solve_linsys.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
extern "C" {
#endif
#include "lin_sys.h"
#include "lin_alg.h"
#ifdef __cplusplus
}
#endif
Expand All @@ -29,7 +30,7 @@ void test_solveKKT() {
osqp_set_default_settings(settings);
settings->rho = data->test_solve_KKT_rho;
settings->sigma = data->test_solve_KKT_sigma;
settings->linsys_solver = OSQP_LINSYS_SOLVER;
settings->linsys_solver = osqp_algebra_default_linsys();

// Set rho_vec
m = data->test_solve_KKT_A->m;
Expand Down

0 comments on commit b8a13ad

Please sign in to comment.