Skip to main content

Constraint comparing Var with one entry of MVar

Answered

Comments

9 comments

  • Kevin Smith
    Gurobi-versary
    First Question
    First Comment

    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
  • Eli Towle
    Gurobi Staff Gurobi Staff

    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
  • Yi Shen Yap
    Gurobi-versary
    First Comment

    I have a similar problem. How do I correct it?

    0
  • Eli Towle
    Gurobi Staff Gurobi Staff

    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
  • Eli Towle
    Gurobi Staff Gurobi Staff

    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
  • Sophie Wuyckens
    Gurobi-versary
    First Question
    Conversationalist

    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
  • Eli Towle
    Gurobi Staff Gurobi Staff

    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
  • Sophie Wuyckens
    Gurobi-versary
    First Question
    Conversationalist

    Excellent, it works now. I was indeed using Gurobi911 until now.Thanks you for the tips !

    0
  • Maliheh Aramon
    Gurobi Staff Gurobi Staff
    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,
    Maliheh
    0

Please sign in to leave a comment.