adding quadratic expression in indicator constraints
回答済みHi 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.
-
正式なコメント
This post is more than two 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 try Gurobot, our chatbot interface offering instant, expert-level support. -
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
投稿コメントは受け付けていません。
コメント
8件のコメント