R/206_reductions_dgp2dcp_canonicalizers_pnorm_canon.R

Defines functions .dgp_pnorm_canon

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

## CVXPY SOURCE: reductions/dgp2dcp/canonicalizers/pnorm_canon.py
## DGP canonicalizer for Pnorm: ||x||_p -> (1/p) * log_sum_exp(p * x_i)
## In log-space: log(||x||_p) = (1/p) * log(sum(exp(p * log(x_i))))

.dgp_pnorm_canon <- function(expr, args) {
  x <- args[[1L]]
  p <- expr@p

  ## Scalar -> promote
  if (expr_is_scalar(x)) {
    x <- cvxr_promote(x, c(1L, 1L))
  }

  ## No axis or 1D: flatten and compute single norm
  if (is.null(expr@axis) || length(x@shape) == 1L ||
      (length(x@shape) == 2L && x@shape[2L] == 1L)) {
    x <- vec(x)
    n <- expr_size(x)
    elems <- lapply(seq_len(n), function(i) x[i] * p)
    result <- (1.0 / p) * log_sum_exp(do.call(hstack, elems))
    return(list(result, list()))
  }

  ## Axis-aware: axis=0 -> transpose so we iterate rows
  if (!is.null(expr@axis) && expr@axis == 2L) {
    x <- t(x)
  }

  rows <- list()
  for (i in seq_len(x@shape[1L])) {
    row_x <- x[i, ]
    ncols <- x@shape[2L]
    elems <- lapply(seq_len(ncols), function(j) row_x[j] * p)
    rows <- c(rows, list((1.0 / p) * log_sum_exp(do.call(hstack, elems))))
  }
  result <- do.call(VStack, rows)
  list(result, list())
}

Try the CVXR package in your browser

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

CVXR documentation built on March 6, 2026, 9:10 a.m.