# Multi-period Inventory Balance in Gurobipy

I would like to get the inventory balance in the oponed facility $$\text{C}$$ such that, the Inventory at time $$t$$ is equal to the previous one, plus the inflow minus the outflow. I have tried to create a list with zeroes, but I could not make it automated. The other issue is with indexing in python. For instance, if $$t$$ which is time in months, and it's range(0,3) then, $$t-1$$ is $$(-1)$$ which gives an error.

$$INV_{c,t}$$: is the inventory at time $$t$$.

$$INV_{c,t-1}$$: is the inventory at time $$t-1$$.

The equations: $$INV_{c,t}=INV_{c,t-1}+\sum{QS}_{c,t}+\sum{QM}_{c,t}-\sum{QG}_{c,t}$$

# Inventory level decision variable

INV_c= m.addVars(storages,months, name="INV_ct")


# Inventory Balance Constraints

m.addConstrs(INV_c[c,t] == INV_c[c,t-1] + sum(QD_wc[w,c,t,p] for w in range(warehouses) for p in range(products)) + sum(QH_hc[h,c,t]\
for h in range(customers)) - sum(QG_co[c,o,t] for o in range(centers)) for c in range(storages) for t in range(months))


I have defined $$INV0_{c,t}$$ as parameter (an array of 3 by 2 dimension), in which $$INV0_{c,t}$$ could replace INV_c[c,t-1]  in the above constraint.

I have tried to write a for loop to capture the cumulative inventory at each period, by defining the following code;

INV0_[c,t]=0
for t in range(months):
for c in range(storages):
INV0_[c,t]=INV0_[c,t]+INV_c[c,t]

• For $t-1$ error just loop over $\{1,2,...T\}$. It's a python thing where if your time period is a list of months or dict keys, T you can code 'for t in T[1:]' Mar 24 at 13:24
• Yes, I am defining a list of periods(months), but if I loop for t in T[1:] I am excluding month one, my concern is to loop over all periods from the initial Inventory to n period, for single dimension decision variable, it is easy, just define an initial parameter and loop by adding new variable to it, in my case decision variables are in two dimension. I a have tried to loop over time and for each period I add the previous one, but still did not figure it out!
– Abde
Mar 24 at 18:51
• @Abde, it would be worth to show your math model and its related code to make a better sense. Mar 24 at 18:59
• @Abde, for your first month, there's no $t-1$ term. First month will be a separate constraint like $Inv_0 = S_0+M_0-G_0$ Mar 24 at 19:08
• @Abde, be aware that, INV_c[c,t] and INV_ct0[c,t] are the same variables and should not be separated into two different variables. Instead, something like that: INV_c[c,t] = INV_c[c,t-1]. Mar 24 at 21:29

A simple approach that does not require much thought would be to split this into two parts:

# the general case for t>0
m.addConstrs(INV_c[c,t] == INV_c[c,t-1] + sum(QD_wc[w,c,t,p] for w in range(warehouses) for p in range(products)) + sum(QH_hc[h,c,t]\
for h in range(customers)) - sum(QG_co[c,o,t] for o in range(centers)) for c in range(storages) for t in range(1,months))

# special case for t=0
m.addConstrs(INV_c[c,0] == INV0[c] + sum(QD_wc[w,c,0,p] for w in range(warehouses) for p in range(products)) + sum(QH_hc[h,c,0]\
for h in range(customers)) - sum(QG_co[c,o,0] for o in range(centers)) for c in range(storages))


where INV0[c] are exogenous values: inventory at t=-1.

IMHO, this is a little bit more straightforward than some of the other suggestions.

• @Erwing Kalvelagen thank you so much, your suggestion is working for me.
– Abde
Mar 28 at 0:12

The standard inventory balance equation would be something like $$I_{t-1} + x_{t} = d_{t} + I_{t}$$ , where $$x$$ and $$d$$ are production quantity and demand respectively. Now, it seems you need to push the flow materials on both sides. Also, besides the inventory term, you have three additional terms in the RHS that needs more clarification. For the second error, I am not sure how it can be implemented in python, but for fixing the indexing error you have to define the inventory variable domain $$\in \{0, \cdots, T \}$$.

You can start your index from $$0$$ to $$n+1$$ if you have $$n$$ months for which you need to write the balance equations. Then you can define $$I_{-1}=0$$ and $$I_{n+1}=0$$ if you don't want to keep inventory at the end of planning period. While you still need to define $$I_{-1}$$ as a variable but you can fix this variable to have the value of $$0$$ by:

$$I_{-1}.lb = 0$$

$$I_{-1}.ub = 0$$

• I have tried to identify $INV_{g,t-1}$ as decision var, and I incorporate it in the constraint, but whenever I run, the error still as previous (KeyError: (0, -1)), but when, I put the range of time for in instance 'for t in range(1,months) it working, but adding just from index 1 to n, but I would like to include $INV_{g,t-1}$ defined and index 0 i.e month one, and each time a decision is made the inventory is updated based on the previous one from last period.
– Abde
Mar 24 at 16:28
• I believe the error is a (Phyton related) syntax error and if you can just update your question to include the code, problem can be easily solved. Mar 24 at 19:18

Ok I see you have updated your code because in the previous version I thought I saw cumulative inventory being used in the constraints. If not used in constraint then yes you can simply use it as expression as you have used in the code INV0_[c,t]=INV0_[c,t]+INV_c[c,t]. But need to change it a bit.
Declare INV0_[c,t] as a python matrix like

INV0_ = [[0,0,0,0],
[0,0,0,]]


Possible if you define it as numpy matrix gurobi throws an error but native python matrix doesn't have a problem.
Then in code

for t in range(months):
for c in range(storages):
INV0_[c][t]=INV0_[c][t-1]+INV_c[c,t]


Then to get the values of INV0 use

for t in range(months):
for c in range(storages):
print(INV0_[c][t].getValue())

• The problem still not solved, in this case, the indexing issue remain for t-1, when t=0 then, INV[0,-1] which is an error, that I got from the very beginning, when I tried to code the constraint as it is, when I push the index (1,months) it may work but it exclude index[0] which month 1. please I need more votes, in order to be visible to the community.
– Abde
Mar 26 at 1:00
• @Abde your first month's cumulative inventory is same as the inventory of that month. INV0_[c,0] = INV[c,0] + or - any input or output. This you may need to code separately from rest of the loop. Mar 26 at 1:24
• The idea of @Oguz Toragay may work, but still did not figure it out.
– Abde
Mar 26 at 13:21