R/186_reductions_dcp2cone_canonicalizers_quad_power_canon.R

Defines functions .quadratic_power power_quad_canon

#####
## DO NOT EDIT THIS FILE!! EDIT THE SOURCE INSTEAD: rsrc_tree/reductions/dcp2cone/canonicalizers/quad/power_canon.R
#####

## CVXPY SOURCE: reductions/dcp2cone/canonicalizers/quad/power_canon.py
## Only handles p in {0, 1, 2}. For p=2: SymbolicQuadForm(x, I, expr).


power_quad_canon <- function(expr, args, solver_context = NULL) {
  affine_expr <- args[[1L]]
  p <- as.numeric(expr@p_used)

  if (is_constant(expr)) {
    return(list(Constant(value(expr)), list()))
  } else if (p == 0) {
    return(list(Constant(matrix(1, nrow = .shape(affine_expr)[1L],
                                ncol = .shape(affine_expr)[2L])), list()))
  } else if (p == 1) {
    return(list(affine_expr, list()))
  } else if (p == 2) {
    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().
    I_mat <- as(as(Matrix::Diagonal(n), "generalMatrix"), "CsparseMatrix")
    if (.s7_is(affine_expr, Variable)) {
      return(list(SymbolicQuadForm(affine_expr, Constant(I_mat), expr), list()))
    } else {
      t <- Variable(shape = .shape(affine_expr))
      return(list(SymbolicQuadForm(t, Constant(I_mat), expr),
                  list(affine_expr == t)))
    }
  }
  cli_abort("Non-constant quadratic forms can't be raised to power > 2.")
}

# -- .quadratic_power: helper for Dcp2Cone dispatch -------------
## CVXPY SOURCE: power.py lines 339-342
.quadratic_power <- function(power_expr) {
  p <- power_expr@p_used
  !is.null(p) && p %in% c(0, 1, 2)
}

method(quad_canonicalize, Power) <- function(expr, args, ...) {
  if (!.quadratic_power(expr)) return(NULL)
  power_quad_canon(expr, args)
}
method(quad_canonicalize, PowerApprox) <- function(expr, args, ...) {
  if (!.quadratic_power(expr)) return(NULL)
  power_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, Power) <- function(expr) TRUE
method(has_quad_canon, PowerApprox) <- function(expr) TRUE

Try the CVXR package in your browser

Any scripts or data that you put into this service are public.

CVXR documentation built on Aug. 24, 2026, 9:10 a.m.