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))