Nothing
#####
## DO NOT EDIT THIS FILE!! EDIT THE SOURCE INSTEAD: rsrc_tree/reductions/dcp2cone/canonicalizers/quad/quad_over_lin_canon.R
#####
## CVXPY SOURCE: reductions/dcp2cone/canonicalizers/quad/quad_over_lin_canon.py
## Builds I/y as the P matrix. With `axis` set, attaches one block of flat
## indices per output element (`block_indices`) so the extractor can scale
## each block by its own coefficient (quad_over_lin_canon.py:39-51, 64-125).
qol_quad_canon <- function(expr, args, solver_context = NULL) {
affine_expr <- args[[1L]]
y <- args[[2L]]
## y must be constant scalar (guarded by quad_canonicalize below).
y_val <- as.numeric(value(y))
n <- prod(.shape(affine_expr))
## Keep P sparse: ddiMatrix has implicit unit diagonal that
## Matrix::summary() doesn't report; convert to dgCMatrix for
## explicit entries. Avoids O(n^2) dense matrix from as.matrix().
quad_mat <- as(as(Matrix::Diagonal(n) / y_val, "generalMatrix"), "CsparseMatrix")
## CVXPY SOURCE: quad_over_lin_canon.py:39-51 -- block indices when axis
## is specified (claims-audit row C0670; before 1.9.2.9141 the axis case
## was handed to the SOC canon, so a QP-only solver refused it).
block_indices <- NULL
if (!is.null(expr@axis)) {
block_indices <- .qol_block_indices(.shape(affine_expr), expr@axis)
}
## CVXPY v1.9.3 fix: #3384 -- a variable with a dim-reducing attribute
## (symmetric/PSD/NSD/diag/sparsity) is substituted by an affine expression
## in CvxAttr2Constr, so it must go through the auxiliary variable.
if (.s7_is(affine_expr, Variable) && !.cvxattr_has_dim_reducing_attr(affine_expr)) {
list(SymbolicQuadForm(affine_expr, Constant(quad_mat), expr,
block_indices = block_indices), list())
} else {
t <- Variable(shape = .shape(affine_expr))
list(SymbolicQuadForm(t, Constant(quad_mat), expr,
block_indices = block_indices),
list(affine_expr == t))
}
}
## CVXPY SOURCE: quad_over_lin_canon.py:64-125 -- _compute_block_indices.
## block_indices[[j]] is the set of flat (column-major, as the canon backend
## vectorizes) indices of the input that output element j reduces over. Flat
## indices are 1-based here because coeff_quad_form consumes them against
## Matrix::summary() triplets. Two-dimensional only, as every CVXR axis atom
## (`.validate_axis(axis, 2L)` in quad_over_lin.R): R axis 2 (column-wise,
## CVXPY axis 0) gives one contiguous block per column; R axis 1 (row-wise,
## CVXPY axis 1) gives one strided block per row.
.qol_block_indices <- function(shape, axis) {
m <- as.integer(shape[1L])
n <- as.integer(if (length(shape) >= 2L) shape[2L] else 1L)
if (axis == 2L) {
lapply(seq_len(n), function(j) (j - 1L) * m + seq_len(m))
} else {
lapply(seq_len(m), function(i) i + m * (seq_len(n) - 1L))
}
}
method(quad_canonicalize, QuadOverLin) <- function(expr, args, ...) {
## CVXPY 1.9 parity: decide from the canonicalized denominator, not
## expr@args[[1L]] being PWL. For quad_over_lin(exp(x), 1), exp(x)
## has already canonicalized to an affine variable plus ExpCone.
## (dcp2cone.py:235: `not args[1].is_constant()` is the only guard; the
## axis case is handled inside the quad canon via block_indices.)
if (!is_constant(args[[2L]])) return(NULL)
qol_quad_canon(expr, args)
}
## Membership marker for the CSE cache: `affine_above` is part of a subtree's
## cache key only when the quad branch could fire inside it
## (`.affine_above_relevant`, dcp2cone.R). CVXPY reads this off its
## `quad_canon_methods` dict; CVXR needs an explicit predicate per class.
method(has_quad_canon, QuadOverLin) <- function(expr) TRUE
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.