R/028_atoms_affine_affine_atom.R

Defines functions .affatom_is_nsd .affatom_is_psd

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

## CVXPY SOURCE: atoms/affine/affine_atom.py
## AffAtom -- abstract base class for affine atoms
##
## Affine atoms are both convex and concave, and allow complex arguments.
## Sign propagation follows sum_signs logic by default.


AffAtom <- new_class("AffAtom", parent = Atom, package = "CVXR",
  constructor = function(args, shape, id = NULL) {
    if (is.null(id)) id <- next_expr_id()
    args <- lapply(args, as_expr)
    if (length(args) == 0L) {
      cli_abort("No arguments given to {.cls AffAtom}.")
    }
    shape <- validate_shape(shape)
    obj <- new_object(S7_object(),
      id    = as.integer(id),
      .cache = new.env(parent = emptyenv()),
      args  = args,
      shape = shape
    )
    validate_arguments(obj)
    obj
  }
)

# -- validate_arguments: AffAtom allows complex ----------------------
## CVXPY SOURCE: affine_atom.py inherits from Atom with _allow_complex = True

method(validate_arguments, AffAtom) <- function(x) {
  ## AffAtom allows complex arguments -- no validation needed
  invisible(NULL)
}

# -- sign: sum_signs of args -----------------------------------------
## CVXPY SOURCE: affine_atom.py lines 33-36

method(sign_from_args, AffAtom) <- function(x) {
  sum_signs(x@args)
}

# -- Complex propagation ---------------------------------------------
## CVXPY SOURCE: affine_atom.py lines 38-48

method(is_imag, AffAtom) <- function(x) {
  .all_args(x, is_imag)
}

method(is_complex, AffAtom) <- function(x) {
  .any_args(x, is_complex)
}

# -- Convexity/concavity: affine is both -----------------------------
## CVXPY SOURCE: affine_atom.py lines 50-58

method(is_atom_convex, AffAtom) <- function(x) TRUE
method(is_atom_concave, AffAtom) <- function(x) TRUE

# -- Monotonicity: default increasing --------------------------------
## CVXPY SOURCE: affine_atom.py lines 60-70

method(is_incr, AffAtom) <- function(x, idx, ...) TRUE
method(is_decr, AffAtom) <- function(x, idx, ...) FALSE

# -- Quadratic / PWL analysis ---------------------------------------
## CVXPY SOURCE: affine_atom.py lines 72-88

method(is_quadratic, AffAtom) <- function(x) {
  .all_args(x, is_quadratic)
}

method(has_quadratic_term, AffAtom) <- function(x) {
  .any_args(x, has_quadratic_term)
}

method(is_qpwa, AffAtom) <- function(x) {
  .all_args(x, is_qpwa)
}

method(is_pwl, AffAtom) <- function(x) {
  .all_args(x, is_pwl)
}

# -- PSD/NSD propagation ---------------------------------------------
## CVXPY SOURCE: affine_atom.py lines 91-109
## For affine atoms, PSD/NSD propagates through monotonicity:
## is_psd: all args satisfy (incr(idx) and arg.is_psd()) or (decr(idx) and arg.is_nsd())
## is_nsd: mirror

method(is_psd, AffAtom) <- function(x) {
  cached <- cache_get(x, "is_psd")
  if (!cache_miss(cached)) return(cached)
  result <- .affatom_is_psd(x)
  cache_set(x, "is_psd", result)
  result
}

.affatom_is_psd <- function(x) {
  for (idx in seq_along(x@args)) {
    arg <- x@args[[idx]]
    if (!((is_incr(x, idx) && is_psd(arg)) ||
          (is_decr(x, idx) && is_nsd(arg)))) {
      return(FALSE)
    }
  }
  TRUE
}

method(is_nsd, AffAtom) <- function(x) {
  cached <- cache_get(x, "is_nsd")
  if (!cache_miss(cached)) return(cached)
  result <- .affatom_is_nsd(x)
  cache_set(x, "is_nsd", result)
  result
}

.affatom_is_nsd <- function(x) {
  for (idx in seq_along(x@args)) {
    arg <- x@args[[idx]]
    if (!((is_decr(x, idx) && is_psd(arg)) ||
          (is_incr(x, idx) && is_nsd(arg)))) {
      return(FALSE)
    }
  }
  TRUE
}

# -- grad ------------------------------------------------------------
## CVXPY SOURCE: affine_atom.py lines 111-166
## Uses fake LinOp tree + canonInterface to compute gradient matrix.
## Deferred -- requires full canonInterface integration.

method(grad, AffAtom) <- function(x) {
  ## Stub: full implementation requires canonInterface.get_problem_matrix
  cli_abort("grad() not yet implemented for {.cls AffAtom} subclasses.")
}

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.