oximo_clarabel/options.rs
1use oximo_solver::{HasUniversal, UniversalOptions};
2
3// TODO: Enable Pardiso backends
4
5/// Direct linear (KKT) solver method for Clarabel.
6///
7/// Selects the sparse LDL factorization backend. The built-in `qdldl` and the
8/// `auto` default are always present.
9#[cfg_attr(
10 feature = "faer",
11 doc = "The [`Faer`](Self::Faer) backend requires this crate's `faer` feature."
12)]
13#[cfg_attr(
14 not(feature = "faer"),
15 doc = "A `Faer` backend is also available behind this crate's `faer` feature."
16)]
17#[derive(Clone, Copy, Debug, Eq, PartialEq)]
18pub enum ClarabelDirectSolve {
19 /// Let Clarabel choose (`"auto"`). Clarabel default.
20 Auto,
21 /// Built-in QDLDL factorization (`"qdldl"`).
22 Qdldl,
23 /// faer sparse LDL factorization (`"faer"`). Requires the `faer` feature.
24 #[cfg(feature = "faer")]
25 #[cfg_attr(docsrs, doc(cfg(feature = "faer")))]
26 Faer,
27}
28
29/// Declare every scalar [`ClarabelOptions`] option once. Its `Option<T>` field
30/// and its `#[must_use]` builder are generated from the same entry, keeping the
31/// field name identical to the matching `clarabel::solver::CoreSettings` field.
32macro_rules! clarabel_options {
33 ($($(#[$meta:meta])* $name:ident : $ty:ty),* $(,)?) => {
34 /// Clarabel-specific solver options.
35 ///
36 /// A typed mirror of the tunable, non-feature-gated fields of
37 /// `clarabel::solver::CoreSettings`. Every field is `Option`, `None`
38 /// leaves Clarabel's own default in place, so the defaults quoted below
39 /// are informational.
40 ///
41 /// The universal `threads` option maps to Clarabel's `max_threads`,
42 /// which only affects multithreaded KKT solvers. The default `qdldl`
43 /// solver is single-threaded.
44 #[derive(Clone, Debug, Default)]
45 pub struct ClarabelOptions {
46 /// Options shared by every backend.
47 pub universal: UniversalOptions,
48 /// Direct linear (KKT) solver method. Clarabel default `Auto`.
49 pub direct_solve_method: Option<ClarabelDirectSolve>,
50 $(
51 $(#[$meta])*
52 pub $name: Option<$ty>,
53 )*
54 }
55
56 impl ClarabelOptions {
57 /// Select the direct linear (KKT) solver method.
58 #[must_use]
59 pub fn direct_solve_method(mut self, m: ClarabelDirectSolve) -> Self {
60 self.direct_solve_method = Some(m);
61 self
62 }
63
64 $(
65 $(#[$meta])*
66 #[must_use]
67 pub fn $name(mut self, v: $ty) -> Self {
68 self.$name = Some(v);
69 self
70 }
71 )*
72 }
73 };
74}
75
76clarabel_options! {
77 /// Interior-point iteration limit. Clarabel default `200`.
78 max_iter: u32,
79 /// Maximum interior-point step length. Clarabel default `0.99`.
80 max_step_fraction: f64,
81 /// Absolute duality-gap tolerance. Clarabel default `1e-8`.
82 tol_gap_abs: f64,
83 /// Relative duality-gap tolerance. Clarabel default `1e-8`.
84 tol_gap_rel: f64,
85 /// Primal/dual feasibility tolerance. Clarabel default `1e-8`.
86 tol_feas: f64,
87 /// Absolute infeasibility tolerance. Clarabel default `1e-8`.
88 tol_infeas_abs: f64,
89 /// Relative infeasibility tolerance. Clarabel default `1e-8`.
90 tol_infeas_rel: f64,
91 /// κ/τ tolerance. Clarabel default `1e-6`.
92 tol_ktratio: f64,
93 /// Reduced (low-accuracy fallback) absolute duality-gap tolerance.
94 /// Clarabel default `5e-5`.
95 reduced_tol_gap_abs: f64,
96 /// Reduced relative duality-gap tolerance. Clarabel default `5e-5`.
97 reduced_tol_gap_rel: f64,
98 /// Reduced feasibility tolerance. Clarabel default `1e-4`.
99 reduced_tol_feas: f64,
100 /// Reduced absolute infeasibility tolerance. Clarabel default `5e-12`.
101 reduced_tol_infeas_abs: f64,
102 /// Reduced relative infeasibility tolerance. Clarabel default `5e-5`.
103 reduced_tol_infeas_rel: f64,
104 /// Reduced κ/τ tolerance. Clarabel default `1e-4`.
105 reduced_tol_ktratio: f64,
106 /// Enable data-equilibration pre-scaling. Clarabel default `true`.
107 equilibrate_enable: bool,
108 /// Maximum equilibration scaling iterations. Clarabel default `10`.
109 equilibrate_max_iter: u32,
110 /// Minimum equilibration scaling allowed. Clarabel default `1e-4`.
111 equilibrate_min_scaling: f64,
112 /// Maximum equilibration scaling allowed. Clarabel default `1e4`.
113 equilibrate_max_scaling: f64,
114 /// Line-search backtracking factor. Clarabel default `0.8`.
115 linesearch_backtrack_step: f64,
116 /// Minimum step for asymmetric cones with PrimalDual scaling.
117 /// Clarabel default `1e-1`.
118 min_switch_step_length: f64,
119 /// Minimum step for symmetric cones / asymmetric cones with Dual scaling.
120 /// Clarabel default `1e-4`.
121 min_terminate_step_length: f64,
122 /// Enable KKT static regularization. Clarabel default `true`.
123 static_regularization_enable: bool,
124 /// KKT static regularization constant. Clarabel default `1e-8`.
125 static_regularization_constant: f64,
126 /// Static regularization proportional to the max abs diagonal term.
127 /// Clarabel default `f64::EPSILON.powi(2)`.
128 static_regularization_proportional: f64,
129 /// Enable KKT dynamic regularization. Clarabel default `true`.
130 dynamic_regularization_enable: bool,
131 /// KKT dynamic regularization threshold. Clarabel default `1e-13`.
132 dynamic_regularization_eps: f64,
133 /// KKT dynamic regularization shift. Clarabel default `2e-7`.
134 dynamic_regularization_delta: f64,
135 /// KKT direct solve with iterative refinement. Clarabel default `true`.
136 iterative_refinement_enable: bool,
137 /// Iterative-refinement relative tolerance. Clarabel default `1e-13`.
138 iterative_refinement_reltol: f64,
139 /// Iterative-refinement absolute tolerance. Clarabel default `1e-12`.
140 iterative_refinement_abstol: f64,
141 /// Iterative-refinement maximum iterations. Clarabel default `10`.
142 iterative_refinement_max_iter: u32,
143 /// Iterative-refinement stalling tolerance. Clarabel default `5.0`.
144 iterative_refinement_stop_ratio: f64,
145 /// Enable presolve constraint reduction. Clarabel default `true`.
146 presolve_enable: bool,
147 /// Drop structural zeros from sparse inputs (disables parametric updating).
148 /// Clarabel default `false`.
149 input_sparse_dropzeros: bool,
150}
151
152impl HasUniversal for ClarabelOptions {
153 fn universal(&self) -> &UniversalOptions {
154 &self.universal
155 }
156
157 fn universal_mut(&mut self) -> &mut UniversalOptions {
158 &mut self.universal
159 }
160}