• Gurobi Staff

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ł

Dear Jaromil, thanks for your prompt response!

This is the code that i currently have.

import gurobipy as gpfrom gurobipy import GRBggm = 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] = 0

Would this be the correct formulation then?

• Gurobi Staff

Hi,

You could go for

gp.quicksum(F_A[t,a] for t,a in t_acc_a)

Best regards,
Jaromił

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 ! :)

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

Regards

Hendrik

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,
Manie

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.

Dear Hendrik,

Thank you so much for your insights. Helped me a lot. How do i set the question as solved then?