• Gurobi Staff

Hi Andrea,

Yes, you can solve this problem with Gurobi. For the logarithm, you would have to use the addGenConstrLog() function.

The bilinear terms can be modeled either through adding each constraint one by one or using the matrix API. We recommend having a look at our Matrix API webinar and our Python Example Tour. Additionally, our Knowledge Base article How do I model multilinear terms in Gurobi? may be helpful.

Best regards,
Jaromił

Are you sure about that?  How is ln x handled?

• Gurobi Staff

Hi Mark,

Gurobi uses piecewise approximation for $$ln(x)$$ and a couple of other functions. You can read more in the documentation on addGenConstrXxx().

Best regards,
Jaromił

My main problem is the quadratic constraint of variance. I really don't know how to write it. I don't know if you can also solve it with MATLAB

• Gurobi Staff

Hi Andrea,

It is possible in MATLAB as well. Please have a look at the MATLAB API Documentation and the MATLAB example tour. The logarithm can be modeled using so-called Function constraints.

In order to slowly make progress in modeling, you can use the gurobi_write() function to write an LP file and inspect it to see whether the model you construct is actually correct.

Best regards,
Jaromił

I found on the documentation you suggested that I can solve the problem using "qcp", but being unfamiliar with the software I don't know how to build the matrices on the gurobi interface for MATLAB.

• Gurobi Staff

Hi Andrea,

Did you have a look at our MATLAB examples? In particular the examples bilinear.m, qp.m, and qcp.m should be helpful. You can find these examples in your Gurobi installation folder at $$\texttt{<pathToGurobi>/examples/matlab/}$$.

Best regards,
Jaromił

I have read the documentation but do not understand how to set the problem. My quadconstraints is represented by X^T*Sigma*X, where X is a ones(n,1) vector and sigma is a square matrix nxn. How can I write this constraint?

• Gurobi Staff

Hi Andrea,

Let's assume that your $$x^T \Sigma x$$ provide the constraints

\begin{align*} 2x^2 - &xy &= 0\\ &xy +2y^2 &= 0 \end{align*}

You can model the above constraint by setting the values of each entry of the $$Q$$ matrix as

%Entry Qrow=1 and Qcol=1 is x^2
%Entry Qrow=1 and Qcol=2 is xy
%Entry Qrow=2 and Qcol=2 is y^2
m.quadcon(1).Qval=[2, -1]; % value of coefficient for (Qrow=1,Qcol=1) is 2, value of coefficient for (Qrow=1,Qcol=2) is -1
m.quadcon(1).q = sparse(2,1); % no linear terms so just create a sparse matrix filled with zeros

m.quadcon(2).Qval=[1, 2]; % value of coefficient for (Qrow=1,Qcol=2) is 1, value of coefficient for (Qrow=2,Qcol=2) is 2
m.quadcon(2).q = sparse(2,1); % no linear terms so just create a sparse matrix filled with zeros

This basically means that you can define your constraints defined by $$x^T \Sigma x$$ in a $$\texttt{for}$$-loop setting each constraint one by one in the loop.

Best regards,
Jaromił

I tried to write the model this way, but gurobi couldn't solve it

• Gurobi Staff

Hi Andrea,

What exactly do you mean by "Gurobi couldn't solve it"? Do you mean that the optimization does not converge or that some other error occured? Could you post the LOG file and/or the error code?

Best regards,
Jaromił

Error using gurobi
Incorrect size(model.obj)

Error in Nicola (line 22)
result=gurobi(model);

• Gurobi Staff

Hi Andrea,

In order to use the logarithm, you have to make use of the $$\texttt{genconlog}$$ function described in the documentation of the model argument. This means that you have to add an auxiliary variable $$w_i$$ for each $$w_i=ln(x_i)$$. Then, your objective function reads $$\mathbf{x}^T \cdot \mathbf{w}$$. The matrix $$\texttt{Q}$$ of the model object describes the quadratic part of the objective, i.e., this is the one you would have to properly set.

Let's say you have 2 variables $$x_1,x_2$$ and introduced 2 auxiliary variables $$w_1,w_2$$, then your $$\texttt{Q}$$ should be given as

model.Q = sparse([0 0 0.5 0.5; 0 0 0.5 0.5; 0.5 0.5 0 0; 0.5 0.5 0 0])

In general, we would recommend to switch to the Python API if possible, as modelling with the Python API is quite more intuitive compared to the MATLAB object based API.

Best regards,
Jaromił

But if \x_i is not defined ? \x_i is my objective variable. So, How can I write \w_i as a function of something that I don't have ?

• Gurobi Staff

Hi Andrea,

You would have to work with the matrices as if the auxiliary variables are there and then you have to set the $$\texttt{xvar}$$ and $$\texttt{yvar}$$ attributes of the $$\texttt{genconlog}$$ object.

I would strongly recommend to switch to the Python API as implementing your model with the use of Gurobi's Python API would be way easier and more intuitive.

Best regards,
Jaromił

Hi Jaromil, I have the same question as Andrea, could you please give an example?

Best regards,

Macarena

• Gurobi Staff

Hi Macarena,

Please note that you can find example files for the usage of general constraints, bilinear terms, and Python Matrix API in our documentation.

Nevertheless, here is a small example with 3 dimensional variables.

import gurobipy as gp
from gurobipy import GRB

m = gp.Model("test")

# create variables
N = 3

# constants
eta = 1.1
Sigma = [[1,2,3],[4,5,6],[7,8,9]]
sigma0 = 1.2

# add auxiliary equality constraint lnx_i = ln(x_i)
for i in range(N):

# set objective to sum x_i * lnx_i
m.setObjective(gp.quicksum(x[i]*lnx[i] for i in range(N)), GRB.MINIMIZE)

# add constraint mu^T * x = eta
m.addConstr(gp.quicksum(mu[i]*x[i] for i in range(N)) == eta, name="mu_x_eta")

# add constraing x^T * Sigma * x = sigma_0
m.addConstr(gp.quicksum(x[i]*Sigma[i][j]*x[j] for i in range(N) for j in range(N)) == sigma0, name="x_Sigma_x_sigma0")

# add constraint u^T * x = 1
m.addConstr(gp.quicksum(u[i]*x[i] for i in range(N)) == 1, name="u_x_1")

# write an LP file to analyze if the constructed problem is correct
m.write("myLP.lp")

Note that the above problem is infeasible because I used just some random values for the constants.

Best regards,
Jaromił