gurobipy.GurobiError: Invalid argument to QuadExpr multiplication
AnsweredHi, I have a quadratic obj function.
I introduced an extra (nt_div) decision variable and a constraint in order to surpass Gurobi division error. n is a numeric value. I don't understand what is the problem.
for i in nodes:
m.addConstr(nt_div[i] * nt[i] == 1)
sum_t = 0
for t in nodes:
o = quicksum(((nkt[t, k] * nt_div[t]) + (nkt[t,
k] *
nt_div[t]))
for k in K)
o = o * nt[t] * 1.0/n
sum_t = sum_t + o
obj = 1 - (sum_t)
m.setParam("NonConvex", 2)
m.setObjective(obj, GRB.MINIMIZE)
I get an error like
File "<ipython-input-77-f34e8eedb13e>", line 189, in generate_model
o = o * nt[t] * 1.0/n
File "src/gurobipy/quadexpr.pxi", line 523, in gurobipy.QuadExpr.__mul__
File "src/gurobipy/quadexpr.pxi", line 245, in gurobipy.QuadExpr._mul
gurobipy.GurobiError: Invalid argument to QuadExpr multiplication
-
I think the problem is in this line, I need this multiplication. I can't find a way to fix it.
o = o * nt[t] * 1.0/n
0 -
It seems like the term computed via \(\texttt{quicksum}\) is a quadratic expression, because \(\texttt{nkt}\) and \(\texttt{nt_div}\) are both optimization variables. Is this correct? If yes, then you get the error because you try to construct a multilinear term
nkt[t,k]*nt_div[t]*nt[t]
which is not supported by Gurobi. You can model multilinear terms via auxiliary variables and constraints, cf. How do I model multilinear terms in Gurobi?
In your particular case, for a fixed \(t\), you are actually computing
\[\left(\sum_k 2\cdot \text{nkt}_{t,k}\cdot \text{ntdiv}_{t} \right)\cdot \text{nt}_{t}\]
with \(\text{ntdiv}_{t} = \frac{1}{\text{nt}_t}\) which simplifies to
\[\sum_k 2\cdot \text{nkt}_{t,k} \]
meaning that you don't need the additional multiplication at all.
Best regards,
Jaromił0 -
Hi,
Thanks for your response. I think I was lost while coding so there are some typo's. Better send you the expression itself.
For every t, I want to calculate this expression in objective function. Not sure if this is possible.
where ntdiv is like below, since gurobi does not allow division with a d.v,
0 -
Thanks for the update. This clarifies a lot. There are couple of possibilities here to approach the term you want to model. In any approach, you have to introduce auxiliary variables and constraints to model your term in a quadratic model. In the following, index \(t\) is fixed.
\[\begin{align}
w_{t,k} &= \text{ntdiv}_t \cdot \text{nkt}_{k,t} \,\, \forall k\\
z_{t} &= \sum_k w_{t,k}^2
\end{align}\]From here you can use \(z_t\) to model \(\text{nt}_t \cdot z_t \cdot \frac{1}{n}\).
In your code, this would be similar to
w = m.addVars(nodes, K, lb=-GRB.INFINITY)
z = m.addVars(nodes)
sum_t = 0
for t in nodes:
m.addConstrs(w[t,k] == ntdiv[t] * nkt[k,t] for k in K)
m.addConstr(z[t] == w[t,k]*w[t,k])
sum_t += z[t] * nt[t] * 1.0/n
#[...]Note that I explicitly set the lower bound of \(w\) variables to \(-\infty\) because it might get negative (depending on the bounds of your other optimization variables) and the default lower bound for variables is \(0\).
Alternatively, you could model
\[
\frac{\text{ntdiv}_{t}}{n} \sum_k \text{nkt}_{k,t}^2
\]in a similar way as above.
z = m.addVars(nodes)
sum_t = 0
for t in nodes:
m.addConstr(z[t] == gp.quicksum(nkt[k,t]*nkt[k,t] for k in K))
sum_t += z[t] * ntdiv[t] * 1.0/n
#[...]One cannot say which formulation will perform better (although I think that the second one might be better) so it is best to try both to be sure.
Best regards,
Jaromił0
Please sign in to leave a comment.
Comments
4 comments