Using log optimization function in Gurobi

I'm trying to use Gurobi to model an optimization max function whose objective function is $$f(x)=\frac{r^Tx}{x^TQx}.$$

Thus maximizing this function $$f(x)$$ is the same as maximizing $$\log f(x)$$ and I want to implement it in Gurobi. My understanding is Gurobi doesn't handle log objective functions so I've made a linear maximization function $$z(x) = t$$ as follows: \begin{align}\max&\quad z(x)=t\\\text{s.t.}&\quad\log(r^Tx) - \log(x^TQx) - t = 0\tag{C1}\\&\quad\vdots\quad\text{(other equality constraints)}.\end{align} Does anyone know how to implement constraint C1 in Gurobi?

• The Sharpe ratio can be cast as a SOCP. We have a blog post about it at themosekblog.blogspot.com/2020/10/… – ErlingMOSEK Dec 10 '20 at 6:13
• Or even simpler a QP (for those not lucky enough to have an SOCP solver) – Johan Löfberg Dec 10 '20 at 8:22
• ...but the important question is if you really wrote your objective correctly? Most likely you want to maximize the so called Sharpe ratio, and then you want to have the square root of the quadratic term. Otherwise the problem i most likely ill-posed – Johan Löfberg Dec 10 '20 at 9:06
• Yes it'll be std deviation but using the log delta that would simply become a scalar – mathcomp guy Dec 10 '20 at 17:38
• Then you should keep the standard Sharpe model, as it allows you to use a very standard QP formulation of the objective (you don't want to unnecessarily solve it is as a nonlinear program as you try to do now) – Johan Löfberg Dec 10 '20 at 19:36

I will make the following assumptions:

1. $$Q$$ is symmetric positive semidefinite
2. $$r^Tx \ge 0$$

Note that maximizing $$\frac{r^Tx}{X^TQx}$$ is equivalent to minimizing $$\frac{X^TQx}{r^Tx}$$ .

Under the stated assumptions, this is a convex optimization problem, which can be submitted to and solved by Gurobi.

The easiest way of doing so is using a convex optimization tool such as CVX or CVXPY. The CVX code would be

cvx_begin
cvx_solver gurobi
variable x(n)

which uses the CVX function quad_over_lin. chol(A) is the upper triangular Cholesky factor of A.
CVXPY also has the same quad_ovdr_lin function as CVX, but depending on which function is called to compute the Cholesky factor, you would need to apply a transpose to the Cholesky factor if a lower triangular Cholesky factor is generated
norm(chol(A)*x) <= sqrt(t*r'*x), t >= 0, r'*x >= 0