Skip to main content

creating binary variables with specific indices from subset of nodepairs (edges)

Answered

Comments

7 comments

  • Official comment
    Simranjit Kaur
    • Gurobi Staff
    This post is more than three years old. Some information may not be up to date. For current information, please check the Gurobi Documentation or Knowledge Base. If you need more help, please create a new post in the community forum, or try Gurobot, our chatbot interface offering instant, expert-level support.
  • Jaromił Najman
    • Gurobi Staff

    Hi Sophia,

    You can construct your edge variables in different ways. One way would be to use a \(\texttt{for}\)-loop and the addVar method, e.g.,

    import gurobipy as gp

    m = gp.Model("test")
    E = [[0,1],[1,2],[2,3]]
    e = {}
    for i in E:
    e[(i[0],i[1])] = m.addVar(vtype='B', name='e%d%d'%(i[0],i[1]))

    m.update()
    # access variables via e[0,1], e[1,2], e[2,3]
    print(e[0,1])

    or by using the addVars method

    import gurobipy as gp

    m = gp.Model("test")
    E = [(0,1),(1,2),(2,3)]
    e = m.addVars(E,vtype='B', name='e')

    m.update()
    print(e[0,1])
    print(e[1,2])

    Note that in the latter case, the entries of \(\texttt{E}\) are tuples and not lists of length 2. If you cannot change your current code to generate tuples instead of lists of length 2, you can execute

    E = [[0,1],[1,2],[2,3]]
    E = [tuple(i) for i in E]

    which will turn each of the lists \(\texttt{[0,1],...}\) into tuples \(\texttt{(0,1),...}\)

    Best regards,
    Jaromił

    0
  • Sophia Beckmann
    • Gurobi-versary
    • First Comment
    • First Question

    Hi Jaromił,

    thank you for helping me with this issue. I constructed my variables as you suggested first using the for loop and it works fine.

    Now I am struggeling with another issue concerning one of my constraints :

    I created another variable v:

    v = {}
    for i in edges:
        v[(i[0],i[1])] = Model.addVar(vtype = 'I', name = 'v'+str(i[0])+'_'+str(i[1]))

    Model.addConstr((gp.quicksum(e[edges[ij]] * d[ij] / v[edges[ij]] for ij in range(len(edges))) <= W * m - T), name = 'constraint 5')

    Since v[edges[ij]] is a decision variable not a constant i get the following Gurobi Error:

    '"GurobiError: Divisor must be a constant"

    Could you give me a hint on how to handle/ solve this problem? Thanks again for your helpt

    Best regards,

    Sophia

     

     

    0
  • Jaromił Najman
    • Gurobi Staff

    Hi Sophia,

    The Knowledge Base article How do I divide by a variable in Gurobi? holds the answer you seek.

    Best regards,
    Jaromił

    0
  • Sophia Beckmann
    • Gurobi-versary
    • First Comment
    • First Question

    Hi Jaromił,

    yes, thank you, thats exactly what I am looking for. I tried to follow the lead of your recommended article but still am making some mistake I cannot seem to solve by myself.

    v = {}
    for i in edges:
    v[(i[0],i[1])] = Model.addVar(vtype = 'I', name = 'v'+str(i[0])+'_'+str(i[1]))

    #introduction continuous variable z
    z = Model.addVar(vtype = 'C', name = 'z')

    #adding constraint v*z = 1
    for ij in range(len(edges)):
        Model.addConstr(z * v[edges[ij]] == 1)

    Model.addConstr((gp.quicksum(e[edges[ij]] * d[ij] /z for ij in range(len(edges))) <= W * m - T))

    I still get the same Gurobi Error that my Divisor must be a constant (which makes sense, since z is a decision variable, just as v)? Did I misunderstand the article?

    Sorry to bother again..

    Best regards,

    Sophia

    0
  • Jaromił Najman
    • Gurobi Staff

    Hi Sophia,

    Note that by introducing the constraint \(z \cdot v_{ij} =1\) it holds that \(z=\frac{1}{v_{ij}}\). Thus, your constraint should read

    Model.addConstr((gp.quicksum(e[edges[ij]] * d[ij] * z for ij in range(len(edges))) <= W * m - T))

    Please note that currently you introduced exactly 1 auxiliary variable \(z\) to represent all divisions by each \(v_{ij}\). However, you should introduce an auxiliary variable \(z\) for each variable \(v_{ij}\)

    v = {}
    z = {}
    for i in edges:
    v[(i[0],i[1])] = Model.addVar(vtype = 'I', name = 'v'+str(i[0])+'_'+str(i[1]))
    z[(i[0],i[1])] = Model.addVar(vtype = 'I', name = 'z'+str(i[0])+'_'+str(i[1]))

    #adding constraint v*z = 1

    for ij in range(len(edges)):
       Model.addConstr(z[edges[ij]] * v[edges[ij]] == 1)

    Model.addConstr((gp.quicksum(e[edges[ij]] * d[ij] * z[ij] for ij in range(len(edges))) <= W * m - T))

    If the variables \(\texttt{e}\) and \(\texttt{d}\) are both optimization variables, then you will have to introduce additional auxiliary variable to deal with the trilinear term, cf. How do I model multilinear terms in Gurobi? If only one of the variables \(\texttt{e}\) and \(\texttt{d}\) is an optimization variable, then you very likely have to set the parameter NonConvex=2, since your model is nonconvex.

    Model.setParam("NonConvex",2)

    Best regards,
    Jaromił

    0
  • Sophia Beckmann
    • Gurobi-versary
    • First Comment
    • First Question

    Hi Jaromił,

    thank you very much for your help! I implemented the necessary auxiliary variables as you suggested and set my parameter to NonConvex = 2 as well. I works just fine now!

    Thank you for your time!

    Best regards, Sophia

    0

Post is closed for comments.