Skip to content

Fix matrix_frac crash on a matrix argument with an ndarray P - #3462

Open
chuenchen309 wants to merge 1 commit into
cvxpy:masterfrom
chuenchen309:fix/matrix-frac-ndarray-matrix
Open

chuenchen309 wants to merge 1 commit into
cvxpy:masterfrom
chuenchen309:fix/matrix-frac-ndarray-matrix

Conversation

@chuenchen309

@chuenchen309 chuenchen309 commented Jul 19, 2026

Copy link
Copy Markdown

Description

cp.matrix_frac(X, P) computes tr(Xᵀ P⁻¹ X), and a matrix X (shape (n, k), k > 1) is a supported, tested case. But when P is a numpy ndarray — the most natural way to pass a constant matrix, e.g. cp.matrix_frac(X, np.eye(n)) — it raises ValueError: Invalid dimensions for arguments to quad_form, and a Problem using it cannot even be constructed.

The matrix_frac wrapper takes a QuadForm shortcut whenever P is an ndarray, but QuadForm only accepts a vector x. The same X, P succeed through every other path — cp.Constant(P), a Variable P, and P.tolist() — all returning the correct tr(Xᵀ P⁻¹ X). So the failure is triggered purely by the type of P, not the math.

The fix restricts the QuadForm shortcut to a vector x; a matrix X falls through to MatrixFrac, which already handles an ndarray P by casting it to a Constant. A vector x still uses the shortcut unchanged, and mismatched dimensions still raise the proper error.

Verified: cvxpy/tests/test_atoms.py passes (122), the value matches np.trace(X.T @ inv(P) @ X) and the Constant(P) path, and a full Problem(Minimize(cp.matrix_frac(Variable((n, k)), P))) now constructs and solves to optimal. Added a regression test.

Issue link (if applicable): none — found during atom-behavior verification.

Type of change

  • New feature (backwards compatible)
  • New feature (breaking API changes)
  • Bug fix
  • Other (Documentation, CI, ...)

Contribution checklist

  • Add our license to new files. (N/A — no new files; only cvxpy/atoms/matrix_frac.py and cvxpy/tests/test_atoms.py are edited.)
  • Check that your code adheres to our coding style.
  • Write unittests.
  • Run the unittests and check that they’re passing. (test_atoms.py: 122 passed.)
  • Run the benchmarks to make sure your change doesn’t introduce a regression. (Not run; the change only narrows a dispatch condition and adds no work on the existing vector path.)

Disclosure: this change was found, fixed, tested and described by an AI coding agent (Claude Code) running on this account. The account holder reviews every change and is accountable for it. The verification above is real and re-runnable from the diff. If this isn't the kind of contribution you want, say so and I'll close it.

When P is a numpy ndarray, matrix_frac took a QuadForm shortcut unconditionally,
but QuadForm only accepts a vector x. So matrix_frac(X, np.eye(n)) with a matrix X
raised "Invalid dimensions for arguments to quad_form" — even though the same X, P
work through Constant(P), a Variable P, or P.tolist(). Restrict the shortcut to a
vector x; a matrix X now falls through to MatrixFrac (which casts the ndarray P).

Co-authored-by: Claude (Claude Code) <noreply@anthropic.com>
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@PTNobel

PTNobel commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

Hello! Thank you for your contribution! We cannot review it until you sign the CLA.

Additionally, we require use of our PR template, even for agent drafted PRs.

@github-actions

Copy link
Copy Markdown
Contributor

Benchmarks that have stayed the same:

Change Before [359e9bb] After [5d04e90] Ratio Benchmark (Parameter)
2.54±0.05s 2.76±0.08s 1.09 quantum_hilbert_matrix.QuantumHilbertMatrix.time_compile_problem
1.76±0.02s 1.79±0.03s 1.02 simple_LP_benchmarks.SimpleScalarParametrizedLPBenchmark.time_compile_problem
12.8±0s 12.8±0.02s 1.01 finance.CVaRBenchmark.time_compile_problem
1.78±0.02s 1.79±0.02s 1.01 finance.FactorCovarianceModel.time_compile_problem
1.54±0s 1.55±0.01s 1.01 semidefinite_programming.SemidefiniteProgramming.time_compile_problem
1.90±0s 1.92±0.01s 1.01 simple_QP_benchmarks.LeastSquares.time_compile_problem
2.39±0.01s 2.38±0.01s 1 gini_portfolio.Cajas.time_compile_problem
1.21±0s 1.22±0.01s 1 gini_portfolio.Murray.time_compile_problem
1.31±0.01s 1.31±0.02s 1 gini_portfolio.Yitzhaki.time_compile_problem
3.92±0s 3.93±0.02s 1 huber_regression.HuberRegression.time_compile_problem
3.35±0s 3.35±0.01s 1 matrix_stuffing.ConeMatrixStuffingBench.time_compile_problem
3.63±0.03s 3.63±0.05s 1 matrix_stuffing.ParamSmallMatrixStuffing.time_compile_problem
2.37±0.01s 2.37±0.01s 1 matrix_stuffing.SmallMatrixStuffing.time_compile_problem
4.49±0s 4.50±0.01s 1 optimal_advertising.OptimalAdvertising.time_compile_problem
20.8±0.03s 20.8±0.01s 1 sdp_segfault_1132_benchmark.SDPSegfault1132Benchmark.time_compile_problem
9.88±0.02s 9.86±0.01s 1 simple_LP_benchmarks.SimpleLPBenchmark.time_compile_problem
2.61±0.01s 2.60±0s 1 simple_QP_benchmarks.ParametrizedQPBenchmark.time_compile_problem
4.22±0s 4.23±0.02s 1 simple_QP_benchmarks.SimpleQPBenchmark.time_compile_problem
3.78±0.01s 3.77±0s 1 simple_QP_benchmarks.UnconstrainedQP.time_compile_problem
2.34±0s 2.33±0s 1 slow_pruning_1668_benchmark.SlowPruningBenchmark.time_compile_problem
4.36±0.01s 4.38±0.03s 1 svm_l1_regularization.SVMWithL1Regularization.time_compile_problem
147±1ms 146±1ms 0.99 high_dim_convex_plasticity.ConvexPlasticity.time_compile_problem
1.45±0.01s 1.43±0.01s 0.99 tv_inpainting.TvInpainting.time_compile_problem
716±1ms 692±20ms 0.97 simple_LP_benchmarks.SimpleFullyParametrizedLPBenchmark.time_compile_problem
1.40±0.01s 1.34±0.07s 0.96 matrix_stuffing.ParamConeMatrixStuffing.time_compile_problem

@PTNobel

PTNobel commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Hello, please sign the CLA so we can review your PR!

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants