How to deal with a product of 3 different decision variables in a term ?
AnsweredHi
I have a couple of constraints that contain such terms which are the product of 3 (decision) variables. For example
f.addQConstr(x[5] + x[6] + x[11]  x[12] + x[15]*a[0]*y + x[15]*b[0] + x[16]*a[3]*y + x[16]*b[3] == 0, "c3")
The term x[15]*a[0]*y is the product of 3 different variables. While optimizing my problem I am getting following error
GurobiError: Invalid argument to QuadExpr multiplication
I also tried it without declaring QuadExpr
f.addConstr(x[5] + x[6] + x[11]  x[12] + x[15]*a[0]*y + x[15]*b[0] + x[16]*a[3]*y + x[16]*b[3] == 0, "c3")
However, getting the same error.
I know a general Power constraint is available: addGenConstrPow. But as the term is the multiplication of 3 different variables rather than the cubic power of a single variable. So, I don't think that this General Power constraint will help me.
Could someone please guide me?
Thanks
Umair

Hi Umair,
Currently the best way is to reformulate such multilinear products as bilinear products by the introduction of auxiliary variables.
For example, you can reformulate \(x \cdot y \cdot z = 0\) as
\[ \begin{align}
x \cdot \omega &= 0 \\
y \cdot z &= \omega \\
x \in &[x^L, x^U] \\
y \in &[y^L, y^U] \\
z \in &[z^L, z^U] \\
\omega \in &[\min\{y^L \cdot z^L, y^L \cdot z^U, y^U \cdot z^L, y^U \cdot z^U\},\\
&\max\{y^L \cdot z^L, y^L \cdot z^U, y^U \cdot z^L, y^U \cdot z^U\}]
\end{align}\]Note that I explicitly added bounds on all variables as this is recommended when working with nonlinear models.
Best regards,
Jaromił0 
Dear Jaromil Najman
Thank you so much for your helping and kind response. I got the idea.
Can I declare such a variable which is the product of two variables, like w = y.z , if yes, how can I do that?
For example (I am using the python interface)
w = model.addVar( y.z , name = "temp" ) ?
Or I have to add a constraint for this purpose?
model.addConstr( w == y.z, "temp") ?
Furthermore, while declaring/adding a variable, can I use min/max{x1,x2,..} constraint for giving lower/upper bounds, for example
w = model.addVar( lb=min{x1.x2, x3.x4}, ub= max{x5.x6, x7.x8}, obj=0, vtype = GRB.INTEGER, name = "temp") ?
Thanking you in advance.
Umair
0 
Hi Umair,
You cannot directly declare the variable as a product of two variables. You have to declare an additional variable and the corresponding equality constraint. You can use the functions you mention in your example. For the bounds you can use the variable attributes but it may be easier to just keep track of the bounds by hand. You can also directly use python min/max functions to determine the values of the new variable's bounds.
For your example, let's assume you have the expression \(x \cdot y \cdot z\) with \(x,y,z \in [2,2]\).
The code for reformulation would then be would then bew = m.addVar(min(2*2,2*2,2*2,2*2),max(2*2,2*2,2*2,2*2),vtype=GRB.CONTINUOUS, name="w")
m.addConstr(w==x*y,name="aux_constr")The expression \(x\cdot y\) on the right hand side of the equality constraint is a QuadExpr making your problem a quadratic one. To make Gurobi solve such problems, please set the parameter NonConvex to 2.
In the above I assumed that all variables are continuous. This works analogously for discrete variables.
Best regards,
Jaromił0 
Dear Jaromil
I got it. Thank you so much.
Umair
0
Please sign in to leave a comment.
Comments
4 comments