adding quadratic expression in indicator constraints
AnsweredHi Gurobi Community,
I am trying to add a conditional indicator constraint as follows:
model = gp.Model()
n = 3
pa=[i for i in range(n)]
P=model.addVars(len(pa), len(pa), vtype=GRB.BINARY, name="P")
x = model.addVars(len(pa), len(v), vtype = GRB.BINARY, name = "x")
y = model.addVars(len(pa), vtype = GRB.BINARY, name = "y")
lst=[[0,1,2],[0,1],[0,2]]
for i in range(1,n):
# nested_sum = gp.QuadExpr()
nested_sum=0
for j in range(n):
sum_m = gp.quicksum(x[k, 0] for k in lst[i])
nested_sum += P[i, j] * sum_m
# model.addConstr((y[i]==0)>>(nested_sum > 1)) (constrs type1)
model.addConstr((y[i] == 0) >>(nested_sum==0)) (constrs type2)
when I use 'constrs type 1' it shows the error:
"NotImplementedError
Traceback (most recent call last) /tmp/ipykernel_765207/466436445.py in <module>
--->17 model.addConstr((y[i]==Integer(0))>>(nested_sum > Integer(1)))
src/gurobipy/quadexpr.pxi in gurobipy.QuadExpr.__richcmp__()
NotImplementedError: "
and when I use 'constr type 2' it shows the error:
"
--->18 model.addConstr((y[i]==Integer(0))>>(nested_sum == Integer(0)))
TypeError: must be real number, not gurobipy.QuadExpr "
I also approached it in a second way by defining more variables as x1
model = gp.Model()
n = 3
pa=[i for i in range(n)]
P=model.addVars(len(pa), len(pa), vtype=GRB.BINARY, name="P")
x = model.addVars(len(pa), len(v), vtype = GRB.BINARY, name = "x")
x1 = model.addVars(len(pa), len(v), vtype = GRB.BINARY, name = "x1")
y = model.addVars(len(pa), vtype = GRB.BINARY, name = "y")
lst=[[0,1,2],[0,1],[0,2]]
for i in range(1,n):
# nested_sum = gp.QuadExpr()
nested_sum=0
for j in range(n):
sum_m = gp.quicksum(x[k, 0] for k in lst[i])
nested_sum += P[i, j] * sum_m
model.addConstr(x1[i]==nested_sum)
model.addConstr((y[i]==1)>>(x1[i]==0))
but again showing some errors.
Pls help me out with this.
-
Hi Vaibhav,
"nested_sum > 1" doesn't work because you can't use strict inequalities, you can change it to ">=" but it will still fail because you can't use quadratic expression in indicator expressions, which is why nested_sum==0 doesn't work.
Your last approach should work. What is the error you are seeing? Please paste the full error message, including traceback.- Riley
1 -
Hi Riley,
Thanks for your reply. It is not showing complete errors.
KeyError
Traceback (most recent call last) /tmp/ipykernel_770156/583479396.py in <module>
18 # model.addConstr((y[i] == 0) >>(nested_sum==0))
19 ---> 20 model.addConstr(x1[i]==nested_sum)
21 model.addConstr((y[i]==Integer(1))>>(x1[i]==Integer(0)))
22 model.update()
KeyError: 1
How can I check actual error?-Vaibhav
0 -
Hi Vaibhav,
"KeyError: 1" is the actual error.
It's pointing to this line: model.addConstr(x1[i]==nested_sum)
There is only one key in this line, and that is the i in x1[i]. The error message is telling you x1[1] does not exist.
You can run print(x) and check what the keys of this tupledict are.
- Riley
1 -
Hi,
Thanks, it's working now.
I have another doubt, till now I only worked on quadratic equations something like
$ \sum_{j=0}^{n-1}P[i,j]* (\sum_{ (k \in lst[i]) } m[k,0] ) == 0 $ for each i in range(1,n)i.e nesed_sum is a quadratic expression but now I'm dealing with an expression of degree 3 like,
$ \sum_{j=0}^{n-1} P[i,j]* (\sum_{l=0}^{n-1} P[i,l]* (\sum_{ (k \in lst[i]) } m[k,0])) == 0$ for each i in range(n)
Can Gurobi handle constraints having a three-degree expression?Now I have model.addConstr( nested_sum == above expression ==0 ) but it is showing TypeError: unsupported operand type(s) for *: 'Var' and 'generator'.
0 -
Hi Vaibhav,
Can Gurobi handle constraints having a three-degree expression?
No not yet, you will need to introduce additional variables and reformulate so that it is no more than degree 2. See this post for an example, https://support.gurobi.com/hc/en-us/community/posts/360072027392-How-to-deal-with-a-product-of-3-different-decision-variables-in-a-term
TypeError: unsupported operand type(s) for *: 'Var' and 'generator'.
This is unrelated to the three-degree expression. Have a look at where * is used in your code. Somewhere you are multiplying a variable by a generator expression - which doesn't make sense. Most of the time this mistake occurs because the user intends to sum the results of the generator expression but forgets to.
- Riley
0 -
Hi,
I have three constraints say
constr1 : gp.quicksum(P[1,t] for t in range(1,n)) >= 1)
constr2 : gp.quicksum(x[i,1] + x[i,2] for i in lst) == len(lst))
constr3 : gp.quicksum(x[i,2] for i in lst) == 1 + 2* rnd[cnt])
How can I write such that :
(1) constr1 = True implies constr2 = True OR constr2 = True
(2) constr1 = True implies constr2 = True AND constr2 = True
model.addConstr((y[count] == 0) >> (gp.quicksum(P[1,t] for t in range(1,n)) == 0))model.addConstr((y[count] == 1) >> (gp.quicksum(x[i,1] + x[i,2] for i in lst) == len(lst)))model.addConstr((y[count] == 1) >> (gp.quicksum(x[i,2] for i in lst) == 1 + 2* rnd[cnt]))I think adding constraints like this represents part (2). Pls correct me if I'm wrong. But I don'tknow how to represent part (1).My actual problem is: I have 4 constrs, say 1,2,3,4. I want, Constr1 = True implies (Constr2 = True ) AND (Constr3 = True OR Constr4 = True).i.e Constr1 is true implies Constr2 is true and at least one of Constr3, Constr4 is true.Thanks.0 -
Hi Vaibhav,
I think adding constraints like this represents part (2).
Yes, what you have looks correct.For part (1) I'd introduce two auxiliary variables, aux1, aux2 (or whatever names you like) and formulatemodel.addConstr((aux1 == 1) >> (gp.quicksum(x[i,1] + x[i,2] for i in lst) == len(lst)))
model.addConstr((aux2 == 1) >> (gp.quicksum(x[i,2] for i in lst) == 1 + 2* rnd[cnt]))
model.addConstr((y[count] == 1) >> (aux1 + aux2 >= 1))- Riley0
Please sign in to leave a comment.
Comments
7 comments