Expand description
§oximo-clarabel
Wraps the clarabel crate: an open-source,
pure-Rust interior-point solver for convex conic programs. Supports LP, convex QP
(quadratic objective, linear constraints), and SOCP model kinds. It has no
integer support, so mixed-integer models are rejected.
§Usage
Enable the clarabel feature on the umbrella oximo crate:
[dependencies]
oximo = { version = "0.5.1", features = ["clarabel"] }To use this crate directly:
[dependencies]
oximo-clarabel = "0.5.1"
oximo-core = "0.5.1"
oximo-solver = "0.5.1"The optional faer feature adds the faer
sparse LDL factorization as an alternative KKT backend.
§Quick example
use oximo_core::prelude::*;
use oximo_clarabel::{Clarabel, ClarabelOptions};
use oximo_solver::{Solver, TerminationStatus};
let m = Model::new("socp");
variable!(m, x);
variable!(m, y);
variable!(m, t >= 0.0);
m.fix(t, 1.0);
soc_constraint!(m, disk, [x, y] <= t); // ||(x, y)||_2 <= t
objective!(m, Min, x + y);
let result = Clarabel.solve(&m, &ClarabelOptions::default()).unwrap();
assert_eq!(result.termination, TerminationStatus::Optimal);
println!("obj = {}", result.objective().unwrap()); // -sqrt(2)Run the bundled SOCP example:
cargo run -p oximo --example gradostat_multiperiod_socp --features clarabel§Supported model kinds
| Kind | Supported |
|---|---|
LP | Yes |
QP (quadratic objective, linear constraints) | Yes, the objective Hessian must be positive semidefinite (Clarabel does not check and a non-convex P fails numerically) |
SOCP | Yes |
MILP/MIQP/MISOCP | No, Clarabel has no integer support (returned as UnsupportedKind) |
QCP/MIQCP | No, convex-QCP-to-SOC reformulation is not implemented. Write the constraint in SOC form instead. |
A quadratic constraint that is already SOC-shaped (sum p_i x_i^2 <= n t^2,
t >= 0) is detected as SOCP and solved, a general convex quadratic
constraint is not.
§Persistent handle (repeated solves)
Clarabel.solve builds a fresh solver for each call. When you re-solve one model
many times (parameter sweeps, sensitivity studies, column generation, rolling
horizons, etc) build a resident handle with Clarabel.persistent() and call
solve on it instead. ClarabelPersistent is a plain Solver. When the next
model has the same dimensions, cone layout, and P/A sparsity pattern, only
the numeric data (P, q, A, b) is overwritten in place via Clarabel’s
update_data, reusing the KKT symbolic factorization. Any structural change
(added/removed rows or columns, a changed sparsity pattern, a new cone, or a
flipped constraint sense that moves a row between cones) triggers a transparent
rebuild, so results always match a cold solve.
§Convex quadratic objectives (QP)
A quadratic objective (e.g. x.powi(2), x * y) with linear constraints is
detected as QP. oximo derives the Hessian from the objective and Clarabel
minimizes c'x + 0.5·x'Px.
Convexity. Clarabel solves only convex QPs. For minimization
Pmust be positive semidefinite; for maximization, negative semidefinite. Clarabel does not check this, so an indefinite or incorrectly signed Hessian may fail numerically or return a non-optimal point.
§Options
ClarabelOptions is a typed builder. All methods return Self for chaining,
and every field is Option. None leaves Clarabel’s own default in place.
§Universal options (via UniversalOptionsExt)
| Method | Clarabel setting | Default |
|---|---|---|
.time_limit(Duration) | time_limit | none |
.threads(usize) | max_threads (KKT solvers only, see note) | none |
.verbose(bool) | verbose | none |
.threads maps to max_threads, which only affects multithreaded KKT solvers.
The default qdldl is single-threaded.
§Clarabel options (selected)
| Method | Clarabel setting | Default |
|---|---|---|
.direct_solve_method(ClarabelDirectSolve) | direct_solve_method | Auto |
.max_iter(u32) | max_iter | 200 |
.max_step_fraction(f64) | max_step_fraction | 0.99 |
.tol_gap_abs(f64) | tol_gap_abs | 1e-8 |
.tol_gap_rel(f64) | tol_gap_rel | 1e-8 |
.tol_feas(f64) | tol_feas | 1e-8 |
.tol_infeas_abs(f64) | tol_infeas_abs | 1e-8 |
.tol_infeas_rel(f64) | tol_infeas_rel | 1e-8 |
.tol_ktratio(f64) | tol_ktratio | 1e-6 |
.equilibrate_enable(bool) | equilibrate_enable | true |
.static_regularization_enable(bool) | static_regularization_enable | true |
.dynamic_regularization_enable(bool) | dynamic_regularization_enable | true |
.iterative_refinement_enable(bool) | iterative_refinement_enable | true |
.presolve_enable(bool) | presolve_enable | true |
.input_sparse_dropzeros(bool) | input_sparse_dropzeros | false |
There is also a matching set of low-accuracy fallback tolerances
(reduced_tol_*) and further equilibration, line-search, and regularization
options. The full list is in src/options.rs.
use oximo_clarabel::{ClarabelOptions, ClarabelDirectSolve};
use oximo_solver::UniversalOptionsExt;
let opts = ClarabelOptions::default()
.max_iter(100)
.tol_gap_rel(1e-9)
.direct_solve_method(ClarabelDirectSolve::Qdldl)
.verbose(true);§Result
SolverResult fields, populated whenever a usable point is available
(primal_status is FeasiblePoint or OptimalPoint):
solutions- primal points (Vec<SolutionPoint>). This backend returns a single point holding theprimalvalues keyed byVarIdand theobjective(adjusted for the objective sign and any constant term). Access viaresult.objective()/result.value_of(var)dual- constraint duals, keyed byConstraintId, access viaresult.dual_of(c). Reported for equality and single-sided/range linear constraints in the LP convention (gradient = A' yof the problem as posed)soc_dual- for each explicitsoc_constraint!, its norm-form bound multiplier (z0), keyed bySocConstraintId, access viaresult.soc_dual_of(soc)reduced_costs- not populated by this backend (always empty)termination- why the solve stopped, mapped from Clarabel’sSolverStatus:Optimal(Solved),Infeasible(PrimalInfeasible),Unbounded(DualInfeasible),IterationLimit(MaxIterations),TimeLimit(MaxTime),Interrupted(AlmostSolved),NumericError(NumericalError/InsufficientProgress),NotSolved(Unsolved)primal_status- whether a usable point came back (NoSolution/FeasiblePoint/OptimalPoint),result.has_solution()is the shortcutbest_bound/gap- alwaysNone(conic solver, no MIP bound)solve_time- wall time measured around the Clarabel solve calliterations- interior-point iteration count
§License
MIT OR Apache-2.0
Structs§
- Clarabel
- Clarabel solver handle.
- Clarabel
Options - Clarabel-specific solver options.
- Clarabel
Persistent - A stateful Clarabel handle that keeps the built solver resident across solves.
Enums§
- Clarabel
Direct Solve - Direct linear (KKT) solver method for Clarabel.
Functions§
- solve
- Translate
modelinto a Clarabel problem, solve, and return the genericSolverResult.