# 6.6 Geometric Programming¶

*Geometric programs* (GP) are a particular class of optimization problems which can be expressed in special polynomial form as positive sums of generalized monomials. More precisely, a geometric problem in canonical form is

where each \(f_0,\ldots,f_m\) is a *posynomial*, that is a function of the form

with arbitrary real \(\alpha_{ki}\) and \(c_k>0\). The standard way to formulate GPs in convex form is to introduce a variable substitution

Under this substitution all constraints in a GP can be reduced to the form

involving a *log-sum-exp* bound. Moreover, constraints involving only a single monomial in \(x\) can be even more simply written as a linear inequality:

We refer to the **MOSEK** Modeling Cookbook and to [BKVH07] for more details on this reformulation. A geometric problem formulated in convex form can be entered into **MOSEK** with the help of exponential cones.

## 6.6.1 Example GP1¶

The following problem comes from [BKVH07]. Consider maximizing the volume of a \(h\times w\times d\) box subject to upper bounds on the area of the floor and of the walls and bounds on the ratios \(h/w\) and \(d/w\):

The decision variables in the problem are \(h,w,d\). We make a substitution

after which (6.16) becomes

Next, we demonstrate how to implement a log-sum-exp constraint (6.15). It can be written as:

This presentation requires one extra variable \(u_k\) for each monomial appearing in the original posynomial constraint. The explicit representation of affine conic constraints (ACC, see Sec. 6.2 (From Linear to Conic Optimization)) in this case is:

We can now use this representation to assemble all constraints in the model. The linear part of the problem is entered as in Sec. 6.1 (Linear Optimization).

```
# Input data
Awall <- 200.0
Afloor <- 50.0
alpha <- 2.0
beta <- 10
gamma <- 2
delta <- 10
# Objective
prob <- list(sense="max")
prob$c <- c(1, 1, 1, 0, 0)
# Linear constraints:
# [ 0 0 0 1 1 ] == 1
# [ 0 1 1 0 0 ] <= log(Afloor)
# [ 1 -1 0 0 0 ] in [log(alpha), log(beta)]
# [ 0 -1 1 0 0 ] in [log(gamma), log(delta)]
#
prob$A <- rbind(c(0, 0, 0, 1, 1),
c(0, 1, 1, 0, 0),
c(1,-1, 0, 0, 0),
c(0,-1, 1, 0, 0))
prob$bc <- rbind(c(1, -Inf, log(alpha), log(gamma)),
c(1, log(Afloor), log(beta), log(delta)))
prob$bx <- rbind(c(-Inf, -Inf, -Inf, -Inf, -Inf),
c( Inf, Inf, Inf, Inf, Inf))
# The conic part FX+g \in Kexp x Kexp
# x y z u v
# [ 0 0 0 1 0 ] 0
# [ 0 0 0 0 0 ] 1 in Kexp
# [ 1 1 0 0 0 ] log(2/Awall)
#
# [ 0 0 0 0 1 ] 0
# [ 0 0 0 0 0 ] 1 in Kexp
# [ 1 0 1 0 0 ] + log(2/Awall)
#
# NOTE: The F matrix is internally stored in the sparse
# triplet form. Use 'giveCsparse' or 'repr' option
# in the sparseMatrix() call to construct the F
# matrix directly in the sparse triplet form.
prob$F <- sparseMatrix(i = c(1, 3, 3, 4, 6, 6),
j = c(4, 1, 2, 5, 1, 3),
x = c(1, 1, 1, 1, 1, 1),
dims = c(6,5))
prob$g <- c(0, 1, log(2/Awall), 0, 1, log(2/Awall))
prob$cones <- matrix(rep(list("PEXP", 3, NULL), 2), ncol=2)
rownames(prob$cones) <- c("type","dim","conepar")
# Optimize and print results
r <- mosek(prob, list(soldetail=1))
print(exp(r$sol$itr$xx[1:3]))
```