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 inventory level at end of month (October = 7, November = 8, etc)
#
# y_1 to y_6 are binary variables, 1 = Order, 0 = Do not order

months = ["Oct","Nov","Dec","Jan","Feb","Mar"]
c = [100, 100, 110, 120, 100, 100, 5, 5, 5, 5, 5, 5]
nVar = len(c)
d = [40, 20, 30, 40, 30, 20] # Demand
maxOrder = [50,50, 50, 50, 50, 50]
y = [1,1, 1, 1, 1, 1] 
nMonths = len(d)
c_F = 200

#
# The following constraints ensures that we do not order more than 50 units, if we order:
#
# 1 * x_i <= 50 * y_i, i = 1,...,6
#
# ==> 1 * x_i - 50 * y_i <= 0, i = 1,...,6
#
best=1e30
yComb = LP.all_binary_combinations(6)
for y in yComb:
   LP.coefficients(c,True)
   for i in range(nMonths):
       A_i = np.zeros([nVar])
       A_i[i] = 1
       LP.upperBound(maxOrder[i]*y[i],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(30,A_i)   
   res=LP.lpSolve(True)
   if res.success: 
       test = res.fun + sum(y)*c_F             
       if test < best:
          best = test
          best_y = y
          best_x = x
print("\nMinimum cost = ", best)
for i in range(nMonths):
      print(months[i]+", x_" + str(i+1),"=",best_x[i], ", y_" + str(i+1),"=",best_y[i])



