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 is said to be log-log convex if the function , with domain , is convex; the function is called the log-log transformation of . The function is log-log concave if is concave, and it is log-log affine if 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 is log-log affine if and only if it is given by
where and the are real numbers. In the context of geometric programming, such a function is called a monomial.
x <-Variable(3, pos =TRUE)cc <-2.0a <-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.0monomial <- constant * x * yposynomial <- 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 is log-log convex if is a log-log convex function and for each one of the following conditions holds:
is increasing in argument and is log-log convex.
is decreasing in argument and is log-log concave.
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 * yposynomial <- 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
where the functions are log-log convex, are log-log concave, and the functions and 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 * zconstraints <-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.