R/038_atoms_affine_wraps.R

Defines functions .validate_real_square

#####
## DO NOT EDIT THIS FILE!! EDIT THE SOURCE INSTEAD: rsrc_tree/atoms/affine/wraps.R
#####

## CVXPY SOURCE: atoms/affine/wraps.py
## Wrap -- no-op wrapper atoms that assert matrix properties
##
## These are used by Complex2Real to annotate expressions with properties
## (PSD, symmetric, Hermitian, etc.) that are known from the structure
## of the real/imaginary decomposition but not inferrable by DCP alone.


# -- Wrap base class --------------------------------------------------

Wrap <- new_class("Wrap", parent = AffAtom, package = "CVXR",
  constructor = function(arg, id = NULL) {
    if (FALSE) new_object(S7_object())  ## S7 static-check guard
    if (is.null(id)) id <- next_expr_id()
    arg <- as_expr(arg)
    obj <- .fast_new(Wrap, S7_object(),
      id    = as.integer(id),
      .cache = new.env(parent = emptyenv()),
      args  = list(arg),
      shape = .shape(arg)
    )
    validate_arguments(obj)
    obj
  }
)

## CVXPY SOURCE: wraps.py lines 29-33
method(is_atom_log_log_convex, Wrap) <- function(x) TRUE
method(is_atom_log_log_concave, Wrap) <- function(x) TRUE

## CVXPY SOURCE: wraps.py lines 35-38
method(numeric_value, Wrap) <- function(x, values, ...) values[[1L]]

## CVXPY SOURCE: wraps.py lines 40-41
method(is_complex, Wrap) <- function(x) is_complex(.args(x)[[1L]])

## CVXPY SOURCE: wraps.py lines 43-46
method(shape_from_args, Wrap) <- function(x) .arg_shape(x)

## CVXPY SOURCE: wraps.py lines 48-67 -- identity passthrough
method(graph_implementation, Wrap) <- function(x, arg_objs, shape, data = NULL, ...) {
  list(arg_objs[[1L]], list())
}

# -- nonneg_wrap ------------------------------------------------------
## CVXPY SOURCE: wraps.py lines 70-74

nonneg_wrap <- new_class("nonneg_wrap", parent = Wrap, package = "CVXR",
  constructor = function(arg, id = NULL) {
    if (FALSE) new_object(S7_object())  ## S7 static-check guard
    if (is.null(id)) id <- next_expr_id()
    arg <- as_expr(arg)
    obj <- .fast_new(nonneg_wrap, S7_object(),
      id    = as.integer(id),
      .cache = new.env(parent = emptyenv()),
      args  = list(arg),
      shape = .shape(arg)
    )
    validate_arguments(obj)
    obj
  }
)
method(is_nonneg, nonneg_wrap) <- function(x) TRUE

# -- nonpos_wrap ------------------------------------------------------
## CVXPY SOURCE: wraps.py lines 77-81

nonpos_wrap <- new_class("nonpos_wrap", parent = Wrap, package = "CVXR",
  constructor = function(arg, id = NULL) {
    if (FALSE) new_object(S7_object())  ## S7 static-check guard
    if (is.null(id)) id <- next_expr_id()
    arg <- as_expr(arg)
    obj <- .fast_new(nonpos_wrap, S7_object(),
      id    = as.integer(id),
      .cache = new.env(parent = emptyenv()),
      args  = list(arg),
      shape = .shape(arg)
    )
    validate_arguments(obj)
    obj
  }
)
method(is_nonpos, nonpos_wrap) <- function(x) TRUE

# -- psd_wrap ---------------------------------------------------------
## CVXPY SOURCE: wraps.py lines 84-107

psd_wrap <- new_class("psd_wrap", parent = Wrap, package = "CVXR",
  constructor = function(arg, id = NULL) {
    if (FALSE) new_object(S7_object())  ## S7 static-check guard
    if (is.null(id)) id <- next_expr_id()
    arg <- as_expr(arg)
    obj <- .fast_new(psd_wrap, S7_object(),
      id    = as.integer(id),
      .cache = new.env(parent = emptyenv()),
      args  = list(arg),
      shape = .shape(arg)
    )
    validate_arguments(obj)
    obj
  }
)

method(validate_arguments, psd_wrap) <- function(x) {
  arg <- .args(x)[[1L]]
  if (length(.shape(arg)) != 2L || .shape(arg)[1L] != .shape(arg)[2L]) {
    cli_abort("The input to {.cls psd_wrap} must be a square matrix.")
  }
  invisible(NULL)
}

method(is_psd, psd_wrap) <- function(x) TRUE
method(is_nsd, psd_wrap) <- function(x) FALSE

## CVXPY SOURCE: wraps.py lines 102-103
## "symmetric" means "real symmetric" -- complex PSD matrices are Hermitian, not symmetric
method(is_symmetric, psd_wrap) <- function(x) !is_complex(.args(x)[[1L]])

## CVXPY SOURCE: wraps.py lines 105-106
method(is_hermitian, psd_wrap) <- function(x) TRUE

# -- nsd_wrap ---------------------------------------------------------
## CVXPY SOURCE: wraps.py lines 107-130
##
## The seventh Wrap subclass, absent from CVXR until 1.9.1.9042. Its two
## upstream consumers had been handled differently, one soundly and one not:
##   - cvx_attr2constr.py:151 -- CVXR used `-psd_wrap(-expr)`, which is
##     curvature-equivalent but two nodes deep and not the upstream tree;
##   - complex2real/canonicalizers/matrix_canon.py:200 -- CVXR had NO
##     substitute, and wrapped in psd_wrap unconditionally instead, asserting
##     that the real embedding of an NSD P is PSD.
## Found by the completeness audit; see notes/audit/completeness_ledger.md
## findings 7 and 8.

nsd_wrap <- new_class("nsd_wrap", parent = Wrap, package = "CVXR",
  constructor = function(arg, id = NULL) {
    if (FALSE) new_object(S7_object())  ## S7 static-check guard
    if (is.null(id)) id <- next_expr_id()
    arg <- as_expr(arg)
    obj <- .fast_new(nsd_wrap, S7_object(),
      id    = as.integer(id),
      .cache = new.env(parent = emptyenv()),
      args  = list(arg),
      shape = .shape(arg)
    )
    validate_arguments(obj)
    obj
  }
)

method(validate_arguments, nsd_wrap) <- function(x) {
  arg <- .args(x)[[1L]]
  if (length(.shape(arg)) != 2L || .shape(arg)[1L] != .shape(arg)[2L]) {
    cli_abort("The input to {.cls nsd_wrap} must be a square matrix.")
  }
  invisible(NULL)
}

## CVXPY SOURCE: wraps.py lines 118-122
method(is_psd, nsd_wrap) <- function(x) FALSE
method(is_nsd, nsd_wrap) <- function(x) TRUE

## CVXPY SOURCE: wraps.py lines 124-125
## "symmetric" means "real symmetric" -- complex NSD matrices are Hermitian.
method(is_symmetric, nsd_wrap) <- function(x) !is_complex(.args(x)[[1L]])

## CVXPY SOURCE: wraps.py lines 127-128
method(is_hermitian, nsd_wrap) <- function(x) TRUE

# -- symmetric_wrap ---------------------------------------------------
## CVXPY SOURCE: wraps.py lines 109-121

symmetric_wrap <- new_class("symmetric_wrap", parent = Wrap, package = "CVXR",
  constructor = function(arg, id = NULL) {
    if (FALSE) new_object(S7_object())  ## S7 static-check guard
    if (is.null(id)) id <- next_expr_id()
    arg <- as_expr(arg)
    obj <- .fast_new(symmetric_wrap, S7_object(),
      id    = as.integer(id),
      .cache = new.env(parent = emptyenv()),
      args  = list(arg),
      shape = .shape(arg)
    )
    validate_arguments(obj)
    obj
  }
)

method(validate_arguments, symmetric_wrap) <- function(x) {
  .validate_real_square(.args(x)[[1L]])
}

method(is_symmetric, symmetric_wrap) <- function(x) TRUE
method(is_hermitian, symmetric_wrap) <- function(x) TRUE

# -- hermitian_wrap ---------------------------------------------------
## CVXPY SOURCE: wraps.py lines 123-136

hermitian_wrap <- new_class("hermitian_wrap", parent = Wrap, package = "CVXR",
  constructor = function(arg, id = NULL) {
    if (FALSE) new_object(S7_object())  ## S7 static-check guard
    if (is.null(id)) id <- next_expr_id()
    arg <- as_expr(arg)
    obj <- .fast_new(hermitian_wrap, S7_object(),
      id    = as.integer(id),
      .cache = new.env(parent = emptyenv()),
      args  = list(arg),
      shape = .shape(arg)
    )
    validate_arguments(obj)
    obj
  }
)

method(validate_arguments, hermitian_wrap) <- function(x) {
  arg <- .args(x)[[1L]]
  if (length(.shape(arg)) != 2L || .shape(arg)[1L] != .shape(arg)[2L]) {
    cli_abort("The input to {.cls hermitian_wrap} must be a square matrix.")
  }
  invisible(NULL)
}

method(is_hermitian, hermitian_wrap) <- function(x) TRUE

# -- skew_symmetric_wrap ----------------------------------------------
## CVXPY SOURCE: wraps.py lines 139-148

skew_symmetric_wrap <- new_class("skew_symmetric_wrap", parent = Wrap, package = "CVXR",
  constructor = function(arg, id = NULL) {
    if (FALSE) new_object(S7_object())  ## S7 static-check guard
    if (is.null(id)) id <- next_expr_id()
    arg <- as_expr(arg)
    obj <- .fast_new(skew_symmetric_wrap, S7_object(),
      id    = as.integer(id),
      .cache = new.env(parent = emptyenv()),
      args  = list(arg),
      shape = .shape(arg)
    )
    validate_arguments(obj)
    obj
  }
)

method(validate_arguments, skew_symmetric_wrap) <- function(x) {
  .validate_real_square(.args(x)[[1L]])
}

method(is_skew_symmetric, skew_symmetric_wrap) <- function(x) TRUE

# -- Helper: validate real square matrix ------------------------------
## CVXPY SOURCE: wraps.py lines 150-157

.validate_real_square <- function(arg) {
  if (length(.shape(arg)) != 2L || .shape(arg)[1L] != .shape(arg)[2L]) {
    cli_abort("The input must be a square matrix.")
  }
  if (!is_real(arg)) {
    cli_abort("The input must be a real matrix.")
  }
  invisible(NULL)
}

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.