R/177_reductions_dcp2cone_canonicalizers_quad_over_lin_canon.R

Defines functions quad_over_lin_canon

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

## CVXPY SOURCE: reductions/dcp2cone/canonicalizers/quad_over_lin_canon.py
## quad_over_lin(x, y) = ||x||^2 / y -> t via SOC
## Supports scalar and axis-aware reductions.


quad_over_lin_canon <- function(expr, args, solver_context = NULL) {
  x <- args[[1L]]
  y <- args[[2L]]
  axis <- expr@axis

  if (is.null(axis)) {
    ## Scalar output -- single SOC constraint
    ## ||[y-t, 2*vec(x)]||_2 <= y+t  ==>  ||x||^2 <= t*y
    ## CVXPY: hstack([y-t, 2*x.flatten()]) -> 1D concat, axis=0 -> single cone
    ## In R (always 2D): VStack to get column vector c(1+n, 1) for 1 cone
    t <- Variable(shape = c(1L, 1L))
    y_flat <- reshape_expr(y, c(1L, 1L))
    x_flat <- .cvxr_vec(x)  # c(n, 1) column vector
    lhs <- VStack(y_flat - t, 2 * x_flat)  # c(1+n, 1)
    constraints <- list(SOC(t = y_flat + t, X = lhs, axis = 2L))
    return(list(t, constraints))
  }

  ## Axis-aware output -- one SOC per reduced row/column slice.
  ## axis=2: column-wise cones, body has columns c(y - t_j, 2*x[, j]).
  ## axis=1: row-wise cones, body has rows c(y - t_i, 2*x[i, ]).
  t <- Variable(shape = .shape(expr))
  if (axis == 2L) {
    lhs <- VStack(y - t, 2 * x)
    list(t, list(SOC(t = .cvxr_vec(y + t), X = lhs, axis = 2L)))
  } else {
    lhs <- HStack(y - t, 2 * x)
    list(t, list(SOC(t = .cvxr_vec(y + t), X = lhs, axis = 1L)))
  }
}

method(dcp_canonicalize, QuadOverLin) <- quad_over_lin_canon
method(has_dcp_canon, QuadOverLin) <- 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.