Nothing
#####
## DO NOT EDIT THIS FILE!! EDIT THE SOURCE INSTEAD: rsrc_tree/expressions/constants/constant.R
#####
## CVXPY SOURCE: expressions/constants/constant.py
## Constant -- a constant value in the expression tree
#' Create a Constant Expression
#'
#' Wraps a numeric value as a CVXR constant for use in optimization
#' expressions. Constants are typically created implicitly when combining
#' numeric values with CVXR expressions via arithmetic operators.
#'
#' @param value A numeric scalar, vector, matrix, or sparse matrix.
#' @param name Optional character string name.
#' @returns A \code{Constant} object (inherits from \code{Leaf} and
#' \code{Expression}).
#'
#' @examples
#' c1 <- Constant(5)
#' c2 <- Constant(matrix(1:6, 2, 3))
#'
#' @export
Constant <- new_class("Constant", parent = Leaf, package = "CVXR",
properties = list(
.name = new_property(class = class_character, default = ""),
.sparse = new_property(class = class_logical, default = FALSE)
),
constructor = function(value, name = NULL) {
if (FALSE) new_object(S7_object()) ## S7 static-check guard
## Convert and normalize
sparse <- intf_is_sparse(value)
value <- intf_convert(value)
shape <- as.integer(intf_shape(value))
id <- next_expr_id()
if (is.null(name)) name <- ""
obj <- .fast_new(Constant, S7_object(),
id = as.integer(id),
.cache = new.env(parent = emptyenv()),
shape = shape,
.value = value,
attributes = list(
nonneg = FALSE, nonpos = FALSE,
pos = FALSE, neg = FALSE,
complex = FALSE, imag = FALSE,
symmetric = FALSE, diag = FALSE,
PSD = FALSE, NSD = FALSE,
hermitian = FALSE, boolean = FALSE,
integer = FALSE, sparsity = FALSE,
bounds = NULL
),
## A Constant is never boolean/integer-constrained (its attributes are
## all FALSE above), but constraint 17 requires both properties be named:
## `.fast_new` gives an object nothing its constructor omits.
.sparse_idx = integer(0),
.boolean_idx = integer(0),
.integer_idx = integer(0),
args = list(),
.name = name,
.sparse = sparse
)
obj
}
)
# -- expr_name ---------------------------------------------------------
## CVXPY SOURCE: constant.py lines 96-108
method(expr_name, Constant) <- function(x) {
if (nchar(x@.name) > 0L) return(x@.name)
v <- x@.value
## is.matrix() is FALSE for a Matrix-package value; the abbreviation applies
## to every dimensioned constant (sweep item 4, pass H1).
if ((is.matrix(v) || inherits(v, "Matrix")) && any(dim(v) > 1L)) {
## Abbreviated representation for matrices
paste0("[", nrow(v), "x", ncol(v), " matrix]")
} else {
as.character(v[1L])
}
}
# -- is_constant: always TRUE -----------------------------------------
## CVXPY SOURCE: constant.py line 115-116
method(is_constant, Constant) <- function(x) TRUE
# -- get_bounds: a constant's bounds are exactly (value, value) --------
## CVXPY SOURCE: constants/constant.py:292-304 (#3080). Needed so bounds
## propagation through e.g. matmul / scaling by a constant treats the constant
## as a point (lb == ub), enabling the exact split formula in matmul_bounds.
method(get_bounds, Constant) <- function(x) {
v <- x@.value
## constant.py:303-304 returns a sparse value as-is, "to avoid memory
## blowup"; a Matrix value is already shaped (sweep item 4, pass B).
if (!inherits(v, "Matrix")) {
v <- matrix(as.numeric(v), nrow = .shape(x)[1L], ncol = .shape(x)[2L])
}
list(v, v)
}
# -- constants: returns self -------------------------------------------
## CVXPY SOURCE: constant.py lines 110-113
method(constants, Constant) <- function(x) list(x)
# -- value: read-only --------------------------------------------------
## CVXPY SOURCE: constant.py lines 118-122
method(value, Constant) <- function(x) x@.value
method(`value<-`, Constant) <- function(x, value) {
cli_abort("Cannot set the value of a {.cls Constant}.")
}
# -- Complex queries: computed from value, cached ----------------------
## CVXPY SOURCE: constant.py lines 190-194, 183-188
## Every cached member goes through compute_once (utilities/performance_utils.R),
## the one mirror of CVXPY's @perf.compute_once. CVXPY decorates is_complex,
## is_symmetric, is_hermitian, is_psd and is_nsd (scope-keyed wrappers); the
## tests on the stored value themselves are plain instance attributes set
## once, whatever the scope: `_imag`/`_nonneg`/`_nonpos` (_compute_attr, lines
## 222-233), `_symm`/`_herm` (_compute_symm_attr, 235-241), `_skew_symm`
## (243-246), `_cached_is_pos` (124-134), `_psd_test`/`_nsd_test` (248-290).
## Those are `compute_once(..., scoped = FALSE)` here; the wrappers keep the
## scoped key. Each member's body is the `.constant_*` function below it.
method(is_complex, Constant) <- function(x) compute_once(x, "is_complex", .constant_is_complex)
.constant_is_complex <- function(x) is.complex(x@.value)
method(is_imag, Constant) <- function(x) {
compute_once(x, "is_imag", .constant_is_imag, scoped = FALSE)
}
.constant_is_imag <- function(x) {
v <- x@.value
if (!is.complex(v)) return(FALSE)
## Imaginary: real part all ~zero, imaginary part has nonzero elements
## CVXPY SOURCE: interface/matrix_utilities.py is_complex() returns (is_real, is_imag)
tol <- 1e-5
real_max <- max(abs(Re(v)))
imag_max <- max(abs(Im(v)))
(real_max < tol) && (imag_max >= tol)
}
# -- Hermitian / skew-symmetric: computed from value, cached -----------
## CVXPY SOURCE: constant.py lines 209-246
## _compute_symm_attr: one intf_is_hermitian() call stores both `_symm` and
## `_herm`, consulted by the is_symmetric and is_hermitian wrappers below.
.constant_symm_herm <- function(x) intf_is_hermitian(x@.value)
method(is_hermitian, Constant) <- function(x) compute_once(x, "is_hermitian", .constant_is_hermitian)
.constant_is_hermitian <- function(x) {
if (expr_is_scalar(x) && is_real(x)) return(TRUE)
if (length(.shape(x)) != 2L || .shape(x)[1L] != .shape(x)[2L]) return(FALSE)
compute_once(x, "symm_herm", .constant_symm_herm, scoped = FALSE)$is_hermitian
}
method(is_skew_symmetric, Constant) <- function(x) {
compute_once(x, "is_skew_symmetric", .constant_is_skew_symmetric, scoped = FALSE)
}
## Delegates to intf_is_skew_symmetric which errors on non-square (matches CVXPY)
.constant_is_skew_symmetric <- function(x) intf_is_skew_symmetric(x@.value)
# -- Sign queries: computed from value, cached -------------------------
## CVXPY SOURCE: constant.py lines 169-181, 222-233
## One cached intf_sign() call answers both queries, as CVXPY's _compute_attr
## stores `self._nonneg, self._nonpos = intf.sign(self.value)` once.
.constant_sign <- function(x) intf_sign(x@.value)
method(is_nonneg, Constant) <- function(x) {
compute_once(x, "sign", .constant_sign, scoped = FALSE)$is_nonneg
}
method(is_nonpos, Constant) <- function(x) {
compute_once(x, "sign", .constant_sign, scoped = FALSE)$is_nonpos
}
# -- is_pos: strictly positive (all elements > 0), cached --------------
## CVXPY SOURCE: constant.py lines 124-134
method(is_pos, Constant) <- function(x) {
compute_once(x, "is_pos", .constant_is_pos, scoped = FALSE)
}
.constant_is_pos <- function(x) {
v <- x@.value
if (is.complex(v)) {
## Complex values cannot be strictly positive
FALSE
} else if (inherits(v, "sparseMatrix")) {
## Sparse constants are NOT elementwise positive (zeros present)
FALSE
} else {
all(v > 0)
}
}
# -- Symmetry: computed from value, cached -----------------------------
## CVXPY SOURCE: constant.py lines 197-207
method(is_symmetric, Constant) <- function(x) compute_once(x, "is_symmetric", .constant_is_symmetric)
.constant_is_symmetric <- function(x) {
if (expr_is_scalar(x)) return(TRUE)
if (length(.shape(x)) != 2L || .shape(x)[1L] != .shape(x)[2L]) return(FALSE)
compute_once(x, "symm_herm", .constant_symm_herm, scoped = FALSE)$is_symmetric
}
# -- PSD / NSD: computed from value, cached ----------------------------
## CVXPY SOURCE: constant.py lines 248-290
method(is_psd, Constant) <- function(x) compute_once(x, "is_psd", .constant_is_psd)
.constant_is_psd <- function(x) {
## Scalar cases
if (expr_is_scalar(x)) return(is_nonneg(x))
## Must be square
if (length(.shape(x)) != 2L || .shape(x)[1L] != .shape(x)[2L]) return(FALSE)
## Must be symmetric (real) or Hermitian (complex) -- matches CVXPY
if (!is_hermitian(x)) return(FALSE)
## Eigenvalue test, stored once (`_psd_test`)
compute_once(x, "psd_test", .constant_psd_test, scoped = FALSE)
}
.constant_psd_test <- function(x) intf_is_psd(x@.value, EIGVAL_TOL)
method(is_nsd, Constant) <- function(x) compute_once(x, "is_nsd", .constant_is_nsd)
.constant_is_nsd <- function(x) {
if (expr_is_scalar(x)) return(is_nonpos(x))
if (length(.shape(x)) != 2L || .shape(x)[1L] != .shape(x)[2L]) return(FALSE)
if (!is_hermitian(x)) return(FALSE)
## Eigenvalue test on negation, stored once (`_nsd_test`)
compute_once(x, "nsd_test", .constant_nsd_test, scoped = FALSE)
}
.constant_nsd_test <- function(x) intf_is_psd(-x@.value, EIGVAL_TOL)
# -- grad: empty (constants have no gradient w.r.t. variables) ---------
## CVXPY SOURCE: constant.py lines 137-145
method(grad, Constant) <- function(x) list()
# -- canonicalize ------------------------------------------------------
## CVXPY SOURCE: constant.py lines 153-160
method(canonicalize, Constant) <- function(x) {
obj <- create_const(x@.value, .shape(x), x@.sparse)
list(obj, list())
}
# -- print -------------------------------------------------------------
method(print, Constant) <- function(x, ...) {
cat(sprintf("Constant(%s, %s, (%s))\n",
expr_curvature(x), expr_sign_str(x),
paste(.shape(x), collapse = ", ")))
invisible(x)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.