Skip to main content

Got error when using the variable as the index for accessing another new variable

Answered

Comments

4 comments

  • Simranjit Kaur
    Gurobi Staff Gurobi Staff

    Hi Qiru,

    The error “gurobipy.GurobiError: Variable has not yet been added to the model” happens due to Gurobi’s lazy update approach, precisely when we try to access and use a variable before updating the model. In your case, this error is happening because you are trying to use the variable e_i before updating the model.

    Please note that a variable cannot be used as an index for another variable or parameter in a gurobi model.

    However, for your model, you can work around this by replacing the following constraints:

    MODEL.addConstr(e_i == 2 * e1 + 4 * e2 + 7 * e3)
    MODEL.addConstr(b[e_i] == gb.max_([b[k] for k in range(0, 8)]))
    for m in range(0, 8):
        MODEL.addConstr(b[m] == b[e_i] - 15 * gb.abs_(m - e_i))

    with the constraint:

    MODEL.addConstr( b[2]*e1 + b[4]*e2 + b[7]*e3 == gb.max_([b[k] for k in range(0, 8)]) )

    The above constraint captures the correct value of b[k] based on which of e1, e2, or e3 is non-zero, and sets it to the maximum of b[k]  for k in range(0, 8). For example, if e1=1 and e2=e3=0, the above constraint will reduce to b[2] = gb.max_([b[k] for k in range(0, 8).

    Regards,

    Simran

    0
  • Qiru MA
    Gurobi-versary
    First Comment
    First Question

    Hi Simranjit,

    Thanks for your reply. I consider this transformation brilliant. However, when I modify the code and rerun it, the following error occurs:

    MODEL.addConstr(b[2]*e1 + b[4]*e2 + b[7]*e3 == gb.max_([b[k] for k in range(0, 8)]) )
    File "src/gurobipy/model.pxi", line 3616, in gurobipy.Model.addConstr
    gurobipy.GurobiError: General expressions can only be equal to a single var

    Below is the modified code.

    Could you please give a further suggestion?

    import gurobipy as gb

    MODEL = gb.Model()

    e1 = MODEL.addVar(vtype=gb.GRB.BINARY, name="e_i_1")
    e2 = MODEL.addVar(vtype=gb.GRB.BINARY, name="e_i_2")
    e3 = MODEL.addVar(vtype=gb.GRB.BINARY, name="e_i_3")

    e_i = MODEL.addVar(vtype=gb.GRB.INTEGER, name="e_i")

    b = MODEL.addVars(8, vtype=gb.GRB.CONTINUOUS, name="b")

    MODEL.addConstr(e_i == 2 * e1 + 4 * e2 + 7 * e3)

    MODEL.addConstr(e1 + e2 + e3 == 1)

    # e_i could be 2,4 or 7, by having e1=1, e2=1 or e3=1

    MODEL.addConstr(b[2]*e1 + b[4]*e2 + b[7]*e3 == gb.max_([b[k] for k in range(0, 8)]) )

    for m in range(0, 8):
    MODEL.addConstr(b[m] == b[2]*e1 + b[4]*e2 + b[7]*e3 - 15 * gb.abs_(m - e_i))

    MODEL.update()
    0
  • Simranjit Kaur
    Gurobi Staff Gurobi Staff

    Hi Qiru,

    Please introduce an auxiliary variable y, and replace the constraint

    MODEL.addConstr(b[2]*e1 + b[4]*e2 + b[7]*e3 == gb.max_([b[k] for k in range(0, 8)]) )

    with the following

    y = MODEL.addVar(vtype=gb.GRB.CONTINUOUS, name="y")
    MODEL.addConstr( y == b[2]*e1 + b[4]*e2 + b[7]*e3 )
    MODEL.addConstr( y == gb.max_([b[k] for k in range(0, 8)]) )

    This should fix the error you mentioned. 

    Also, please note that the following constraints are redundant and can be removed from your model, as we have already stored the correct b[k] value in the "y" variable based on the non-zero value of e1, e2 and e3.

    for m in range(0, 8):
        MODEL.addConstr(b[m] == b[2]*e1 + b[4]*e2 + b[7]*e3 - 15 * gb.abs_(m - e_i))

    Regards,

    Simran

     

     

     

     

    0
  • Qiru MA
    Gurobi-versary
    First Comment
    First Question

    Hi Simranjit,

    Problem solved.

    As a novice for Gurobi, I appreciate your help.

     

    Best,

    Qiru

    0

Please sign in to leave a comment.