Repository navigation
Conversation
Three gradcheck tests failed on scs >= 3.3.0 and passed on 3.2.11. The
cause is not a regression in SCS, cvxpy or the implicit derivative: both
sides of the comparison were only accurate to ~1e-4, which is the atol
being asserted.
Measured against the closed-form Jacobian of the vector-equality case,
the analytic gradient is off by 1.25e-02 at SCS's default tolerance and
by 7.0e-10 at eps=1e-10. The same holds for the SDP (3.05e-04 vs
2.4e-08). So the derivative machinery is correct and its accuracy is
capped by the forward solve. The finite difference is worse still: at
default tolerance its error is pinned at ~3.4e-04 for every step size
from 1e-6 to 1e-3, i.e. pure solver noise, and only scales with h once
the solve is tight.
3.3.x broke nothing. It stopped over-delivering on the requested
tolerance, so the two noise realizations stopped cancelling.
Ask for a solve accurate enough that finite differencing is meaningful,
instead of loosening the assertions or bounding scs:
- GRADCHECK_SOLVER_ARGS = {"eps": 1e-10}, passed at layer construction
in all 14 diffcp-backed gradcheck tests, not only the three that
failed - every one of them had the same latent exposure.
- test_sdp also takes eps=1e-4 for the finite-difference step. Its
optimum is a rank-one projector, so most entries of dX/dC are near
zero and are compared against atol alone; a tight solve alone leaves
those at the finite-difference floor.
No assertion is loosened and no version bound is added. The tightest
margin across all 18 gradcheck tests goes from ~1x to 1000x: 87 passed
on both scs 3.3.1 and 3.2.11, against 3 failed / 84 passed before.
The MOREAU-backed gradcheck tests are left alone: eps is a diffcp/SCS
key and those tests are unaffected.
Diagnosis confirmed independently by SCS upstream in cvxgrp/scs#464,
which prescribes this fix. cvxgrp/scs#463 investigated 3.3.0's
b-dependent equilibration as the mechanism and ruled it out.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Author
|
@PTNobel please have a look. This seems to be an annoying problem for cvxpy at the moment |
SteveDiamond
approved these changes
Oct 24, 2026
SteveDiamond
left a comment
Collaborator
There was a problem hiding this comment.
The tighter forward solves and larger SDP finite-difference step are a reasonable fix for solver-noise-sensitive gradchecks. Assertions are preserved and production code is unchanged. Reviewed the diff; I did not rerun the reported local tests, and the historical failing CI job details are no longer available.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #244.
The variable is the tolerance, not the SCS version
scs >= 3.3.0broke three gradcheck tests. It turns out neither SCS nor the implicit derivative is wrong — both sides of the gradcheck comparison were only accurate to ~1e-4, which is theatolbeing asserted.Measured against the closed-form Jacobian of
test_dual_gradcheck_vector_equality:eps=1e-10Same story for
test_sdp: the layer's analytic Jacobian is off by 3.05e-04 at default tolerance and 2.4e-08 ateps=1e-8. So cvxpylayers' derivative machinery is correct, and its accuracy is capped by the forward solve.The finite difference is worse. At default tolerance its error is pinned at ~3.4e-04 for every step size from 1e-6 to 1e-3 — that is solver noise, not curvature — and only starts scaling with
honce the solve is tight:eps=1e-103.3.x broke nothing. It stopped over-delivering on the requested tolerance, so the two noise realizations stopped cancelling. The 1.4x margin on 3.2.11 reported in the issue was the noise floor rather than a margin.
The fix
Of the three directions in #244 this is (3): fix the accuracy, don't hide the symptom. No assertion is loosened and no
scsbound is added.GRADCHECK_SOLVER_ARGS = {"eps": 1e-10}, passed at layer construction in all 14 diffcp-backed gradcheck tests — not just the three that failed, since every one of them had the same latent exposure.test_sdpadditionally takeseps=1e-4for the finite-difference step. Its optimum is the rank-one projector onto the smallest eigenvector ofC, so most entries ofdX/dCare near zero and are compared againstatolalone; a tight solve alone leaves those sitting exactly at the finite-difference floor.solver="MOREAU"gradcheck tests are left alone:epsis a diffcp/SCS key and those tests are unaffected.Margins
From a harness that shrinks
atolon each gradcheck test until it fails:test_sdptest_dual_gradcheck_inequalitytest_dual_gradcheck_vector_equalityVerification
scs==3.3.1andscs==3.2.11(baseline: 3 failed / 84 passed on 3.3.1)ruff@0.12.7 checkclean on both touched files;ruff format --diffis byte-identical before and after, so the change is format-neutral (tests/test_torch.pyis CRLF and already failsformat --checkon master, along with two other test files — left as-is rather than dragging in ~2700 lines of reformatting)This should turn
test_cvxpylayersin cvxpy'sextensions.ymlgreen again.Upstream
Diagnosis confirmed independently by SCS upstream in cvxgrp/scs#464, which closed with exactly this prescription: "gradcheck tests should pass tight solver tolerances via
solver_args, and the SDP check needs either a larger finite-difference step or a comparison against a closed-form derivative." cvxgrp/scs#463 investigated 3.3.0's b-dependent equilibration as the mechanism and ruled it out.🤖 Generated with Claude Code