from scipy.optimize import linprog
import numpy as np
# Define the problem:
# The lpLib library is a LP-library that can easily load UB, LB and EQ constraints
import lpLib as LP
'''
x_1 to x_6 are order size for each month (October = 1, November = 2, etc).
x_7 to x_12 are holding inventory level at end of month (October = 7, November = 8, etc)
'''
c = [100, 100, 110, 120, 100, 100, 5, 5, 5, 5, 5, 5] # Objective function
nVar = len(c)
d = [40, 20, 30, 40, 30, 20] # Demand
nMonths = len(d)
LP.coefficients(c) # We use the lpLib functions for model specification, default minimization 
'''
The following constraints ensure that we do not order more than 50 units:

   x_i is # to order in month i, logically i runs from 1, but in Python from 0

   1 * x_i <= 50, i = 1,...,6
   
'''
for i in range(nMonths):
      A_i = np.zeros([nVar])
      A_i[i] = 1
      LP.upperBound(50,A_i) # Cannot order more than 50 units
'''
The following constraints ensures that the demand is met:

  x_i    +    x_(i+6-1)         =   d_i    +      x_[i+6]      , i = 1,...,6 
 "order" + "leftover last mnth" = "demand" + "leftover nxt month" 

which can be written:

  x_i + x_(i+6-1) - x_[i+6]  = d_i, i = 1,...,6

'''
for i in range(nMonths):
      A_i = np.zeros([nVar])
      A_i[i] = 1
      A_i[i+nMonths] = -1
      if i > 0:
          A_i[i+nMonths-1] = 1 # Assume empty inventory in the beginning of October         
      LP.equalityConstraint(d[i],A_i)
'''
he following constraints ensures that inventory does not exceed 30 at end of month:

 1 * x_(i+6) <= 30, i = 1,...,6

'''
for i in range(nMonths):
      A_i = np.zeros([nVar])
      A_i[i + nMonths]= 1
      LP.upperBound(30,A_i) # Inventory can not exceed 30 at end of month  
#
# Find solution:
#
res = LP.lpSolve()
c_F = 200
print("Cost inclusive fixed cost = ", res.fun + c_F * 6)


print("\nResults when max inventory at end of month = 40")
LP.coefficients(c)
for i in range(nMonths):
      A_i = np.zeros([nVar])
      A_i[i] = 1
      LP.upperBound(50,A_i)
for i in range(nMonths):
      A_i = np.zeros([nVar])
      A_i[i] = 1
      A_i[i+nMonths] = -1
      if i > 0: 
          A_i[i+nMonths-1] = 1          
      LP.equalityConstraint(d[i],A_i)
for i in range(nMonths):
      A_i = np.zeros([nVar])
      A_i[i + nMonths]= 1
      LP.upperBound(40,A_i) # Increase inventory to 40  
res = LP.lpSolve()


