Skip to main content

Error on my lazy cuts

Answered

Comments

10 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 Jose,

    You probably get this message from your quicksum() terms:

    gp.quicksum(1-valsy[i])

    The argument provided to quicksum() should be iterable (like a list), not a single value like \( \texttt{1 - valsy[i]} \). Should this just be the term \( \texttt{1 - valsy[i]} \)? If so, you don't need to use the quicksum() function.

    Thanks,

    Eli

     

    0
  • Jose Vindel
    Gurobi-versary
    Thought Leader
    Investigator

    Thank you Eli, 

     

    I want to iterate using the values from the dictionaries 

    valsy[i] and vals[i]

    to add this cut

    \[pi\leq\ v_b + M*\sum (1-y_i)*v_i - M* \sum(1-y_i)*v_i\]

    I assumed it could iterate from there, to add a cut for every \(v_i\), I will try to add them without the summation and also I will check my formulation, thanks again  

     

    0
  • Eli Towle
    Gurobi Staff Gurobi Staff

    Hi Jose,

    Based on that inequality, it seems like you want a single lazy constraint that does sum over all of the \( i \) indices inside of a quicksum() function. Basically, you would just move your outer \( \texttt{for} \) loop to be inside each quicksum() function. Right now, you are adding 95 separate lazy constraints.  

    However, this inequality is confusing to me, since \( M \sum_i ( 1 - y_i ) v_i - M \sum_i ( 1 - y_i ) v_i \) is equal to \( 0 \), leaving you with the inequality \( \pi \leq v_b \). Are you sure this inequality is correct?

    Thanks,

    Eli

    0
  • Jose Vindel
    Gurobi-versary
    Thought Leader
    Investigator

    Hello Eli, 

    After checking my inequality, it is in part incorrect the first term \(M*\sum (1-y_i)*v_i\) only applies when the values of \(v_i\) are positive and the second term,\(- M* \sum(1-y_i)*v_i\),  when the values are negative, could it be possible to construct the cut using something like this?

    keys = model._vars.keys()
    vals = model.cbGetSolution(model._vars)
    vars = model._vars
    varsy = model._varsy
    if abs(vbi - vbm) >= .00001:

    for i in keys:
    if vals[i] >= 0:
    c += (1-varsy[i])*vals[i]
    elif vals[i] < 0:
    c -= (1-varsy[i])*alvs[i]

    model.cbLazy(vbi <= vars[12] + c)
    else:
    print('Solution...')

    I will try to add it like that,  and also I was wondering if inside the list comprehension you could have both terms 'if' and 'else' I know you can have 'if' like in the tsp example but, so far I haven't seen that use,  

    0
  • Eli Towle
    Gurobi Staff Gurobi Staff

    Hi Jose,

    Yes, something like this should work. But note that \( M \sum_{i : v_i > 0} (1 - y_i) v_i - M \sum_{i : v_i < 0} (1 - y_i) v_i \) is equivalent to \( M \sum_{i} (1 - y_i) |v_i| \). So you should be able to use \( \texttt{abs(vals[i])} \) inside of a single \( \texttt{quicksum()} \) function to accomplish the same thing.

    And yes, you can use \( \texttt{if} \) and \( \texttt{else} \) together in a list comprehension. Here is an example:

    >>> ['odd' if i % 2 else 'even' for i in range(10)]
    ['even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd']

    Eli

    1
  • Jose Vindel
    Gurobi-versary
    Thought Leader
    Investigator

    Thanks Eli,

     

    I tried it and it worked out, with some minor corrections on the code, now I have to figure it out to do it in a more pythonic way, and how to incorporate the absvals in the quicksum, thanks a lot!!

    Using the quicksum function the resulting cut is

    model.cbLazy(vbi <= vars[12] + 2000*(gp.quicksum((1-varsy[i])*abs(vals[i]) for i in keys))

     

    0
  • Jose Vindel
    Gurobi-versary
    Thought Leader
    Investigator

    Hello, 

    I am trying to add another lazy cut, but this time it has the following structure:

    \(v_{of interest} > value + M * (y_i + y_j)\) 

    It will be done based on a combination of the variables \(y\), suppose I have the following vectors:

    \(v = [10,0,0,0,40,50]\) , \(y = [1,0,0,1,1,1]\), so, lazy constraints would be defined as:

    \(v_1 > (some value) + M*(y_1 + y_2)\)

    \(v_1 > (some value) + M*(y_1 + y_3)\)

    \(v_1 > (some value) + M*(y_2 + y_3)\)

    So I coded like this:

    from itertools import combinations
    #rxn is a list with the name of my variables
    v_o = [i for i in range(len(rxn)) if model._voj[i] == 0]

    comb_v = list(combinations(v_o,2))

    model.cbLazy(model._vars[chemical] > model._vij[chemical] +
    (2000*(model._varsy[i]+model._varsy[j]) for (i,j) in comb_v))

    But, I get this error:

    I'd appreciate your help

    1
  • Eli Towle
    Gurobi Staff Gurobi Staff

    The expression below is a Python generator expression:

    (2000*(model._varsy[i]+model._varsy[j]) for (i,j) in comb_v)

    As the error indicates, adding together a generator expression and a number (\(\texttt{model._vij[chemical]}\)) isn't supported in Python. You can add multiple lazy constraints with a \( \texttt{for} \) loop:

    for i, j in comb_v:
    model.cbLazy(model._vars[chemical] >= model._vij[chemical] +
    2000*(model._varsy[i] + model._varsy[j]))

    Note that mathematical solvers like Gurobi do not support strict inequality constraints.

    1
  • Jose Vindel
    Gurobi-versary
    Thought Leader
    Investigator

    Thanks!

    0

Post is closed for comments.