R/237_reductions_dnlp2smooth_canonicalizers_rel_entr_canon.R

Defines functions .smooth_rel_entr_canon

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

## CVXPY SOURCE: reductions/dnlp2smooth/canonicalizers/rel_entr_canon.py
## rel_entr(x, y) = x*log(x/y). Special-cased when either argument is constant
## (reuse log / entr canons); otherwise fresh nonneg copies of both arguments.

.dnlp_relentr_MIN_INIT <- 1e-3

.smooth_rel_entr_canon <- function(expr, args) {
  ## first argument constant -> canonicalize using log
  if (is_constant(args[[1L]])) {
    .log <- Log(args[[2L]])
    lc <- .smooth_log_canon(.log, .args(.log))
    x <- value(args[[1L]])
    return(list(x * log(x) - x * lc[[1L]], lc[[2L]]))
  }
  ## second argument constant -> canonicalize using entropy
  if (is_constant(args[[2L]])) {
    .entr <- Entr(args[[1L]])
    ec <- .smooth_entr_canon(.entr, .args(.entr))
    return(list(-ec[[1L]] - args[[1L]] * log(value(args[[2L]])), ec[[2L]]))
  }
  ## neither argument constant
  t1 <- Variable(.shape(args[[1L]]), nonneg = TRUE)
  t2 <- Variable(.shape(args[[2L]]), nonneg = TRUE)
  constraints <- list(t1 == args[[1L]], t2 == args[[2L]])
  v1 <- value(args[[1L]])
  if (!is.null(v1)) value(t1) <- pmax(v1, .dnlp_relentr_MIN_INIT)
  v2 <- value(args[[2L]])
  if (!is.null(v2)) value(t2) <- pmax(v2, .dnlp_relentr_MIN_INIT)
  list(expr_copy(expr, list(t1, t2)), constraints)
}

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.