R/032_expressions_constants_callback_param.R

#####
## DO NOT EDIT THIS FILE!! EDIT THE SOURCE INSTEAD: rsrc_tree/expressions/constants/callback_param.R
#####

## CVXPY SOURCE: expressions/constants/callback_param.py
## CallbackParam -- Parameter whose value is computed by a callback.
##
## Useful when an expression must remain DPP-compliant but its numeric
## value is a function of other Parameters: e.g. p * q is not DPP, but
## wrapping it as CallbackParam(callback = function() value(p) * value(q))
## yields a DPP-compliant Parameter that tracks p, q automatically.

#' Callback Parameter
#'
#' A `Parameter` whose value is computed by a user-supplied callback
#' function rather than stored explicitly.  Mirrors CVXPY's
#' `cp.CallbackParam` (`cvxpy/expressions/constants/callback_param.py`).
#'
#' Each call to `value(param)` re-evaluates the callback and validates
#' the returned numeric against the parameter's shape and attribute
#' domain.  Setting via `value(param) <- v` is not allowed and signals
#' an error.
#'
#' @section DPP use:
#' If `p` and `q` are scalar `Parameter`s, the expression `p * q` is
#' not DPP.  Wrapping it in a `CallbackParam`,
#' \preformatted{
#' pq <- CallbackParam(callback = function() value(p) * value(q))
#' }
#' yields a DPP-compliant Parameter whose value tracks `p` and `q`
#' automatically.
#'
#' @param callback A function (no arguments) returning the parameter's
#'   numeric value.  Re-evaluated on every read of `value(param)`.
#' @param shape Integer vector of length 1 or 2 giving parameter
#'   dimensions.  Defaults to `c(1, 1)` (scalar).
#' @param name Optional character string name.
#' @param id Optional integer ID. If `NULL`, a unique ID is generated.
#' @param latex_name Optional LaTeX name for visualisation.
#' @param ... Other Parameter attributes (e.g., `nonneg`, `nonpos`).
#' @returns A `CallbackParam` object (subclass of `Parameter`).
#'
#' @examples
#' p <- Parameter(); value(p) <- 2
#' q <- Parameter(); value(q) <- 3
#' pq <- CallbackParam(callback = function() value(p) * value(q))
#' value(pq)   # evaluates the callback => 6
#'
#' @export
CallbackParam <- new_class("CallbackParam", parent = Parameter, package = "CVXR",
  properties = list(
    .callback = new_property(class = class_function)
  ),
  constructor = function(callback, shape = c(1L, 1L), name = NULL,
                         id = NULL, latex_name = NULL, ...) {
    if (FALSE) new_object(S7_object())  ## S7 static-check guard
    if (!is.function(callback)) {
      cli_abort("CallbackParam {.arg callback} must be a function with no required arguments.")
    }

    ## Inline construction (project rule: no parent-constructor delegation,
    ## new_object() must be inline).  Mirrors Parameter()'s body.
    if (is.numeric(shape) && length(shape) == 1L) {
      shape <- c(as.integer(shape), 1L)
    }
    shape <- validate_shape(shape)

    if (is.null(id)) id <- next_expr_id()
    nm <- if (!is.null(name)) name else ""
    lnm <- if (is.null(latex_name)) "" else as.character(latex_name)
    attrs <- do.call(.build_leaf_attrs, c(list(shape = shape, allow_expr_bounds = FALSE), list(...)))

    .fast_new(CallbackParam, S7_object(),
      id = as.integer(id),
      .cache = new.env(parent = emptyenv()),
      shape = shape,
      .value = NULL,
      attributes = attrs,
      ## Constraint 17: derived from whatever `...` put in `attrs`, since a
      ## CallbackParam takes its leaf attributes through the same helper.
      .sparse_idx  = .mip_idx(attrs$sparsity, shape, "sparsity"),
      .boolean_idx = .mip_idx(attrs$boolean, shape, "boolean"),
      .integer_idx = .mip_idx(attrs$integer, shape, "integer"),
      args = list(),
      .name = nm,
      .latex_name = lnm,
      .callback = callback
    )
  }
)

# -- value: evaluate the callback, validate, return ---------------------
## CVXPY SOURCE: callback_param.py value property -- evaluates
## self._callback() then validates via Leaf's _validate_value.

method(value, CallbackParam) <- function(x) {
  raw <- x@.callback()
  .validate_leaf_value(x, raw)
}

# -- value<-: explicitly forbid -----------------------------------------
## CVXPY SOURCE: callback_param.py value setter -- raises NotImplementedError.

method(`value<-`, CallbackParam) <- function(x, value) {
  cli_abort("Cannot set the value of a {.cls CallbackParam}; its value is computed by its callback.")
}

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.