#[derive(Clone, Debug)]
pub struct SolverOptions {
pub scaling: ScalingOptions,
pub x0: Option<Vec<f64>>,
pub assume_symmetric: bool,
pub lipschitz: LipschitzOptions,
pub stopping: StoppingOptions,
pub polish: PolishOptions,
pub logging: LoggingOptions,
}
impl Default for SolverOptions {
fn default() -> Self {
Self {
scaling: ScalingOptions::default(),
x0: None,
assume_symmetric: false,
lipschitz: LipschitzOptions::default(),
stopping: StoppingOptions::default(),
polish: PolishOptions::default(),
logging: LoggingOptions::default(),
}
}
}
#[derive(Clone, Debug)]
pub struct ScalingOptions {
pub mode: ScalingMode,
pub eps: f64,
pub min: f64,
pub max: f64,
}
impl Default for ScalingOptions {
fn default() -> Self {
Self {
mode: ScalingMode::HessianDiag,
eps: 1e-12,
min: 1e-6,
max: 1e6,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ScalingMode {
None,
HessianDiag,
}
#[derive(Clone, Debug)]
pub struct LipschitzOptions {
pub value: Option<f64>,
pub method: LipschitzMethod,
}
impl Default for LipschitzOptions {
fn default() -> Self {
Self {
value: None,
method: LipschitzMethod::Auto,
}
}
}
#[derive(Clone, Debug)]
pub enum LipschitzMethod {
Gershgorin,
Auto,
}
impl LipschitzMethod {
pub fn name(&self) -> &'static str {
match self {
Self::Gershgorin => "gershgorin",
Self::Auto => "auto",
}
}
}
#[derive(Clone, Debug)]
pub struct StoppingOptions {
pub max_iter: usize,
pub tol: f64,
pub dual_certification: bool,
pub check_every: usize,
pub bound_tol: f64,
}
impl Default for StoppingOptions {
fn default() -> Self {
Self {
max_iter: 5_000,
tol: 1e-6,
dual_certification: true,
check_every: 100,
bound_tol: 1e-10,
}
}
}
#[derive(Clone, Debug)]
pub struct PolishOptions {
pub enabled: bool,
pub bound_tol: f64,
pub grad_tol: f64,
pub rho_sequence: Vec<f64>,
pub num_passes: usize,
pub prefer_direct: bool,
pub direct_max_n: usize,
pub cg_rtol: f64,
pub cg_maxiter: usize,
pub use_preconditioner: bool,
pub max_backtracks: usize,
}
impl Default for PolishOptions {
fn default() -> Self {
Self {
enabled: true,
bound_tol: 1e-7,
grad_tol: 1e-8,
rho_sequence: vec![0.0, 1e-10, 1e-8, 1e-6, 1e-4],
num_passes: 2,
prefer_direct: true,
direct_max_n: 1500,
cg_rtol: 1e-10,
cg_maxiter: 10_000,
use_preconditioner: true,
max_backtracks: 20,
}
}
}
#[derive(Clone, Debug)]
pub struct LoggingOptions {
pub verbose: bool,
pub print_every: usize,
}
impl Default for LoggingOptions {
fn default() -> Self {
Self {
verbose: false,
print_every: 500,
}
}
}
#[derive(Clone, Debug)]
pub struct SolverResult {
pub x: Vec<f64>,
pub objective: f64,
pub iterations: usize,
pub num_restarts: usize,
pub quality: SolverQuality,
pub timing: SolverTiming,
pub lipschitz: f64,
pub step_size: f64,
pub scaling: ScalingSummary,
}
#[derive(Clone, Debug)]
pub struct SolverQuality {
pub gap: f64,
pub rel_gap: f64,
pub certified_lower_bound: f64,
pub kkt_inf: f64,
}
#[derive(Clone, Debug)]
pub struct SolverTiming {
pub apgd_time_sec: f64,
pub polish_time_sec: f64,
pub total_time_sec: f64,
}
#[derive(Clone, Debug)]
pub struct ScalingSummary {
pub applied: bool,
pub name: &'static str,
pub scale_min: f64,
pub scale_max: f64,
}
#[derive(Clone, Debug)]
pub(crate) struct Diagnostics {
pub kkt_inf: f64,
pub rel_kkt: f64,
pub gap: f64,
pub rel_gap: f64,
pub certified_lower_bound: f64,
}