Error on my lazy cuts
AnsweredHello,
I am trying to solve a model using lazy cuts, I've given a look on the example, to the best of my knowledge I am using it right, however, I guess not since I get this error
TypeError Traceback (most recent call last) callback.pxi in gurobipy.CallbackClass.callback() <ipython-input-7-25748d53b30c> in lazy(model, where) 41 else: 42 for i in model._vars.keys(): ---> 43 model.cbLazy(pi <= vbm + 2000*(gp.quicksum(1-valsy[i])*vals[i]) - 2000*(gp.quicksum(1-valsy[i])*vals[i])) 44 45 gurobi.pxi in gurobipy.quicksum() TypeError: 'float' object is not iterable
model._vars.keys()
gives me list [0,...,94]
pi and vbm are values
valsy {0:0,1:0,...,94:1} binary variables
vals {0:0.0,1:0,...,94:1.226} free variables
Am I getting the error because it cannot use the float values from vals?
-
Official comment
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?. -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
Thanks!
0
Post is closed for comments.
Comments
10 comments