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 |
|---|---|---|
|
any |
Heuristic or auto-tuned (default) |
|
CPU |
Small/sparse KKT systems |
|
CPU |
Large CPU problems (multi-threaded) |
|
CPU |
Large CPU problems (single-threaded) |
|
CPU |
Large CPU problems (automatic thread count) |
|
CUDA |
Large GPU problems |
|
CPU / CUDA |
Block-tridiagonal problems (MPC/LQR) |
|
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 |
|---|---|
|
Lower = more accurate objective |
|
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,
)