Skipping nonexisting decision variables in for loop
AnsweredHello,
I'm working on an assignment problem that has a binary decision variable set with 4 indices: y,s,i,t, (assigning y to s,i,t) and unfortunately all y,s,i,t are large numbers. Therefore I'm currently working on speeding my existing model. To do so, I wanted to decrease the number of decision variables by creating separate "availability" lists for each y (e.g. y[1] can be assigned to s[1,2,17] and i[2,4,33,56] and t[1:90]). So, I only created decision variables corresponding to that and haven't created: x[1,0,0,0] or x[1,1,2,91].
However, I'm having trouble with my constraints because currently I cannot sum all y from 0:Y for each s,i,t because some y within 0:Y do not exist, since their availability limits are different. (Showed an example constraint below.)
for s,i,t in zip(available_s, available_i, available_t):
m.addConstr(sum(x[y,s,i,t] for y in range(Y))<= c_si[s,i])
I was wondering if there's a way that I can say: sum all "existing y" within the 0:Y limit.
Thank you so much!
Best regards,
Yaren

Hi Yaren,
Could you post a minimal working example reproducing the issue?
In general, you can use the addVars and provide arbitrary lists to generate a multiindexed variable, e.g.,
A = [0,5,7]
B = [2,8,11]
x = m.addVars(A,B)
# loop over all variables
for a in A:
for b in B:
m.addConstr(x[a,b] >= a*b)Best regards,
Jaromił 
Hello Jaromił,
Sure, I can! So, let's say our sets are defined this way, though we want them to work with a for loop using "zip" :
Y = [0,1,2,3]
S = [1,2,1,3]
I = [2,6,6,7]
T = [0,1,5,6]
x={}
for y,s,i,t in zip(Y,S,I,T):
x[y,s,i,t] = m.addVar(vtype=GRB.BINARY)(There're only 4 variables created, x[0,1,2,0], x[1,2,6,1], x[2,1,6,5], x[3,3,7,6] )
Then I'm trying to create a constraint for every s,i,t pair:
for s,i,t in zip(S, I, T):
m.addConstr(sum(x[y,s,i,t] for y in range(Y) <= c[s,i])Though as you can imagine I'm getting an error. Because on the first iteration of the for loop I'm trying to sum(x[0,1,2,0], x[1,1,2,0], x[2,1,2,0], x[3,1,2,0]) though x[1,1,2,0], x[2,1,2,0] or x[3,1,2,0] do not exist.
That's why, I was wondering if there's a way that I can say "sum only the existing (predefined) x within a limit".
Best regards,
Yaren

Hi Yaren,
Thank you for the clarification. One way to achieve what you want is
for s,i,t in zip(S, I, T):
m.addConstr( sum( x[y,s,i,t] for y in Y if (y,s,i,t) in zip(Y,S,I,T) ) <= c[s,i])Only \(\texttt{y}\) will be used which are actually in the \(\texttt{zip}\) of the 4 lists. Please note that in your example the \(\texttt{sum}\) always only consists of exactly one variable, because there is no 2 \(\texttt{y}\) with the same \(\texttt{s,i,t}\).
Best regards,
Jaromił
Please sign in to leave a comment.
Comments
3 comments