Skip to content

CVXR 1.9.3 - #161

Merged
bnaras merged 13 commits into
masterfrom
release-1.9.3
Oct 19, 2026
Merged

bnaras merged 13 commits into
masterfrom
release-1.9.3

Conversation

@bnaras

@bnaras bnaras commented Oct 16, 2026

Copy link
Copy Markdown
Collaborator

CVXR 1.9.3, tracking CVXPY 1.9.3.

Synced from the development tree (publish.sh). Highlights:

  • Fixes for wrong answers: GUROBI quadratic cross terms and SOC duals, CVXOPT without
    inequality constraints, matrix norms aligned with base R and CVXPY, gmatmul with
    parameters under DGP, DPP-scoped curvature caches, perspective() of structured matrix
    variables.
  • Solver selection follows CVXPY 1.9 (problem form first, then the solver's QP or conic
    interface).
  • CPLEX returns SOC and linear duals.

Full list in NEWS.md under "CVXR 1.9.3".

Checks before this PR: R CMD check Status OK (full suite); --as-cran on the CRAN build
Status OK; reverse dependencies: no new problems caused by CVXR.

bnaras added 13 commits October 15, 2026 18:32
Fixes the Windows CI test crash: a matrix product by a 1 x 1 constant
read past the matrix in the C++ backend. Also honors axis and keepdims
in sum/max/min/prod of an expression, and guards the DIFFCP test.
Temporary: Posit Package Manager still serves 0.6.1. Revert to
any::ECOSolveR once 0.6.2 propagates.
Temporary; the five-leg workflow is restored next.
Drops the linux-arm64 leg and the temporary GitHub install of ECOSolveR,
which confirmed 0.6.2 fixes ECOS_BB on aarch64.
0.6.2 fixes ECOS_BB on aarch64 Linux (wrong mixed-integer answers);
confirmed on the linux-arm64 CI leg.
Synced from the development repo (commits bb13104..ce6ef36 plus the vignette):

* x / A with a matrix or vector A is entrywise (was division by A[1, 1]);
  C++ get_div_mat.
* Constants from any Matrix class are stored as general double CSC; a
  logical matrix constant keeps its shape.
* Sparse bounds are validated against the variable's sparsity pattern, as
  CVXPY does; BOUNDED_VARIABLES solvers receive them as bounds.
* CLARABEL and OSQP warm paths start a fresh solver when the sparsity
  pattern of A or P changes.
* whats_new.Rmd lists these and the 1 x 1 constant and axis fixes.

NEWS has one bullet per fix under "Changed results". Tests seen failing on
the previous build accompany each fix. R CMD check --as-cran on the CRAN
tarball: Status OK.
Sync from new_design d76d55b (DESCRIPTION 1.9.3, 2026-10-17), covering the
dev versions 1.9.2.9500 to 1.9.2.9515:

- %*% rejects a scalar or non-conforming 1 x 1 operand; division with
  non-broadcastable shapes is an error; value() of expressions over
  Matrix-class constants evaluates.
- Variable bounds accept every container Constant() accepts.
- conv, cumsum and kron are not log-log affine; four atoms reject a complex
  argument; cvxr_norm rejects an unknown string p; variadic atoms reject a
  named argument; several silent fallthroughs now raise; Matrix generics
  imported (colSums, rowSums, which, determinant, format); bounds
  propagation keeps sparse constants sparse; cone membership by class name.
- problem_data() shares the compile cache with psolve(); GLPK_MI reports an
  infeasible MILP as infeasible and uses presolve for integer problems.
- The C++ bridge no longer draws from R's random number stream (the S4-era
  debug id and the _R_DEBUG facility are removed).

New tests: test-problem-data-cache.R, test-cpp-bridge-rng.R. NEWS and the
what's-new vignette updated. R CMD check --as-cran OK on the CRAN tarball;
UBSAN and ASAN legs clean; full benchmark shows no regression.
…ings)

The 1.9.3 revdep check (43 packages) found aramappings 0.2.0 newly broken:
six tests do `Pvar[idx, ] %*% v_k` with an (N-1) x 1 expression and a
length-1 `v_k`. Base R promotes a length-1 vector to 1 x 1 and accepts the
product whenever the other operand's inner dimension is 1 (?matmult), and
CVXR 1.9.2 gave the right answer; 1.9.2.9500 (F1) rejected every bare
scalar operand with CVXPY's "Scalar operands are not allowed" message.

CVXPY's check (expression.py:842-843) is on a () operand, which R does not
have. .check_matmul_scalar now takes the Expression operand and rejects a
bare scalar only when that operand's inner dimension is not 1, which is
exactly what base R rejects; a conforming scalar goes on as a 1 x 1 constant
through mul_shapes_promote. Recorded deviation, better-in-r. The eight F1
rejection expectations in test-cvxpy-expr-problem-parity.R are all
non-conforming and still pass; the F1-era test in test-phase2d-dispatch.R
asserted that x(3 x 1) %*% 5 errors and now asserts the base R rule.

New test in test-cvxpy-expr-problem-parity.R (seen failing on the pre-fix
build). aramappings re-checked serially against the fix: Status OK, PASS 388.
NEWS, the what's-new vignette and cran-comments reworded (the conforming
case is a product). The CI matrix gains the ubuntu-24.04-arm (release) leg:
ECOSolveR 0.6.2 and arm64 binaries of every compiled hard dependency are on
Posit Package Manager. Version stays 1.9.3.
…e base R option formals

A release candidate rejected every named entry in `...` to these four
functions, which broke do.call(vstack, <list named by split()>), an idiom
1.9.2 accepted (found by the cvxr_docs regression pass, isotonic-regression
example). They now follow base R: a name on an operand labels it and is
dropped; max_elemwise and min_elemwise take na.rm as pmax/pmin do, and
hstack and vstack take deparse.level as cbind/rbind do, with no effect.
max_elemwise(u, v, na.rm = TRUE) no longer takes TRUE as a third operand.

Dev check Status OK PASS 19573; CRAN-form --as-cran Status OK, subset PASS
1442; docs regression 73/73. cran-comments updated for the superseding
upload. Version stays 1.9.3.
…mwise, sum, max, min, prod; multi-operand sum, prod, max, min are base R's

A release candidate rejected every named entry in `...` to hstack,
vstack, max_elemwise and min_elemwise, which broke
do.call(vstack, <list named by split()>), an idiom 1.9.2 accepted (found
by the cvxr_docs regression pass, isotonic-regression example). The
Summary methods did the same for any name other than axis and keepdims,
so sum(a = x) and do.call(sum, <named list>) errored.

All eight now follow base R: a name on an operand labels it and is
dropped; max_elemwise and min_elemwise take na.rm as pmax/pmin do, and
hstack and vstack take deparse.level as cbind/rbind do, with no effect;
sum, max, min and prod keep axis and keepdims as their only options.
max_elemwise(u, v, na.rm = TRUE) no longer takes TRUE as a third operand.

sum, prod, max and min with more than one operand also mean what they
mean in base R: each operand is reduced on its own and the results
combined, so sum(x, 2) is sum(x) + 2 and max(x, y) is one scalar, the
largest entry of either. They were sum(x + 2) with broadcasting,
prod(x * y), and the elementwise maximum and minimum (present in 1.9.2);
max_elemwise and min_elemwise remain for the elementwise forms.

Dev check Status OK PASS 19602; CRAN-form --as-cran Status OK, subset PASS
1442; docs regression 73/73; revdep 43 checked, only the known savvyGLM
MOSEK option problem. cran-comments updated for the superseding upload.
Version stays 1.9.3.
@bnaras
bnaras merged commit b69c8ed into master Oct 19, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant