R/013_utilities_solver_context.R

Defines functions .maybe_warn_soc_approx .solver_supports_cone

#####
## DO NOT EDIT THIS FILE!! EDIT THE SOURCE INSTEAD: rsrc_tree/utilities/solver_context.R
#####

## CVXPY SOURCE: utilities/solver_context.py
##
## SolverInfo carries the chosen solver's name and supported-constraint
## set down through the solving chain so canonicalizers can see what the
## target solver can handle (used today only by the SOC-approximation
## warnings in power/geo_mean/pnorm approx canonicalizers and by auxiliary
## variable bound propagation).
##
## Mirrors CVXPY's `SolverInfo` (lines 18-32; its `dir_cone_kinds` field is
## n/a-for-r, ExtractDirectCones is not targeted).  `solver_supported_constraints`
## holds S7 class objects (e.g. PowCone3D, PowConeND, SOC), matching how
## CVXR stores `@SUPPORTED_CONSTRAINTS` on solver instances.

## `psd_triangle_kind` / `psd_sqrt2_scaling` mirror solver_context.py:28-29 --
## the chosen solver's PSD svec format, carried so the PSD -> svec conversion
## and its dual recovery read it from ONE place instead of each solver
## interface re-deriving it (ADR D_19.6).  NA means the solver takes full PSD
## matrices (CVXPY's `None`).

SolverInfo <- new_class("SolverInfo", package = "CVXR",
  properties = list(
    solver_name                  = class_character,
    solver_supported_constraints = class_list,
    solver_supports_bounds       = class_logical,
    psd_triangle_kind            = class_character,
    psd_sqrt2_scaling            = class_logical
  ),
  constructor = function(solver_name = NA_character_,
                         solver_supported_constraints = list(),
                         solver_supports_bounds = FALSE,
                         psd_triangle_kind = NA_character_,
                         psd_sqrt2_scaling = NA) {
    if (FALSE) new_object(S7_object())  ## S7 static-check guard
    .fast_new(SolverInfo, S7_object(),
      solver_name                  = as.character(solver_name),
      solver_supported_constraints = solver_supported_constraints,
      solver_supports_bounds       = isTRUE(solver_supports_bounds),
      psd_triangle_kind            = as.character(psd_triangle_kind),
      psd_sqrt2_scaling            = as.logical(psd_sqrt2_scaling)
    )
  }
)

## CVXPY SOURCE: settings.py:233-234
.POWERCONE_APPROX_ERROR_THRESHOLD <- 1e-6
.POWERCONE_APPROX_SOC_THRESHOLD   <- 4L

## Predicate: is `target_cone` listed in this solver's supported constraints?
## `solver_supported_constraints` is a list of S7 class objects; membership is
## by class NAME (`.cone_has`, reductions/solvers/solver.R), as in the rest of
## the chain. Upstream (`power_canon.py:90-92`) tests `PowCone3D in
## solver_context.solver_supported_constraints`, type identity on a Python
## class; `identical()` on an R class object is a structural walk that fails
## on an instrumented copy (covr, trace()) (sweep item 4, pass J).
.solver_supports_cone <- function(solver_context, target_cone) {
  if (is.null(solver_context)) return(FALSE)
  .cone_has(solver_context@solver_supported_constraints, target_cone)
}

## Emit a UserWarning analogue when the chosen solver supports the
## target power cone yet we are still expanding into an SOC tower.
## Mirrors the warn-emission blocks in CVXPY's power_canon / geo_mean_canon /
## pnorm_canon (lines 90-106, 74-89, 127-142 respectively).
.maybe_warn_soc_approx <- function(solver_context, target_cone,
                                    approx_error, num_soc, msg_head) {
  if (!.solver_supports_cone(solver_context, target_cone)) return(invisible(NULL))
  if (approx_error <= .POWERCONE_APPROX_ERROR_THRESHOLD &&
      num_soc      <= .POWERCONE_APPROX_SOC_THRESHOLD) {
    return(invisible(NULL))
  }
  cli::cli_warn(c(
    "{msg_head} (error: {sprintf('%.2e', approx_error)}) using {num_soc} SOC constraints.",
    "i" = "Consider using {.code approx = FALSE} to use power cones instead."
  ))
  invisible(NULL)
}

Try the CVXR package in your browser

Any scripts or data that you put into this service are public.

CVXR documentation built on Oct. 19, 2026, 5:07 p.m.