R/131_problems_objective.R

Defines functions .div_objective .mul_objective .sub_objectives .add_objectives .negate_objective scalar_value

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

## CVXPY SOURCE: problems/objective.py
## Objective, Minimize, Maximize -- optimization objective wrappers

# -- scalar_value: extract scalar from 1x1 matrix ---------------------
## CVXPY SOURCE: interface/matrix_utilities.py::scalar_value

scalar_value <- function(v) {
  if (is.null(v)) return(NULL)
  if (is.numeric(v) && length(v) == 1L) return(as.double(v))
  if (is.matrix(v) || inherits(v, "Matrix")) {
    if (prod(dim(v)) == 1L) return(as.double(v[1L, 1L]))
  }
  as.double(v[1L])
}

# -- Objective base class ---------------------------------------------
## CVXPY SOURCE: objective.py lines 25-116

Objective <- new_class("Objective", parent = Canonical, package = "CVXR",
  properties = list(
    .name = new_property(class = class_character, default = "objective")
  ),
  constructor = function(expr) {
    expr <- as_expr(expr)
    ## Validate scalar
    ## CVXPY SOURCE: objective.py lines 46-49
    if (!expr_is_scalar(expr)) {
      cli_abort("The {.val objective} objective must resolve to a scalar.")
    }
    if (!is_real(expr)) {
      cli_abort("The {.val objective} objective must be real valued.")
    }
    new_object(S7_object(),
      id = next_expr_id(),
      .cache = new.env(parent = emptyenv()),
      args = list(expr),
      .name = "objective"
    )
  }
)

# -- Objective value --------------------------------------------------
## CVXPY SOURCE: objective.py lines 97-105

method(value, Objective) <- function(x) {
  v <- value(x@args[[1L]])
  if (is.null(v)) return(NULL)
  scalar_value(v)
}

# -- Objective print --------------------------------------------------

method(print, Objective) <- function(x, ...) {
  cat(sprintf("%s %s\n", x@.name, expr_name(x@args[[1L]])))
  invisible(x)
}

# -- Objective is_quadratic / is_qpwa --------------------------------
## CVXPY SOURCE: objective.py lines 107-115

method(is_quadratic, Objective) <- function(x) is_quadratic(x@args[[1L]])
method(is_qpwa, Objective) <- function(x) is_qpwa(x@args[[1L]])

# -- Objective is_dcp default -----------------------------------------

method(is_dcp, Objective) <- function(x) FALSE

# -- Minimize ---------------------------------------------------------
## CVXPY SOURCE: objective.py lines 118-186

#' Create a Minimization Objective
#'
#' Specifies that the objective expression should be minimized. The expression
#' must be convex and scalar for a DCP-compliant problem.
#'
#' @param expr A CVXR expression or numeric value to minimize.
#' @returns A \code{Minimize} object.
#'
#' @examples
#' x <- Variable()
#' obj <- Minimize(x^2 + 1)
#'
#' @seealso \code{\link{Maximize}}, \code{\link{Problem}}
#' @export
Minimize <- new_class("Minimize", parent = Objective, package = "CVXR",
  constructor = function(expr) {
    expr <- as_expr(expr)
    if (!expr_is_scalar(expr)) {
      cli_abort("The {.val minimize} objective must resolve to a scalar.")
    }
    if (!is_real(expr)) {
      cli_abort("The {.val minimize} objective must be real valued.")
    }
    new_object(S7_object(),
      id = next_expr_id(),
      .cache = new.env(parent = emptyenv()),
      args = list(expr),
      .name = "minimize"
    )
  }
)

## is_dcp: the objective expression must be convex
## CVXPY SOURCE: objective.py lines 151-157
method(is_dcp, Minimize) <- function(x) is_convex(x@args[[1L]])

## is_dqcp: the objective expression must be quasiconvex
## CVXPY SOURCE: objective.py lines 176-179
method(is_dqcp, Minimize) <- function(x) is_quasiconvex(x@args[[1L]])

## is_dgp: the objective expression must be log-log convex
## CVXPY SOURCE: objective.py lines 159-165
method(is_dgp, Minimize) <- function(x) is_log_log_convex(x@args[[1L]])

## is_dpp: check DPP compliance within DPP scope
## CVXPY SOURCE: objective.py lines 167-174
method(is_dpp, Minimize) <- function(x) {
  with_dpp_scope(is_convex(x@args[[1L]]))
}

## canonicalize: pass through the expression's canonical form
## CVXPY SOURCE: objective.py lines 146-149
method(canonicalize, Minimize) <- function(x) canonical_form(x@args[[1L]])

## print
method(print, Minimize) <- function(x, ...) {
  cat(sprintf("minimize %s\n", expr_name(x@args[[1L]])))
  invisible(x)
}

# -- Maximize ---------------------------------------------------------
## CVXPY SOURCE: objective.py lines 188-257

#' Create a Maximization Objective
#'
#' Specifies that the objective expression should be maximized. The expression
#' must be concave and scalar for a DCP-compliant problem.
#'
#' @param expr A CVXR expression or numeric value to maximize.
#' @returns A \code{Maximize} object.
#'
#' @examples
#' x <- Variable()
#' obj <- Maximize(-x^2 + 1)
#'
#' @seealso \code{\link{Minimize}}, \code{\link{Problem}}
#' @export
Maximize <- new_class("Maximize", parent = Objective, package = "CVXR",
  constructor = function(expr) {
    expr <- as_expr(expr)
    if (!expr_is_scalar(expr)) {
      cli_abort("The {.val maximize} objective must resolve to a scalar.")
    }
    if (!is_real(expr)) {
      cli_abort("The {.val maximize} objective must be real valued.")
    }
    new_object(S7_object(),
      id = next_expr_id(),
      .cache = new.env(parent = emptyenv()),
      args = list(expr),
      .name = "maximize"
    )
  }
)

## is_dcp: the objective expression must be concave
## CVXPY SOURCE: objective.py lines 222-228
method(is_dcp, Maximize) <- function(x) is_concave(x@args[[1L]])

## is_dqcp: the objective expression must be quasiconcave
## CVXPY SOURCE: objective.py lines 247-250
method(is_dqcp, Maximize) <- function(x) is_quasiconcave(x@args[[1L]])

## is_dgp: the objective expression must be log-log concave
## CVXPY SOURCE: objective.py lines 230-236
method(is_dgp, Maximize) <- function(x) is_log_log_concave(x@args[[1L]])

## is_dpp: check DPP compliance within DPP scope
## CVXPY SOURCE: objective.py lines 238-245
method(is_dpp, Maximize) <- function(x) {
  with_dpp_scope(is_concave(x@args[[1L]]))
}

## canonicalize: negate the expression's canonical form
## CVXPY SOURCE: objective.py lines 216-220
method(canonicalize, Maximize) <- function(x) {
  result <- canonical_form(x@args[[1L]])
  obj <- result[[1L]]
  constraints <- result[[2L]]
  list(neg_expr_linop(obj), constraints)
}

## print
method(print, Maximize) <- function(x, ...) {
  cat(sprintf("maximize %s\n", expr_name(x@args[[1L]])))
  invisible(x)
}

# -- Objective arithmetic ---------------------------------------------
## CVXPY SOURCE: objective.py lines 61-105 (Objective.__add__, __mul__, etc.)

## Negate: -Minimize(f) -> Maximize(-f), -Maximize(f) -> Minimize(-f)
## CVXPY SOURCE: objective.py Minimize.__neg__ / Maximize.__neg__
.negate_objective <- function(obj) {

  expr <- obj@args[[1L]]
  if (S7_inherits(obj, Minimize)) Maximize(-expr) else Minimize(-expr)
}

## Add: both must be same type (Minimize+Minimize or Maximize+Maximize)
## CVXPY SOURCE: objective.py Minimize.__add__ / Maximize.__add__
.add_objectives <- function(o1, o2) {
  if (!S7_inherits(o2, Objective))
    cli_abort("Cannot add {.cls {class(o2)[[1L]]}} to an objective.")
  e1 <- o1@args[[1L]]
  e2 <- o2@args[[1L]]
  if (S7_inherits(o1, Minimize) && S7_inherits(o2, Minimize)) {
    Minimize(e1 + e2)
  } else if (S7_inherits(o1, Maximize) && S7_inherits(o2, Maximize)) {
    Maximize(e1 + e2)
  } else {
    cli_abort("Cannot add {.cls Minimize} and {.cls Maximize} (violates DCP).")
  }
}

## Subtract: o1 - o2 = o1 + (-o2)
.sub_objectives <- function(o1, o2) {
  .add_objectives(o1, .negate_objective(o2))
}

## Multiply by scalar: sign flip reverses direction
## CVXPY SOURCE: objective.py Objective.__mul__
.mul_objective <- function(obj, scalar) {
  if (!is.numeric(scalar) || length(scalar) != 1L)
    cli_abort("Objective can only be multiplied by a numeric scalar.")
  expr <- obj@args[[1L]]
  ## If (Maximize && negative) or (Minimize && negative), flip direction
  if ((S7_inherits(obj, Maximize)) == (scalar < 0)) {
    Minimize(expr * scalar)
  } else {
    Maximize(expr * scalar)
  }
}

## Divide by scalar
.div_objective <- function(obj, scalar) {
  if (!is.numeric(scalar) || length(scalar) != 1L)
    cli_abort("Objective can only be divided by a numeric scalar.")
  .mul_objective(obj, 1.0 / scalar)
}

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.