Skip to main content

unsupported operand type(s) for -: 'generator' and 'generator'

Answered

Comments

14 comments

  • Riley Clement
    Gurobi Staff Gurobi Staff

    Hi Sidney,

    Let's take a look at the error message

    unsupported operand type(s) for -: 'generator' and 'generator'

    The first clue is that it mentions the minus operator:  -

    From there you should ask yourself whether there is something wrong with the subtraction you are trying to do and try to run the following:

    (X[p,t] for p in P if p[1] == n) - (X[p,t] for p in P if p[0] == n)

    This will give the same error, meaning you can rule out anything to do with the addConstrs method.  Next you should ask yourself is there anything wrong the other pieces of this line, eg if you run the following

    (X[p,t] for p in P if p[1] == n)

    in an interactive Python session (such as a notebook) it will run without error and will tell you that it is a

    <generator object <genexpr> at 0x11c526a40>

    So now your error message may start to make a bit more sense to you.  You are trying to subtract a generator object from another generator object and Python doesn't like this - this is not specifically a Gurobi error.

    Your next step should be to consult a simple example such as diet.py where the addConstrs method is used with a generator.  You will notice in that example that the generator is an argument to the quicksum method.  The quicksum method will take an iterable (like a generator) and return an expression by adding together the elements of the iterable.  So, in your example you need to do the following:

     

    for n in N:
        for t in T:
              m.addConstrs(Z[p,t] >= gp.quicksum(X[p,t] for p in P if p[1] == n) - gp.quicksum(X[p,t] for p in P if p[0] == n))
              m.addConstrs(Z[p,t] >= gp.quicksum(X[p,t] for p in P if p[0] == n) - gp.quicksum(X[p,t] for p in P if p[1] == n))

    Is this code now correct?  No.

    The addConstrs method is expecting multiple constraints and you are only giving it one.  You will need to use addConstr instead.

    Would it then be correct?  It is hard to say.  It is entirely possible to index gurobipy variables using tuples, eg

    P = [(0,1), (2,1)]
    m.addVars(P)

    in which case conditions such as 

    if p[1] == n

    (for an element of P called p) are fine to use, but if this not what you are doing and (P is a list of numbers or strings for example) then I suspect your code will not yet be correct.

    - Riley

    0
  • Laynufar Silsilia
    First Question
    First Comment

    halo! Now, i have the same problem.

    What is causing the error? thanks!

      File d:\pemograman\iis.py:39
        m.setObjective(((sum(sum(x[n,d,1]) ** 2) / (17) for n in range(5,N) for d in range (D)) - (sum(sum(x[n,d,1]) / (17) ** 2) for n in range(5,N) for d in range (D)) + ((sum(sum(x[n,d,2]) ** 2) / (17) for n in range(5,N) for d in range (D)) - (sum(sum(x[n,d,2]) / (17)) ** 2) for n in range(5,N) for d in range (D)) + ((sum(sum(x[n,d,3]) ** 2) / (17) for n in range(5,N) for d in range (D)) - (sum(sum(x[n,d,3]) / (17)) ** 2) for n in range(5,N) for d in range (D)) + ((sum(sum(x[n,d,4]) ** 2) / (17) for n in range(5,N) for d in range (D)) - (sum(sum(x[n,d,4]) / (17)) ** 2) for n in range(5,N) for d in range (D))), GRB.MINIMIZE)

    TypeError: unsupported operand type(s) for -: 'generator' and 'generator'
    0
  • Riley Clement
    Gurobi Staff Gurobi Staff

    Hi Laynufar,

    I would try and run smaller parts of this line in isolation to try and narrow down where the error is occurring as suggested in my answer above.  The idea of the answer above was to show how the issue can be discovered, rather than solving it.

    You could for example set:

    A = (sum(sum(x[n,d,1]) ** 2) / (17) for n in range(5,N) for d in range (D))
    B = (sum(sum(x[n,d,1]) / (17) ** 2) for n in range(5,N) for d in range (D)) 
    ...

    Then try A-B.  Does that work?  If so, try A-B+C, etc.  Use Python's "type" function to inspect what the result of these things are.  Be on the lookout for generators as the error message tells you what is going wrong: there is a subtraction between two generators.

    - Riley

    0
  • Laynufar Silsilia
    First Question
    First Comment

    Halo, Thank you in advance for your response, is it like this? 

    ###
    A = (sum(sum(x[n,d,1]) ** 2) / (17) for n in range(5,N) for d in range (D))
    B = (sum(sum(x[n,d,1]) / (17) ** 2) for n in range(5,N) for d in range (D))
    F = (sum(sum(x[n,d,2]) ** 2) / (17) for n in range(5,N) for d in range (D))
    G = (sum(sum(x[n,d,2]) / (17) ** 2) for n in range(5,N) for d in range (D))
    Q = (sum(sum(x[n,d,3]) ** 2) / (17) for n in range(5,N) for d in range (D))
    R = (sum(sum(x[n,d,3]) / (17) ** 2) for n in range(5,N) for d in range (D)) 
    Y = (sum(sum(x[n,d,4]) ** 2) / (17) for n in range(5,N) for d in range (D))
    Z = (sum(sum(x[n,d,4]) / (17) ** 2) for n in range(5,N) for d in range (D))

    # Fungsi Tujuan
    m.setObjective(((A-B) + (F-G) + (Q-R) + (Y-Z)), GRB.MINIMIZE)

    but I still get the same error 

      File d:\pemograman\iis2.py:48
        m.setObjective(((A-B) + (F-G) + (Q-R) + (Y-Z)), GRB.MINIMIZE)

    TypeError: unsupported operand type(s) for -: 'generator' and 'generator'

     

    0
  • Riley Clement
    Gurobi Staff Gurobi Staff

    Hi Laynafur,

    Yes you will get the same error, as nothing has essentially changed.  The idea is that you now have more manageable components to experiment with:

    Then try A-B.  Does that work?  If so, try A-B+C, etc.  Use Python's "type" function to inspect what the result of these things are.  Be on the lookout for generators as the error message tells you what is going wrong: there is a subtraction between two generators.

    - Riley

    0
  • Laynufar Silsilia
    First Question
    First Comment

    okey, but thank you for your response.

    0
  • Riley Clement
    Gurobi Staff Gurobi Staff

    No problem, once you've reduced the issue as much as possible, to the smallest piece that causes an error, then let me know if you're unsure what to do at that point.

    - Riley

    0
  • Yutian He
    Conversationalist
    First Question

    Hi! I also got the same error here,  I'm going to set this constraint: \sum_{i from 1 to m-1} ((b_{i+1} - b_i)*eta_i^2) <= nu. Could you please help me to check this?

    var_new = list(range(m-1))
    var3=list(range(1))
    b= array([0.        , 0.125     , 0.14285714, 0.25      , 0.28571429,
           0.375     , 0.42857143, 0.5       , 0.57142857, 0.625     ,
           0.71428571, 0.75      , 0.85714286, 0.875     , 1.        ])
    
    eta = m1.addVars(var_new, vtype=GRB.CONTINUOUS, name = "eta")
    nu = m1.addVars(var3, vtype=GRB.CONTINUOUS, lb=0, name = "v")
    
    for s in var_new:
        expr1_3=(b[s+1]-b[s])*(eta[s]**2)
        # print(f"{expr1_3 =}")
    m1.addConstr((sum(b[s+1]-b[s])*(eta[s]**2) for s in var_new) <= nu[0])
    0
  • Eli Towle
    Gurobi Staff Gurobi Staff

    Your constraint is

    m1.addConstr((sum(b[s + 1] - b[s]) * (eta[s] ** 2) for s in var_new) <= nu[0])

    Notice that the  \(\texttt{for s in var_new}\) is outside of the \(\texttt{sum()}\) function, creating a generator. Try moving this \(\texttt{for}\) statement and the multiplication with \(\texttt{eta[s]**2}\) inside of the \(\texttt{sum()}\) function:

    m1.addConstr(sum((b[s + 1] - b[s]) * (eta[s] ** 2) for s in var_new) <= nu[0])
    0
  • Yutian He
    Conversationalist
    First Question

    Hi Eli,

    Thank you so much, this worked!

    And I have a general question about model.write(). I usually get this comment called: 

    Warning: Q constraint 0 doesn't have a name

    I tried addQConstr, but still had this warning, and the constraint didn't show in the writing file. Will this influence the result we get in Gurobi? If yes, could you please tell me how I can improve the code? Thank you!

    0
  • Eli Towle
    Gurobi Staff Gurobi Staff

    Do you have a minimal reproducible example? I would expect the constraint to be included in the model file with the default name (e.g., \(\texttt{qc0}\)). Note you can always give the constraint a name via the \(\texttt{name}\) keyword argument of Model.addConstr()/Model.addQConstr().

    Not naming constraints should not affect the solve. However, there may be cases where variable/constraint names cause issues when reading the model file back into Gurobi (non-unique names, names starting with certain symbols, etc.). See the LP format documentation for more details.

    0
  • Yutian He
    Conversationalist
    First Question

    Hi Eli,

    Here is the minimal example I have for the quadratic constraint:

    b= 

    array([0. , 0.125 , 0.14285714, 0.25 , 0.28571429, 0.375 , 0.42857143, 0.5 , 0.57142857, 0.625 , 0.71428571, 0.75 , 0.85714286, 0.875 , 1. ])

    eta = m1.addVars(var_new, vtype=GRB.CONTINUOUS, name = "eta")

    nu = m1.addVars(var3, vtype=GRB.CONTINUOUS, lb=0, name = "v")

    m1.addQConstr(sum((b[s + 1] - b[s]) * (eta[s] ** 2) for s in var_new) <= nu[0])

    Now this constraint is shown in the .lp file,but still have the waring. I think it might because I named nu as v. But anyway it will not affect the result. Thank you for your help.

    0
  • Eli Towle
    Gurobi Staff Gurobi Staff

    Yes, you did not explicitly name the quadratic constraint. If you want to name the quadratic constraint and get rid of the warning, you can pass the \(\texttt{name}\) keyword argument to Model.addConstr() or Model.addQConstr(). For example:

    m1.addConstr(
        sum((b[s + 1] - b[s]) * (eta[s] ** 2) for s in var_new) <= nu[0],
        name="my_constraint",
    )
    0
  • Yutian He
    Conversationalist
    First Question

    Got it! Thank you so much.

    0

Please sign in to leave a comment.