R/133_problems_param_prob.R

Defines functions apply_parameters get_parameter_vector

#####
## DO NOT EDIT THIS FILE!! EDIT THE SOURCE INSTEAD: rsrc_tree/problems/param_prob.R
#####

## CVXPY SOURCE: problems/param_prob.py + reductions/dcp2cone/cone_matrix_stuffing.py
## ParamConeProg -- parameterized cone program for DPP fast re-solve
##
## Stores sparse tensor representation of the problem data as a function
## of parameters. apply_parameters() multiplies tensor @ param_vec to
## recover numeric A, b, c (and optionally P for QP).


# -- get_parameter_vector -----------------------------------------------
## CVXPY SOURCE: canonInterface.py lines 28-62
## Builds a flattened parameter vector from current parameter values.
## Length = total_param_size (sum of all param sizes including CONSTANT_ID).
## CONSTANT_ID gets value 1.0 at its column (unless zero_offset = TRUE).

get_parameter_vector <- function(param_to_size, param_id_to_col,
                                  parameters, zero_offset = FALSE) {
  total <- sum(as.integer(unlist(param_to_size)))
  param_vec <- numeric(total)
  for (pid_str in names(param_id_to_col)) {
    col <- param_id_to_col[[pid_str]]  # 0-based offset
    pid <- as.integer(pid_str)
    if (pid == LINOP_CONSTANT_ID) {
      if (!zero_offset) param_vec[col + 1L] <- 1.0
    } else {
      ## Find matching Parameter object
      for (p in parameters) {
        if (p@id == pid) {
          val <- value(p)
          if (is.null(val)) {
            cli_abort(c(
              "Problem contains an unspecified parameter.",
              "i" = "Set {.code value({name(p)}) <- <value>} before solving."
            ))
          }
          sz <- param_to_size[[pid_str]]
          param_vec[(col + 1L):(col + sz)] <- as.vector(val)  # column-major
          break
        }
      }
    }
  }
  param_vec
}

# -- ParamConeProg class ------------------------------------------------
## CVXPY SOURCE: cone_matrix_stuffing.py lines 145-318
## Stores tensor representation and applies parameters to produce data.

ParamConeProg <- new_class("ParamConeProg", package = "CVXR",
  properties = list(
    c_tensor     = class_any,  # sparse Matrix: objective tensor (x_length+1, param_size)
    A_tensor     = class_any,  # sparse Matrix: constraint tensor (constr*(x_length+1), param_size)
    P_tensor     = class_any,  # sparse Matrix or NULL: QP tensor (x_length*x_length, param_size)
    x_length     = class_integer,
    x_id         = class_integer,  # variable id for solver inverse data
    parameters   = class_list,
    param_id_to_col = class_list,
    param_to_size   = class_list,
    variables    = class_list,
    var_id_to_col = class_list,
    constraints  = class_list,
    cone_dims    = class_any
  ),
  constructor = function(c_tensor, A_tensor, x_length, x_id, parameters,
                          param_id_to_col, param_to_size,
                          variables, var_id_to_col, constraints,
                          cone_dims, P_tensor = NULL) {
    new_object(S7_object(),
      c_tensor = c_tensor,
      A_tensor = A_tensor,
      P_tensor = P_tensor,
      x_length = as.integer(x_length),
      x_id = as.integer(x_id),
      parameters = parameters,
      param_id_to_col = param_id_to_col,
      param_to_size = param_to_size,
      variables = variables,
      var_id_to_col = var_id_to_col,
      constraints = constraints,
      cone_dims = cone_dims
    )
  }
)

# -- apply_parameters ---------------------------------------------------
## CVXPY SOURCE: cone_matrix_stuffing.py lines 206-240
## Applies current parameter values to tensors, producing A, b, c, (P).
##
## Returns list(c, d, A, b) or list(P, c, d, A, b) if quad_obj.
## c: numeric(x_length), d: numeric(1), A: sparse (m, x_length), b: numeric(m)

apply_parameters <- function(param_prog, quad_obj = FALSE) {
  pv <- get_parameter_vector(param_prog@param_to_size,
                              param_prog@param_id_to_col,
                              param_prog@parameters)
  xl <- param_prog@x_length

  ## Objective: c_tensor is (x_length + 1, param_size) sparse
  ## c_tensor %*% pv -> (x_length + 1) vector
  ## First x_length entries = c, last entry = d (constant offset)
  if (is.null(param_prog@c_tensor))
    cli_abort("DPP fast path requires c_tensor. This is a bug -- please report.")
  c_flat <- as.numeric(param_prog@c_tensor %*% pv)
  c_vec <- c_flat[seq_len(xl)]
  d_offset <- c_flat[xl + 1L]

  ## Constraints: A_tensor is (constr * (x_length + 1), param_size) sparse
  ## A_tensor %*% pv -> (constr * (x_length + 1)) vector
  ## Reshape F-order to (constr, x_length + 1)
  ## First x_length cols = A, last col = b
  Ab_flat <- as.numeric(param_prog@A_tensor %*% pv)
  n_cols <- xl + 1L
  n_rows <- length(Ab_flat) %/% n_cols
  if (n_rows > 0L) {
    ## Reshape to (n_rows, n_cols) column-major
    Ab_mat <- matrix(Ab_flat, nrow = n_rows, ncol = n_cols)
    A <- as(Matrix::Matrix(Ab_mat[, seq_len(xl), drop = FALSE], sparse = TRUE),
            "generalMatrix")
    b <- Ab_mat[, n_cols]
  } else {
    A <- Matrix::sparseMatrix(i = integer(0), j = integer(0), x = numeric(0),
                               dims = c(0L, xl))
    b <- numeric(0)
  }

  if (quad_obj && !is.null(param_prog@P_tensor)) {
    ## P_tensor is (x_length * x_length, param_size) sparse
    P_flat <- as.numeric(param_prog@P_tensor %*% pv)
    P_mat <- Matrix::Matrix(matrix(P_flat, nrow = xl, ncol = xl), sparse = TRUE)
    list(P = P_mat, c = c_vec, d = d_offset, A = A, b = b)
  } else {
    list(c = c_vec, d = d_offset, A = A, b = b)
  }
}

## DEFERRED: ParamConeProg derivative methods (cone_matrix_stuffing.py lines 242-318)
## These 3 methods are needed for Problem$backward()/derivative() via diffcp.
## Deferred because the derivative API depends on diffcp (no R equivalent).
## See notes/derivative_api_deferred.md.
##
## apply_param_jac(param_prog, delc, delA, delb) -- Jacobian of parameter mapping
## split_solution(param_prog, sltn) -- split solution into individual variables
## split_adjoint(param_prog, del_vars) -- adjoint of split_solution

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.