Solver Settings

Configure solver behavior through the Settings and IPMSettings classes.

Settings Overview

import moreau

settings = moreau.Settings(
    solver='ipm',         # Solver algorithm (only 'ipm' currently)
    device='auto',        # Device selection ('auto', 'cpu', 'cuda')
    device_id=-1,         # CUDA device ID (-1 = current device, ignored on CPU)
    batch_size=1,         # Batch size for CompiledSolver
    enable_grad=False,    # Enable gradient computation
    auto_tune=False,      # Benchmark solver configs on first solve (opt-in)
    max_iter=200,         # Maximum IPM iterations
    time_limit=float('inf'),  # Time limit in seconds
    verbose=False,        # Print solver progress
    ipm_settings=None,    # Fine-grained IPM control (auto-created if None)
)

Device Settings

# Automatic device selection (default)
settings = moreau.Settings(device='auto')

# Force CPU
settings = moreau.Settings(device='cpu')

# Force CUDA GPU
settings = moreau.Settings(device='cuda')

# Force a specific CUDA device
settings = moreau.Settings(device='cuda', device_id=1)

See Device Selection for more details.


Batch Settings

For CompiledSolver, specify batch size:

settings = moreau.Settings(batch_size=64)

solver = moreau.CompiledSolver(
    n=2, m=3,
    P_row_offsets=[0, 1, 2], P_col_indices=[0, 1],
    A_row_offsets=[0, 2, 3, 4], A_col_indices=[0, 1, 0, 1],
    cones=cones,
    settings=settings,
)

Iteration & Time Control

settings = moreau.Settings(
    max_iter=200,               # Maximum iterations (default: 200)
    time_limit=30.0,            # Time limit in seconds (default: infinity)
    verbose=True,               # Print iteration progress
)

Gradient Settings

Enable gradients for differentiation through the solver:

# Core API (NumPy)
settings = moreau.Settings(enable_grad=True)
solver = moreau.CompiledSolver(..., settings=settings)

# PyTorch (enable_grad is True by default)
from moreau.torch import Solver
solver = Solver(...)  # Gradients enabled automatically

IPM Settings

Fine-tune the interior-point method:

ipm_settings = moreau.IPMSettings(
    # Convergence tolerances
    tol_gap_abs=1e-8,     # Absolute duality gap tolerance
    tol_gap_rel=1e-8,     # Relative duality gap tolerance
    tol_feas=1e-8,        # Primal/dual feasibility tolerance
    tol_infeas_abs=1e-8,  # Infeasibility detection tolerance
    tol_infeas_rel=1e-8,  # Relative infeasibility tolerance
    tol_ktratio=1e-6,     # KKT ratio tolerance

    # Algorithm control
    max_step_fraction=0.99,    # Maximum step size fraction (0, 1]
    equilibrate_enable=True,   # Enable matrix equilibration

    # KKT solver method
    direct_solve_method='auto',  # See table below
)

settings = moreau.Settings(ipm_settings=ipm_settings)

KKT Solver Method

The direct_solve_method controls which linear algebra backend solves the KKT system at each IPM iteration:

Method

Device

Best For

'auto'

any

Heuristic or auto-tuned (default)

'qdldl'

CPU

Small/sparse KKT systems

'faer'

CPU

Large CPU problems (multi-threaded)

'faer-1t'

CPU

Large CPU problems (single-threaded)

'faer-nt'

CPU

Large CPU problems (automatic thread count)

'cudss'

CUDA

Large GPU problems

'riccati'

CPU / CUDA

Block-tridiagonal problems (MPC/LQR)

'woodbury'

CUDA

Portfolio-type: diagonal P + low-rank constraints

When set to 'auto' (the default), a heuristic picks the best method for the device without benchmarking. To enable benchmarking on the first solve() call, set auto_tune=True:

# Heuristic selection (default, no benchmarking)
settings = moreau.Settings(device='auto')

# Benchmarking on first solve
settings = moreau.Settings(device='auto', auto_tune=True)

Set both device and method explicitly to skip all automatic selection.

Reduced Tolerances

When the solver cannot meet the primary tolerances, it checks against a set of relaxed “reduced” tolerances. If those are met, the status is AlmostSolved (or AlmostPrimalInfeasible/AlmostDualInfeasible):

ipm_settings = moreau.IPMSettings(
    reduced_tol_gap_abs=5e-5,       # default 5e-5
    reduced_tol_gap_rel=5e-5,       # default 5e-5
    reduced_tol_feas=1e-4,          # default 1e-4
    reduced_tol_infeas_abs=5e-12,   # default 5e-12
    reduced_tol_infeas_rel=5e-5,    # default 5e-5
    reduced_tol_ktratio=1e-4,       # default 1e-4
)

Warm Start Retry Control

By default, if a warm-started solve returns a “bad” status, the solver automatically retries cold. The warm_start_no_retry parameter controls which statuses are considered “acceptable” (i.e. do not trigger a retry):

from moreau import IPMSettings, SolverStatus

# Default behavior (None): {Solved, AlmostSolved, MaxIterations, CallbackTerminated}
ipm = moreau.IPMSettings()

# Custom: also accept MaxIterations without retrying cold
ipm = moreau.IPMSettings(
    warm_start_no_retry=frozenset({
        SolverStatus.Solved,
        SolverStatus.AlmostSolved,
        SolverStatus.MaxTime,
        SolverStatus.MaxIterations,
        SolverStatus.CallbackTerminated,
    })
)

Tolerance Guidelines

Tolerance

Effect

tol_gap_abs/rel

Lower = more accurate objective

tol_feas

Lower = stricter constraint satisfaction

Higher tolerances

Faster convergence, less accuracy

Lower tolerances

More iterations, higher accuracy

Default tolerances (1e-8) are suitable for most applications.


Common Configurations

High Accuracy

ipm_settings = moreau.IPMSettings(
    tol_gap_abs=1e-10,
    tol_gap_rel=1e-10,
    tol_feas=1e-10,
)
settings = moreau.Settings(
    max_iter=500,
    ipm_settings=ipm_settings,
)

Fast/Approximate

ipm_settings = moreau.IPMSettings(
    tol_gap_abs=1e-6,
    tol_gap_rel=1e-6,
    tol_feas=1e-6,
)
settings = moreau.Settings(
    max_iter=100,
    ipm_settings=ipm_settings,
)

GPU Batched with Time Limit

settings = moreau.Settings(
    device='cuda',
    batch_size=1024,
    enable_grad=True,
    time_limit=60.0,
)