R/129_constraints_finite_set.R

#####
## DO NOT EDIT THIS FILE!! EDIT THE SOURCE INSTEAD: rsrc_tree/constraints/finite_set.R
#####

## CVXPY SOURCE: constraints/finite_set.py
## FiniteSet -- constrain each entry of an expression to a finite set of values
##
## For each element e of expre: e in vec (a finite set of real numbers).
## Canonicalized to MIP constraints via Valinvec2mixedint.

# -- FiniteSet class ---------------------------------------------
## CVXPY SOURCE: finite_set.py lines 23-136

#' FiniteSet Constraint
#'
#' Constrain each entry of an Expression to take a value in a given
#' finite set of real numbers.
#'
#' @param expre An affine Expression.
#' @param vec A numeric vector (or set) of allowed values.
#' @param ineq_form Logical; controls MIP canonicalization strategy.
#'   If \code{FALSE} (default), uses equality formulation (one-hot binary).
#'   If \code{TRUE}, uses inequality formulation (sorted differences + ordering).
#' @param constr_id Optional integer constraint ID (internal use).
#' @returns A \code{FiniteSet} constraint.
#' @export
FiniteSet <- new_class("FiniteSet", parent = Constraint, package = "CVXR",
  properties = list(
    expre      = class_any,   # The expression being constrained
    vec        = class_any,   # The allowed values (stored as Constant)
    .ineq_form = class_logical
  ),
  constructor = function(expre, vec, ineq_form = FALSE, constr_id = NULL) {
    ## Coerce vec: if set (list) or numeric, wrap as Constant and flatten
    if (is.list(vec) && !S7_inherits(vec, Atom)) vec <- unlist(vec)
    if (is.numeric(vec)) vec <- Constant(vec)
    if (S7_inherits(vec, Expression)) {
      ## Flatten the vec expression (column-major)
      vec <- Reshape(vec, c(expr_size(vec), 1L))
    }

    ## Validate: expression must be affine or log-log affine
    if (!is_affine(expre) && !is_log_log_affine(expre)) {
      cli_abort(c(
        "Provided Expression must be affine or log-log affine.",
        "i" = "Got curvature: {curvature(expre)}."
      ))
    }

    ## Build constraint
    id <- if (!is.null(constr_id)) as.integer(constr_id) else as.integer(next_expr_id())
    args_list <- list(expre, vec)
    dvars <- lapply(args_list, function(a) Variable(a@shape))
    shape <- expre@shape

    obj <- new_object(S7_object(),
      id     = id,
      .cache = new.env(parent = emptyenv()),
      args   = args_list,
      dual_variables = dvars,
      shape  = shape,
      .label = "",
      expre  = expre,
      vec    = vec,
      .ineq_form = ineq_form
    )
    obj
  }
)

# -- expr_name ----------------------------------------------------
## CVXPY SOURCE: finite_set.py lines 75-76
method(expr_name, FiniteSet) <- function(x) {
  paste0("FiniteSet(", expr_name(x@args[[1L]]), ", ", expr_name(x@args[[2L]]), ")")
}

# -- get_data -----------------------------------------------------
## CVXPY SOURCE: finite_set.py lines 78-79
method(get_data, FiniteSet) <- function(x) {
  list(x@.ineq_form, x@id)
}

# -- is_dcp -------------------------------------------------------
## CVXPY SOURCE: finite_set.py lines 81-88
method(is_dcp, FiniteSet) <- function(x, ...) {
  is_affine(x@args[[1L]])
}

# -- is_dgp -------------------------------------------------------
## CVXPY SOURCE: finite_set.py lines 90-101
method(is_dgp, FiniteSet) <- function(x, ...) {
  ## Not DGP if vec has parameters
  if (length(parameters(x@vec)) > 0L) return(FALSE)
  ## vec is fixed; check values are all positive
  vec_val <- value(x@vec)
  if (any(vec_val <= 0)) return(FALSE)
  ## DGP if expre is log-log affine
  is_log_log_affine(x@expre)
}

# -- is_dqcp ------------------------------------------------------
## CVXPY SOURCE: finite_set.py lines 103-104
method(is_dqcp, FiniteSet) <- function(x, ...) {
  is_dcp(x)
}

# -- constr_size --------------------------------------------------
## CVXPY SOURCE: finite_set.py lines 106-108
method(constr_size, FiniteSet) <- function(x) {
  expr_size(x@expre)
}

# -- residual -----------------------------------------------------
## CVXPY SOURCE: finite_set.py lines 122-135
method(residual, FiniteSet) <- function(x) {
  expr_val <- as.numeric(value(x@expre))
  vec_val <- as.numeric(value(x@vec))
  resids <- vapply(expr_val, function(val) min(abs(val - vec_val)), numeric(1))
  max(resids)
}

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.