R/257_zzz_R_specific_exports.R

Defines functions multiply unpack_results .cvxr_as_character_Expression .cvxr_dim_Expression curvature is_matrix is_vector is_scalar size id name objective constraints `%<<%` `%>>%` set_excluded_solvers include_solvers exclude_solvers available_solvers installed_solvers norm2 tv

Documented in available_solvers constraints curvature exclude_solvers id include_solvers installed_solvers is_matrix is_scalar is_vector multiply name norm2 objective set_excluded_solvers size tv unpack_results

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

## CVXPY SOURCE: (R-specific exports)
## This file manages the public API exports for CVXR.
## It will be populated as classes and functions are implemented in each phase.

# Phase 0: Foundation
# (no user-facing exports yet -- generics/settings exported via NAMESPACE)

# Phase 1: Core Expression System
# Exported via NAMESPACE: Variable, Constant, Parameter, as_expr,
#   expr_curvature, expr_sign_str, expr_size, expr_ndim,
#   expr_is_scalar, expr_is_vector, expr_is_matrix

# Phase 2A: Prerequisite Utilities
# Exported via NAMESPACE: sum_signs, mul_sign, sum_shapes, mul_shapes,
#   DCPError, SolverError

# Phase 2B: Atom + AffAtom Base Classes
# Exported via NAMESPACE: Atom, AffAtom, validate_arguments, is_atom_affine

# Phase 2C: Concrete Affine Operators
# Exported via NAMESPACE: Promote, cvxr_promote, broadcast_args,
#   NegExpression, AddExpression, BinaryOperator, MulExpression,
#   Multiply, DivExpression

# Phase 2D: Arithmetic Operator Dispatch
# No new exports -- operators registered via .onLoad()

# Phase 2E: Constraint Classes
# Exported via NAMESPACE: Constraint, Zero, Equality, NonPos, NonNeg,
#   Inequality, residual, violation, dual_value, save_dual_value, constr_expr

# Phase 2F: Comparison Operator Dispatch
# No new exports -- operators registered via .onLoad() (==, <=, >=)

# Phase 2G: Objective Classes
# Exported via NAMESPACE: Objective, Minimize, Maximize, scalar_value

# Phase 2H: Index + Transpose Atoms
# Exported via NAMESPACE: Index, Transpose

# Phase 2: Remaining
# Problem will be exported here

# Phase 3: Atoms & DCP
# Base classes: Elementwise, AxisAtom, AxisAffAtom, atom_domain,
#   is_atom_log_log_convex, is_atom_log_log_concave
# Elementwise: power, entr, huber, max_elemwise, min_elemwise,
#   square, pos, neg, inv_pos
# Axis atoms: norm1, norm_inf, p_norm, cvxr_norm, max_entries, min_entries
# Non-affine: quad_form, quad_over_lin, sum_squares, sum_largest
# Affine: sum_entries, reshape_expr, matrix_trace, hstack, vstack,
#   kron, upper_tri, conv, cumsum_axis, DiagVec, DiagMat,
#   SumEntries, Reshape, Trace, HStack, VStack, Kron, UpperTri,
#   Convolve, Cumsum
# Dispatch: S3 Math (abs, exp, log, sqrt, cumsum), Summary (sum, max, min),
#   Ops ^ -> power()

# Phase 4: Cone Constraints
# Exported via NAMESPACE: Cone, SOC, PSD, ExpCone, PowCone3D, PowConeND,
#   dual_cone, dual_residual, num_cones, cone_sizes, constr_size,
#   save_dual_value

# Phase 5a: Problem + Canonicalization Infrastructure
# Exported via NAMESPACE: Problem, is_qp, is_lp, status (+ deprecated problem_status),
#   solution (+ deprecated problem_solution), problem_data (+ deprecated get_problem_data),
#   value, Reduction, InverseData, FlipObjective, Canonicalization, Dcp2Cone,
#   CANON_METHODS, reduction_accepts, reduction_apply, reduction_invert,
#   reduction_reduce, reduction_retrieve

# Phase 5b+: Solvers
# solve(), Chain, SolvingChain, CoeffExtractor will be exported here
# Decomposed solve pipeline: solve_via_data (generic), problem_unpack_results,
# unpack_results (backward-compat alias for speed.Rmd)

# -- Backward-compatibility aliases (v1.8.1) -------------------------
# These aliases help users migrating from old CVXR (1.0-15).

#' Total variation (deprecated alias)
#'
#' `r lifecycle::badge("deprecated")`
#'
#' Use [total_variation()] instead.
#'
#' @param ... Arguments passed to [total_variation()].
#' @seealso [total_variation()]
#' @export
tv <- function(...) {
  cli_warn(c(
    "{.fn tv} is deprecated. Use {.fn total_variation} instead."
  ), .frequency = "once", .frequency_id = "cvxr_tv_deprecated")
  total_variation(...)
}

#' Euclidean norm (deprecated alias)
#'
#' `r lifecycle::badge("deprecated")`
#'
#' Use `p_norm(x, 2)` instead.
#'
#' @param x An Expression.
#' @returns An Expression representing the L2 norm.
#' @seealso [p_norm()]
#' @export
norm2 <- function(x) {
  cli_warn(c(
    "{.fn norm2} is deprecated. Use {.code p_norm(x, 2)} instead."
  ), .frequency = "once", .frequency_id = "cvxr_norm2_deprecated")
  p_norm(x, 2)
}

#' List installed solvers
#'
#' Returns the names of solvers whose R packages are available.
#'
#' @returns A character vector of solver names.
#' @export
installed_solvers <- function() {
  names(Filter(function(pkg) requireNamespace(pkg, quietly = TRUE), .SOLVER_PACKAGES))
}

#' List available solvers
#'
#' Returns the names of installed solvers that are not currently excluded.
#' Use [exclude_solvers()] to temporarily disable solvers.
#'
#' @returns A character vector of solver names.
#' @seealso [installed_solvers()], [exclude_solvers()], [include_solvers()], [set_excluded_solvers()]
#' @export
available_solvers <- function() {
  setdiff(installed_solvers(), .cvxr_env$excluded_solvers)
}

#' @param solvers A character vector of solver names.
#' @returns The current exclusion list (character vector), invisibly.
#' @describeIn available_solvers Add solvers to the exclusion list
#' @export
exclude_solvers <- function(solvers) {
  stopifnot(is.character(solvers))
  result <- unique(c(.cvxr_env$excluded_solvers, solvers))
  .cvxr_env$excluded_solvers <- result
  invisible(result)
}

#' @describeIn available_solvers Remove solvers from the exclusion list
#' @export
include_solvers <- function(solvers) {
  stopifnot(is.character(solvers))
  result <- setdiff(.cvxr_env$excluded_solvers, solvers)
  .cvxr_env$excluded_solvers <- result
  invisible(result)
}

#' @describeIn available_solvers Replace the entire exclusion list
#' @export
set_excluded_solvers <- function(solvers) {
  stopifnot(is.character(solvers))
  .cvxr_env$excluded_solvers <- solvers
  invisible(solvers)
}

# -- PSD/NSD infix operators ---------------------------------------
# R equivalent of Python's A >> B (PSD) and A << B (NSD).
# These existed in old CVXR (1.0-15) and are essential for
# expressing semidefinite constraints naturally.

#' Positive Semidefinite Constraint Operator
#'
#' Creates a PSD constraint: \code{e1 - e2} is positive semidefinite.
#' This is the R equivalent of Python's \code{A >> B}.
#'
#' @param e1,e2 CVXR expressions or numeric matrices.
#' @returns A \code{PSD} constraint object.
#' @seealso [PSD()]
#' @examples
#' \dontrun{
#' X <- Variable(3, 3, symmetric = TRUE)
#' constr <- X %>>% diag(3)  # X - I is PSD
#' }
#' @export
`%>>%` <- function(e1, e2) {
  PSD(as_expr(e1) - as_expr(e2))
}

#' Negative Semidefinite Constraint Operator
#'
#' Creates an NSD constraint: \code{e2 - e1} is positive semidefinite,
#' i.e., \code{e1} is NSD relative to \code{e2}.
#' This is the R equivalent of Python's \code{A << B}.
#'
#' @param e1,e2 CVXR expressions or numeric matrices.
#' @returns A \code{PSD} constraint object.
#' @seealso [PSD()]
#' @examples
#' \dontrun{
#' X <- Variable(3, 3, symmetric = TRUE)
#' constr <- X %<<% diag(3)  # I - X is PSD (X is NSD relative to I)
#' }
#' @export
`%<<%` <- function(e1, e2) {
  PSD(as_expr(e2) - as_expr(e1))
}

# =======================================================================
# Read-only Problem accessors
# Problem objects are IMMUTABLE (following CVXPY design).
# Constraints and objective cannot be modified after construction.
# Users who need different constraints should create a new Problem().
# =======================================================================

#' Get Problem Constraints (read-only)
#'
#' Returns a copy of the problem's constraint list.
#'
#' @details
#' Problem objects are **immutable**: constraints cannot be modified after
#' construction. To change constraints, create a new [Problem()].
#' This matches CVXPY's design where problems are immutable except
#' through [Parameter] value changes.
#'
#' @param x A [Problem] object.
#' @returns A list of constraint objects.
#' @seealso [Problem()], [objective()]
#' @examples
#' x <- Variable(2)
#' prob <- Problem(Minimize(sum_entries(x)), list(x >= 1))
#' length(constraints(prob))  # 1
#'
#' @export
constraints <- function(x) {
  if (!S7_inherits(x, Problem)) {
    cli_abort("{.fn constraints} requires a {.cls Problem} object.")
  }
  x@constraints
}

#' Get Problem Objective (read-only)
#'
#' Returns the problem's objective.
#'
#' @details
#' Problem objects are **immutable**: the objective cannot be modified after
#' construction. To change the objective, create a new [Problem()].
#'
#' @param x A [Problem] object.
#' @returns A [Minimize] or [Maximize] object.
#' @seealso [Problem()], [constraints()]
#' @examples
#' x <- Variable(2)
#' prob <- Problem(Minimize(sum_entries(x)), list(x >= 1))
#' objective(prob)
#'
#' @export
objective <- function(x) {
  if (!S7_inherits(x, Problem)) {
    cli_abort("{.fn objective} requires a {.cls Problem} object.")
  }
  x@objective
}

# =======================================================================
# Expression introspection -- user-facing wrappers for internal helpers
# =======================================================================

#' Get Expression Name
#'
#' Returns a human-readable string representation of a CVXR expression,
#' variable, or constraint.
#'
#' @param x A CVXR expression, variable, parameter, constant, or constraint.
#' @returns A character string.
#' @examples
#' x <- Variable(2, name = "x")
#' name(x)  # "x"
#' name(x + 1)  # "x + 1"
#'
#' @export
name <- function(x) {
  expr_name(x)
}

#' Get Expression ID
#'
#' Returns the unique integer identifier for a CVXR object.
#'
#' @param x A CVXR expression, variable, parameter, or constraint.
#' @returns An integer.
#' @export
id <- function(x) {
  x@id
}

#' Get Expression Size
#'
#' Returns the total number of elements in the expression.
#'
#' @param x A CVXR expression.
#' @returns An integer (product of shape dimensions).
#' @seealso [is_scalar()], [is_vector()], [is_matrix()]
#' @export
size <- function(x) {
  expr_size(x)
}

#' Is the Expression a Scalar?
#'
#' @param x A CVXR expression.
#' @returns Logical.
#' @seealso [size()], [is_vector()], [is_matrix()]
#' @export
is_scalar <- function(x) {
  expr_is_scalar(x)
}

#' Is the Expression a Vector?
#'
#' Returns `TRUE` if the expression has at most one dimension greater than 1.
#'
#' @param x A CVXR expression.
#' @returns Logical.
#' @seealso [size()], [is_scalar()], [is_matrix()]
#' @export
is_vector <- function(x) {
  expr_is_vector(x)
}

#' Is the Expression a Matrix?
#'
#' Returns `TRUE` if the expression has both dimensions greater than 1.
#'
#' @param x A CVXR expression.
#' @returns Logical.
#' @seealso [size()], [is_scalar()], [is_vector()]
#' @export
is_matrix <- function(x) {
  expr_is_matrix(x)
}

#' Get Expression Curvature
#'
#' Returns the DCP curvature of an expression as a string.
#'
#' @param x A CVXR expression.
#' @returns Character: `"CONSTANT"`, `"AFFINE"`, `"CONVEX"`, `"CONCAVE"`,
#'   or `"UNKNOWN"`.
#' @seealso [is_convex()], [is_concave()], [is_affine()], [is_constant()]
#' @export
curvature <- function(x) {
  expr_curvature(x)
}

#' Is the Expression Piecewise Linear?
#'
#' @param x A CVXR expression.
#' @returns Logical.
#' @name is_pwl
#' @export
#' @rdname is_pwl
NULL

# Note: is_pwl is already an S7 generic; we just need to export it.
# The @export @rdname above will be picked up by roxygen.

# -- S3 methods for dim/as.character ------------------------------
# These are registered in .onLoad() via registerS3method() because
# S7 class names contain "::" which can't appear in S3 method names.
# nrow()/ncol() work automatically once dim() is defined.

#' @keywords internal
.cvxr_dim_Expression <- function(x) x@shape

#' @keywords internal
.cvxr_as_character_Expression <- function(x, ...) expr_name(x)

#' Unpack Results (backward-compatible alias)
#'
#' `r lifecycle::badge("deprecated")`
#'
#' Use [problem_unpack_results()] instead. This alias exists for
#' backward compatibility with older CVXR examples.
#'
#' @inheritParams problem_unpack_results
#' @returns The problem object (invisibly), with solution unpacked.
#' @seealso [problem_unpack_results()]
#' @export
unpack_results <- function(problem, solution, chain, inverse_data) {
  cli_warn(
    "{.fn unpack_results} is deprecated. Use {.fn problem_unpack_results} instead.",
    .frequency = "once", .frequency_id = "cvxr_unpack_results_deprecated"
  )
  problem_unpack_results(problem, solution, chain, inverse_data)
}

#' Elementwise multiplication (deprecated)
#'
#' `r lifecycle::badge("deprecated")`
#'
#' Use the `*` operator instead: `x * y`.
#'
#' @param x,y Expressions or numeric values.
#' @returns An Expression representing the elementwise product.
#' @export
multiply <- function(x, y) {
  cli_warn(c(
    "{.fn multiply} is deprecated. Use {.code x * y} instead."
  ), .frequency = "once", .frequency_id = "cvxr_multiply_deprecated")
  x * y
}

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.