github cvxgrp/scs 3.3.0
SCS 3.3.0

4 hours ago

SCS 3.3.0 is a major performance release: across a 505-problem validation suite (netlib, Maros–Mészáros, MIPLIB LP relaxations, Kennington, SDPLIB) it solves 92 more problems than 3.2.11 (328 → 420 at eps 1e-6 under a 300s cap) while running a 3–7× lower shifted-geometric-mean solve time on every LP/QP suite, at equal-or-better independently verified accuracy. On LP benchmarks SCS now trades evenly with (and on MIPLIB beats) Google's PDLP at matched accuracy.

Performance vs 3.2.11

Protocol: eps_abs = eps_rel = 1e-6, 300s per-problem cap, max_iters 1e6, identical hardware/toolchain for both versions, both at their shipped defaults otherwise. All accuracy figures are KKT residuals recomputed independently from the returned primal/dual vectors and raw problem data — never solver-reported values.

suite solved 3.2.11 → 3.3.0 sgm time both-solved iterations
netlib feasible (93) 56 → 82 46.9 → 6.8s 23× fewer
Maros–Mészáros (138) 116 → 129 16.4 → 5.1s 6.3× fewer
MIPLIB LP relax. <20MB (169) 116 → 157 36.2 → 7.7s 6.9× fewer
Kennington (16) 10 → 12 89.8 → 33.6s 8.1× fewer
SDPLIB (89) 30 → 40 113.5 → ~91s ~1.3× fewer

The SDPLIB figure includes the new PSD block metric (#417); it replicated at 39–40 solves across four runs (the pre-metric 3.3.0 core measured 34–37).

Performance vs PDLP

OR-Tools PDLP at its defaults (eps 1e-6, 1 thread), identical hardware, all accuracy figures recomputed independently from returned vectors and raw data. The two solvers' termination criteria differ (they measure and normalize residuals differently), so equal requested tolerances do not mean equal delivered accuracy: SCS over-delivers its target by roughly an order of magnitude on LP/QP (a byproduct of the new equilibration) while PDLP delivers approximately at target. The meaningful comparison therefore matches delivered accuracy: SCS at eps 1e-5 against PDLP at its defaults, where both deliver the same residual class (independently measured medians below):

suite SCS 3.3.0 @ 1e-5 PDLP @ defaults
netlib (93) 88 solved @ 3.3s sgm 88 solved @ 8.6s sgm
Kennington (16) 12 @ 37.4s 16 @ 37.1s
MIPLIB <20MB (169) 161 @ 5.8s 149 @ 15.8s

Delivered residuals (primal/dual medians): netlib SCS 1.3e-7 / 9.6e-7 vs PDLP 7.9e-8 / 3.0e-7; MIPLIB SCS 9.1e-9 / 2.3e-7 vs PDLP 5.9e-8 / 2.6e-7; Kennington SCS 5.1e-7 / 3.0e-6 vs PDLP 1.5e-7 / 6.8e-6. At matched delivered accuracy SCS ties PDLP's netlib solve count at 2.6× less time and wins MIPLIB on both axes; the very large Kennington LPs remain PDLP's strongest suite. For context, 3.2.11 solved 56 netlib problems against PDLP's 88.

(Measurement note: each table is a single paired benchmark run; comparisons within a table are same-run. Across tables, shifted-geometric-mean times on the small 16-problem Kennington suite carry a few seconds of run-to-run variance — its instances sit near the time cap — which is why its 1e-5 time here reads slightly above its 1e-6 time in the table above.)

Accuracy defaults and guidance

The default eps (1e-4) is unchanged, deliberately: on SDPs, delivered accuracy tracks requested accuracy almost exactly and each decade costs ~2× solve time, so a tighter default would regress conic workloads. For LP/QP workloads, eps_abs = eps_rel = 1e-5 is recommended when accuracy matters: the new equilibration over-delivers by roughly an order, so 1e-5 requests deliver ~1e-7 median residuals for only ~10–15% extra time.

Algorithmic changes

  • Fully stacked equilibration (#399, #403): Ruiz equilibration now operates on the stacked [P Aᵀ c; A 0 b; cᵀ bᵀ 0] operator, jointly scaling b, c and the τ-scalar with the matrix data, followed by a root-mean-square ℓ2 pass. This was the single largest contributor to the iteration reductions above.
  • Dynamic per-row metric refinement (#401, #412): new adaptive_diag_scale setting (on by default) refines the diagonal DR metric R_y per row at scale-update events, driven by the per-row primal residual profile — a dynamic analog of row equilibration using the residuals the algorithm actually produces.
  • Rank-one metrics for PSD blocks (#417): PSD cone blocks, previously restricted to a single metric scalar, now get the richest cone-invariant svec-diagonal family — the diagonal congruence X → DXD (n parameters per block) — fitted in closed form from the residual profile, with the projection computed exactly via a congruence sandwich around the eigendecomposition. Zero linear-system fill; bit-identical when inactive.
  • eigCG deflation for the indirect solver (#407): the CG solver harvests approximate eigenvectors of the reduced system from its own iterations (Stathopoulos & Orginos) and deflates the smallest eigenvalues from subsequent solves — 1.7–2× fewer matvecs on ill-conditioned problems at no extra matrix-multiply cost. Default 30 vectors.
  • Retuned CG termination (#408): each inner solve now targets a small fraction (0.03) of the current outer residual with a faster decay schedule (rate 2.0), trading ~9% more matvecs for ~30% fewer outer iterations.
  • Anderson acceleration (#384, #386, #387, #402): updated AA library with rank-revealing QR + iterative refinement, detailed per-solve diagnostics in info.aa_stats, exposed AA settings, and a retuned default acceleration_interval of 5 (was 10).
  • Infeasibility certificate hardening (#400): certificate tests are now invariant to rescaling b (resp. c) against A, and must hold at two consecutive residual checks — eliminating false infeasibility declarations on badly scaled feasible problems (netlib agg/grow families).
  • Numerically stable root_plus (#391) and assorted wall-clock optimizations (#355, #357, #362, #363).

New backends and platform support

  • Apple Accelerate linear-solver backend (#378) and dense Cholesky (Gram matrix) backend (#365).
  • MKL interface-layer (LP64/ILP64) runtime check (#383); cuDSS 0.8 API support (#397) and many-solves tuning for cuDSS and MKL Pardiso (#362, #363).
  • Thread-safe interrupt handling (#375); streaming CSV logging (#392); CMake generated-header fix (#393).

Correctness fixes

  • Spectral cone projection fix (#410, #411): the sorted-ℓ1 projection underlying the nuclear-norm and ℓ1 cones could return points far outside the cone for inputs with repeated leading entries near the polar boundary (silently, since residuals never verify cone membership — the returned y could be off the dual cone while reporting convergence). Replaced with the tie-robust Duchi et al. scan; also fixed stale spectral objects surviving make clean.
  • Complex PSD spectral bugs (#369); MEX persistent-allocation fix (#368); false infeasibility on warm-start with small sigma (#354); undefined behavior in scs_update (#349); read/write serialization (#388); allocation-failure handling (#390); input validation hardening (#389).

Documentation

Comprehensive refresh: algorithm pages now match the shipped code exactly (equilibration, CG/deflation, dynamic scaling, certificate criteria — #413), regenerated example outputs (#414), spectral cone docs (#359, #360, #361, #373), MATLAB/Python install and backend guides (#371, #372, #367, #379, #381, #382).

Compatibility

No breaking API changes. New settings: adaptive_diag_scale (default on; requires adaptive_scale). Changed defaults: acceleration_interval 10 → 5. Note that scs_update deliberately reuses the equilibration computed at scs_init when b/c change (see #399 discussion).

Full log: 3.2.11...3.3.0

Don't miss a new scs release

NewReleases is sending notifications on new releases.