I'm trying to optimize reorder quantities for $n$ products over $m$ periods in PuLP. The total reorder quantity should fill a container. I've never worked with multiple periods before, and I can't get it to work. I tried to formulate it the following way:
Minimize the sum over all ROQ (reorder quantity)
s.t.
ROQ > 0
Inventory m+1 = Inventory m - demand m + ROQ m > 0
sum(ROQ n) m = container * trigger
I've created an integer trigger variable so I can order any quantity that's a multiple of a container, or nothing. It seemed relatively straightforward, but the solver keeps telling me the problem is infeasible to solve. I assume the problem is where I try to set next periods inventory as this periods inventory - demand + ROQ, because turning the equation around throws an error. I can't figure out how to overcome this problem. Can you point me in the right direction?
The formulation in pulp is:
import numpy as np
import pandas as pd
import random
import pulp
import warnings
SKUs = 10
periods = 12
initial_inv = 50
container = 100
warnings.filterwarnings("ignore")
df_DEM = pd.DataFrame(np.random.randint(0,200, size=(SKUs,periods)))
df_INV = pd.DataFrame(np.random.randint(0,200, size=(SKUs,periods+1)))
df_REP = pd.DataFrame(np.random.randint(0,1, size=(SKUs,periods)))
problem = pulp.LpProblem('inventory', pulp.LpMinimize)
#variables
ROQ = pulp.LpVariable.dicts('ROQ', ((i, j) for i in range(SKUs) for j in range(periods)), lowBound=0, cat='Continuous')
trigger = pulp.LpVariable.dicts('trigger', (i for i in range(periods)), cat='Integer')
# set objective function
problem += pulp.lpSum((ROQ[i,j]) for i in range(SKUs) for j in range(periods))
#constraints
#1 ROQs > 0
for i in range(SKUs):
for j in range(periods):
problem += ROQ[i,j] >= 0
#2 trigger >= 0
for j in range(periods):
problem += trigger[i] >= 0
#3 inventory in each period > 0
for i in range(SKUs):
for j in range(periods):
problem += df_INV.loc[i,j]-df_DEM.loc[i,j]+ROQ[i,j] >= 0
#4 inventory for the next period = inventory from this period + demand - reorder quantity
for i in range(SKUs):
for j in range(periods):
problem += df_INV.loc[i,j] - df_DEM.loc[i,j] + ROQ[i,j] == df_INV.loc[i,j+1]
#5 ROQ is in multiples of a container
for j in range(periods):
problem += pulp.lpSum(ROQ[i,j] for i in range(SKUs)) == trigger[j] * container
# set solver options
solver = pulp.PULP_CBC_CMD(fracGap=0.001, msg=True, warmStart=False)
# solve problem
status = problem.solve(solver)
print(pulp.LpStatus[status], round(pulp.value(problem.objective),0))