// // Copyright: Copyright (c) MOSEK ApS, Denmark. All rights reserved. // // File: gp1.cs // // Purpose: Demonstrates how to solve a simple Geometric Program (GP) // cast into conic form with exponential cones and log-sum-exp. // // Example from // https://gpkit.readthedocs.io/en/latest/examples.html//maximizing-the-volume-of-a-box // using System; using mosek.fusion; namespace mosek.fusion.example { public class gp1 { // Models log(sum(exp(Ax+b))) <= 0. // Each row of [A b] describes one of the exp-terms public static void logsumexp(Model M, double[,] A, Variable x, double[] b) { int k = A.GetLength(0); Variable u = M.Variable(k); M.Constraint(Expr.Sum(u), Domain.EqualsTo(1.0)); M.Constraint(Expr.Hstack(u, Expr.ConstTerm(k, 1.0), Expr.Add(Expr.Mul(A, x), b)), Domain.InPExpCone()); } // maximize h*w*d // subjecto to 2*(h*w + h*d) <= Awall // w*d <= Afloor // alpha <= h/w <= beta // gamma <= d/w <= delta // // Variable substitutions: h = exp(x), w = exp(y), d = exp(z). // // maximize x+y+z // subject log( exp(x+y+log(2/Awall)) + exp(x+z+log(2/Awall)) ) <= 0 // y+z <= log(Afloor) // log( alpha ) <= x-y <= log( beta ) // log( gamma ) <= z-y <= log( delta ) public static double[] max_volume_box(double Aw, double Af, double alpha, double beta, double gamma, double delta) { using (Model M = new Model("max_vol_box")) { Variable xyz = M.Variable(3); M.Objective("Objective", ObjectiveSense.Maximize, Expr.Sum(xyz)); logsumexp(M, new double[,] {{1,1,0}, {1,0,1}}, xyz, new double[] {System.Math.Log(2.0/Aw), System.Math.Log(2.0/Aw)}); M.Constraint(Expr.Dot(new double[] {0,1,1}, xyz), Domain.LessThan(System.Math.Log(Af))); M.Constraint(Expr.Dot(new double[] {1,-1,0}, xyz), Domain.InRange(System.Math.Log(alpha),System.Math.Log(beta))); M.Constraint(Expr.Dot(new double[] {0,-1,1}, xyz), Domain.InRange(System.Math.Log(gamma),System.Math.Log(delta))); M.SetLogHandler(Console.Out); M.Solve(); double[] xyzVal = xyz.Level(); double[] hwdVal = new double[3]; for(int i=0; i<3; i++) hwdVal[i] = System.Math.Exp(xyzVal[i]); return hwdVal; } } public static void Main(String[] args) { double Aw = 200.0; double Af = 50.0; double alpha = 2.0; double beta = 10.0; double gamma = 2.0; double delta = 10.0; double[] hwd = max_volume_box(Aw, Af, alpha, beta, gamma, delta); Console.WriteLine("h={0:f4} w={1:f4} d={2:f4}", hwd[0], hwd[1], hwd[2]); } } }