R/242_reductions_dnlp2smooth_dnlp2smooth.R

Defines functions .dnlp2smooth_expr .dnlp2smooth_tree

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

## CVXPY SOURCE: reductions/dnlp2smooth/dnlp2smooth.py
## Dnlp2Smooth -- reduce a disciplined nonlinear program (DNLP) to an equivalent
## smooth program. Inherits from Canonicalization but, like Dgp2Dcp, uses its
## own tree walk that dispatches via the smooth_canonicalize generic (NULL ->
## copy). Dual remapping is inherited from Canonicalization (cons_id_map).


## smooth_canonicalize generic is defined in smooth_canonicalizers.R (loads first).

Dnlp2Smooth <- new_class("Dnlp2Smooth", parent = Canonicalization, package = "CVXR",
  constructor = function() {
    if (FALSE) new_object(S7_object())  ## S7 static-check guard
    .fast_new(Dnlp2Smooth, S7_object(),
      .cache = new.env(parent = emptyenv())
    )
  }
)

## -- reduction_accepts: a problem is always accepted -----------------
## CVXPY SOURCE: dnlp2smooth.py:37-39
method(reduction_accepts, Dnlp2Smooth) <- function(x, problem, ...) TRUE

## -- reduction_apply -------------------------------------------------
## CVXPY SOURCE: dnlp2smooth.py:41-65
method(reduction_apply, Dnlp2Smooth) <- function(x, problem, ...) {
  inverse_data <- InverseData(problem)
  ## Record objective sense for the NLP solve path (Wave-1 steps 5-7).
  inverse_data@.extra$minimize <- .s7_is(problem@objective, Minimize)

  ## Smoothen objective via OWN tree walk
  obj_result <- .dnlp2smooth_tree(problem@objective)
  canon_objective <- obj_result[[1L]]

  ## Smoothen each constraint -- collect chunks, flatten once
  n_cons <- length(problem@constraints)
  all_chunks <- vector("list", n_cons + 1L)
  all_chunks[[1L]] <- obj_result[[2L]]
  for (i in seq_len(n_cons)) {
    con <- problem@constraints[[i]]
    con_result <- .dnlp2smooth_tree(con)
    all_chunks[[i + 1L]] <- c(con_result[[2L]], list(con_result[[1L]]))
    assign(as.character(.id(con)), .id(con_result[[1L]]),
           envir = inverse_data@cons_id_map)
  }
  canon_constraints <- unlist(all_chunks, recursive = FALSE)
  if (is.null(canon_constraints)) canon_constraints <- list()

  new_problem <- Problem(canon_objective, canon_constraints)
  list(new_problem, inverse_data)
}

## reduction_invert is inherited from Canonicalization (cons_id_map dual remap).


## ==================================================================
## Own tree walk
## ==================================================================
## CVXPY SOURCE: dnlp2smooth.py:67-111.
## NOTE: CVXPY threads an `affine_above` flag through canonicalize_tree /
## canonicalize_expr, but in 1.9.0 it is computed and never consumed by any
## canon method, so we omit it -- the canonicalized output is identical.

## .dnlp2smooth_tree: recursive bottom-up walk
.dnlp2smooth_tree <- function(expr) {
  n_args <- length(.args(expr))
  canon_args <- vector("list", n_args)
  constr_chunks <- vector("list", n_args + 1L)
  for (i in seq_len(n_args)) {
    arg_result <- .dnlp2smooth_tree(.args(expr)[[i]])
    canon_args[[i]] <- arg_result[[1L]]
    constr_chunks[[i]] <- arg_result[[2L]]
  }
  node_result <- .dnlp2smooth_expr(expr, canon_args)
  constr_chunks[[n_args + 1L]] <- node_result[[2L]]
  constrs <- unlist(constr_chunks, recursive = FALSE)
  if (is.null(constrs)) constrs <- list()
  list(node_result[[1L]], constrs)
}

## .dnlp2smooth_expr: canonicalize a single node
.dnlp2smooth_expr <- function(expr, args) {
  ## Constant trees are collapsed, but parameter trees are preserved.
  if (.s7_is(expr, Expression) &&
      is_constant(expr) && length(parameters(expr)) == 0L) {
    return(list(expr, list()))
  }
  ## smooth_canonicalize -- NULL means no method registered for this class
  result <- smooth_canonicalize(expr, args)
  if (!is.null(result)) return(result)
  ## Default: copy with canonicalized args
  list(expr_copy(expr, args), list())
}

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.