Constraint comparing Var with one entry of MVar
AnsweredConsider the following simple model:
model = Model()
x = model.addMVar(10)
y = model.addVar()
model.setObjective(y, GRB.MINIMIZE)
I would like to constrain y with respect to a particular entry of x. I tried:
model.addConstr(y <= x[0])
But this leads to the error "Unsupported type (<class 'gurobipy.MLinExpr'>) for LinExpr addition argument". What is the correct way to handle this?
-
I was able to get around this problem by promoting y to a "scalar" MVar:
x = model.addMVar(10)
y = model.addMVar(1)
model.addConstr(y <= x[0])
model.setMObjective(Q=None, c=np.ones(1,), constant=0, xc=y, sense=GRB.MINIMIZE)This feels rather inelegant, and I am still curious if there is a better way.
0 -
Operations that mix term-based modeling objects like Var with matrix-based objects like MVar are largely unsupported, hence why your first approach doesn't work. However, this is a very reasonable use case. We have logged this usage/syntax internally as a feature request.
After defining \( \texttt{y} \) as a singleton \( \texttt{MVar} \), it would be ideal to simply set the objective with
model.setObjective(y)
Unfortunately, Model.setObjective() does not currently accept a one-dimensional \(\texttt{MVar}\) object as an argument. We will work to fix this for a future release. In the meantime, a workaround is to convert the objective to an MLinExpr object:
model.setObjective(1*y)
Thanks for asking about this; we will use your comments to improve the matrix-based Python API.
0 -
I have a similar problem. How do I correct it?
0 -
Mixing Var objects with MVar objects, like you do in the last set of constraints, is mostly unsupported. I recommend changing the \( \texttt{z} \) variables to term-based Vars by adding them with Model.addVars(), or changing the \( \texttt{x} \) variables to a matrix-based MVar object by adding them with Model.addMVar(). Either the objective or the constraints will have to be restructured depending on which you choose.
0 -
In Gurobi 9.1, you can now set a singleton MVar as the objective. E.g.:
import gurobipy as gp
m = gp.Model()
x = m.addMVar((3,4))
m.setObjective(x[1,2])Mixing Var and MVar objects is still largely unsupported in Gurobi 9.1. The developers are aware of the limitation and may improve how these objects interact in a future release.
0 -
Hi,
I have a similar issue except that I am comparing a MVar object with a LinExpr() object. I understand the best way would be to convert my Var "e_raw" into MVar and then a construct a MLinExpr() out of it but this is a lot of work for my model. Indeed it looks like I cannot use quicksum with MLinExpr(), I tried to use .sum() instead but the problem is that I cannot include condition 'if -else' that I need in my model. Therefore I was wondering if there is a possibility to convert a LinExpr() into a MLinExpr() or a 1-D MVar to a Var ? See below an insight of my model:
x = model.addMVar(shape = (M,), lb = 0.0, ub = 30, vtype = GRB.CONTINUOUS)
e_raw = [model.addVar(lb = 0.0, ub = 1.0, obj = 0.0, vtype=GRB.BINARY) for i in range(N*N)]
# e_id = large squared matrix NxN filled with specific numbers
# Many constraints built on e_raw not trivial
# ...
# My problem
for i in range(N):
if (i == source_id or i ==sink_id) : continue
linexpr = gp.quicksum(e_raw[e_id[j][i]] for j in range(N) if e_id[j][i] >= 0)
for j in range(M):
# Bug
model.addConstr(x[j] <= linexpr)0 -
Starting with Gurobi 9.5, indexing an MVar like \( \texttt{x[j]} \) should yield a Var object, not an MVar object. Which version of Gurobi are you using? You can check with
import gurobipy as gp
print(gp.gurobi.version())If you are using Gurobi 9.1.2 or earlier, you can upgrade to the latest version of Gurobi by following the instructions in the article How do I update my Gurobi installation to a newer version?.
Also, you could define your \( \texttt{e_raw} \) variables a bit more concisely with Model.addVars():
e_raw = model.addVars(N*N, vtype=GRB.BINARY)
With this approach, \( \texttt{e_raw} \) is a tupledict, which offers additional functionality like tupledict.sum() that you might find useful for building some of your other constraints.
0 -
Excellent, it works now. I was indeed using Gurobi911 until now.Thanks you for the tips !
0 -
Hi All,
Gurobi 10.0 was recently released. Included in this release is an improved Python Matrix API which allows broadcasting a Gurobi Var object in comparison with Gurobi MVar objects.
The code snippet below will add 12 constraints in the form \(x \leq y\) to the model.m = gp.Model()
x = m.addMVar((3, 4))
y = m.addVar()
m.addConstr(x <= y)Checkout the Matrix-friendly Modeling with Gurobipy webinar if you would like to learn more about this new functionality.
Please continue submitting new community posts for any bugs you might encounter in the future or for any comments/questions you might have. Users like you help to make Gurobi better!Best regards,Maliheh0
Please sign in to leave a comment.
Comments
9 comments