A firm makes seven products $1,\ldots,7$ on the following machines: 4 grinders, 2 vertical drills, 3 horizontal drills, 1 borer, and 1 planer.
Each product yields a certain contribution to the profit (defined as selling price minus cost of raw materials expressed in Euro/unit). These quantities (in Euro/unit) together with the production times (hours/unit) required on each process are given below.
product 1 2 3 4 5 6 7
profit 10 6 8 4 11 9 3
grinding 0.5 0.7 0 0 0.3 0.2 0.5
vdrill 0.1 0.2 0 0.3 0 0.6 0
hdrill 0.2 0 0.8 0 0 0 0.6
boring 0.05 0.03 0 0.07 0.1 0 0.08
planning 0 0 0.01 0 0.05 0 0.05
In the first month (January) and the five subsequent months certain machines will be down for maintenance. These machines will be:
January 1 grinder
February 2 hdrill
March 1 borer
April 1 vdrill
May 1 grinder
May 1 vdrill
June 1 planer
June 1 hdrill
There are marketing limitations on each product in each month. That is, in each month the amount sold for each product cannot exceed these values:
product 1 2 3 4 5 6 7
January 500 1000 300 300 800 200 100
February 600 500 200 0 400 300 150
March 300 600 0 0 500 400 100
April 200 300 400 500 200 0 100
May 0 100 500 100 1000 300 0
June 500 500 100 300 1100 500 60
It is possible to store products in a warehouse. The capacity of the storage is 100 units per product type per month. The cost is 0.5 Euro per unit of product per months. There are no stocks in the first month but it is desired to have a stock of 50 of each product type at the end of June.
The factory works 6 days a week with two shifts of 8 hours each day. (It can be assumed that each month consists of 24 working days.)
The factory wants to determine a production plan, that is, the quantity to produce, sell and store in each month for each product, that maximizes the total profit.
Model the factory planning problem for the month of January as an LP problem.
Model the multi-period (from January to June) factory planning problem as an LP problem. Use mathematical notation and indicate in general terms how many variables and how many constraints your model has.
Implement the single-period model (Task 1) in a SpreadSheet. Implement the multi-period model (Task 2) in Python and Gurobi. Solve the problem on the data given.
Here are the data of the problem:
from collections import OrderedDict
class Data:
def __init__(self):
self.products = [1, 2, 3, 4, 5, 6, 7];
self.machines = ["grinder","vdrill","hdrill","borer","planer"]
self.months = ["january","february","march","april","may","june"]
self.profits = [10, 6, 8, 4, 11, 9, 3]
tmp = {
'grinder' :[0.5, 0.7, 0, 0, 0.3, 0.2, 0.5],
'vdrill' :[0.1 , 0.2 , 0 , 0.3 , 0 , 0.6, 0],
'hdrill' :[0.2 , 0 , 0.8 , 0 , 0 , 0 , 0.6],
'borer' :[0.05, 0.03, 0 , 0.07, 0.1 , 0 , 0.08],
'planer' :[0 , 0 , 0.01, 0 , 0.05, 0 , 0.05]
}
self.coeff=OrderedDict()
for m in self.machines:
for (j,p) in enumerate(self.products):
self.coeff[m,p] = tmp[m][j]
self.capacity = {"grinder": 4,"vdrill": 2,"hdrill": 3, "borer": 1, "planer": 1}
tmp = {
"grinder": [("january", 1), ("may", 1)],
"hdrill": [("february", 2),("june", 1)],
"borer": [("march", 1)],
"vdrill": [("april", 1),("may", 1)],
"planer": [("june", 1)]
}
self.maintainance = OrderedDict()
for m in self.machines:
for t in self.months:
self.maintainance[m,t] = 0
if m in tmp:
for s in tmp[m]:
self.maintainance[m,s[0]]=s[1]
tmp = {
"january": [500 ,1000 ,300 ,300 ,800 ,200 ,100],
"february": [600 ,500 ,200 ,0 ,400 ,300 ,150],
"march": [300 ,600 ,0 ,0 ,500 ,400 ,100],
"april": [200 ,300 ,400 ,500 ,200 ,0 ,100],
"may": [0 ,100 ,500 ,100 ,1000 ,300 ,0 ],
"june": [500 ,500 ,100 ,300 ,1100 ,500 ,60 ]
}
self.market_limits = OrderedDict()
for m in self.months:
for (j,p) in enumerate(self.products):
self.market_limits[m,p] = tmp[m][j]
def printData(self):
print("Months:", self.months)
print("Products:", self.products)
print("Machines:", self.machines)
print("Coefficients: ",self.coeff)
print("Market_limits:", self.market_limits)
print("Maitainance:", self.maintainance)
We import the Gurobi Python Module and other Python libraries. With Gurobi 9.1.1, a pip installation of the product will automatically include a size-limited (2000 variables, 2000 linear constraints, and 200 quadratic constraints) license that should work in a Docker container, which is used by Google Colab.
%pip install -i https://pypi.gurobi.com gurobipy
import gurobipy as gp
Here, instead of stipulating when each machine is down for maintenance, it is desired to find the best month for each machine to be down.
Each machine must be down for maintenance in one month of the six apart from the grinding machines, only two of which need to be down in any six months.
Extend the model that correctly addressed tasks 2 and 3 to allow it to make these extra decisions.
How many variables did you need to add? What is the domain of these variables?
Has the matrix of the problem a similar structure to the one of the point above?
Is the solution from Task 3 a valid solution to this problem? What information can it bear in this new case?
Implement and solve the model in Python and Gurobi. After how many nodes in the branch and bound tree is the optimal solution found? And after how many is it proven optimal?
How much worth is the extra flexibility of choosing when to place downtimes?
The column ``LP iter'' indicates the number of simplex iterations for solving the LP problem. Why is this number increasing through the search?
Can you devise another model and compare them computationally? Which is best? Why?