# 7.5 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.

## 7.5.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 (7.10) becomes

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

This presentation requires one extra variable \(u_k\) for each monomial appearing in the original posynomial constraint.

```
# Models log(sum(exp(Ax+b))) <= 0.
# Each row of [A b] describes one of the exp-terms
def logsumexp(M, A, x, b):
k = int(A.shape[0])
u = M.variable(k)
M.constraint(Expr.sum(u) == 1.0)
M.constraint(Expr.hstack(u,
Expr.constTerm(k, 1.0),
A @ x + b), Domain.inPExpCone())
```

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

```
def max_volume_box(Aw, Af, alpha, beta, gamma, delta):
with Model('max_vol_box') as M:
xyz = M.variable(3)
M.objective('Objective', ObjectiveSense.Maximize, Expr.sum(xyz))
logsumexp(M, array([[1,1,0],[1,0,1]]), xyz, array([log(2.0/Aw), log(2.0/Aw)]))
M.constraint(Expr.dot([0, 1, 1], xyz) <= log(Af))
M.constraint(Expr.dot([1,-1, 0], xyz) == Domain.inRange(log(alpha),log(beta)))
M.constraint(Expr.dot([0,-1, 1], xyz) == Domain.inRange(log(gamma),log(delta)))
M.setLogHandler(sys.stdout)
M.solve()
return exp(xyz.level())
```

Given sample data we obtain the solution \(h,w,d\) as follows:

```
Aw, Af, alpha, beta, gamma, delta = 200.0, 50.0, 2.0, 10.0, 2.0, 10.0
h,w,d = max_volume_box(Aw, Af, alpha, beta, gamma, delta)
print("h={0:.3f}, w={1:.3f}, d={2:.3f}".format(h, w, d))
```