R/231_reductions_dnlp2smooth_canonicalizers_common_smooth_canons.R

Defines functions make_smooth_range_dom_canon smooth_nonnegative_dom_canon smooth_full_domain_canon_chain_rule smooth_full_domain_canon_non_chain_rule

#####
## DO NOT EDIT THIS FILE!! EDIT THE SOURCE INSTEAD: rsrc_tree/reductions/dnlp2smooth/canonicalizers/common_smooth_canons.R
#####

## CVXPY SOURCE: reductions/dnlp2smooth/canonicalizers/common_smooth_canons.py
## Common DNLP canonicalizers for smooth atoms (CVXPY 1.9.0).
##
## Four categories, grouped by the atom's domain type:
##  - Full domain (exp, sin, cos, ...): two variants depending on whether the
##    atom's chain rule is implemented in the differentiation engine.
##  - Nonnegative domain (log, entr): require nonnegative inputs.
##  - Bounded domain (tan, atanh): domain is a bounded interval.
##
## All canon functions follow the signature  canon(expr, args) -> list(new_expr,
## constraints)  where `args` are the already-canonicalized arguments of `expr`.

MIN_INIT_NONNEG_CANON <- 1e-3

## Smooth atom, full domain, one argument, chain rule NOT implemented in the
## diff engine. CVXPY SOURCE: common_smooth_canons.py:40-48
smooth_full_domain_canon_non_chain_rule <- function(expr, args) {
  if (.s7_is(args[[1L]], Variable)) {
    return(list(expr_copy(expr, list(args[[1L]])), list()))
  }
  t <- Variable(.shape(args[[1L]]))
  v <- value(args[[1L]])
  if (!is.null(v)) value(t) <- v
  list(expr_copy(expr, list(t)), list(t == args[[1L]]))
}

## Smooth atom, full domain (possibly multiple arguments), chain rule
## implemented in the diff engine. CVXPY SOURCE: common_smooth_canons.py:50-53
smooth_full_domain_canon_chain_rule <- function(expr, args) {
  list(expr_copy(expr, args), list())
}

## Smooth atom (one argument) whose domain is the nonnegative reals.
## CVXPY SOURCE: common_smooth_canons.py:55-61
smooth_nonnegative_dom_canon <- function(expr, args) {
  t <- Variable(.shape(args[[1L]]), nonneg = TRUE)
  v <- value(args[[1L]])
  if (!is.null(v)) value(t) <- pmax(v, MIN_INIT_NONNEG_CANON)
  list(expr_copy(expr, list(t)), list(t == args[[1L]]))
}

## Wrapper for canonicalizers whose domain is a bounded interval [lower, upper].
## CVXPY SOURCE: common_smooth_canons.py:63-76
make_smooth_range_dom_canon <- function(lower, upper) {
  function(expr, args) {
    t <- Variable(.shape(args[[1L]]), bounds = list(lower, upper))
    ## If the initial value is within 10% of the interval length from either
    ## bound, initialize at the midpoint instead.
    margin <- 0.1 * (upper - lower)
    midpoint <- (lower + upper) / 2.0
    v <- value(args[[1L]])
    if (!is.null(v)) {
      safe_idxs <- (v >= lower + margin) & (v <= upper - margin)
      value(t) <- ifelse(safe_idxs, v, midpoint)
    }
    list(expr_copy(expr, list(t)), list(t == args[[1L]]))
  }
}

# -- aliases (CVXPY SOURCE: common_smooth_canons.py:78-102) -----------
## NOTE: function names carry a `.smooth_` prefix (like dgp2dcp's `.dgp_`)
## because the package namespace is flat -- bare names like `log_canon`/
## `exp_canon` already exist in dcp2cone and must not be shadowed.

## atoms with domain equal to the nonnegative reals
.smooth_entr_canon <- smooth_nonnegative_dom_canon
.smooth_log_canon  <- smooth_nonnegative_dom_canon

## atoms that do not yet have the chain rule implemented in the diff engine
.smooth_prod_canon <- smooth_full_domain_canon_non_chain_rule

## elementwise atoms with chain rule implemented in the diff engine
.smooth_exp_canon      <- smooth_full_domain_canon_chain_rule
.smooth_sin_canon      <- smooth_full_domain_canon_chain_rule
.smooth_cos_canon      <- smooth_full_domain_canon_chain_rule
.smooth_sinh_canon     <- smooth_full_domain_canon_chain_rule
.smooth_tanh_canon     <- smooth_full_domain_canon_chain_rule
.smooth_asinh_canon    <- smooth_full_domain_canon_chain_rule
.smooth_logistic_canon <- smooth_full_domain_canon_chain_rule
.smooth_normcdf_canon  <- smooth_full_domain_canon_chain_rule

## other atoms with chain rule implemented in the diff engine
.smooth_multiply_canon  <- smooth_full_domain_canon_chain_rule
.smooth_matmul_canon    <- smooth_full_domain_canon_chain_rule
.smooth_quad_form_canon <- smooth_full_domain_canon_chain_rule

## atoms with domain equal to a bounded interval
.smooth_atanh_canon <- make_smooth_range_dom_canon(-1, 1)
.smooth_tan_canon   <- make_smooth_range_dom_canon(-pi / 2, pi / 2)

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.