diff --git a/.clang-format b/.clang-format index 3759ef5..7d9636c 100644 --- a/.clang-format +++ b/.clang-format @@ -2,7 +2,7 @@ Language: Cpp # Breaks -ColumnLimit: 0 +ColumnLimit: 120 BreakBeforeBraces: Custom BraceWrapping: AfterClass: true @@ -12,7 +12,9 @@ BraceWrapping: AfterNamespace: true AfterStruct: true AfterUnion: true - +BinPackParameters: false +AlwaysBreakTemplateDeclarations: Yes +AlignAfterOpenBracket: BlockIndent # Indentation IndentWidth: 4 diff --git a/examples/c/example_expcone.c b/examples/c/example_expcone.c index 33f003c..ce17917 100644 --- a/examples/c/example_expcone.c +++ b/examples/c/example_expcone.c @@ -7,7 +7,8 @@ int main(void) { // 3 x 3 zero matrix ClarabelCscMatrix P; - clarabel_CscMatrix_init(&P, + clarabel_CscMatrix_init( + &P, 3, // row 3, // col (uintptr_t[]){ 0, 0, 0, 0 }, // colptr @@ -36,11 +37,7 @@ int main(void) ClarabelFloat b[5] = { 0., 0., 0., 1., exp(5.0) }; - ClarabelSupportedConeT cones[2] = - { - ClarabelExponentialConeT(), - ClarabelZeroConeT(2) - }; + ClarabelSupportedConeT cones[2] = { ClarabelExponentialConeT(), ClarabelZeroConeT(2) }; // Settings ClarabelDefaultSettings settings = clarabel_DefaultSettings_default(); @@ -53,8 +50,7 @@ int main(void) &A, // A b, // b 2, // n_cones - cones, - &settings + cones, &settings ); // Solve diff --git a/examples/c/example_lp.c b/examples/c/example_lp.c index f0e5ed2..562dc46 100644 --- a/examples/c/example_lp.c +++ b/examples/c/example_lp.c @@ -31,10 +31,7 @@ int main(void) ClarabelFloat b[4] = { 1.0, 1.0, 1.0, 1.0 }; - ClarabelSupportedConeT cones[1] = - { - ClarabelNonnegativeConeT(4) - }; + ClarabelSupportedConeT cones[1] = { ClarabelNonnegativeConeT(4) }; // Settings ClarabelDefaultSettings settings = clarabel_DefaultSettings_default(); @@ -48,8 +45,7 @@ int main(void) &A, // A b, // b 1, // n_cones - cones, - &settings + cones, &settings ); // Solve diff --git a/examples/c/example_powcone.c b/examples/c/example_powcone.c index b49aff3..51a7b9a 100644 --- a/examples/c/example_powcone.c +++ b/examples/c/example_powcone.c @@ -30,15 +30,15 @@ int main(void) ClarabelFloat q[6] = { 0., 0., -1., 0., 0., -1. }; /* From dense matrix: - * [[-1., 0., 0., 0., 0., 0.], - * [0., -1., 0., 0., 0., 0.], - * [0., 0., -1., 0., 0., 0.], - * [0., 0., 0., -1., 0., 0.], - * [0., 0., 0., 0., -1., 0.], - * [0., 0., 0., 0., 0., -1.], - * [1., 2., 0., 3., 0., 0.], - * [0., 0., 0., 0., 1., 0.]] - */ + * [[-1., 0., 0., 0., 0., 0.], + * [0., -1., 0., 0., 0., 0.], + * [0., 0., -1., 0., 0., 0.], + * [0., 0., 0., -1., 0., 0.], + * [0., 0., 0., 0., -1., 0.], + * [0., 0., 0., 0., 0., -1.], + * [1., 2., 0., 3., 0., 0.], + * [0., 0., 0., 0., 1., 0.]] + */ ClarabelCscMatrix A; clarabel_CscMatrix_init( &A, @@ -51,13 +51,8 @@ int main(void) ClarabelFloat b[8] = { 0., 0., 0., 0., 0., 0., 3., 1. }; - ClarabelSupportedConeT cones[4] = - { - ClarabelPowerConeT(0.6), - ClarabelPowerConeT(0.1), - ClarabelZeroConeT(1), - ClarabelZeroConeT(1) - }; + ClarabelSupportedConeT cones[4] = { ClarabelPowerConeT(0.6), ClarabelPowerConeT(0.1), ClarabelZeroConeT(1), + ClarabelZeroConeT(1) }; // Settings ClarabelDefaultSettings settings = clarabel_DefaultSettings_default(); @@ -71,8 +66,7 @@ int main(void) &A, // A b, // b 4, // n_cones - cones, - &settings + cones, &settings ); // Solve diff --git a/examples/c/example_qp.c b/examples/c/example_qp.c index b3c1f94..be9510e 100644 --- a/examples/c/example_qp.c +++ b/examples/c/example_qp.c @@ -44,11 +44,7 @@ int main(void) ClarabelFloat b[5] = { 0., 1., 1., 1., 1. }; - ClarabelSupportedConeT cones[2] = - { - ClarabelZeroConeT(1), - ClarabelNonnegativeConeT(4) - }; + ClarabelSupportedConeT cones[2] = { ClarabelZeroConeT(1), ClarabelNonnegativeConeT(4) }; // Settings ClarabelDefaultSettings settings = clarabel_DefaultSettings_default(); @@ -60,8 +56,7 @@ int main(void) &A, // A b, // b 2, // n_cones - cones, - &settings + cones, &settings ); // Solve diff --git a/examples/c/example_qp_f32.c b/examples/c/example_qp_f32.c index 448a8c8..0dae910 100644 --- a/examples/c/example_qp_f32.c +++ b/examples/c/example_qp_f32.c @@ -41,11 +41,7 @@ int main(void) float b[5] = { 0., 1., 1., 1., 1. }; - ClarabelSupportedConeT_f32 cones[2] = - { - ClarabelZeroConeT_f32(1), - ClarabelNonnegativeConeT_f32(4) - }; + ClarabelSupportedConeT_f32 cones[2] = { ClarabelZeroConeT_f32(1), ClarabelNonnegativeConeT_f32(4) }; // Settings ClarabelDefaultSettings_f32 settings = clarabel_DefaultSettings_f32_default(); @@ -57,8 +53,7 @@ int main(void) &A, // A b, // b 2, // n_cones - cones, - &settings + cones, &settings ); // Solve diff --git a/examples/c/example_qp_f64.c b/examples/c/example_qp_f64.c index a1ed9fa..d7d0fb6 100644 --- a/examples/c/example_qp_f64.c +++ b/examples/c/example_qp_f64.c @@ -41,11 +41,7 @@ int main(void) double b[5] = { 0., 1., 1., 1., 1. }; - ClarabelSupportedConeT_f64 cones[2] = - { - ClarabelZeroConeT_f64(1), - ClarabelNonnegativeConeT_f64(4) - }; + ClarabelSupportedConeT_f64 cones[2] = { ClarabelZeroConeT_f64(1), ClarabelNonnegativeConeT_f64(4) }; // Settings ClarabelDefaultSettings_f64 settings = clarabel_DefaultSettings_f64_default(); @@ -57,8 +53,7 @@ int main(void) &A, // A b, // b 2, // n_cones - cones, - &settings + cones, &settings ); // Solve diff --git a/examples/c/example_sdp.c b/examples/c/example_sdp.c index d8154c1..3582cce 100644 --- a/examples/c/example_sdp.c +++ b/examples/c/example_sdp.c @@ -20,8 +20,8 @@ int main(void) ClarabelCscMatrix P; clarabel_CscMatrix_init( &P, - nvec, // row - nvec, // col + nvec, // row + nvec, // col (uintptr_t[]){ 0, 0, 0, 0, 0, 0, 0 }, // colptr NULL, // rowval NULL // nzval @@ -44,15 +44,14 @@ int main(void) &A, 7, // row 6, // col - (uintptr_t[]){0, 2, 4, 6, 8, 10, 12}, // colptr - (uintptr_t[]){0, 6, 1, 6, 2, 6, 3, 6, 4, 6, 5, 6}, // rowval + (uintptr_t[]){ 0, 2, 4, 6, 8, 10, 12 }, // colptr + (uintptr_t[]){ 0, 6, 1, 6, 2, 6, 3, 6, 4, 6, 5, 6 }, // rowval (ClarabelFloat[]){ -1.0, 1.0, -sqrt2, 4.0, -1.0, 3.0, -sqrt2, 8.0, -sqrt2, 10.0, -1.0, 6.0 } // nzval ); ClarabelFloat b[7] = { 0., 0., 0., 0., 0., 0., 1. }; - ClarabelSupportedConeT cones[2] = - { + ClarabelSupportedConeT cones[2] = { ClarabelPSDTriangleConeT(n), ClarabelZeroConeT(1), }; @@ -67,8 +66,7 @@ int main(void) &A, // A b, // b 2, // n_cones - cones, - &settings + cones, &settings ); // Solve diff --git a/examples/c/example_socp.c b/examples/c/example_socp.c index cb4a209..2a02a73 100644 --- a/examples/c/example_socp.c +++ b/examples/c/example_socp.c @@ -39,10 +39,7 @@ int main(void) ClarabelFloat b[3] = { 1., -2., -2. }; - ClarabelSupportedConeT cones[1] = - { - ClarabelSecondOrderConeT(3) - }; + ClarabelSupportedConeT cones[1] = { ClarabelSecondOrderConeT(3) }; // Settings ClarabelDefaultSettings settings = clarabel_DefaultSettings_default(); @@ -54,8 +51,7 @@ int main(void) &A, // A b, // b 1, // n_cones - cones, - &settings + cones, &settings ); // Solve diff --git a/examples/c/utils.c b/examples/c/utils.c index abc3bda..50b0b61 100644 --- a/examples/c/utils.c +++ b/examples/c/utils.c @@ -1,4 +1,5 @@ #include "utils.h" + #include // f64 diff --git a/include/c/CscMatrix.h b/include/c/CscMatrix.h index dadf176..f25c1f3 100644 --- a/include/c/CscMatrix.h +++ b/include/c/CscMatrix.h @@ -58,21 +58,19 @@ typedef ClarabelCscMatrix_f64 ClarabelCscMatrix; // ClarabelCscMatrix APIs // ClarabelCscMatrix::init -void clarabel_CscMatrix_f32_init( - ClarabelCscMatrix_f32 *ptr, - uintptr_t m, - uintptr_t n, - const uintptr_t *colptr, - const uintptr_t *rowval, - const float *nzval); +void clarabel_CscMatrix_f32_init(ClarabelCscMatrix_f32 *ptr, + uintptr_t m, + uintptr_t n, + const uintptr_t *colptr, + const uintptr_t *rowval, + const float *nzval); -void clarabel_CscMatrix_f64_init( - ClarabelCscMatrix_f64 *ptr, - uintptr_t m, - uintptr_t n, - const uintptr_t *colptr, - const uintptr_t *rowval, - const double *nzval); +void clarabel_CscMatrix_f64_init(ClarabelCscMatrix_f64 *ptr, + uintptr_t m, + uintptr_t n, + const uintptr_t *colptr, + const uintptr_t *rowval, + const double *nzval); /// @brief Initialize a sparse matrix in Compressed Sparse Column format /// @param m Number of rows @@ -80,13 +78,12 @@ void clarabel_CscMatrix_f64_init( /// @param colptr CSC format column pointer array (always have length n+1) /// @param rowval Array of row indices (always have length colptr[n]) /// @param nzval Array of nonzero values (always have length colptr[n]) -static inline void clarabel_CscMatrix_init( - ClarabelCscMatrix_f64 *ptr, - uintptr_t m, - uintptr_t n, - const uintptr_t *colptr, - const uintptr_t *rowval, - const double *nzval) +static inline void clarabel_CscMatrix_init(ClarabelCscMatrix_f64 *ptr, + uintptr_t m, + uintptr_t n, + const uintptr_t *colptr, + const uintptr_t *rowval, + const double *nzval) { #ifdef CLARABEL_USE_FLOAT clarabel_CscMatrix_f32_init(ptr, m, n, colptr, rowval, nzval); diff --git a/include/c/DefaultSolver.h b/include/c/DefaultSolver.h index e3db73e..28e38e7 100644 --- a/include/c/DefaultSolver.h +++ b/include/c/DefaultSolver.h @@ -26,32 +26,29 @@ typedef ClarabelDefaultSolver_f64 ClarabelDefaultSolver; // Default solver APIs // DefaultSolver::new -ClarabelDefaultSolver_f64 *clarabel_DefaultSolver_f64_new( - const ClarabelCscMatrix_f64 *P, - const double *q, - const ClarabelCscMatrix_f64 *A, - const double *b, - uintptr_t n_cones, - const ClarabelSupportedConeT_f64 *cones, - const ClarabelDefaultSettings_f64 *settings); - -ClarabelDefaultSolver_f32 *clarabel_DefaultSolver_f32_new( - const ClarabelCscMatrix_f32 *P, - const float *q, - const ClarabelCscMatrix_f32 *A, - const float *b, - uintptr_t n_cones, - const ClarabelSupportedConeT_f32 *cones, - const ClarabelDefaultSettings_f32 *settings); - -static inline ClarabelDefaultSolver *clarabel_DefaultSolver_new( - const ClarabelCscMatrix *P, - const ClarabelFloat *q, - const ClarabelCscMatrix *A, - const ClarabelFloat *b, - uintptr_t n_cones, - const ClarabelSupportedConeT *cones, - const ClarabelDefaultSettings *settings) +ClarabelDefaultSolver_f64 *clarabel_DefaultSolver_f64_new(const ClarabelCscMatrix_f64 *P, + const double *q, + const ClarabelCscMatrix_f64 *A, + const double *b, + uintptr_t n_cones, + const ClarabelSupportedConeT_f64 *cones, + const ClarabelDefaultSettings_f64 *settings); + +ClarabelDefaultSolver_f32 *clarabel_DefaultSolver_f32_new(const ClarabelCscMatrix_f32 *P, + const float *q, + const ClarabelCscMatrix_f32 *A, + const float *b, + uintptr_t n_cones, + const ClarabelSupportedConeT_f32 *cones, + const ClarabelDefaultSettings_f32 *settings); + +static inline ClarabelDefaultSolver *clarabel_DefaultSolver_new(const ClarabelCscMatrix *P, + const ClarabelFloat *q, + const ClarabelCscMatrix *A, + const ClarabelFloat *b, + uintptr_t n_cones, + const ClarabelSupportedConeT *cones, + const ClarabelDefaultSettings *settings) { #ifdef CLARABEL_USE_FLOAT return clarabel_DefaultSolver_f32_new(P, q, A, b, n_cones, cones, settings); diff --git a/include/c/SupportedConeT.h b/include/c/SupportedConeT.h index 28e3c78..c281234 100644 --- a/include/c/SupportedConeT.h +++ b/include/c/SupportedConeT.h @@ -38,12 +38,12 @@ typedef enum ClarabelSupportedConeT_Tag * The parameter indicates the power. */ ClarabelPowerConeT_Tag, - /** - * The positive semidefinite cone in triangular form. - * - * The parameter indicates the matrix dimension, i.e. size = n - * means that the variable is the upper triangle of an nxn matrix. - */ +/** + * The positive semidefinite cone in triangular form. + * + * The parameter indicates the matrix dimension, i.e. size = n + * means that the variable is the upper triangle of an nxn matrix. + */ #ifdef FEATURE_SDP ClarabelPSDTriangleConeT_Tag, #endif @@ -114,44 +114,42 @@ typedef ClarabelSupportedConeT_f64 ClarabelSupportedConeT; // Tagged union constructors // f64 -#define ClarabelZeroConeT_f64(size) \ +#define ClarabelZeroConeT_f64(size) \ ((ClarabelSupportedConeT_f64){ .tag = ClarabelZeroConeT_Tag, .zero_cone_t = (uintptr_t)(size) }) -#define ClarabelNonnegativeConeT_f64(size) \ - (ClarabelSupportedConeT_f64){ .tag = ClarabelNonnegativeConeT_Tag, .nonnegative_cone_t = (uintptr_t)(size) } +#define ClarabelNonnegativeConeT_f64(size) \ + (ClarabelSupportedConeT_f64) { .tag = ClarabelNonnegativeConeT_Tag, .nonnegative_cone_t = (uintptr_t)(size) } -#define ClarabelSecondOrderConeT_f64(size) \ +#define ClarabelSecondOrderConeT_f64(size) \ ((ClarabelSupportedConeT_f64){ .tag = ClarabelSecondOrderConeT_Tag, .second_order_cone_t = (uintptr_t)(size) }) -#define ClarabelExponentialConeT_f64() \ - ((ClarabelSupportedConeT_f64){ .tag = ClarabelExponentialConeT_Tag }) +#define ClarabelExponentialConeT_f64() ((ClarabelSupportedConeT_f64){ .tag = ClarabelExponentialConeT_Tag }) -#define ClarabelPowerConeT_f64(power) \ +#define ClarabelPowerConeT_f64(power) \ ((ClarabelSupportedConeT_f64){ .tag = ClarabelPowerConeT_Tag, .power_cone_t = (double)(power) }) #ifdef FEATURE_SDP -#define ClarabelPSDTriangleConeT_f64(size) \ +#define ClarabelPSDTriangleConeT_f64(size) \ ((ClarabelSupportedConeT_f64){ .tag = ClarabelPSDTriangleConeT_Tag, .psd_triangle_cone_t = (uintptr_t)(size) }) #endif // f32 -#define ClarabelZeroConeT_f32(size) \ +#define ClarabelZeroConeT_f32(size) \ ((ClarabelSupportedConeT_f32){ .tag = ClarabelZeroConeT_Tag, .zero_cone_t = (uintptr_t)(size) }) -#define ClarabelNonnegativeConeT_f32(size) \ - (ClarabelSupportedConeT_f32){ .tag = ClarabelNonnegativeConeT_Tag, .nonnegative_cone_t = (uintptr_t)(size) } +#define ClarabelNonnegativeConeT_f32(size) \ + (ClarabelSupportedConeT_f32) { .tag = ClarabelNonnegativeConeT_Tag, .nonnegative_cone_t = (uintptr_t)(size) } -#define ClarabelSecondOrderConeT_f32(size) \ +#define ClarabelSecondOrderConeT_f32(size) \ ((ClarabelSupportedConeT_f32){ .tag = ClarabelSecondOrderConeT_Tag, .second_order_cone_t = (uintptr_t)(size) }) -#define ClarabelExponentialConeT_f32() \ - ((ClarabelSupportedConeT_f32){ .tag = ClarabelExponentialConeT_Tag }) +#define ClarabelExponentialConeT_f32() ((ClarabelSupportedConeT_f32){ .tag = ClarabelExponentialConeT_Tag }) -#define ClarabelPowerConeT_f32(power) \ +#define ClarabelPowerConeT_f32(power) \ ((ClarabelSupportedConeT_f32){ .tag = ClarabelPowerConeT_Tag, .power_cone_t = (double)(power) }) #ifdef FEATURE_SDP -#define PSDTriangleConeT_f32(size) \ +#define PSDTriangleConeT_f32(size) \ ((ClarabelSupportedConeT_f32){ .tag = ClarabelPSDTriangleConeT_Tag, .psd_triangle_cone_t = (uintptr_t)(size) }) #endif diff --git a/include/cpp/CscMatrix.h b/include/cpp/CscMatrix.h index f0f0005..e6360a0 100644 --- a/include/cpp/CscMatrix.h +++ b/include/cpp/CscMatrix.h @@ -1,28 +1,27 @@ #pragma once #include -#include #include +#include namespace clarabel { - template - struct CscMatrix - { - static_assert(std::is_same::value || std::is_same::value, "T must be float or double"); - uintptr_t m; - uintptr_t n; - const uintptr_t* colptr; - const uintptr_t* rowval; - const T* nzval; +template +struct CscMatrix +{ + static_assert(std::is_same::value || std::is_same::value, "T must be float or double"); + + uintptr_t m; + uintptr_t n; + const uintptr_t *colptr; + const uintptr_t *rowval; + const T *nzval; + + CscMatrix(uintptr_t _m, uintptr_t _n, const uintptr_t *_colptr, const uintptr_t *_rowval, const T *_nzval) + : m(_m), n(_n), colptr(_colptr), rowval(_rowval), nzval(_nzval) + { + } +}; - CscMatrix( - uintptr_t _m, - uintptr_t _n, - const uintptr_t *_colptr, - const uintptr_t *_rowval, - const T *_nzval) - : m(_m), n(_n), colptr(_colptr), rowval(_rowval), nzval(_nzval) { } - }; -} \ No newline at end of file +} // namespace clarabel \ No newline at end of file diff --git a/include/cpp/DefaultSettings.h b/include/cpp/DefaultSettings.h index 9464539..16173d3 100644 --- a/include/cpp/DefaultSettings.h +++ b/include/cpp/DefaultSettings.h @@ -5,322 +5,316 @@ namespace clarabel { - enum class ClarabelDirectSolveMethods - { - QDLDL, - // MKL, (not supported in Rust yet) - // CHOLMOD, (not supported in Rust yet) - }; - - template - struct DefaultSettings - { - static_assert(std::is_same::value || std::is_same::value, "T must be float or double"); - - uint32_t max_iter; - double time_limit; - bool verbose; - T max_step_fraction; - T tol_gap_abs; - T tol_gap_rel; - T tol_feas; - T tol_infeas_abs; - T tol_infeas_rel; - T tol_ktratio; - T reduced_tol_gap_abs; - T reduced_tol_gap_rel; - T reduced_tol_feas; - T reduced_tol_infeas_abs; - T reduced_tol_infeas_rel; - T reduced_tol_ktratio; - bool equilibrate_enable; - uint32_t equilibrate_max_iter; - T equilibrate_min_scaling; - T equilibrate_max_scaling; - T linesearch_backtrack_step; - T min_switch_step_length; - T min_terminate_step_length; - bool direct_kkt_solver; - ClarabelDirectSolveMethods direct_solve_method; - bool static_regularization_enable; - T static_regularization_constant; - T static_regularization_proportional; - bool dynamic_regularization_enable; - T dynamic_regularization_eps; - T dynamic_regularization_delta; - bool iterative_refinement_enable; - T iterative_refinement_reltol; - T iterative_refinement_abstol; - uint32_t iterative_refinement_max_iter; - T iterative_refinement_stop_ratio; - bool presolve_enable; - - static DefaultSettings default_settings(); - }; - - // Instantiate the templates - template struct DefaultSettings; - template struct DefaultSettings; - - template - class DefaultSettingsBuilder - { - static_assert(std::is_same::value || std::is_same::value, "T must be float or double"); - private: - DefaultSettings settings; - DefaultSettingsBuilder() - { - settings = DefaultSettings::default_settings(); - } - - public: - static DefaultSettingsBuilder default_settings() - { - return DefaultSettingsBuilder(); - } - - DefaultSettings build() { return settings; } - - DefaultSettingsBuilder &max_iter(uint32_t max_iter) - { - settings.max_iter = max_iter; - return *this; - } - - DefaultSettingsBuilder &time_limit(double time_limit) - { - settings.time_limit = time_limit; - return *this; - } - - DefaultSettingsBuilder &verbose(bool verbose) - { - settings.verbose = verbose; - return *this; - } - - DefaultSettingsBuilder &max_step_fraction(T max_step_fraction) - { - settings.max_step_fraction = max_step_fraction; - return *this; - } - - DefaultSettingsBuilder &tol_gap_abs(T tol_gap_abs) - { - settings.tol_gap_abs = tol_gap_abs; - return *this; - } - - DefaultSettingsBuilder &tol_gap_rel(T tol_gap_rel) - { - settings.tol_gap_rel = tol_gap_rel; - return *this; - } - - DefaultSettingsBuilder &tol_feas(T tol_feas) - { - settings.tol_feas = tol_feas; - return *this; - } - - DefaultSettingsBuilder &tol_infeas_abs(T tol_infeas_abs) - { - settings.tol_infeas_abs = tol_infeas_abs; - return *this; - } - - DefaultSettingsBuilder &tol_infeas_rel(T tol_infeas_rel) - { - settings.tol_infeas_rel = tol_infeas_rel; - return *this; - } - - DefaultSettingsBuilder &tol_ktratio(T tol_ktratio) - { - settings.tol_ktratio = tol_ktratio; - return *this; - } - - DefaultSettingsBuilder &reduced_tol_gap_abs(T reduced_tol_gap_abs) - { - settings.reduced_tol_gap_abs = reduced_tol_gap_abs; - return *this; - } - - DefaultSettingsBuilder &reduced_tol_gap_rel(T reduced_tol_gap_rel) - { - settings.reduced_tol_gap_rel = reduced_tol_gap_rel; - return *this; - } - - DefaultSettingsBuilder &reduced_tol_feas(T reduced_tol_feas) - { - settings.reduced_tol_feas = reduced_tol_feas; - return *this; - } - - DefaultSettingsBuilder &reduced_tol_infeas_abs(T reduced_tol_infeas_abs) - { - settings.reduced_tol_infeas_abs = reduced_tol_infeas_abs; - return *this; - } - - DefaultSettingsBuilder &reduced_tol_infeas_rel(T reduced_tol_infeas_rel) - { - settings.reduced_tol_infeas_rel = reduced_tol_infeas_rel; - return *this; - } - - DefaultSettingsBuilder &reduced_tol_ktratio(T reduced_tol_ktratio) - { - settings.reduced_tol_ktratio = reduced_tol_ktratio; - return *this; - } - - DefaultSettingsBuilder &equilibrate_enable(bool equilibrate_enable) - { - settings.equilibrate_enable = equilibrate_enable; - return *this; - } - - DefaultSettingsBuilder &equilibrate_max_iter(uint32_t equilibrate_max_iter) - { - settings.equilibrate_max_iter = equilibrate_max_iter; - return *this; - } - - DefaultSettingsBuilder &equilibrate_min_scaling(T equilibrate_min_scaling) - { - settings.equilibrate_min_scaling = equilibrate_min_scaling; - return *this; - } - - DefaultSettingsBuilder &equilibrate_max_scaling(T equilibrate_max_scaling) - { - settings.equilibrate_max_scaling = equilibrate_max_scaling; - return *this; - } - - DefaultSettingsBuilder &linesearch_backtrack_step(T linesearch_backtrack_step) - { - settings.linesearch_backtrack_step = linesearch_backtrack_step; - return *this; - } - - DefaultSettingsBuilder &min_switch_step_length(T min_switch_step_length) - { - settings.min_switch_step_length = min_switch_step_length; - return *this; - } - - DefaultSettingsBuilder &min_terminate_step_length(T min_terminate_step_length) - { - settings.min_terminate_step_length = min_terminate_step_length; - return *this; - } - - DefaultSettingsBuilder &direct_kkt_solver(bool direct_kkt_solver) - { - settings.direct_kkt_solver = direct_kkt_solver; - return *this; - } - - DefaultSettingsBuilder &direct_solve_method(ClarabelDirectSolveMethods direct_solve_method) - { - settings.direct_solve_method = direct_solve_method; - return *this; - } - - DefaultSettingsBuilder &static_regularization_enable(bool static_regularization_enable) - { - settings.static_regularization_enable = static_regularization_enable; - return *this; - } - - DefaultSettingsBuilder &static_regularization_constant(T static_regularization_constant) - { - settings.static_regularization_constant = static_regularization_constant; - return *this; - } - - DefaultSettingsBuilder &static_regularization_proportional(T static_regularization_proportional) - { - settings.static_regularization_proportional = static_regularization_proportional; - return *this; - } - - DefaultSettingsBuilder &dynamic_regularization_enable(bool dynamic_regularization_enable) - { - settings.dynamic_regularization_enable = dynamic_regularization_enable; - return *this; - } - - DefaultSettingsBuilder &dynamic_regularization_eps(T dynamic_regularization_eps) - { - settings.dynamic_regularization_eps = dynamic_regularization_eps; - return *this; - } - - DefaultSettingsBuilder &dynamic_regularization_delta(T dynamic_regularization_delta) - { - settings.dynamic_regularization_delta = dynamic_regularization_delta; - return *this; - } - - DefaultSettingsBuilder &iterative_refinement_enable(bool iterative_refinement_enable) - { - settings.iterative_refinement_enable = iterative_refinement_enable; - return *this; - } - - DefaultSettingsBuilder &iterative_refinement_reltol(T iterative_refinement_reltol) - { - settings.iterative_refinement_reltol = iterative_refinement_reltol; - return *this; - } - - DefaultSettingsBuilder &iterative_refinement_abstol(T iterative_refinement_abstol) - { - settings.iterative_refinement_abstol = iterative_refinement_abstol; - return *this; - } - - DefaultSettingsBuilder &iterative_refinement_max_iter(uint32_t iterative_refinement_max_iter) - { - settings.iterative_refinement_max_iter = iterative_refinement_max_iter; - return *this; - } - - DefaultSettingsBuilder &iterative_refinement_stop_ratio(T iterative_refinement_stop_ratio) - { - settings.iterative_refinement_stop_ratio = iterative_refinement_stop_ratio; - return *this; - } - - DefaultSettingsBuilder &presolve_enable(bool presolve_enable) - { - settings.presolve_enable = presolve_enable; - return *this; - } - - }; - - extern "C" - { - DefaultSettings clarabel_DefaultSettings_f64_default(); - DefaultSettings clarabel_DefaultSettings_f32_default(); - } - - template<> - inline DefaultSettings DefaultSettings::default_settings() - { - return clarabel_DefaultSettings_f64_default(); - } - - template<> - inline DefaultSettings DefaultSettings::default_settings() - { - return clarabel_DefaultSettings_f32_default(); - } - -} \ No newline at end of file + +enum class ClarabelDirectSolveMethods +{ + QDLDL, + // MKL, (not supported in Rust yet) + // CHOLMOD, (not supported in Rust yet) +}; + +template +struct DefaultSettings +{ + static_assert(std::is_same::value || std::is_same::value, "T must be float or double"); + + uint32_t max_iter; + double time_limit; + bool verbose; + T max_step_fraction; + T tol_gap_abs; + T tol_gap_rel; + T tol_feas; + T tol_infeas_abs; + T tol_infeas_rel; + T tol_ktratio; + T reduced_tol_gap_abs; + T reduced_tol_gap_rel; + T reduced_tol_feas; + T reduced_tol_infeas_abs; + T reduced_tol_infeas_rel; + T reduced_tol_ktratio; + bool equilibrate_enable; + uint32_t equilibrate_max_iter; + T equilibrate_min_scaling; + T equilibrate_max_scaling; + T linesearch_backtrack_step; + T min_switch_step_length; + T min_terminate_step_length; + bool direct_kkt_solver; + ClarabelDirectSolveMethods direct_solve_method; + bool static_regularization_enable; + T static_regularization_constant; + T static_regularization_proportional; + bool dynamic_regularization_enable; + T dynamic_regularization_eps; + T dynamic_regularization_delta; + bool iterative_refinement_enable; + T iterative_refinement_reltol; + T iterative_refinement_abstol; + uint32_t iterative_refinement_max_iter; + T iterative_refinement_stop_ratio; + bool presolve_enable; + + static DefaultSettings default_settings(); +}; + +// Instantiate the templates +template struct DefaultSettings; +template struct DefaultSettings; + +template +class DefaultSettingsBuilder +{ + static_assert(std::is_same::value || std::is_same::value, "T must be float or double"); + + private: + DefaultSettings settings; + DefaultSettingsBuilder() { settings = DefaultSettings::default_settings(); } + + public: + static DefaultSettingsBuilder default_settings() { return DefaultSettingsBuilder(); } + + DefaultSettings build() { return settings; } + + DefaultSettingsBuilder &max_iter(uint32_t max_iter) + { + settings.max_iter = max_iter; + return *this; + } + + DefaultSettingsBuilder &time_limit(double time_limit) + { + settings.time_limit = time_limit; + return *this; + } + + DefaultSettingsBuilder &verbose(bool verbose) + { + settings.verbose = verbose; + return *this; + } + + DefaultSettingsBuilder &max_step_fraction(T max_step_fraction) + { + settings.max_step_fraction = max_step_fraction; + return *this; + } + + DefaultSettingsBuilder &tol_gap_abs(T tol_gap_abs) + { + settings.tol_gap_abs = tol_gap_abs; + return *this; + } + + DefaultSettingsBuilder &tol_gap_rel(T tol_gap_rel) + { + settings.tol_gap_rel = tol_gap_rel; + return *this; + } + + DefaultSettingsBuilder &tol_feas(T tol_feas) + { + settings.tol_feas = tol_feas; + return *this; + } + + DefaultSettingsBuilder &tol_infeas_abs(T tol_infeas_abs) + { + settings.tol_infeas_abs = tol_infeas_abs; + return *this; + } + + DefaultSettingsBuilder &tol_infeas_rel(T tol_infeas_rel) + { + settings.tol_infeas_rel = tol_infeas_rel; + return *this; + } + + DefaultSettingsBuilder &tol_ktratio(T tol_ktratio) + { + settings.tol_ktratio = tol_ktratio; + return *this; + } + + DefaultSettingsBuilder &reduced_tol_gap_abs(T reduced_tol_gap_abs) + { + settings.reduced_tol_gap_abs = reduced_tol_gap_abs; + return *this; + } + + DefaultSettingsBuilder &reduced_tol_gap_rel(T reduced_tol_gap_rel) + { + settings.reduced_tol_gap_rel = reduced_tol_gap_rel; + return *this; + } + + DefaultSettingsBuilder &reduced_tol_feas(T reduced_tol_feas) + { + settings.reduced_tol_feas = reduced_tol_feas; + return *this; + } + + DefaultSettingsBuilder &reduced_tol_infeas_abs(T reduced_tol_infeas_abs) + { + settings.reduced_tol_infeas_abs = reduced_tol_infeas_abs; + return *this; + } + + DefaultSettingsBuilder &reduced_tol_infeas_rel(T reduced_tol_infeas_rel) + { + settings.reduced_tol_infeas_rel = reduced_tol_infeas_rel; + return *this; + } + + DefaultSettingsBuilder &reduced_tol_ktratio(T reduced_tol_ktratio) + { + settings.reduced_tol_ktratio = reduced_tol_ktratio; + return *this; + } + + DefaultSettingsBuilder &equilibrate_enable(bool equilibrate_enable) + { + settings.equilibrate_enable = equilibrate_enable; + return *this; + } + + DefaultSettingsBuilder &equilibrate_max_iter(uint32_t equilibrate_max_iter) + { + settings.equilibrate_max_iter = equilibrate_max_iter; + return *this; + } + + DefaultSettingsBuilder &equilibrate_min_scaling(T equilibrate_min_scaling) + { + settings.equilibrate_min_scaling = equilibrate_min_scaling; + return *this; + } + + DefaultSettingsBuilder &equilibrate_max_scaling(T equilibrate_max_scaling) + { + settings.equilibrate_max_scaling = equilibrate_max_scaling; + return *this; + } + + DefaultSettingsBuilder &linesearch_backtrack_step(T linesearch_backtrack_step) + { + settings.linesearch_backtrack_step = linesearch_backtrack_step; + return *this; + } + + DefaultSettingsBuilder &min_switch_step_length(T min_switch_step_length) + { + settings.min_switch_step_length = min_switch_step_length; + return *this; + } + + DefaultSettingsBuilder &min_terminate_step_length(T min_terminate_step_length) + { + settings.min_terminate_step_length = min_terminate_step_length; + return *this; + } + + DefaultSettingsBuilder &direct_kkt_solver(bool direct_kkt_solver) + { + settings.direct_kkt_solver = direct_kkt_solver; + return *this; + } + + DefaultSettingsBuilder &direct_solve_method(ClarabelDirectSolveMethods direct_solve_method) + { + settings.direct_solve_method = direct_solve_method; + return *this; + } + + DefaultSettingsBuilder &static_regularization_enable(bool static_regularization_enable) + { + settings.static_regularization_enable = static_regularization_enable; + return *this; + } + + DefaultSettingsBuilder &static_regularization_constant(T static_regularization_constant) + { + settings.static_regularization_constant = static_regularization_constant; + return *this; + } + + DefaultSettingsBuilder &static_regularization_proportional(T static_regularization_proportional) + { + settings.static_regularization_proportional = static_regularization_proportional; + return *this; + } + + DefaultSettingsBuilder &dynamic_regularization_enable(bool dynamic_regularization_enable) + { + settings.dynamic_regularization_enable = dynamic_regularization_enable; + return *this; + } + + DefaultSettingsBuilder &dynamic_regularization_eps(T dynamic_regularization_eps) + { + settings.dynamic_regularization_eps = dynamic_regularization_eps; + return *this; + } + + DefaultSettingsBuilder &dynamic_regularization_delta(T dynamic_regularization_delta) + { + settings.dynamic_regularization_delta = dynamic_regularization_delta; + return *this; + } + + DefaultSettingsBuilder &iterative_refinement_enable(bool iterative_refinement_enable) + { + settings.iterative_refinement_enable = iterative_refinement_enable; + return *this; + } + + DefaultSettingsBuilder &iterative_refinement_reltol(T iterative_refinement_reltol) + { + settings.iterative_refinement_reltol = iterative_refinement_reltol; + return *this; + } + + DefaultSettingsBuilder &iterative_refinement_abstol(T iterative_refinement_abstol) + { + settings.iterative_refinement_abstol = iterative_refinement_abstol; + return *this; + } + + DefaultSettingsBuilder &iterative_refinement_max_iter(uint32_t iterative_refinement_max_iter) + { + settings.iterative_refinement_max_iter = iterative_refinement_max_iter; + return *this; + } + + DefaultSettingsBuilder &iterative_refinement_stop_ratio(T iterative_refinement_stop_ratio) + { + settings.iterative_refinement_stop_ratio = iterative_refinement_stop_ratio; + return *this; + } + + DefaultSettingsBuilder &presolve_enable(bool presolve_enable) + { + settings.presolve_enable = presolve_enable; + return *this; + } +}; + +extern "C" { +DefaultSettings clarabel_DefaultSettings_f64_default(); +DefaultSettings clarabel_DefaultSettings_f32_default(); +} + +template<> +inline DefaultSettings DefaultSettings::default_settings() +{ + return clarabel_DefaultSettings_f64_default(); +} + +template<> +inline DefaultSettings DefaultSettings::default_settings() +{ + return clarabel_DefaultSettings_f32_default(); +} + +} // namespace clarabel \ No newline at end of file diff --git a/include/cpp/DefaultSolution.h b/include/cpp/DefaultSolution.h index e2203ae..d675d7a 100644 --- a/include/cpp/DefaultSolution.h +++ b/include/cpp/DefaultSolution.h @@ -6,65 +6,62 @@ namespace clarabel { - enum class SolverStatus - { - Unsolved, - Solved, - PrimalInfeasible, - DualInfeasible, - AlmostSolved, - AlmostPrimalInfeasible, - AlmostDualInfeasible, - MaxIterations, - MaxTime, - NumericalError, - InsufficientProgress, - }; - template - class DefaultSolution - { - static_assert(std::is_same::value || std::is_same::value, "T must be float or double"); +enum class SolverStatus +{ + Unsolved, + Solved, + PrimalInfeasible, + DualInfeasible, + AlmostSolved, + AlmostPrimalInfeasible, + AlmostDualInfeasible, + MaxIterations, + MaxTime, + NumericalError, + InsufficientProgress, +}; - public: - struct ClarabelDefaultSolution - { - T *x; - uintptr_t x_length; - T *z; - uintptr_t z_length; - T *s; - uintptr_t s_length; - SolverStatus status; - T obj_val; - double solve_time; - uint32_t iterations; - T r_prim; - T r_dual; - }; +template +class DefaultSolution +{ + static_assert(std::is_same::value || std::is_same::value, "T must be float or double"); - Eigen::Map> x, z, s; + public: + struct ClarabelDefaultSolution + { + T *x; + uintptr_t x_length; + T *z; + uintptr_t z_length; + T *s; + uintptr_t s_length; SolverStatus status; T obj_val; double solve_time; uint32_t iterations; T r_prim; T r_dual; - - DefaultSolution(ClarabelDefaultSolution &solution) - : x(solution.x, solution.x_length), - z(solution.z, solution.z_length), - s(solution.s, solution.s_length), - status(solution.status), - solve_time(solution.solve_time), - iterations(solution.iterations), - r_prim(solution.r_prim), - r_dual(solution.r_dual) - { - } }; - // Instantiate the templates - template struct DefaultSolution; - template struct DefaultSolution; -} \ No newline at end of file + Eigen::Map> x, z, s; + SolverStatus status; + T obj_val; + double solve_time; + uint32_t iterations; + T r_prim; + T r_dual; + + DefaultSolution(ClarabelDefaultSolution &solution) + : x(solution.x, solution.x_length), z(solution.z, solution.z_length), s(solution.s, solution.s_length), + status(solution.status), solve_time(solution.solve_time), iterations(solution.iterations), + r_prim(solution.r_prim), r_dual(solution.r_dual) + { + } +}; + +// Instantiate the templates +template struct DefaultSolution; +template struct DefaultSolution; + +} // namespace clarabel \ No newline at end of file diff --git a/include/cpp/DefaultSolver.h b/include/cpp/DefaultSolver.h index fdb5594..8e50851 100644 --- a/include/cpp/DefaultSolver.h +++ b/include/cpp/DefaultSolver.h @@ -12,267 +12,253 @@ namespace clarabel { - using RustObjectHandle = void *; - using RustDefaultSolverHandle_f64 = RustObjectHandle; - using RustDefaultSolverHandle_f32 = RustObjectHandle; - template - class DefaultSolver - { - static_assert(std::is_same::value || std::is_same::value, "T must be float or double"); +using RustObjectHandle = void *; +using RustDefaultSolverHandle_f64 = RustObjectHandle; +using RustDefaultSolverHandle_f32 = RustObjectHandle; + +template +class DefaultSolver +{ + static_assert(std::is_same::value || std::is_same::value, "T must be float or double"); + + private: + struct ConvertedCscMatrix; - private: - struct ConvertedCscMatrix; - - RustObjectHandle handle = nullptr; + RustObjectHandle handle = nullptr; - // Helper function for converting a Eigen sparse matrix into a temporary object of type ConvertedCscMatrix - // The temporary object is used to provide the problem data for constructing the solver. - static ConvertedCscMatrix eigen_sparse_to_clarabel( - const Eigen::SparseMatrix &matrix) + // Helper function for converting a Eigen sparse matrix into a temporary object of type ConvertedCscMatrix + // The temporary object is used to provide the problem data for constructing the solver. + static ConvertedCscMatrix eigen_sparse_to_clarabel(const Eigen::SparseMatrix &matrix) + { + // Make a copy of data in SparseMatrix to convert StorageIndex to uintptr_t + std::vector row_indices(matrix.nonZeros()); + std::vector col_pointers(matrix.outerSize() + 1); + + // Convert to uintptr_t + for (int k = 0; k < matrix.nonZeros(); ++k) { - // Make a copy of data in SparseMatrix to convert StorageIndex to uintptr_t - std::vector row_indices(matrix.nonZeros()); - std::vector col_pointers(matrix.outerSize() + 1); - - // Convert to uintptr_t - for (int k = 0; k < matrix.nonZeros(); ++k) - { - row_indices[k] = matrix.innerIndexPtr()[k]; - } - for (int k = 0; k < matrix.outerSize(); ++k) - { - col_pointers[k] = matrix.outerIndexPtr()[k]; - } - col_pointers[matrix.outerSize()] = matrix.nonZeros(); - - // No conversion needed for nz values - const T *nzval_ptr = matrix.nonZeros() == 0 ? nullptr : matrix.valuePtr(); - - ConvertedCscMatrix csc_matrix( - static_cast(matrix.rows()), - static_cast(matrix.cols()), - std::move(col_pointers), - std::move(row_indices), - nzval_ptr); - - return std::move(csc_matrix); + row_indices[k] = matrix.innerIndexPtr()[k]; } - - static void check_dimensions( - const Eigen::SparseMatrix &P, - const Eigen::Ref> &q, - const Eigen::SparseMatrix &A, - const Eigen::Ref> &b, - const std::vector> &cones) + for (int k = 0; k < matrix.outerSize(); ++k) { - if (P.rows() != P.cols()) - { - throw std::invalid_argument("P must be a square matrix"); - } - - if (P.rows() != q.size()) - { - throw std::invalid_argument("P and q must have the same number of rows"); - } - - if (A.cols() != P.cols()) - { - throw std::invalid_argument("A and P must have the same number of columns"); - } - - if (A.rows() != b.size()) - { - throw std::invalid_argument("A and b must have the same number of rows"); - } - - unsigned int p = 0; - for (const auto &cone : cones) - { - p += cone.nvars(); - } - if (p != b.size()) - { - throw std::invalid_argument("Constraint dimensions inconsistent with size of cones"); - } + col_pointers[k] = matrix.outerIndexPtr()[k]; } + col_pointers[matrix.outerSize()] = matrix.nonZeros(); - public: - // Lifetime of problem data: matrices P, A, vectors q, b, cones and the settings are copied when the DefaultSolver object is created in Rust. - // Eigen::SparseMatrix objects need to be converted to the format supported by Clarabel. Since the problem data is copied, the converted data exists as local variables in the constructor and is not stored as part of this class. - DefaultSolver( - const Eigen::SparseMatrix &P, - const Eigen::Ref> &q, - const Eigen::SparseMatrix &A, - const Eigen::Ref> &b, - const std::vector> &cones, - const DefaultSettings &settings); - - ~DefaultSolver(); + // No conversion needed for nz values + const T *nzval_ptr = matrix.nonZeros() == 0 ? nullptr : matrix.valuePtr(); - void solve(); + ConvertedCscMatrix csc_matrix(static_cast(matrix.rows()), static_cast(matrix.cols()), + std::move(col_pointers), std::move(row_indices), nzval_ptr); - // The solution can only be obtained when the solver is in the Solved state, and the DefaultSolution object is only valid when the solver is alive. - DefaultSolution solution() const; - DefaultInfo info() const; - }; + return std::move(csc_matrix); + } - template - struct DefaultSolver::ConvertedCscMatrix + static void check_dimensions(const Eigen::SparseMatrix &P, + const Eigen::Ref> &q, + const Eigen::SparseMatrix &A, + const Eigen::Ref> &b, + const std::vector> &cones) { - uintptr_t m; - uintptr_t n; - const std::vector colptr; - const std::vector rowval; - const T *nzval; - - ConvertedCscMatrix( - uintptr_t m, - uintptr_t n, - std::vector &&colptr, - std::vector &&rowval, - const T *nzval) - : m(m), n(n), - colptr(std::move(colptr)), - rowval(std::move(rowval)), - nzval(nzval) + if (P.rows() != P.cols()) { + throw std::invalid_argument("P must be a square matrix"); } - }; - - extern "C" - { - RustDefaultSolverHandle_f64 clarabel_DefaultSolver_f64_new( - const CscMatrix *P, - const double *q, - const CscMatrix *A, - const double *b, - uintptr_t n_cones, - const SupportedConeT *cones, - const DefaultSettings *settings); - - RustDefaultSolverHandle_f32 clarabel_DefaultSolver_f32_new( - const CscMatrix *P, - const float *q, - const CscMatrix *A, - const float *b, - uintptr_t n_cones, - const SupportedConeT *cones, - const DefaultSettings *settings); - - void clarabel_DefaultSolver_f64_solve(RustDefaultSolverHandle_f64 solver); - - void clarabel_DefaultSolver_f32_solve(RustDefaultSolverHandle_f32 solver); - - void clarabel_DefaultSolver_f64_free(RustDefaultSolverHandle_f64 solver); - void clarabel_DefaultSolver_f32_free(RustDefaultSolverHandle_f32 solver); - - DefaultSolution::ClarabelDefaultSolution clarabel_DefaultSolver_f64_solution(RustDefaultSolverHandle_f64 solver); + if (P.rows() != q.size()) + { + throw std::invalid_argument("P and q must have the same number of rows"); + } - DefaultSolution::ClarabelDefaultSolution clarabel_DefaultSolver_f32_solution(RustDefaultSolverHandle_f32 solver); + if (A.cols() != P.cols()) + { + throw std::invalid_argument("A and P must have the same number of columns"); + } - DefaultInfo clarabel_DefaultSolver_f64_info(RustDefaultSolverHandle_f64 solver); + if (A.rows() != b.size()) + { + throw std::invalid_argument("A and b must have the same number of rows"); + } - DefaultInfo clarabel_DefaultSolver_f32_info(RustDefaultSolverHandle_f32 solver); + unsigned int p = 0; + for (const auto &cone : cones) + { + p += cone.nvars(); + } + if (p != b.size()) + { + throw std::invalid_argument("Constraint dimensions inconsistent with size of cones"); + } } - // Convert unique_ptr P, A to CscMatrix objects, then init the solver - // The CscMatrix objects are only used to pass the information needed to Rust. - // The colptr and rowptr are stored in the ConvertedCscMatrix objects, which are kept alive by the unique_ptr. - // No conversion is needed for nzval, so the Eigen sparse matrices must be kept alive until the solver is destroyed. - template<> - inline DefaultSolver::DefaultSolver( - const Eigen::SparseMatrix &P, - const Eigen::Ref> &q, - const Eigen::SparseMatrix &A, - const Eigen::Ref> &b, - const std::vector> &cones, - const DefaultSettings &settings) + public: + // Lifetime of problem data: matrices P, A, vectors q, b, cones and the settings are copied when the DefaultSolver + // object is created in Rust. Eigen::SparseMatrix objects need to be converted to the format supported by Clarabel. + // Since the problem data is copied, the converted data exists as local variables in the constructor and is not + // stored as part of this class. + DefaultSolver(const Eigen::SparseMatrix &P, + const Eigen::Ref> &q, + const Eigen::SparseMatrix &A, + const Eigen::Ref> &b, + const std::vector> &cones, + const DefaultSettings &settings); + + ~DefaultSolver(); + + void solve(); + + // The solution can only be obtained when the solver is in the Solved state, and the DefaultSolution object is only + // valid when the solver is alive. + DefaultSolution solution() const; + DefaultInfo info() const; +}; + +template +struct DefaultSolver::ConvertedCscMatrix +{ + uintptr_t m; + uintptr_t n; + const std::vector colptr; + const std::vector rowval; + const T *nzval; + + ConvertedCscMatrix( + uintptr_t m, uintptr_t n, std::vector &&colptr, std::vector &&rowval, const T *nzval) + : m(m), n(n), colptr(std::move(colptr)), rowval(std::move(rowval)), nzval(nzval) { - check_dimensions(P, q, A, b, cones); // Rust wrapper will assume the pointers represent matrices with the right dimensions. - - // segfault will occur if the dimensions are incorrect - ConvertedCscMatrix matrix_P = DefaultSolver::eigen_sparse_to_clarabel(P); - ConvertedCscMatrix matrix_A = DefaultSolver::eigen_sparse_to_clarabel(A); - CscMatrix p(matrix_P.m, matrix_P.n, matrix_P.colptr.data(), matrix_P.rowval.data(), matrix_P.nzval); - CscMatrix a(matrix_A.m, matrix_A.n, matrix_A.colptr.data(), matrix_A.rowval.data(), matrix_A.nzval); - - this->handle = clarabel_DefaultSolver_f64_new(&p, q.data(), &a, b.data(), cones.size(), cones.data(), &settings); } +}; + +extern "C" { +RustDefaultSolverHandle_f64 clarabel_DefaultSolver_f64_new(const CscMatrix *P, + const double *q, + const CscMatrix *A, + const double *b, + uintptr_t n_cones, + const SupportedConeT *cones, + const DefaultSettings *settings); + +RustDefaultSolverHandle_f32 clarabel_DefaultSolver_f32_new(const CscMatrix *P, + const float *q, + const CscMatrix *A, + const float *b, + uintptr_t n_cones, + const SupportedConeT *cones, + const DefaultSettings *settings); + +void clarabel_DefaultSolver_f64_solve(RustDefaultSolverHandle_f64 solver); + +void clarabel_DefaultSolver_f32_solve(RustDefaultSolverHandle_f32 solver); + +void clarabel_DefaultSolver_f64_free(RustDefaultSolverHandle_f64 solver); + +void clarabel_DefaultSolver_f32_free(RustDefaultSolverHandle_f32 solver); + +DefaultSolution::ClarabelDefaultSolution +clarabel_DefaultSolver_f64_solution(RustDefaultSolverHandle_f64 solver); + +DefaultSolution::ClarabelDefaultSolution clarabel_DefaultSolver_f32_solution(RustDefaultSolverHandle_f32 solver); + +DefaultInfo clarabel_DefaultSolver_f64_info(RustDefaultSolverHandle_f64 solver); + +DefaultInfo clarabel_DefaultSolver_f32_info(RustDefaultSolverHandle_f32 solver); +} + +// Convert unique_ptr P, A to CscMatrix objects, then init the solver +// The CscMatrix objects are only used to pass the information needed to Rust. +// The colptr and rowptr are stored in the ConvertedCscMatrix objects, which are kept alive by the unique_ptr. +// No conversion is needed for nzval, so the Eigen sparse matrices must be kept alive until the solver is destroyed. +template<> +inline DefaultSolver::DefaultSolver(const Eigen::SparseMatrix &P, + const Eigen::Ref> &q, + const Eigen::SparseMatrix &A, + const Eigen::Ref> &b, + const std::vector> &cones, + const DefaultSettings &settings) +{ + // Rust wrapper will assume the pointers represent matrices with the right dimensions. + // segfault will occur if the dimensions are incorrect + check_dimensions(P, q, A, b, cones); + + ConvertedCscMatrix matrix_P = DefaultSolver::eigen_sparse_to_clarabel(P); + ConvertedCscMatrix matrix_A = DefaultSolver::eigen_sparse_to_clarabel(A); + CscMatrix p(matrix_P.m, matrix_P.n, matrix_P.colptr.data(), matrix_P.rowval.data(), matrix_P.nzval); + CscMatrix a(matrix_A.m, matrix_A.n, matrix_A.colptr.data(), matrix_A.rowval.data(), matrix_A.nzval); + + this->handle = clarabel_DefaultSolver_f64_new(&p, q.data(), &a, b.data(), cones.size(), cones.data(), &settings); +} + +template<> +inline DefaultSolver::DefaultSolver(const Eigen::SparseMatrix &P, + const Eigen::Ref> &q, + const Eigen::SparseMatrix &A, + const Eigen::Ref> &b, + const std::vector> &cones, + const DefaultSettings &settings) +{ + // Rust wrapper will assume the pointers represent matrices with the right dimensions. + // segfault will occur if the dimensions are incorrect + check_dimensions(P, q, A, b, cones); - template<> - inline DefaultSolver::DefaultSolver( - const Eigen::SparseMatrix &P, - const Eigen::Ref> &q, - const Eigen::SparseMatrix &A, - const Eigen::Ref> &b, - const std::vector> &cones, - const DefaultSettings &settings) - { - check_dimensions(P, q, A, b, cones); // Rust wrapper will assume the pointers represent matrices with the right dimensions. - - // segfault will occur if the dimensions are incorrect - ConvertedCscMatrix matrix_P = DefaultSolver::eigen_sparse_to_clarabel(P); - ConvertedCscMatrix matrix_A = DefaultSolver::eigen_sparse_to_clarabel(A); - CscMatrix p(matrix_P.m, matrix_P.n, matrix_P.colptr.data(), matrix_P.rowval.data(), matrix_P.nzval); - CscMatrix a(matrix_A.m, matrix_A.n, matrix_A.colptr.data(), matrix_A.rowval.data(), matrix_A.nzval); - - this->handle = clarabel_DefaultSolver_f32_new(&p, q.data(), &a, b.data(), cones.size(), cones.data(), &settings); - } + ConvertedCscMatrix matrix_P = DefaultSolver::eigen_sparse_to_clarabel(P); + ConvertedCscMatrix matrix_A = DefaultSolver::eigen_sparse_to_clarabel(A); + CscMatrix p(matrix_P.m, matrix_P.n, matrix_P.colptr.data(), matrix_P.rowval.data(), matrix_P.nzval); + CscMatrix a(matrix_A.m, matrix_A.n, matrix_A.colptr.data(), matrix_A.rowval.data(), matrix_A.nzval); - template<> - inline DefaultSolver::~DefaultSolver() - { - if (handle != nullptr) // handle is null when an exception is thrown in the constructor - clarabel_DefaultSolver_f64_free(handle); - } + this->handle = clarabel_DefaultSolver_f32_new(&p, q.data(), &a, b.data(), cones.size(), cones.data(), &settings); +} - template<> - inline DefaultSolver::~DefaultSolver() - { - if (handle != nullptr) - clarabel_DefaultSolver_f32_free(handle); - } +template<> +inline DefaultSolver::~DefaultSolver() +{ + if (handle != nullptr) // handle is null when an exception is thrown in the constructor + clarabel_DefaultSolver_f64_free(handle); +} - - template<> - inline void DefaultSolver::solve() - { - clarabel_DefaultSolver_f64_solve(handle); - } +template<> +inline DefaultSolver::~DefaultSolver() +{ + if (handle != nullptr) + clarabel_DefaultSolver_f32_free(handle); +} - template<> - inline void DefaultSolver::solve() - { - clarabel_DefaultSolver_f32_solve(handle); - } +template<> +inline void DefaultSolver::solve() +{ + clarabel_DefaultSolver_f64_solve(handle); +} +template<> +inline void DefaultSolver::solve() +{ + clarabel_DefaultSolver_f32_solve(handle); +} - template<> - inline DefaultSolution DefaultSolver::solution() const - { - auto solution = clarabel_DefaultSolver_f64_solution(handle); - return std::move(DefaultSolution(solution)); - } +template<> +inline DefaultSolution DefaultSolver::solution() const +{ + auto solution = clarabel_DefaultSolver_f64_solution(handle); + return std::move(DefaultSolution(solution)); +} - template<> - inline DefaultSolution DefaultSolver::solution() const - { - auto solution = clarabel_DefaultSolver_f32_solution(handle); - return std::move(DefaultSolution(solution)); - } +template<> +inline DefaultSolution DefaultSolver::solution() const +{ + auto solution = clarabel_DefaultSolver_f32_solution(handle); + return std::move(DefaultSolution(solution)); +} - template<> - inline DefaultInfo DefaultSolver::info() const - { - return clarabel_DefaultSolver_f64_info(handle); - } +template<> +inline DefaultInfo DefaultSolver::info() const +{ + return clarabel_DefaultSolver_f64_info(handle); +} - template<> - inline DefaultInfo DefaultSolver::info() const - { - return clarabel_DefaultSolver_f32_info(handle); - } +template<> +inline DefaultInfo DefaultSolver::info() const +{ + return clarabel_DefaultSolver_f32_info(handle); +} } // namespace clarabel \ No newline at end of file diff --git a/include/cpp/SupportedConeT.h b/include/cpp/SupportedConeT.h index 3b117ef..cb9204a 100644 --- a/include/cpp/SupportedConeT.h +++ b/include/cpp/SupportedConeT.h @@ -6,151 +6,167 @@ namespace clarabel { - // Provides the layout for SupportedConeT objects in Rust - // Base type of all cones - template - struct SupportedConeT - { - static_assert(std::is_same::value || std::is_same::value, "T must be float or double"); - public: - // Tag for the type of the cone - enum class Tag - { - ZeroConeT, - NonnegativeConeT, - SecondOrderConeT, - ExponentialConeT, - PowerConeT, +// Provides the layout for SupportedConeT objects in Rust +// Base type of all cones +template +struct SupportedConeT +{ + static_assert(std::is_same::value || std::is_same::value, "T must be float or double"); + + public: + // Tag for the type of the cone + enum class Tag + { + ZeroConeT, + NonnegativeConeT, + SecondOrderConeT, + ExponentialConeT, + PowerConeT, #ifdef FEATURE_SDP - PSDTriangleConeT, + PSDTriangleConeT, #endif - }; - Tag tag; - - protected: - struct ZeroConeT_Body { uintptr_t _0; }; - struct NonnegativeConeT_Body { uintptr_t _0; }; - struct SecondOrderConeT_Body { uintptr_t _0; }; - struct ExponentialConeT_Body {}; - struct PowerConeT_Body { T _0; }; + }; + Tag tag; + + protected: + struct ZeroConeT_Body + { + uintptr_t _0; + }; + struct NonnegativeConeT_Body + { + uintptr_t _0; + }; + struct SecondOrderConeT_Body + { + uintptr_t _0; + }; + struct ExponentialConeT_Body + { + }; + struct PowerConeT_Body + { + T _0; + }; #ifdef FEATURE_SDP - struct PSDTriangleConeT_Body { uintptr_t _0; }; + struct PSDTriangleConeT_Body + { + uintptr_t _0; + }; #endif - // Data - union { - ZeroConeT_Body zero_cone_t; - NonnegativeConeT_Body nonnegative_cone_t; - SecondOrderConeT_Body second_order_cone_t; - ExponentialConeT_Body exponential_cone_t; - PowerConeT_Body power_cone_t; + // Data + union + { + ZeroConeT_Body zero_cone_t; + NonnegativeConeT_Body nonnegative_cone_t; + SecondOrderConeT_Body second_order_cone_t; + ExponentialConeT_Body exponential_cone_t; + PowerConeT_Body power_cone_t; #ifdef FEATURE_SDP - PSDTriangleConeT_Body psd_triangle_cone_t; + PSDTriangleConeT_Body psd_triangle_cone_t; #endif - }; + }; - public: - unsigned int nvars() const + public: + unsigned int nvars() const + { + switch (this->tag) { - switch (this->tag) - { - case Tag::ZeroConeT: - return this->zero_cone_t._0; - case Tag::NonnegativeConeT: - return this->nonnegative_cone_t._0; - case Tag::SecondOrderConeT: - return this->second_order_cone_t._0; - case Tag::ExponentialConeT: - return 3; - case Tag::PowerConeT: - return 3; + case Tag::ZeroConeT: + return this->zero_cone_t._0; + case Tag::NonnegativeConeT: + return this->nonnegative_cone_t._0; + case Tag::SecondOrderConeT: + return this->second_order_cone_t._0; + case Tag::ExponentialConeT: + return 3; + case Tag::PowerConeT: + return 3; #ifdef FEATURE_SDP - case Tag::PSDTriangleConeT: - { - unsigned int k = this->psd_triangle_cone_t._0; - return (k * (k + 1)) >> 1; - } + case Tag::PSDTriangleConeT: { + unsigned int k = this->psd_triangle_cone_t._0; + return (k * (k + 1)) >> 1; + } #endif - default: - throw std::invalid_argument("Invalid cone type"); - } + default: + throw std::invalid_argument("Invalid cone type"); } - }; + } +}; - template - struct ZeroConeT : public SupportedConeT +template +struct ZeroConeT : public SupportedConeT +{ + public: + ZeroConeT(uintptr_t dimension) { - public: - ZeroConeT(uintptr_t dimension) - { - this->tag = SupportedConeT::Tag::ZeroConeT; - this->nonnegative_cone_t = { dimension }; - } + this->tag = SupportedConeT::Tag::ZeroConeT; + this->nonnegative_cone_t = { dimension }; + } - uintptr_t dimension() const { return this->nonnegative_cone_t._0; } - }; + uintptr_t dimension() const { return this->nonnegative_cone_t._0; } +}; - template - struct NonnegativeConeT : public SupportedConeT +template +struct NonnegativeConeT : public SupportedConeT +{ + public: + NonnegativeConeT(uintptr_t dimension) { - public: - NonnegativeConeT(uintptr_t dimension) - { - this->tag = SupportedConeT::Tag::NonnegativeConeT; - this->zero_cone_t = { dimension }; - } + this->tag = SupportedConeT::Tag::NonnegativeConeT; + this->zero_cone_t = { dimension }; + } - uintptr_t dimension() const { return this->zero_cone_t._0; } - }; + uintptr_t dimension() const { return this->zero_cone_t._0; } +}; - template - struct SecondOrderConeT : public SupportedConeT +template +struct SecondOrderConeT : public SupportedConeT +{ + public: + SecondOrderConeT(uintptr_t dimension) { - public: - SecondOrderConeT(uintptr_t dimension) - { - this->tag = SupportedConeT::Tag::SecondOrderConeT; - this->second_order_cone_t = { dimension }; - } + this->tag = SupportedConeT::Tag::SecondOrderConeT; + this->second_order_cone_t = { dimension }; + } - T dimension() const { return this->second_order_cone_t._0; } - }; + T dimension() const { return this->second_order_cone_t._0; } +}; - template - struct ExponentialConeT : public SupportedConeT - { - public: - ExponentialConeT() - { - this->tag = SupportedConeT::Tag::ExponentialConeT; - } - }; +template +struct ExponentialConeT : public SupportedConeT +{ + public: + ExponentialConeT() { this->tag = SupportedConeT::Tag::ExponentialConeT; } +}; - template - struct PowerConeT : public SupportedConeT +template +struct PowerConeT : public SupportedConeT +{ + public: + PowerConeT(T power) { - public: - PowerConeT(T power) - { - this->tag = SupportedConeT::Tag::PowerConeT; - this->power_cone_t = { power }; - } + this->tag = SupportedConeT::Tag::PowerConeT; + this->power_cone_t = { power }; + } - T power() const { return this->power_cone_t._0; } - }; + T power() const { return this->power_cone_t._0; } +}; #ifdef FEATURE_SDP - template - struct PSDTriangleConeT : public SupportedConeT +template +struct PSDTriangleConeT : public SupportedConeT +{ + public: + PSDTriangleConeT(uintptr_t dimension) { - public: - PSDTriangleConeT(uintptr_t dimension) - { - this->tag = SupportedConeT::Tag::PSDTriangleConeT; - this->psd_triangle_cone_t = { dimension }; - } + this->tag = SupportedConeT::Tag::PSDTriangleConeT; + this->psd_triangle_cone_t = { dimension }; + } - T dimension() const { return this->psd_triangle_cone_t._0; } - }; + T dimension() const { return this->psd_triangle_cone_t._0; } +}; #endif -} \ No newline at end of file + +} // namespace clarabel \ No newline at end of file