R/004_zzz_R_specific_generics.R

#####
## DO NOT EDIT THIS FILE!! EDIT THE SOURCE INSTEAD: rsrc_tree/zzz_R_specific/generics.R
#####

## CVXPY SOURCE: (R-specific generic definitions)
## S7 generics for the CVXR expression interface
##
## These correspond to methods on CVXPY's Expression class and Atom subclasses.
## Naming convention: avoid base R conflicts (e.g., expr_sign instead of sign).
##
## NOTE on additional arguments: S7 generics dispatch on the first argument only.
## Additional arguments (like idx for is_incr) are passed through as extra formals.
## See: https://rconsortium.github.io/S7/articles/generics-methods.html

# -- Expression interface ----------------------------------------------

#' Get the Numeric Value of an Expression
#'
#' Returns the numeric value of a CVXR expression, variable, or constant.
#' For variables, the value is set after solving a problem.
#'
#' @param x An expression object.
#' @param ... Not used.
#' @returns A numeric matrix, or \code{NULL} if no value has been set.
#' @export
value <- new_generic("value", "x")

#' Get the Gradient of an Expression
#' @param x An expression object.
#' @param ... Not used.
#' @returns Gradient information.
#' @keywords internal
grad <- new_generic("grad", "x")

#' Get the Domain Constraints of an Expression
#' @param x An expression object.
#' @param ... Not used.
#' @returns List of constraints defining the domain.
#' @keywords internal
domain <- new_generic("domain", "x")

#' Canonicalize an Expression
#' @param x An expression object.
#' @param ... Not used.
#' @returns List with canonicalized expression and constraints.
#' @keywords internal
canonicalize <- new_generic("canonicalize", "x")

#' Check if an Expression is Constant
#'
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_constant <- new_generic("is_constant", "x")

#' Check if an Expression is Affine
#'
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_affine <- new_generic("is_affine", "x")

#' Check if an Expression is Convex
#'
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_convex <- new_generic("is_convex", "x")

#' Check if an Expression is Concave
#'
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_concave <- new_generic("is_concave", "x")

#' Check if an Expression is DCP-Compliant
#'
#' Tests whether an expression follows the Disciplined Convex Programming
#' (DCP) rules.
#'
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_dcp <- new_generic("is_dcp", "x")

#' Check DPP Compliance
#'
#' Determines whether an expression or problem satisfies the rules of
#' Disciplined Parameterized Programming (DPP). A DPP-compliant problem
#' enables caching the compilation across parameter value changes.
#'
#' @param x An expression, constraint, or problem object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_dpp <- new_generic("is_dpp", "x")

#' Get Atom-Specific Data
#' @param x An expression object.
#' @param ... Not used.
#' @returns List of data.
#' @keywords internal
get_data <- new_generic("get_data", "x")

#' Get the Variables in an Expression
#'
#' @param x An expression or problem object.
#' @param ... Not used.
#' @returns List of \code{\link{Variable}} objects.
#' @export
variables <- new_generic("variables", "x")

#' Get the Parameters in an Expression
#'
#' @param x An expression or problem object.
#' @param ... Not used.
#' @returns List of \code{\link{Parameter}} objects.
#' @export
parameters <- new_generic("parameters", "x")

#' Get the Constants in an Expression
#'
#' @param x An expression or problem object.
#' @param ... Not used.
#' @returns List of \code{\link{Constant}} objects.
#' @export
constants <- new_generic("constants", "x")

#' Get the DCP Sign of an Expression
#'
#' Returns the sign of an expression under DCP analysis. Use this instead
#' of \code{sign()}, which conflicts with the base R function.
#'
#' @param x An expression object.
#' @param ... Not used.
#' @returns Character string: \code{"POSITIVE"}, \code{"NEGATIVE"},
#'   \code{"ZERO"}, or \code{"UNKNOWN"}.
#' @export
expr_sign <- new_generic("expr_sign", "x")

# -- Sign/attribute queries (dispatched on Expression, overridden by Leaf) --

#' Check if Expression is Non-Negative
#'
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_nonneg <- new_generic("is_nonneg", "x")

#' Check if Expression is Non-Positive
#'
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_nonpos <- new_generic("is_nonpos", "x")

#' Check if Expression is Zero
#'
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_zero <- new_generic("is_zero", "x")

#' Check if Expression is Positive Semidefinite
#'
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_psd <- new_generic("is_psd", "x")

#' Check if Expression is Negative Semidefinite
#'
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_nsd <- new_generic("is_nsd", "x")

#' Check if Expression is Symmetric
#'
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_symmetric <- new_generic("is_symmetric", "x")

# -- Phase 1: additional generics -------------------------------------

#' Get the Name of an Expression
#' @param x An expression object.
#' @param ... Not used.
#' @returns Character string.
#' @keywords internal
expr_name <- new_generic("expr_name", "x")

#' Set the Value of a Leaf Expression
#'
#' Assigns a numeric value to a \code{\link{Variable}} or
#' \code{\link{Parameter}}.
#'
#' @param x A leaf expression object.
#' @param value The value to assign.
#' @returns The modified object (invisibly).
#' @export
`value<-` <- new_generic("value<-", "x",
  function(x, value) S7_dispatch())

#' Get the Atoms in an Expression
#' @param x An expression object.
#' @param ... Not used.
#' @returns List of atom objects.
#' @keywords internal
atoms <- new_generic("atoms", "x")

#' Check if Expression is Complex
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @keywords internal
is_complex <- new_generic("is_complex", "x")

#' Check if Expression is Imaginary
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @keywords internal
is_imag <- new_generic("is_imag", "x")

#' Project a Value onto the Domain of a Leaf
#' @param x A leaf expression object.
#' @param val The value to project.
#' @param ... Additional arguments.
#' @returns The projected value.
#' @keywords internal
project <- new_generic("project", "x",
  function(x, val, ...) S7_dispatch())

#' Check if Expression is Hermitian
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @keywords internal
is_hermitian <- new_generic("is_hermitian", "x")

#' Check if Expression is Skew-Symmetric
#'
#' Tests whether \code{X + t(X) == 0} (real matrices only).
#' CVXPY SOURCE: expression.py line 470-473
#'
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @keywords internal
is_skew_symmetric <- new_generic("is_skew_symmetric", "x")

#' Check if Expression is Real
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @keywords internal
is_real <- new_generic("is_real", "x")

#' Check if Expression is Log-Log Convex
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_log_log_convex <- new_generic("is_log_log_convex", "x")

#' Check if Expression is Log-Log Concave
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_log_log_concave <- new_generic("is_log_log_concave", "x")

#' Check if Expression is Log-Log Affine
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_log_log_affine <- new_generic("is_log_log_affine", "x")

#' Get the Canonical Form
#' @param x A canonicalizable object.
#' @param ... Not used.
#' @returns List with (expression, constraints).
#' @keywords internal
canonical_form <- new_generic("canonical_form", "x")

#' Shallow Copy of an Expression Tree Node
#' @param x A canonicalizable object.
#' @param args Optional replacement args.
#' @param id_objects Optional identity map for deduplication.
#' @returns A copy of the object.
#' @keywords internal
expr_copy <- new_generic("expr_copy", "x",
  function(x, args = NULL, id_objects = NULL) S7_dispatch())

#' Deep Copy of an Expression Tree
#' @param x A canonicalizable object.
#' @param id_objects Optional identity map for deduplication.
#' @returns A deep copy of the entire expression tree.
#' @keywords internal
tree_copy <- new_generic("tree_copy", "x",
  function(x, id_objects = NULL) S7_dispatch())

# -- Quadratic / piecewise-linear analysis --------------------------
## CVXPY SOURCE: expression.py lines 448-484
## These are needed by the QP solver path (OSQP) for problem classification.

#' Check if an Expression is Quadratic
#'
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_quadratic <- new_generic("is_quadratic", "x")

#' Check if Expression Has a Quadratic Term
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @keywords internal
has_quadratic_term <- new_generic("has_quadratic_term", "x")

#' Check if Expression is Piecewise Linear
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_pwl <- new_generic("is_pwl", "x")

#' Check if Expression is Quadratic or Piecewise Affine
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @keywords internal
is_qpwa <- new_generic("is_qpwa", "x")

# -- Strictly positive check ---------------------------------------
## CVXPY SOURCE: leaf.py::is_pos -- checks attributes['pos'] on Leaf,
## checks actual value > 0 on Constant.

#' Check if Expression is Strictly Positive
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @keywords internal
is_pos <- new_generic("is_pos", "x")

# -- Domain hook ---------------------------------------------------

#' Get Atom-Specific Domain Constraints
#' @param x An atom object.
#' @param ... Not used.
#' @returns List of Constraint objects.
#' @keywords internal
atom_domain <- new_generic("atom_domain", "x")

# -- Constraint generics --------------------------------------------

#' Get the Residual of a Constraint
#'
#' Returns the residual of a constraint, measuring how much the constraint
#' is violated or satisfied.
#'
#' @param x A constraint object.
#' @param ... Not used.
#' @returns Numeric array, or \code{NULL} if expression has no value.
#' @export
residual <- new_generic("residual", "x")

#' Get the Violation of a Constraint
#'
#' Returns the scalar violation (distance to feasibility) of a constraint.
#'
#' @param x A constraint object.
#' @param ... Not used.
#' @returns Numeric scalar.
#' @export
violation <- new_generic("violation", "x")

# -- Cone constraint generics --------------------------------------
## CVXPY SOURCE: constraints/cones.py, second_order.py, psd.py, etc.

#' Get the Number of Cones in a Constraint
#' @param x A cone constraint object.
#' @param ... Not used.
#' @returns Integer.
#' @keywords internal
num_cones <- new_generic("num_cones", "x")

#' Get the Sizes of Individual Cones
#' @param x A cone constraint object.
#' @param ... Not used.
#' @returns Integer vector of cone sizes.
#' @keywords internal
cone_sizes <- new_generic("cone_sizes", "x")

#' Get the Total Size of a Constraint
#' @param x A constraint object.
#' @param ... Not used.
#' @returns Integer.
#' @keywords internal
constr_size <- new_generic("constr_size", "x")

#' Get the Dual Cone Constraint
#' @param x A cone constraint object.
#' @param ... Optional arguments.
#' @returns A cone constraint representing the dual cone.
#' @keywords internal
dual_cone <- new_generic("dual_cone", "x",
  function(x, ...) S7_dispatch())

#' Get the Dual Residual
#' @param x A cone constraint object.
#' @param ... Not used.
#' @returns Numeric residual.
#' @keywords internal
dual_residual <- new_generic("dual_residual", "x")

#' Check if a Constraint is DGP-Compliant
#' @param x A constraint object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_dgp <- new_generic("is_dgp", "x")

#' Save Dual Variable Values from Solver Output
#' @param x A constraint object.
#' @param val The dual value from the solver.
#' @returns Invisible constraint (side effect: sets dual variable values).
#' @keywords internal
save_dual_value <- new_generic("save_dual_value", "x",
  function(x, val) S7_dispatch())

# -- Atom validation -------------------------------------------------

#' Validate Arguments to an Atom
#' @param x An atom object.
#' @param ... Not used.
#' @returns Invisible \code{NULL} (or error if invalid).
#' @keywords internal
validate_arguments <- new_generic("validate_arguments", "x")

# -- Atom hooks --------------------------------------------------------

#' Infer Shape from Arguments
#' @param x An atom object.
#' @param ... Not used.
#' @returns Integer vector of shape dimensions.
#' @keywords internal
shape_from_args <- new_generic("shape_from_args", "x")

#' Infer Sign from Arguments
#' @param x An atom object.
#' @param ... Not used.
#' @returns Character string: sign constant.
#' @keywords internal
sign_from_args <- new_generic("sign_from_args", "x")

#' Check if Atom is Convex
#' @param x An atom object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @keywords internal
is_atom_convex <- new_generic("is_atom_convex", "x")

#' Check if Atom is Concave
#' @param x An atom object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @keywords internal
is_atom_concave <- new_generic("is_atom_concave", "x")

#' Check if Atom is Log-Log Convex
#' @param x An atom object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @keywords internal
is_atom_log_log_convex <- new_generic("is_atom_log_log_convex", "x")

#' Check if Atom is Log-Log Concave
#' @param x An atom object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @keywords internal
is_atom_log_log_concave <- new_generic("is_atom_log_log_concave", "x")

#' Check if Atom is Increasing in an Argument
#' @param x An atom object.
#' @param idx Integer: argument index (1-based, R convention).
#' @param ... Additional arguments.
#' @returns Logical scalar.
#' @keywords internal
is_incr <- new_generic("is_incr", "x",
  function(x, idx, ...) S7_dispatch())

#' Check if Atom is Decreasing in an Argument
#' @param x An atom object.
#' @param idx Integer: argument index (1-based, R convention).
#' @param ... Additional arguments.
#' @returns Logical scalar.
#' @keywords internal
is_decr <- new_generic("is_decr", "x",
  function(x, idx, ...) S7_dispatch())

#' Get the Graph Implementation of an Atom
#' @param x An atom object.
#' @param arg_objs List of canonicalized argument LinOps.
#' @param shape Integer vector: target shape.
#' @param data Optional atom-specific data.
#' @param ... Additional arguments.
#' @returns List with (expression, constraints).
#' @keywords internal
graph_implementation <- new_generic("graph_implementation", "x",
  function(x, arg_objs, shape, data = NULL, ...) S7_dispatch())

#' Compute the Numeric Value of an Atom
#' @param x An atom object.
#' @param values List of numeric values of the atom's arguments.
#' @param ... Additional arguments.
#' @returns Numeric value.
#' @keywords internal
numeric_value <- new_generic("numeric_value", "x",
  function(x, values, ...) S7_dispatch())

# -- DQCP curvature queries ---------------------------------------
## CVXPY SOURCE: expression.py lines 411-429, atom.py lines 288-335

#' Check if Expression is Quasiconvex
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_quasiconvex <- new_generic("is_quasiconvex", "x")

#' Check if Expression is Quasiconcave
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_quasiconcave <- new_generic("is_quasiconcave", "x")

#' Check if Expression is Quasilinear
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_quasilinear <- new_generic("is_quasilinear", "x")

#' Check if Expression is DQCP-Compliant
#'
#' Tests whether an expression follows the Disciplined Quasiconvex
#' Programming (DQCP) rules.
#'
#' @param x An expression object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_dqcp <- new_generic("is_dqcp", "x")

#' Check if Atom is Quasiconvex
#' @param x An atom object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @keywords internal
is_atom_quasiconvex <- new_generic("is_atom_quasiconvex", "x")

#' Check if Atom is Quasiconcave
#' @param x An atom object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @keywords internal
is_atom_quasiconcave <- new_generic("is_atom_quasiconcave", "x")

# -- Problem classification ---------------------------------------

#' Check if a Problem is a Quadratic Program
#'
#' @param x A \code{\link{Problem}} object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_qp <- new_generic("is_qp", "x")

#' Check if a Problem is a Linear Program
#'
#' @param x A \code{\link{Problem}} object.
#' @param ... Not used.
#' @returns Logical scalar.
#' @export
is_lp <- new_generic("is_lp", "x")

# -- Reduction interface ------------------------------------------

#' Check if a Reduction Accepts a Problem
#' @param x A Reduction object.
#' @param problem A Problem object.
#' @param ... Additional arguments.
#' @returns Logical scalar.
#' @keywords internal
reduction_accepts <- new_generic("reduction_accepts", "x",
  function(x, problem, ...) S7_dispatch())

#' Apply a Reduction to a Problem
#' @param x A Reduction object.
#' @param problem A Problem object.
#' @param ... Additional arguments.
#' @returns List with (new_problem, inverse_data).
#' @keywords internal
reduction_apply <- new_generic("reduction_apply", "x",
  function(x, problem, ...) S7_dispatch())

#' Invert a Solution through a Reduction
#' @param x A Reduction object.
#' @param solution A solution object.
#' @param inverse_data Inverse data from apply.
#' @param ... Additional arguments.
#' @returns A solution to the original problem.
#' @keywords internal
reduction_invert <- new_generic("reduction_invert", "x",
  function(x, solution, inverse_data, ...) S7_dispatch())

#' Update Parameters for DPP Fast Path
#' @param x A Reduction object.
#' @param problem A Problem object.
#' @param ... Additional arguments.
#' @returns NULL (called for side effects).
#' @keywords internal
update_parameters <- new_generic("update_parameters", "x",
  function(x, problem, ...) S7_dispatch())

# -- Solver interface -----------------------------------------------

#' Get Solver Name
#' @param x A Solver object.
#' @param ... Not used.
#' @returns Character string with solver name.
#' @keywords internal
solver_name <- new_generic("solver_name", "x")

#' Solve via Raw Data
#'
#' Calls the solver on pre-compiled problem data (step 2 of the
#' decomposed solve pipeline). Dispatches on \code{x}: when \code{x}
#' is a \code{SolvingChain}, delegates to the terminal solver with
#' proper cache management.
#'
#' @param x A \code{SolvingChain} (preferred) or \code{Solver} object.
#' @param data Named list of solver data from \code{\link{problem_data}()}.
#' @param warm_start Logical; use warm-start if supported.
#' @param verbose Logical; print solver output.
#' @param solver_opts Named list of solver-specific options.
#' @param ... Additional arguments (e.g., \code{problem} for
#'   \code{SolvingChain} dispatch, \code{solver_cache} for
#'   \code{Solver} dispatch).
#' @returns Solver-specific result (a named list).
#'
#' @seealso \code{\link{problem_data}}, \code{\link{problem_unpack_results}}
#' @export
solve_via_data <- new_generic("solve_via_data", "x",
  function(x, data, warm_start = FALSE, verbose = FALSE, solver_opts = list(), ...) S7_dispatch())

#' Get Problem Data for a Solver
#'
#' Returns the problem data that would be passed to a specific solver,
#' along with the reduction chain and inverse data for solution retrieval.
#'
#' @param x A \code{\link{Problem}} object.
#' @param solver Character string naming solver, or \code{NULL} for
#'   automatic selection.
#' @param ... Additional arguments.
#' @returns A list with components \code{data}, \code{chain}, and
#'   \code{inverse_data}.
#' @export
problem_data <- new_generic("problem_data", "x",
  function(x, solver = NULL, ...) S7_dispatch())

#' Get Problem Data for a Solver (deprecated)
#'
#' `r lifecycle::badge("deprecated")`
#'
#' Use \code{\link{problem_data}} instead.
#'
#' @param x A \code{\link{Problem}} object.
#' @param solver Character string naming solver, or \code{NULL} for
#'   automatic selection.
#' @param ... Additional arguments.
#' @returns A list with components \code{data}, \code{chain}, and
#'   \code{inverse_data}.
#' @seealso \code{\link{problem_data}}
#' @export
get_problem_data <- new_generic("get_problem_data", "x",
  function(x, solver = NULL, ...) S7_dispatch())

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.