Skip to main content

TypeError: '<' not supported between instances of 'Var' and 'Var'

Answered

Comments

6 comments

  • Official comment
    Simranjit Kaur
    Gurobi Staff 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 why not try our AI Gurobot?.
  • Eli Towle
    Gurobi Staff Gurobi Staff

    Hi Sab,

    You can use the min_() general constraint helper function to model minimums. But in your case, it seems much better to just break each of these constraints into two separate constraints. For example:

    $$\begin{align*} E_{1,2} &\leq x_1 \\ E_{1,2} &\leq x_2. \end{align*}$$

    Thanks,

    Eli

    0
  • Sab
    Gurobi-versary
    First Comment
    First Question

    Thank you for your answer!

    If I wanted to use min_() would it work this way?

     

    for i in I:
    for ii in I:
    k = model.addConstr(E[i, ii] == min_(x[i], x[ii]), name="k")
    0
  • Eli Towle
    Gurobi Staff Gurobi Staff

    Yes, that works. A few comments:

    • For the case where \( \texttt{i} \) and \( \texttt{ii} \) are the same, a general constraint isn't necessary. You can instead add the constraint \( E_{i,i} = x_i \), since \( x_i = \min\{x_i, x_i\} \). Alternatively, use \( x_i \) directly whenever you would need \( E_{i,i}. \)
    • You don't need two separate variables \( E_{i,j} \) and \( E_{j,i} \) for each \( i \neq j \), since \( \min\{x_i, x_j\} = \min\{x_j, x_i\} \). I recommend only adding variables \( E_{i,j} \) for \( i < j \). Then, if \( E_{j,i} \) is not defined (because \( j > i \)), just use \( E_{i,j} \) instead.
    • Each constraint should have a unique name. All of these constraints have the same name, \( \texttt{'k'} \). 
    • I don't see a reason to store the constraint object in a Python variable \( \texttt{k} \), since \( \texttt{k} \) is overwritten many times.

    Altogether:

    import gurobipy as gp

    model = gp.Model()


    I = [1, 2, 5]
    J = [(i, j) for i in I for j in I if i < j]

    x = model.addVars(I, name='x')
    E = model.addVars(J, name='E')

    for i, j in J:
    model.addConstr(E[i, j] == gp.min_(x[i], x[j]), name=f"k{i}_{j}")

    This produces a model with the following variables/constraints:

    k1_2: E[1,2] = MIN ( x[1] , x[2] )
    k1_5: E[1,5] = MIN ( x[1] , x[5] )
    k2_5: E[2,5] = MIN ( x[2] , x[5] )
    0
  • Sab
    Gurobi-versary
    First Comment
    First Question

    Thank you for you help!

    I tried using the same idea the following way: 

    from gurobipy import *

    I = ["1", "5", "4", "9", "6", "8", "2", "3", "7"]
    Z = [(i, j) for i in I for j in I if i < j]
    R = [(i, j, r) for i in I for j in I for r in I if i < j and j < r]
    model = Model("Base Model")

    x = model.addVars(I, vtype=GRB.BINARY, name="x")
    E = model.addVars(Z, Z, vtype=GRB.BINARY, name="E")
    E3 = model.addVars(R, R, R, vtype=GRB.BINARY, name="E3")

    for i, j in Z:
    model.addConstr(E[i, j] <= model.min_(x[i], x[j]))

    for i, j, r in R:
    model.addConstr(E3[i, j, r] <= model.min_(x[i], x[j], x[r]))

    But I am getting this error as if the value couldn't been found but the for loop seems to be working:

    File "base.py", line 172, in <module>
    model.addConstr(E[i, j] <= model.min_(x[i], x[j]))
    KeyError: ('1', '5')

     

    0
  • Eli Towle
    Gurobi Staff Gurobi Staff

    \( \texttt{Z} \) and \( \texttt{R} \) are defined as lists of length-2 tuples and length-3 tuples, respectively:

    >>> Z
    [('1', '5'), ('1', '4'), ('1', '9'), ('1', '6'), ... ]
    >>> R
    [('1', '5', '9'), ('1', '5', '6'), ('1', '5', '8'), ... ]

    So, you only have to pass a single instance of \( \texttt{Z} \) and \( \texttt{R} \) to Model.addVars() when you define the \( \texttt{E} \) and \( \texttt{E3} \) variables, since the tuples in the list become the indices for the variables.

    x = model.addVars(I, vtype=GRB.BINARY, name="x")
    E = model.addVars(Z, vtype=GRB.BINARY, name="E")
    E3 = model.addVars(R, vtype=GRB.BINARY, name="E3")

    Next, the min_() function is not a method of the Model class. Since you import everything from the \( \texttt{gurobipy} \) module's namespace into the main namespace, you should write \( \texttt{min_(...)} \) instead.

    Lastly, the min_() function can only be used to set one variable equal to the minimum of others (and possibly some constants). Thus you can't directly use a \( \texttt{<=} \) constraint with the min_() function. In your case, it might be better to forgo the min_() function completely and instead add individual constraints that a particular \( \texttt{E} \) variable is less than or equal to the corresponding \( \texttt{x} \) variables. E.g.:

    for i, j in Z:
    model.addConstr(E[i, j] <= x[i])
    model.addConstr(E[i, j] <= x[j])

    This is really adding the constraint \( E_{i,j} \leq \min\{x_i, x_j\} \), not \( E_{i,j} = \min\{x_i, x_j\} \). But it might be sufficient for your model, and it is what your current code is trying to do anyways.

    0

Post is closed for comments.