DGP Fundamentals

Author

CVXPY Developers and Balasubramanian Narasimhan

Introduction

This example will introduce you to the fundamentals of disciplined geometric programming (DGP), which lets you formulate and solve log-log convex programs (LLCPs) in CVXR.

LLCPs are problems that become convex after the variables, objective functions, and constraint functions are replaced with their logs, an operation that we refer to as a log-log transformation. LLCPs generalize geometric programming.

1. Log-Log Curvature

Just as every Expression in CVXR has a curvature (constant, affine, convex, concave, or unknown), every Expression also has a log-log curvature.

A function f:DR++nR is said to be log-log convex if the function F(u)=logf(eu), with domain {uRn:euD}, is convex; the function F is called the log-log transformation of f. The function f is log-log concave if F is concave, and it is log-log affine if F is affine.

Notice that if a function has log-log curvature, then its domain and range can only include positive numbers.

For an Expression to have known log-log curvature, all of the Constants, Variables, and Parameters it refers to must be elementwise positive.

Variables and Parameters

Variables and parameters must be positive, i.e., they must be constructed with the option pos = TRUE:

v <- Variable(pos = TRUE)
cat("Positive variable is log-log affine:", is_log_log_affine(v), "\n")

p <- Parameter(pos = TRUE)
cat("Positive parameter is log-log affine:", is_log_log_affine(p), "\n")
Positive variable is log-log affine: TRUE 
Positive parameter is log-log affine: TRUE 

Functions from Geometric Programming

A function f(x) is log-log affine if and only if it is given by

f(x)=cx1a1x2a2xnan,

where c>0 and the ai are real numbers. In the context of geometric programming, such a function is called a monomial.

x <- Variable(3, pos = TRUE)
cc <- 2.0
a <- c(0.5, 2.0, 1.8)

monomial <- cc * power(x[1], a[1]) * power(x[2], a[2]) * power(x[3], a[3])
cat("Monomial is log-log affine:", is_log_log_affine(monomial), "\n")
Monomial is log-log affine: TRUE 

A sum of monomial functions is log-log convex; in the context of geometric programming, such a function is called a posynomial. There are functions that are not posynomials that are still log-log convex.

x <- Variable(pos = TRUE)
y <- Variable(pos = TRUE)

constant <- 2.0
monomial <- constant * x * y
posynomial <- monomial + power(x, 1.5) * power(y, -1)
reciprocal <- power(posynomial, -1)

cat("monomial is log-log affine:", is_log_log_affine(monomial), "\n")
cat("posynomial is log-log convex:", is_log_log_convex(posynomial), "\n")
cat("reciprocal is log-log concave:", is_log_log_concave(reciprocal), "\n")
monomial is log-log affine: TRUE 
posynomial is log-log convex: TRUE 
reciprocal is log-log concave: TRUE 

2. Log-Log Curvature Ruleset

CVXR has a library of atomic functions with known log-log curvature and monotonicity. It uses this information to tag every Expression with a log-log curvature. The composition rules are:

A function f(expr1,expr2,,exprn) is log-log convex if f is a log-log convex function and for each expri one of the following conditions holds:

  • f is increasing in argument i and expri is log-log convex.
  • f is decreasing in argument i and expri is log-log concave.
  • expri is log-log affine.

Similar rules apply for log-log concave and log-log affine expressions.

If an Expression satisfies the composition rule, we colloquially say that the Expression “is DGP.” You can check the log-log curvature of an expression using is_log_log_convex(), is_log_log_concave(), and is_log_log_affine(). You can check whether a Problem is DGP by calling is_dgp().

x <- Variable(pos = TRUE)
y <- Variable(pos = TRUE)

monomial <- 2.0 * x * y
posynomial <- monomial + power(x, 1.5) * power(y, -1)

cat("monomial is log-log affine:", is_log_log_affine(monomial), "\n")
cat("posynomial is log-log convex:", is_log_log_convex(posynomial), "\n")
monomial is log-log affine: TRUE 
posynomial is log-log convex: TRUE 

3. DGP Problems

An LLCP is an optimization problem of the form

minimizef0(x)subject tofi(x)fi~,i=1,,mgi(x)=gi~,i=1,,p,

where the functions fi are log-log convex, fi~ are log-log concave, and the functions gi and gi~ are log-log affine.

A problem is DGP if additionally all the functions are DGP. You can check whether a CVXR Problem is DGP by calling is_dgp() on the problem object.

x <- Variable(pos = TRUE)
y <- Variable(pos = TRUE)
z <- Variable(pos = TRUE)

objective_fn <- x * y * z
constraints <- list(
  4 * x * y * z + 2 * x * z <= 10,
  x <= 2 * y,
  y <= 2 * x,
  z >= 1
)
problem <- Problem(Maximize(objective_fn), constraints)
cat("Is this problem DGP?", is_dgp(problem), "\n")
Is this problem DGP? TRUE 

Solving DGP Problems

You can solve a DGP Problem by calling psolve() with gp = TRUE.

result <- psolve(problem, gp = TRUE)
check_solver_status(problem)
cat("Optimal value:", result, "\n")
cat("x:", value(x), "\n")
cat("y:", value(y), "\n")
cat("z:", value(z), "\n")
Optimal value: 2 
x: 1 
y: 2 
z: 1 

If you forget to supply gp = TRUE, an error will be raised because the problem is not DCP-compliant.

4. Next Steps

Atoms

CVXR has a large library of log-log convex functions, including common functions like exp(), log(), and the difference between two numbers via one_minus_pos(). Check out the DGP tutorial page for the full list of atoms.

References

For a reference on DGP, consult the following paper: https://web.stanford.edu/~boyd/papers/dgp.html

Session Info

R version 4.5.2 (2025-10-31)
Platform: aarch64-apple-darwin20
Running under: macOS Tahoe 26.3

Matrix products: default
BLAS:   /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRblas.0.dylib 
LAPACK: /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.1

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

time zone: America/Los_Angeles
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices datasets  utils     methods   base     

other attached packages:
[1] CVXR_1.8.0.9207

loaded via a namespace (and not attached):
 [1] slam_0.1-55       cli_3.6.5         knitr_1.51        ECOSolveR_0.6.1  
 [5] rlang_1.1.7       xfun_0.56         clarabel_0.11.2   otel_0.2.0       
 [9] gurobi_13.0-1     Rglpk_0.6-5.1     highs_1.12.0-3    cccp_0.3-3       
[13] scs_3.2.7         S7_0.2.1          jsonlite_2.0.0    backports_1.5.0  
[17] Rcplex_0.3-8      Rmosek_11.1.1     rprojroot_2.1.1   htmltools_0.5.9  
[21] gmp_0.7-5.1       piqp_0.6.2        rmarkdown_2.30    grid_4.5.2       
[25] evaluate_1.0.5    fastmap_1.2.0     yaml_2.3.12       compiler_4.5.2   
[29] codetools_0.2-20  htmlwidgets_1.6.4 Rcpp_1.1.1        here_1.0.2       
[33] osqp_1.0.0        lattice_0.22-9    digest_0.6.39     checkmate_2.3.4  
[37] Matrix_1.7-4      tools_4.5.2