• 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ł

• Gurobi Staff

Hi,

You could go for

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

Best regards,
Jaromił

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 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 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?

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

Dear Hendrik,

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