Set value for variable based on condition (if marketer has access to arc)
Answered-
Hi,
Could you provide a mathematical formulation? This would ease the understanding of what you are trying to model, see Posting to the Community Forum for details on how to use MathJax. Additionally, please post a minimal working example reproducing your issue. You don't have to post the full code, just the parts which are enough to reproduce the error.
Best regards,
Jaromił1 -
Dear Jaromil, thanks for your prompt response!
This is the code that i currently have.
import gurobipy as gp
from gurobipy import GRB
ggm = gp.Model("Global Gas Model")
A = {"BRA_USA", "ARG_CHI"}
T = {"BRA"}
t_acc_a = {("BRA","BRA_USA"): 1 }
F_A= ggm.addVars(t_acc_a.keys(),vtype=GRB.CONTINUOUS,name="TraderArcFlow(mcm/year)")
eq_mass_bal = {(t,a):
ggm.addConstr(
lhs=2,
sense=gp.GRB.EQUAL,
rhs=gp.quicksum(F_A[t,a] for a in A),
name="Sum of sales cannot exceed arc flow".format(t,a))
for t in T for a in A }It throws a key however since there is no key for ("BRA","ARG_CHI") in the dictionary t_acc_a. (marketer , t access to arc, a). The only workaround i can think of currently is to add a key ("BRA","ARG_CHI") with value 0 in the dictionary. This would mean however the the variable for arc flow F_A["BRA","ARG_CHI"] must be equal 0 (since the marketer does not have access to this arc.
I presume it will be something along the lines of:
for t in T:
for a in A:
if not t_acc_a[t,a]:
F_A[t,a] = 0Would this be the correct formulation then?
0 -
Hi,
You could go for
gp.quicksum(F_A[t,a] for t,a in t_acc_a)
Best regards,
Jaromił1 -
Thanks Jaromil,
That doesnt work however, as the original equation is a lot more complex than the one presented here.
eq_mass_bal = {(t,n,d,y):
ggm.addConstr(
lhs=grb.quicksum(Q_P[t,n,r,d,y] for r in R if t_acc_np[t,n])+grb.quicksum(F_A[t,a,d,y]*(1-l_a[a]) \
for a in A if a_e[a,n])+grb.quicksum(F_X[t,n,w,d,y] for w in W),
sense=grb.GRB.EQUAL,
rhs=Q_S[t,n,d,y] + grb.quicksum(F_A[t,a,d,y] for a in A if a_s[a,n]) + grb.quicksum(F_I[t,n,w,d,y]for w in W),
name="Sum of sales + injections + exports cannot exceed purchases + extractions + loss-adjusted imports".format(t,n,d,y))
for t in T for n in N for d in D.keys() for y in Y}I am looking more for a way to set the value of variable F_A[t,a,d,y] based on whether it fulfills certain conditions. Thanks again ! :)
0 -
Hey Maniesegaran,
I see this question very often and I always refer to this video then: https://youtu.be/aKsfqB-ONfk?t=1686
I have linked to the part "sparsity done right", I found it very helpful [around minute 28].
I also would advise against your proposed fix of simply defining the variables [to prevent any key errors] and then setting them to zero. This can be done in a more elegant fashion.
I will check tomorrow at work whether I can find an example and let you know.
Sometimes I do this via an "if-statement" in the grb.quicksum list comprehension to be as close to the mathematical set notation as possible. [Sum over all items of a set and that set only includes elements based on a specific logic, this is also addressed in the video at time stamp: 35:40]However I think for you these tuplelist.select and tupledict.selet might be of help:
https://www.gurobi.com/documentation/9.1/refman/py_tuplelist_select.html
https://www.gurobi.com/documentation/9.1/refman/py_tupledict_select.html
Regards
Hendrik
1 -
Hey Hendrik !
Thanks for your response, the video did clear some things up for me! I have indeed now solved most of the problems using a "if statement" in the grb.quicksum list.
eq_mass_bal = {(t,n,d,y):
ggm.addConstr(
lhs=grb.quicksum(Q_P[t,n,r,d,y] for r in R if t_acc_np[t,n])+grb.quicksum(F_A[t,a,d,y]*(1-l_a[a]) \
for a in A if a_e[a,n] if t_acc_a[t,a])+grb.quicksum(F_X[t,n,w,d,y] for w in W if t_acc_n[t,n] if map_w_n[w,n]),
sense=grb.GRB.EQUAL,
rhs= Q_S[t,n,d,y] + grb.quicksum(F_A[t,a,d,y] for a in A if a_s[a,n] if t_acc_a[t,a]) + grb.quicksum(F_I[t,n,w,d,y]for w in W if t_acc_n[t,n] if map_w_n[w,n]),
name="Sum of sales + injections + exports cannot exceed purchases + extractions + loss-adjusted imports".format(t,n,d,y))
for t in T for n in N for d in D.keys() for y in Y}I just have one question more. How would the code look if i used a conditional statement for a variable (Q_S on the rhs in this case) if im not summing it. If i simply write it as
rhs= Q_S[t,n,d,y] if t_acc_n[t,n] + grb.quicksum(F_A[t,a,d,y]......
it throws a syntax Error. Thanks again for your insights. I would also welcome the examples that you mentioned if you manage to find them !
Regards,
Manie0 -
Hey Manie,
most of the things I do are also based on trial and error, so please take this with a grain of salt.
One quick fix would be to also use quicksum and only sum over Q_S[t,n,d,y] using the list comprehension idea that you previously implemented:
If Q_S[t,n,d,y] is defined for a specific combination of t,n,d,y, then you would be summing up over a list with length 1, only including that specific variable Q_S[t,n,d,y]. If Q_S[t,n,d,y] however is not defined, then the list comprehension would return an empty list, effectively summing up over 0 elements [making it 0 as intended].
This seems kind of clunky however.1 -
Dear Hendrik,
Thank you so much for your insights. Helped me a lot. How do i set the question as solved then?0
Please sign in to leave a comment.
Comments
8 comments