Skip to main content

Crate oximo_clarabel

Crate oximo_clarabel 

Source
Expand description

§oximo-clarabel

Clarabel backend for oximo.

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

KindSupported
LPYes
QP (quadratic objective, linear constraints)Yes, the objective Hessian must be positive semidefinite (Clarabel does not check and a non-convex P fails numerically)
SOCPYes
MILP/MIQP/MISOCPNo, Clarabel has no integer support (returned as UnsupportedKind)
QCP/MIQCPNo, 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 P must 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)

MethodClarabel settingDefault
.time_limit(Duration)time_limitnone
.threads(usize)max_threads (KKT solvers only, see note)none
.verbose(bool)verbosenone

.threads maps to max_threads, which only affects multithreaded KKT solvers. The default qdldl is single-threaded.

§Clarabel options (selected)

MethodClarabel settingDefault
.direct_solve_method(ClarabelDirectSolve)direct_solve_methodAuto
.max_iter(u32)max_iter200
.max_step_fraction(f64)max_step_fraction0.99
.tol_gap_abs(f64)tol_gap_abs1e-8
.tol_gap_rel(f64)tol_gap_rel1e-8
.tol_feas(f64)tol_feas1e-8
.tol_infeas_abs(f64)tol_infeas_abs1e-8
.tol_infeas_rel(f64)tol_infeas_rel1e-8
.tol_ktratio(f64)tol_ktratio1e-6
.equilibrate_enable(bool)equilibrate_enabletrue
.static_regularization_enable(bool)static_regularization_enabletrue
.dynamic_regularization_enable(bool)dynamic_regularization_enabletrue
.iterative_refinement_enable(bool)iterative_refinement_enabletrue
.presolve_enable(bool)presolve_enabletrue
.input_sparse_dropzeros(bool)input_sparse_dropzerosfalse

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 the primal values keyed by VarId and the objective (adjusted for the objective sign and any constant term). Access via result.objective() / result.value_of(var)
  • dual - constraint duals, keyed by ConstraintId, access via result.dual_of(c). Reported for equality and single-sided/range linear constraints in the LP convention (gradient = A' y of the problem as posed)
  • soc_dual - for each explicit soc_constraint!, its norm-form bound multiplier (z0), keyed by SocConstraintId, access via result.soc_dual_of(soc)
  • reduced_costs - not populated by this backend (always empty)
  • termination - why the solve stopped, mapped from Clarabel’s SolverStatus: 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 shortcut
  • best_bound / gap - always None (conic solver, no MIP bound)
  • solve_time - wall time measured around the Clarabel solve call
  • iterations - interior-point iteration count

§License

MIT OR Apache-2.0

Structs§

Clarabel
Clarabel solver handle.
ClarabelOptions
Clarabel-specific solver options.
ClarabelPersistent
A stateful Clarabel handle that keeps the built solver resident across solves.

Enums§

ClarabelDirectSolve
Direct linear (KKT) solver method for Clarabel.

Functions§

solve
Translate model into a Clarabel problem, solve, and return the generic SolverResult.