Skip to content

Commit f957a06

Browse files
committed
v0.11.1
2 parents b5183ff + dffde9c commit f957a06

8 files changed

Lines changed: 159 additions & 99 deletions

File tree

README.md

Lines changed: 22 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ __Clarabel.cpp__ is a C/C++ wrapper of [Clarabel.rs](https://github.com/oxfordco
1919

2020
# Installation
2121

22-
> **Note:** The C++ interface is WIP and there might be breaking changes in future releases.
23-
2422
Clarabel.cpp uses CMake to generate the build system and requires the following dependencies:
2523

2624
- Rust
@@ -53,7 +51,7 @@ git clone --recurse-submodules https://github.com/oxfordcontrol/Clarabel.cpp.git
5351
cd Clarabel.cpp
5452
```
5553

56-
## Build
54+
## Building the solver
5755

5856
```sh
5957
mkdir build
@@ -82,51 +80,39 @@ where `VCPKG_TOOLCHAIN_PATH` is the path to the vcpkg toolchain file.
8280

8381
- For 32-bit platforms, use `x86-windows` instead of `x64-windows`.
8482

85-
## CMake options
86-
87-
### SDP support
88-
89-
To enable SDP features, set the `-DCLARABEL_FEATURE_SDP` option to one of the following values:
90-
- `sdp-accelerate`
91-
- `sdp-netlib`
92-
- `sdp-openblas`
93-
- `sdp-mkl`
94-
- `sdp-r`
95-
96-
By default, `-DCLARABEL_FEATURE_SDP=none` and SDP support is disabled.
97-
98-
### JSON file input/output support
99-
100-
To enable reading and writing of problem data to JSON files, set
101-
`-DCLARABEL_FEATURE_SERDE=true`.
102-
103-
When reporting issues with the solver, it can be helpful to provide a JSON file that reproduces the problem.
104-
105-
### Alternative linear algebra libraries
106-
107-
To enable the [faer-rs](https://faer-rs.github.io/) sparse linear algebra library as an additional solver option, set `-DCLARABEL_FEATURE_FAER_SPARSE=true`.
108-
109-
To enable the [`MKL Pardiso`](https://www.intel.com/content/www/us/en/docs/onemkl/developer-reference-c/) sparse linear algebra library as an additional solver option, set `-DCLARABEL_FEATURE_PARDISO_MKL=true`.
83+
## Optional solver features
11084

111-
The solver will dynamically link to the MKL library, which must be accessible via the system library path (e.g. on `LD_LIBRARY_PATH` on Linux).
85+
Clarabel.rs supports a variety of build options for semidefinite program (SDP) support, JSON file read/write, 3rd party linear solvers etc. Feature options can be passed to cargo via CMake using `-DCLARABEL_RUST_FEATURES = "feature1,feature2,..."`.
11286

113-
Alternatively, set the `MKLROOT` environment variable to the root of the MKL installation or `MKL_PARDISO_PATH` to the location of the MKL Pardiso library (e.g. the location of `libmkl_rt.so` in Linux).
87+
| Feature | Description |
88+
|---------|-------------|
89+
| `serde` | enables read/write of problem instances to .json files (enabled by default) |
90+
| `faer-sparse` | enables "faer" as an optional direct_solve_method |
91+
| `pardiso-mkl` | enables "mkl" as an optional direct_solve_method (Intel only) |
92+
| `pardiso-panua` | enables "panua" as an optional direct_solve_method (requires separate license) |
93+
| `pardiso` | enables both the "mkl" and "panua" options |
94+
| `sdp-accelerate` | enables solution of SDPs using Apple's "accelerate" BLAS/LAPACK implementation (OSX only) |
95+
| `sdp-mkl` | enables solution of SDPs using Intel's BLAS/LAPACK implementation (Intel only) |
96+
| `sdp-openblas` | enables solution of SDPs using OpenBlas |
97+
| `sdp-netlib` | enables solution of SDPs using the Netlib reference BLAS/LAPACK (not recommended) |
98+
| `buildinfo` | adds a buildinfo function to the package that reports on the build configuration |
11499

115-
To enable the [`Panua Pardiso`](https://panua.ch/pardiso/) sparse linear algebra library as an additional solver option, set `-DCLARABEL_FEATURE_PARDISO_PANUA=true`. This library is not open source and requires a license.
100+
### Linking to Pardiso
101+
To enable dynamic linking to MKL Pardiso, the MKL Pardiso libary (e.g. `libmkl_rt.so`) must be on the system library path (e.g. on `LD_LIBRARY_PATH` on Linux). Alternatively, set the `MKLROOT` environment variable to the root of the MKL installation or `MKL_PARDISO_PATH` to the location of the library. The Intel MKL library is available as part of the Intel oneAPI toolkit and is only available on x86_64 platforms.
116102

117-
The solver will dynamically link to the Panua Pardiso library, which must be accessible via the system library path (e.g. on `LD_LIBRARY_PATH` on Linux).
103+
To enable dynamic linking to Panua Pardiso, the Panua Pardiso library (e.g. `libpardiso.so`) must be on the system library path (e.g. on `LD_LIBRARY_PATH` on Linux). Alternatively, set the `PARDISO_PATH` environment variable to the location of the library.
118104

119-
Alternatively, set the `PARDISO_PATH` environment variable to the location of the Panua Pardiso library (e.g. the location of `libpardiso.so` in Linux).
105+
Panua Pardiso is a commercial solver and requires a separate license.
120106

121-
### Unit tests
107+
## Unit tests
122108

123109
By default, unit tests are disabled to reduce build time. To enable unit tests, set `-DCLARABEL_BUILD_TESTS=true` in cmake.
124110

125-
### Release mode
111+
## Release mode
126112

127113
The solver will build the Rust source in debug mode. To build in release mode, set `-DCMAKE_BUILD_TYPE=Release` in cmake.
128114

129-
## Run examples
115+
## Running examples
130116

131117
Examples for both C and C++ are available in `examples/c` and `examples/cpp` and can be run from the `build` directory using:
132118

rust_wrapper/CMakeLists.txt

Lines changed: 110 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -18,82 +18,149 @@ endif()
1818

1919
set(CLARABEL_C_OUTPUT_DIR ${clarabel_c_output_directory} PARENT_SCOPE)
2020

21+
if(NOT DEFINED CLARABEL_RUST_FEATURES)
22+
set(CLARABEL_RUST_FEATURES "")
23+
endif()
24+
25+
# -------------------------------------
26+
# Cargo feature configuration helper functions
27+
#--------------------------------------
28+
29+
# Check if CLARABEL_RUST_FEATURES contains a specific feature
30+
function(rust_feature_is_enabled PATTERN RESULT_VAR)
31+
string(REPLACE "," ";" FEATURE_LIST "${CLARABEL_RUST_FEATURES}")
32+
set(${RESULT_VAR} FALSE PARENT_SCOPE)
33+
foreach(FEATURE ${FEATURE_LIST})
34+
if(FEATURE MATCHES "${PATTERN}")
35+
set(${RESULT_VAR} TRUE PARENT_SCOPE)
36+
break()
37+
endif()
38+
endforeach()
39+
endfunction()
40+
41+
# Check if CLARABEL_RUST_FEATURES contains any of the "sdp" options
42+
function(rust_features_has_sdp RESULT_VAR)
43+
if(CLARABEL_RUST_FEATURES MATCHES ".*sdp.*")
44+
set(${RESULT_VAR} TRUE PARENT_SCOPE)
45+
else()
46+
set(${RESULT_VAR} FALSE PARENT_SCOPE)
47+
endif()
48+
endfunction()
49+
50+
# Helper function to append a feature to a comma-separated list
51+
function(append_feature FEATURE_LIST_VAR NEW_FEATURE)
52+
if(${FEATURE_LIST_VAR} STREQUAL "")
53+
set(${FEATURE_LIST_VAR} "${NEW_FEATURE}" PARENT_SCOPE)
54+
else()
55+
set(${FEATURE_LIST_VAR} "${${FEATURE_LIST_VAR}},${NEW_FEATURE}" PARENT_SCOPE)
56+
endif()
57+
endfunction()
58+
59+
# Automatically prefix features with 'clarabel/' if not already prefixed
60+
# For serde, add it as both clarabel/serde and serde, with the latter
61+
# necessary for the rust_wrapper cargo configuration.
62+
63+
function(format_clarabel_rust_features INPUT_FEATURES OUTPUT_VAR)
64+
string(REPLACE "," ";" FEATURE_LIST "${INPUT_FEATURES}")
65+
set(FORMATTED_FEATURES "")
66+
foreach(FEATURE ${FEATURE_LIST})
67+
# Regular handling: prefix with clarabel/ if not already prefixed
68+
if(NOT FEATURE MATCHES "^clarabel/")
69+
set(FEATURE "clarabel/${FEATURE}")
70+
endif()
71+
append_feature(FORMATTED_FEATURES "${FEATURE}")
72+
endforeach()
73+
set(${OUTPUT_VAR} "${FORMATTED_FEATURES}" PARENT_SCOPE)
74+
endfunction()
75+
2176

2277
# -------------------------------------
23-
# Cargo features configuration
78+
# Cargo feature configuration backward compatibility
2479
#--------------------------------------
2580

26-
# A list of features to pass to rustc
27-
set(CLARABEL_BUILD_FEATURES "")
2881

29-
# SDP feature flag
3082
if(NOT CLARABEL_FEATURE_SDP STREQUAL "none")
83+
append_feature(CLARABEL_RUST_FEATURES "${CLARABEL_FEATURE_SDP}")
84+
endif()
85+
86+
if(CLARABEL_FEATURE_FAER_SPARSE)
87+
append_feature(CLARABEL_RUST_FEATURES "faer-sparse")
88+
endif()
3189

32-
# Set the Rust feature flag
33-
set(CLARABEL_BUILD_FEATURES "${CLARABEL_BUILD_FEATURES},${CLARABEL_FEATURE_SDP}")
90+
if(CLARABEL_FEATURE_PARDISO_MKL)
91+
append_feature(CLARABEL_RUST_FEATURES "pardiso-mkl")
92+
endif()
93+
94+
# SERDE feature flag
95+
if(CLARABEL_FEATURE_SERDE)
96+
append_feature(CLARABEL_RUST_FEATURES "serde")
97+
endif()
98+
99+
100+
# -------------------------------------
101+
# Cargo feature configuration
102+
#--------------------------------------
34103

104+
# ----
105+
# Rust features should be passed via the CLARABEL_RUST_FEATURES variable.
106+
# For some features, we requires some additional CMake configuration.
107+
# ---
108+
109+
rust_features_has_sdp(CONFIG_SDP)
110+
if(CONFIG_SDP)
35111
# Define the FEATURE_SDP flag for all targets that link against clarabel_c
36112
target_compile_definitions(libclarabel_c_static INTERFACE FEATURE_SDP)
37113
target_compile_definitions(libclarabel_c_shared INTERFACE FEATURE_SDP)
38114
endif()
39115

40-
# FAER_SPARSE feature flag
41-
if(CLARABEL_FEATURE_FAER_SPARSE)
42-
43-
# Set the Rust feature flag
44-
set(CLARABEL_BUILD_FEATURES "${CLARABEL_BUILD_FEATURES},faer-sparse")
45-
46-
# Define the FEATURE_FAER_SPARSE flag for all targets that link against clarabel_c
116+
rust_feature_is_enabled("faer-sparse" CONFIG_FAER_SPARSE)
117+
if(CONFIG_FAER_SPARSE)
47118
target_compile_definitions(libclarabel_c_static INTERFACE FEATURE_FAER_SPARSE)
48119
target_compile_definitions(libclarabel_c_shared INTERFACE FEATURE_FAER_SPARSE)
49120
endif()
50121

51-
# PARDISO_MKL feature flag
52-
if(CLARABEL_FEATURE_PARDISO_MKL)
53-
54-
# Set the Rust feature flag
55-
set(CLARABEL_BUILD_FEATURES "${CLARABEL_BUILD_FEATURES},pardiso-mkl")
56-
57-
# Define the FEATURE_PARDISO_MKL flag for all targets that link against clarabel_c
122+
rust_feature_is_enabled("pardiso-mkl" CONFIG_PARDISO_MKL)
123+
if(CONFIG_PARDISO_MKL)
58124
target_compile_definitions(libclarabel_c_static INTERFACE FEATURE_PARDISO_MKL)
59125
target_compile_definitions(libclarabel_c_shared INTERFACE FEATURE_PARDISO_MKL)
60-
61126
endif()
62127

63-
# PARDISO_PANUA feature flag
64-
if(CLARABEL_FEATURE_PARDISO_PANUA)
65-
66-
# Set the Rust feature flag
67-
set(CLARABEL_BUILD_FEATURES "${CLARABEL_BUILD_FEATURES},pardiso-panua")
68-
69-
# Define the FEATURE_PARDISO_PANUA flag for all targets that link against clarabel_c
128+
rust_feature_is_enabled("pardiso-panua" CONFIG_PARDISO_PANUA)
129+
if(CONFIG_PARDISO_PANUA)
70130
target_compile_definitions(libclarabel_c_static INTERFACE FEATURE_PARDISO_PANUA)
71131
target_compile_definitions(libclarabel_c_shared INTERFACE FEATURE_PARDISO_PANUA)
72132
endif()
73133

74-
if(CLARABEL_FEATURE_PARDISO_MKL OR CLARABEL_FEATURE_PARDISO_PANUA)
134+
if(CONFIG_PARDISO_MKL OR CONFIG_PARDISO_PANUA)
75135
target_compile_definitions(libclarabel_c_static INTERFACE FEATURE_PARDISO_ANY)
76136
target_compile_definitions(libclarabel_c_shared INTERFACE FEATURE_PARDISO_ANY)
77137
endif()
78138

79-
80-
# SERDE feature flag
81-
if(CLARABEL_FEATURE_SERDE)
82-
83-
# Set the Rust feature flag
84-
set(CLARABEL_BUILD_FEATURES "${CLARABEL_BUILD_FEATURES},serde")
85-
86-
# Define the FEATURE_SERDE flag for all targets that link against clarabel_c
139+
rust_feature_is_enabled("serde" CONFIG_SERDE)
140+
if(CONFIG_SERDE)
87141
target_compile_definitions(libclarabel_c_static INTERFACE FEATURE_SERDE)
88142
target_compile_definitions(libclarabel_c_shared INTERFACE FEATURE_SERDE)
89143
endif()
90144

145+
# replace each rust <feature> with clarabel/<feature> so that they pass through
146+
# this wrapper to the clarabel crate underneath
147+
format_clarabel_rust_features("${CLARABEL_RUST_FEATURES}" CLARABEL_RUST_FEATURES)
91148

149+
# some features must also be specified at the wrapper level
150+
# add them again, but after prepending clarabel/ to everything
151+
if(CONFIG_SDP)
152+
append_feature(CLARABEL_RUST_FEATURES "sdp")
153+
endif()
154+
if(CONFIG_SERDE)
155+
append_feature(CLARABEL_RUST_FEATURES "serde")
156+
endif()
92157

93-
set(clarabel_c_build_flags "${clarabel_c_build_flags};--features=${CLARABEL_BUILD_FEATURES}")
94-
message("-- Rust feature list: " ${CLARABEL_BUILD_FEATURES})
95-
message("-- Cargo options: " "${clarabel_c_build_flags}")
158+
if(NOT CLARABEL_RUST_FEATURES STREQUAL "")
159+
set(clarabel_c_build_flags "${clarabel_c_build_flags};--features=${CLARABEL_RUST_FEATURES}")
160+
endif()
96161

162+
message("-- Rust feature list: " ${CLARABEL_RUST_FEATURES})
163+
message("-- Cargo options: " "${clarabel_c_build_flags}")
97164

98165
# -------------------------------------
99166
# -------------------------------------
@@ -118,11 +185,11 @@ add_custom_target(
118185
WORKING_DIRECTORY ${CLARABEL_ROOT_DIR}/rust_wrapper
119186
# Commands for building the Rust library
120187
COMMAND cargo build ${clarabel_c_build_flags}
121-
COMMAND cargo install cbindgen --version 0.24.5
188+
COMMAND cargo install cbindgen
122189
# Generate the C header
123-
COMMAND cbindgen --config cbindgen.toml --crate clarabel_c --output ./headers/clarabel.h --lang c
190+
COMMAND cbindgen --config cbindgen.toml --quiet --crate clarabel_c --output ./headers/clarabel.h --lang c
124191
# Generate the C++ header
125-
COMMAND cbindgen --config cbindgen.toml --crate clarabel_c --output ./headers/clarabel.hpp
192+
COMMAND cbindgen --config cbindgen.toml --quiet --crate clarabel_c --output ./headers/clarabel.hpp
126193
BYPRODUCTS
127194
"${LIBCLARABEL_C_SHARED_PATH}"
128195
"${LIBCLARABEL_C_STATIC_PATH}"

rust_wrapper/Cargo.toml

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,6 @@ lto = true
1818
codegen-units = 1
1919

2020
[features]
21-
# Define features for SDP support in Clarabel.rs
22-
sdp = ["clarabel/sdp"]
23-
sdp-accelerate = ["sdp", "clarabel/sdp-accelerate"]
24-
sdp-netlib = ["sdp", "clarabel/sdp-netlib"]
25-
sdp-openblas = ["sdp", "clarabel/sdp-openblas"]
26-
sdp-mkl = ["sdp", "clarabel/sdp-mkl"]
27-
sdp-r = ["sdp", "clarabel/sdp-r"]
28-
29-
serde = ["dep:serde", "clarabel/serde"]
30-
faer-sparse = ["clarabel/faer-sparse"]
31-
pardiso-mkl = ["clarabel/pardiso-mkl"]
32-
pardiso-panua = ["clarabel/pardiso-panua"]
33-
pardiso = ["clarabel/pardiso"] #chooses both
21+
default = []
22+
sdp = []
23+
serde = ["dep:serde"]

rust_wrapper/cbindgen.toml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,19 @@ documentation = false
1212

1313
[defines]
1414
"feature = sdp" = "FEATURE_SDP"
15+
"feature = serde" = "FEATURE_SERDE"
1516
"feature = faer-sparse" = "FEATURE_FAER_SPARSE"
16-
"feature = serde" = "FEATURE_SERDE"
17+
"feature = pardiso-mkl" = "FEATURE_PARDISO_MKL"
18+
"feature = pardiso-panua" = "FEATURE_PARDISO_PANUA"
19+
20+
[parse]
21+
parse_deps = true
22+
include = ["clarabel"]
23+
exclude = ["indexmap"]
24+
25+
[export]
26+
include = [
27+
"SolverStatusFFI",
28+
"DefaultInfoFFI",
29+
"DefaultSettingsFFI",
30+
]

rust_wrapper/src/algebra.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pub struct ClarabelCscMatrix<T = f64> {
99
pub n: usize,
1010
/// CSC format column pointer.
1111
///
12-
/// Ths field should have length `n+1`. The last entry corresponds
12+
/// This field should have length `n+1`. The last entry corresponds
1313
/// to the the number of nonzeros and should agree with the lengths
1414
/// of the `rowval` and `nzval` fields.
1515
pub colptr: *const usize,

rust_wrapper/src/core.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ pub mod cones {
1919
/// The exponential cone in R^3.
2020
///
2121
/// This cone takes no parameters
22-
ExponentialConeT(),
22+
/// NB: Just a plain enum variant and not a unit type (i.e. not ExponentialConeT())
23+
/// as in the clarabel crate to avoid ZST / FFI complaints from cbindgen
24+
ExponentialConeT,
2325
/// The power cone in R^3.
2426
///
2527
/// The parameter indicates the power.

rust_wrapper/src/solver/implementations/default/solver.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::solver::implementations::default::settings::{
77
ClarabelDefaultSettings, ClarabelDefaultSettings_f32, ClarabelDefaultSettings_f64,
88
};
99
use crate::utils;
10+
use clarabel::solver::ffi::SolverStatusFFI;
1011

1112
use clarabel::algebra::FloatT;
1213
use clarabel::io::ConfigurablePrintTarget;
@@ -29,7 +30,7 @@ use super::solution::DefaultSolution;
2930
pub type ClarabelDefaultSolver_f32 = c_void;
3031
pub type ClarabelDefaultSolver_f64 = c_void;
3132

32-
pub type ClarabelSolverStatus = clarabel::solver::ffi::SolverStatusFFI;
33+
pub type ClarabelSolverStatus = SolverStatusFFI;
3334

3435
// Wrapper function to create a DefaultSolver object from C using dynamic memory allocation
3536
// - Matrices and vectors are constructed from raw pointers

rust_wrapper/src/utils/supported_cones_T.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ pub fn convert_from_C_cone<T: FloatT>(cone: &ClarabelSupportedConeT<T>) -> lib::
2828
ClarabelSupportedConeT::SecondOrderConeT(payload) => {
2929
lib::SupportedConeT::SecondOrderConeT(*payload)
3030
}
31-
ClarabelSupportedConeT::ExponentialConeT() => lib::SupportedConeT::ExponentialConeT(),
31+
ClarabelSupportedConeT::ExponentialConeT => lib::SupportedConeT::ExponentialConeT(),
3232
ClarabelSupportedConeT::PowerConeT(payload) => lib::SupportedConeT::PowerConeT(*payload),
33-
ClarabelSupportedConeT::GenPowerConeT(ptr_alpha,dim1,dim2) => {
33+
ClarabelSupportedConeT::GenPowerConeT(ptr_alpha, dim1, dim2) => {
3434
let alpha = unsafe { std::slice::from_raw_parts(*ptr_alpha, *dim1) };
35-
lib::SupportedConeT::GenPowerConeT(alpha.to_vec(),*dim2)
35+
lib::SupportedConeT::GenPowerConeT(alpha.to_vec(), *dim2)
3636
}
3737
#[cfg(feature = "sdp")]
3838
ClarabelSupportedConeT::PSDTriangleConeT(payload) => {

0 commit comments

Comments
 (0)