Skip to main content

The index() function doesn't work well with gurobi variable

Answered

Comments

6 comments

  • Riley Clement
    • Gurobi Staff

    Hi Jingwei,

    I am fairly certain this issue is due to the equality operation on our gurobipy variable class.

    Consider the following code:

    >>> 5 == 4
    False
    >>> 4 == 4
    True

    >>> x[0,0] == x[0,0]
    <gurobi.TempConstr: C0 == <gurobi.Var C0>>

    As you can see when you use the equality operator with gurobipy variables you get back a constraint, not a boolean.  This is what allows us to write constraints in a natural manner such as

    m.addConstr(x[0,0] + x[0,1] == 1)

    Let's say we write our own index method like so:

    def index(list, value):
        for i, element in enumerate(list):
            if value == element:
                return i
        raise ValueError(f"{value} is not in list")

    and call it:

    >>> index(L, x[0,1])

    It will suffer from the same problem, that is the same error will be raised.  On the third line the equality operator will return a constraint, as the condition in an "if" statement, and then this "condition" is checked to see if it is "true or false".  When python does this it looks for a __bool__ method on whatever is returned by the condition and this is where the error is raised because our gurobipy constraint objects do not have this method (and we don't want them to).  I suspect this is the problem when using list.index.

    However we can write an alternative method like so which uses "is" for comparison instead of the equality operator:

    def index(list, value):
        for i, element in enumerate(list):
            if value is element:
                return i
        raise ValueError(f"{value} is not in list")

    and using this will return the value you want

    >>> index(L, x[0,1])
    1

    - Riley

     

    1
  • jingwei xie
    • Gurobi-versary
    • First Comment
    • First Question

    Hi Riley,

    Thank you so much for your timely reply!

    It's extremely exhaustive and helpful. I will follow your advice and revise my implementation.

    Best regards,

    Jingwei

    0
  • Riley Clement
    • Gurobi Staff

    No problem Jingwei.

    Although my suggestion is to avoid this approach when building your models - if they are large models. 

    If the time to build the models is large then, if you want to describe why you're using this index approach, I may be able to show you a better way to do it.

    - Riley

    0
  • jingwei xie
    • Gurobi-versary
    • First Comment
    • First Question

    Hi Riley,

    It's very kind of you to help.

    Actually I'm working with branch and price algorithm. Each time when I add a variable and corresponding column to the restricted master problem, I store each of them to a list, respectively. So they are one-to-one on index.

    When column generation completes, which means the LP of master problem is solved to optimality, I need to find the corresponding column of a variable whose value is closest to 0.5 for branching. That means I need to iterate the "variable list", find the exact one, and use the index of that variable to find the corresponding column in "column list".

    I'm not sure if there's a more efficient way. Thank you.

    Best regards,

    Jingwei

    0
  • Riley Clement
    • Gurobi Staff

    Hi Jingwei,

    Perhaps Model.getCol can help here?

    If that doesn't work for you case then my advice would be to just set a "_col" attribute on your variables which you use to store the corresponding column, eg

    a_variable._col = a_column

    Then you won't need to worry finding the index.

    You can also pair a list of variables with a list of columns like so:

    for variable, column in zip(variables, columns):
      variable._col = column

    - Riley

    0
  • jingwei xie
    • Gurobi-versary
    • First Comment
    • First Question

    Hi Riley,

    Thanks for your hint.

    I use the following statement as what I want are exactly coefficients corresponding to the variable. It seems  suitable for subsequent operations. 

    coeffs = [Model.getCoeff(constr, var) for constr in Model.getConstrs()]

    Best regards,

    Jingwei

    0

Please sign in to leave a comment.