Objective
Requirements and Specifications
Product |
Ingredient (grams per kg of product) |
|||
---|---|---|---|---|
|
||||
|
Polymer A |
Polymer B |
Polymer C |
Base |
Airtex |
250 |
120 |
250 |
380 |
Extendex |
180 |
125 |
125 |
570 |
Resistex |
375 |
180 |
320 ; |
125 |
Polymer | Monthly production (kg) |
Cost of manufacture (£ per kg) |
---|---|---|
A |
A |
k1 |
B |
B |
k2 |
C |
C |
k3 |
Base |
D |
k4 |
Production of the platforms takes place on a special fully automated machine, that can produce platforms (of any type) at a rate of 100 platforms per day (any type), and operates for 20 days per month. Postproduction requires also requires a special sonic calibration process:
Airtex 2 minutes per platform inspected
Extendex 2 minutes per platform inspected
Resistex 30 seconds per platform inspected
Total time available in the Sonic Calibration Room (SCR) next month is 45 hours.
For the coming month, Hindle Hifi has confirmed orders to produce 500 Airtex platforms, 500 Extendex platforms and 400 Resistex platforms, a total of 1,400 platforms. The current selling prices for the products are p1 for the Airtex platform, p2 for Extendex and p3 for Resistex.
Production Planning Analysis
Hindle Hifi have asked you analyse their production and present the results in a management report. They require the analysis to be carried out in Python and a copy of your code provided.
This month’s production planning
- What is the expected cost of supplying exactly the confirmed orders next month?
- What is the expected profit associated with the confirmed orders next month?
- If Hindle Hifi satisfies the confirmed orders and is free to make more platforms, then what is the maximum profit possible, and how many of the three platforms should they make?
- What would the maximum profit be, and how many of the three platforms should they make?
- If an additional 5 hours are available in the Sonic Calibration Room this month, how would this impact on the maximum profit and optimal plan?
- If the machine time could be extended by an additional 2 days this month, how would this impact on the maximum profit and optimal plan?
- If the machine time could be extended by an additional 2 days this month and an additional 5 hours are available in the Sonic Calibration Room this month, how would this impact on the maximum profit and optimal plan?
- Perform a sensitivity analysis on the selling price of Airtex, from £45 to £60, in £1 increments, and show graphically how it relates to the number of Airtex platforms made. You can assume all the other production conditions are the same as task 4.
- Assuming at least 200 platforms have to be made for each of the three products, perform a sensitivity analysis on the machine time between 10 and 20 days per month, in 1-day increments, and show graphically how it relates to both the cost of production and the optimal profit. You can assume all the other production conditions are the same as task 4.
- In two months’ time, the production facility will be partially closed for a month for refurbishments to take place. The production of all four polymers during this month will be significantly reduced, and the estimate is that production will be 10% of their current monthly production.
- The platform machine and SCR will also be impacted and will be only operate at around half of the current activity. During this refurbishment period Hindle Hifi have decided to focus solely on making Airtex platforms.
- How many Airtex platforms can be made under these reduced production conditions?
- If Hindle Hifi want to produce E platforms during this period, what is the lowest percentage of polymer production that is necessary to achieve this?
Future production planning
[For question 4 onwards, you can assume that Hindle Hifi does not have to satisfy the confirmed orders next month, and is free to make any number of platforms.]
Python Code
- Well-structured and well-commented
- Intuitive to use (i.e., straightforward for us to run the code)
- Generalisable (i.e., your code can be used with any datafiles)
- Flexible (i.e., provide user options via a user interface)
An example of the user interface is as follows:
> Enter the name of the file:
datafile 0.csv
> Choose one of the following options:
> 1: Expected cost of supplying exactly the confirmed orders next month
> 2: Expected profit associated with the confirmed orders next month
> . . .
> Q: Quit the program
1
> The expected cost is X
> Do you want to continue (Y/N)?
Y
> Choose one of the following options:
> 1: Expected cost of supplying exactly the confirmed orders next month
> 2: Expected profit associated with the confirmed orders next month
> . . .
> Q: Quit the program
2
> The expected profit is X
> Do you want to continue (Y/N)?
N
The program should run without errors and sensibly uses programming techniques developed on the module. The source code should be programmed with Jupyter Notebook as an Editor. It is important to break your code into small, meaningful functions and appropriately comment your code.
A | 504 |
k1 |
100 | p1 |
49.99 |
---|---|---|---|---|---|
|
|
|
|
|
|
B |
300 |
k2 |
60 |
p2 |
63.99 |
|
|
|
|
|
|
C |
435 |
k3 |
52 |
p3 |
99.99 |
|
|
|
|
|
|
D |
700 |
k4 |
6 |
|
|
|
|
|
|
|
|
E |
490 |
|
|
|
|
Source Code
### Required Libraries
import numpy as np
import pulp
import matplotlib.pyplot as plt
### Define the data and constants
Required 'grams per kg' of each ingredient (Polymers A, B, C and Base) for each product (Airtex, Extendex, Resistex)
The values are stored in a NumPy array as kilograms
gpkg = np.array([
[250, 120, 250, 380], #Airtex
[180, 125, 125, 570], # Extendex
[375, 180, 320, 125] # Resistex
])/1000.0
### Dataset containing the monthly production of each ingredient $M_{i}$, the cost of manufacture (per kg) $k_{i}$, and the price of each platform $p_{i}$
M = list()
k = list()
p = list()
with open('data.csv', 'r') as f:
lines = f.readlines()
# Parse each line
for line in lines:
data = line.split(',')
# The first element in the row contains the name of the polymer
# The second element contains the monthly production
mi = int(data[1])
M.append(mi)
# If there is a third element 'ki', then there is a manufacture price
if len(data) > 3:
ki = float(data[3])
else:
ki = 0
k.append(ki)
# If there is a fifth element then there is a price
if len(data) > 5:
pi = float(data[5])
else:
pi = 0
p.append(pi)
'''
# Load the dataset with the monthly production, cost and price
production_data = np.loadtxt('data.csv', delimiter = ',')
M = production_data[:,0] # Monthly production
k = production_data[:, 1] # Cost of manufacture per kg
p = production_data[:, 2] # Price per platform (unit)
'''
### Number of minimum units to be produced for each platform
# Number of orders for each product
# Airtex, Extendex, Resistex
n_orders = [500, 500, 400]
### Some other parameters as the weight of each platorm (in kg), the number of units that can be produced per day, the number of days that the machine will be working, the calibration time (in seconds) and the maximum calibration room
Note: the calibration time is given in minutes and then converted to seconds. So for example a calibration time of 2 minutes is declared as 120 seconds
# Weight of each platform in kg
# Airtex, Extendex, Resistex
w = [0.5, 1, 1]
# Number of platforms that the machine can produce each day
units_per_day = 100
# Number of days per month that the machine operates
machine_days = 20
# Calibration time in seconds
# Airtex, Extendex, Resistex (per seconds)
ct = [120, 120, 30]
# Total time in calibration room (in seconds)
total_calibration_time = 45*60*60
## Create Model and all variables
Let:
* $x_{1}$: Number of units of Airtex platforms
* $x_{2}$: Number of units of Extendex platforms
* $x_{3}$: Number of units of Resistex platforms
* $A$: Number of kilograms of Polymer A used
* $B$: Number of kilograms of Polymer B used
* $C$: Number of kilograms of Polymer C used
* $Base$: Number of kilograms of Base used
----------------
### Objective function
Given the units of each platform produced $x_{i}$, the total revenue is calculated as the number of plaforms multiplied by the price of each platorm
$$Revenue = x_{1}*p_{1}+x_{2}*p_{2}+x_{3}*p_{3}$$
The total cost of production is equal to the number of kilograms of each ingredient multiplued by its price
$$Cost = A*k_{1}+B*k_{2}+C*k_{3}+Base*k_{4}$$
Finally, the objective function is:
$$Maximize: Revenue - Cost$$
$$Maximize: (x_{1}*p_{1}+x_{2}*p_{2}+x_{3}*p_{3}) - (A*k_{1}+B*k_{2}+C*k_{3}+Base*k_{4})$$
-----------------
### Constraints
* The number of units for each platform must be equal to the number of orders required for the month
$$x_{i} = M_{i}$$
* The number of kilograms used for each ingredient is equal to, the number of units of each platform, multiplied by the weight of that platform, and multiplied by the weight of each required ingredients
-----------------
We have that, the machine can produce 100 units per days. So, the time (in days) required to get all the units produced is equal to:
$$ t_{days} = \frac{x_{1}+x_{2}+x_{3}}{100}$$
The total time of calibration for all the production is equal to the time required for each platform multiplied by the total number of platforms, and then all these values are added.
Note that, the calibration time for each platform is given in seconds, so these values are converted to days
Finally, the total number of days required for the production is equal to the number of days used by the machine plus the calibration time
# create model
model = pulp.LpProblem(name = "ATLAS", sense = pulp.LpMaximize)
# define the variable
x1 = pulp.LpVariable(name = "units_of_airtex", lowBound = 0, cat = "Integer")
x2 = pulp.LpVariable(name = "units_of_extendex", lowBound = 0, cat = "Integer")
x3 = pulp.LpVariable(name = "units_of_resistex", lowBound = 0, cat = "Integer")
A = pulp.LpVariable(name = "kg of Polymer A", lowBound = 0) # Total kilorams of Polymer A produced
B = pulp.LpVariable(name = "kg of Polymer B", lowBound = 0) # Total kilorams of Polymer B produced
C = pulp.LpVariable(name = "kg of Polymer C", lowBound = 0) # Total kilorams of Polymer C produced
Base = pulp.LpVariable(name = "kg of Base", lowBound = 0) # Total kilorams of Base produced
# Objective function: Max profit
# In the explanation above we used k1, k2, k3 ... but since python uses zero-indexing in the code we use k0, k1, k2...
model += (p[0]*x1 + p[1]*x2 + p[2]*x3) - (A*k[0] + B*k[1] + C*k[2] + Base*k[3]), "total profit"
# Number of platforms produced
model += x1 == n_orders[0], "minimum units of Airtex"
model += x2 == n_orders[1], "minimum units of Extendex"
model += x3 == n_orders[2], "minimum units of Resistex"
# For each kg of each product, the total kg of ingredients must be less or equal to their monthly production
# Polymer A
model += A == x1*w[0]*gpkg[0,0] + x2*w[1]*gpkg[1,0] + x3*w[2] *gpkg[0,2], "kg of Polymer A" # formula for the number of kg of polymer A
model += A <= M[0], "max. production of Polymer A"
# Polymer B
model += B == x1*w[0]*gpkg[0,1] + x2*w[1]*gpkg[1,1] + x3*w[2] *gpkg[1,2], "kg of Polymer B" # formula for the number of kg of polymer B
model += B <= M[1], "max. production of Polymer B"
#Polymer C
model += C == x1*w[0]*gpkg[0,2] + x2*w[1]*gpkg[1,2] + x3*w[2] *gpkg[2,2], "kg of Polymer C" # formula for the number of kg of polymer C
model += C <= M[2], "max. production of Polymer C"
# Base
model += Base == x1*w[0]*gpkg[0,3] + x2*w[1]*gpkg[1,3] + x3*w[2] *gpkg[2,3], "kg of Base" # formula for the number of kg of Base
model += Base <= M[3], "max. production of Base"
# The time in days must be less than 20
# The time in days is equal to the number of units produced divided by 100, plus the calibration time
model += (ct[0]*x1 + ct[1]*x2 + ct[2]*x3) <= total_calibration_time, "max. calibration time"
model += (x1+x2+x3)/units_per_day + (ct[0]*x1 + ct[1]*x2 + ct[2]*x3)/(24*60*60) <= machine_days, "max. days for the machine"
## Solve and print results
# Let's solve
# solve
model.solve()
# Print
print("------------------------------------")
print("Status: " + pulp.LpStatus[model.status])
'''
print("Total profit = " + str(pulp.value(model.objective)))
print("\nVariables")
print("---------")
for v in model.variables():
print("{:<25s}{:>20.2f}{:>25s}".format(v.name, v.varValue, "\tReduced Cost = " + str(v.dj)))
print("\nConstraints")
print("-----------")
for name, c in model.constraints.items():
print("{:<35s}{:>30s}{:>25s}".format(name, "shadow price = " + str(c.pi), "\tReduced Cost = " + str(c.slack)))
print()
print()
'''
# Do calculations
total_profit = p[0]*x1.varValue + p[1]*x2.varValue + p[2]*x3.varValue - (A.varValue*k[0] + B.varValue*k[1] + C.varValue*k[2] + Base.varValue*k[3])
total_cost = A.varValue*k[0] + B.varValue*k[1] + C.varValue*k[2] + Base.varValue*k[3]
# Question 1: Expected cost
print("The expected cost of supplying exactly the confirmed orders is: ${:.2f}".format(total_cost))
# Question 2: Expected profit
print("The expected profit of supplying exactly the confirmed orders is: ${:.2f}".format(total_profit))
# Question 3
For this question, we need to solve the model again, but this time set the number of required platforms higher-than or equal to the monthly requirement
# create model
model = pulp.LpProblem(name = "ATLAS", sense = pulp.LpMaximize)
# define the variable
x1 = pulp.LpVariable(name = "units_of_airtex", lowBound = 0, cat = "Integer")
x2 = pulp.LpVariable(name = "units_of_extendex", lowBound = 0, cat = "Integer")
x3 = pulp.LpVariable(name = "units_of_resistex", lowBound = 0, cat = "Integer")
A = pulp.LpVariable(name = "kg of Polymer A", lowBound = 0) # Total kilorams of Polymer A produced
B = pulp.LpVariable(name = "kg of Polymer B", lowBound = 0) # Total kilorams of Polymer B produced
C = pulp.LpVariable(name = "kg of Polymer C", lowBound = 0) # Total kilorams of Polymer C produced
Base = pulp.LpVariable(name = "kg of Base", lowBound = 0) # Total kilorams of Base produced
# Objective function: Max profit
# In the explanation above we used k1, k2, k3 ... but since python uses zero-indexing in the code we use k0, k1, k2...
model += (p[0]*x1 + p[1]*x2 + p[2]*x3) - (A*k[0] + B*k[1] + C*k[2] + Base*k[3]), "total profit"
# Number of platforms produced
model += x1 >= n_orders[0], "minimum units of Airtex"
model += x2 >= n_orders[1], "minimum units of Extendex"
model += x3 >= n_orders[2], "minimum units of Resistex"
# For each kg of each product, the total kg of ingredients must be less or equal to their monthly production
# Polymer A
model += A == x1*w[0]*gpkg[0,0] + x2*w[1]*gpkg[1,0] + x3*w[2] *gpkg[0,2], "kg of Polymer A" # formula for the number of kg of polymer A
model += A <= M[0], "max. production of Polymer A"
# Polymer B
model += B == x1*w[0]*gpkg[0,1] + x2*w[1]*gpkg[1,1] + x3*w[2] *gpkg[1,2], "kg of Polymer B" # formula for the number of kg of polymer B
model += B <= M[1], "max. production of Polymer B"
#Polymer C
model += C == x1*w[0]*gpkg[0,2] + x2*w[1]*gpkg[1,2] + x3*w[2] *gpkg[2,2], "kg of Polymer C" # formula for the number of kg of polymer C
model += C <= M[2], "max. production of Polymer C"
# Base
model += Base == x1*w[0]*gpkg[0,3] + x2*w[1]*gpkg[1,3] + x3*w[2] *gpkg[2,3], "kg of Base" # formula for the number of kg of Base
model += Base <= M[3], "max. production of Base"
# The time in days must be less than 20
# The time in days is equal to the number of units produced divided by 100, plus the calibration time
model += (ct[0]*x1 + ct[1]*x2 + ct[2]*x3) <= total_calibration_time, "max. calibration time"
model += (x1+x2+x3)/units_per_day + (ct[0]*x1 + ct[1]*x2 + ct[2]*x3)/(24*60*60) <= machine_days, "max. days for the machine"
# Let's solve
# solve
model.solve()
# Print
print("------------------------------------")
print("Status: " + pulp.LpStatus[model.status])
# Do calculations
total_profit = p[0]*x1.varValue + p[1]*x2.varValue + p[2]*x3.varValue - (A.varValue*k[0] + B.varValue*k[1] + C.varValue*k[2] + Base.varValue*k[3])
total_cost = A.varValue*k[0] + B.varValue*k[1] + C.varValue*k[2] + Base.varValue*k[3]
print("The new profit is ${:.2f}".format(total_profit))
print("{0} new Airtex platforms were produced".format(x1.varValue - n_orders[0]))
print("{0} new Extendex platforms were produced".format(x2.varValue - n_orders[1]))
print("{0} new Resistex platforms were produced".format(x3.varValue - n_orders[2]))
# Question 5
For this case, we need to solve the model again
total_calibration_time = 50*60*60 # 50 hours converted to seconds
# create model
model = pulp.LpProblem(name = "ATLAS", sense = pulp.LpMaximize)
# define the variable
x1 = pulp.LpVariable(name = "units_of_airtex", lowBound = 0, cat = "Integer")
x2 = pulp.LpVariable(name = "units_of_extendex", lowBound = 0, cat = "Integer")
x3 = pulp.LpVariable(name = "units_of_resistex", lowBound = 0, cat = "Integer")
A = pulp.LpVariable(name = "kg of Polymer A", lowBound = 0) # Total kilorams of Polymer A produced
B = pulp.LpVariable(name = "kg of Polymer B", lowBound = 0) # Total kilorams of Polymer B produced
C = pulp.LpVariable(name = "kg of Polymer C", lowBound = 0) # Total kilorams of Polymer C produced
Base = pulp.LpVariable(name = "kg of Base", lowBound = 0) # Total kilorams of Base produced
# Objective function: Max profit
# In the explanation above we used k1, k2, k3 ... but since python uses zero-indexing in the code we use k0, k1, k2...
model += (p[0]*x1 + p[1]*x2 + p[2]*x3) - (A*k[0] + B*k[1] + C*k[2] + Base*k[3]), "total profit"
# Number of platforms produced
model += x1 >= n_orders[0], "minimum units of Airtex"
model += x2 >= n_orders[1], "minimum units of Extendex"
model += x3 >= n_orders[2], "minimum units of Resistex"
# For each kg of each product, the total kg of ingredients must be less or equal to their monthly production
# Polymer A
model += A == x1*w[0]*gpkg[0,0] + x2*w[1]*gpkg[1,0] + x3*w[2] *gpkg[0,2], "kg of Polymer A" # formula for the number of kg of polymer A
model += A <= M[0], "max. production of Polymer A"
# Polymer B
model += B == x1*w[0]*gpkg[0,1] + x2*w[1]*gpkg[1,1] + x3*w[2] *gpkg[1,2], "kg of Polymer B" # formula for the number of kg of polymer B
model += B <= M[1], "max. production of Polymer B"
#Polymer C
model += C == x1*w[0]*gpkg[0,2] + x2*w[1]*gpkg[1,2] + x3*w[2] *gpkg[2,2], "kg of Polymer C" # formula for the number of kg of polymer C
model += C <= M[2], "max. production of Polymer C"
# Base
model += Base == x1*w[0]*gpkg[0,3] + x2*w[1]*gpkg[1,3] + x3*w[2] *gpkg[2,3], "kg of Base" # formula for the number of kg of Base
model += Base <= M[3], "max. production of Base"
# The time in days must be less than 20
# The time in days is equal to the number of units produced divided by 100, plus the calibration time
model += (ct[0]*x1 + ct[1]*x2 + ct[2]*x3) <= total_calibration_time, "max. calibration time"
model += (x1+x2+x3)/units_per_day + (ct[0]*x1 + ct[1]*x2 + ct[2]*x3)/(24*60*60) <= machine_days, "max. days for the machine"
# Let's solve
# solve
model.solve()
# Print
print("------------------------------------")
print("Status: " + pulp.LpStatus[model.status])
# Do calculations
total_profit = p[0]*x1.varValue + p[1]*x2.varValue + p[2]*x3.varValue - (A.varValue*k[0] + B.varValue*k[1] + C.varValue*k[2] + Base.varValue*k[3])
total_cost = A.varValue*k[0] + B.varValue*k[1] + C.varValue*k[2] + Base.varValue*k[3]
print("The new profit is ${:.2f}".format(total_profit))
print("{0} Airtex platforms were produced".format(x1.varValue))
print("{0} Extendex platforms were produced".format(x2.varValue))
print("{0} Resistex platforms were produced".format(x3.varValue))
# Question 6
total_calibration_time = 45*60*60 # set the calibration time back to 45 hours
machine_days = 22 # two days more
# create model
model = pulp.LpProblem(name = "ATLAS", sense = pulp.LpMaximize)
# define the variable
x1 = pulp.LpVariable(name = "units_of_airtex", lowBound = 0, cat = "Integer")
x2 = pulp.LpVariable(name = "units_of_extendex", lowBound = 0, cat = "Integer")
x3 = pulp.LpVariable(name = "units_of_resistex", lowBound = 0, cat = "Integer")
A = pulp.LpVariable(name = "kg of Polymer A", lowBound = 0) # Total kilorams of Polymer A produced
B = pulp.LpVariable(name = "kg of Polymer B", lowBound = 0) # Total kilorams of Polymer B produced
C = pulp.LpVariable(name = "kg of Polymer C", lowBound = 0) # Total kilorams of Polymer C produced
Base = pulp.LpVariable(name = "kg of Base", lowBound = 0) # Total kilorams of Base produced
# Objective function: Max profit
# In the explanation above we used k1, k2, k3 ... but since python uses zero-indexing in the code we use k0, k1, k2...
model += (p[0]*x1 + p[1]*x2 + p[2]*x3) - (A*k[0] + B*k[1] + C*k[2] + Base*k[3]), "total profit"
# Number of platforms produced
model += x1 >= n_orders[0], "minimum units of Airtex"
model += x2 >= n_orders[1], "minimum units of Extendex"
model += x3 >= n_orders[2], "minimum units of Resistex"
# For each kg of each product, the total kg of ingredients must be less or equal to their monthly production
# Polymer A
model += A == x1*w[0]*gpkg[0,0] + x2*w[1]*gpkg[1,0] + x3*w[2] *gpkg[0,2], "kg of Polymer A" # formula for the number of kg of polymer A
model += A <= M[0], "max. production of Polymer A"
# Polymer B
model += B == x1*w[0]*gpkg[0,1] + x2*w[1]*gpkg[1,1] + x3*w[2] *gpkg[1,2], "kg of Polymer B" # formula for the number of kg of polymer B
model += B <= M[1], "max. production of Polymer B"
#Polymer C
model += C == x1*w[0]*gpkg[0,2] + x2*w[1]*gpkg[1,2] + x3*w[2] *gpkg[2,2], "kg of Polymer C" # formula for the number of kg of polymer C
model += C <= M[2], "max. production of Polymer C"
# Base
model += Base == x1*w[0]*gpkg[0,3] + x2*w[1]*gpkg[1,3] + x3*w[2] *gpkg[2,3], "kg of Base" # formula for the number of kg of Base
model += Base <= M[3], "max. production of Base"
# The time in days must be less than 20
# The time in days is equal to the number of units produced divided by 100, plus the calibration time
model += (ct[0]*x1 + ct[1]*x2 + ct[2]*x3) <= total_calibration_time, "max. calibration time"
model += (x1+x2+x3)/units_per_day + (ct[0]*x1 + ct[1]*x2 + ct[2]*x3)/(24*60*60) <= machine_days, "max. days for the machine"
# Let's solve
# solve
model.solve()
# Print
print("------------------------------------")
print("Status: " + pulp.LpStatus[model.status])
# Do calculations
total_profit = p[0]*x1.varValue + p[1]*x2.varValue + p[2]*x3.varValue - (A.varValue*k[0] + B.varValue*k[1] + C.varValue*k[2] + Base.varValue*k[3])
total_cost = A.varValue*k[0] + B.varValue*k[1] + C.varValue*k[2] + Base.varValue*k[3]
print("The new profit is ${:.2f}".format(total_profit))
print("{0} Airtex platforms were produced".format(x1.varValue))
print("{0} Extendex platforms were produced".format(x2.varValue))
print("{0} Resistex platforms were produced".format(x3.varValue))
# Question 7
total_calibration_time = 50*60*60 # set the calibration time to 50 hours
machine_days = 22 # two days more
# create model
model = pulp.LpProblem(name = "ATLAS", sense = pulp.LpMaximize)
# define the variable
x1 = pulp.LpVariable(name = "units_of_airtex", lowBound = 0, cat = "Integer")
x2 = pulp.LpVariable(name = "units_of_extendex", lowBound = 0, cat = "Integer")
x3 = pulp.LpVariable(name = "units_of_resistex", lowBound = 0, cat = "Integer")
A = pulp.LpVariable(name = "kg of Polymer A", lowBound = 0) # Total kilorams of Polymer A produced
B = pulp.LpVariable(name = "kg of Polymer B", lowBound = 0) # Total kilorams of Polymer B produced
C = pulp.LpVariable(name = "kg of Polymer C", lowBound = 0) # Total kilorams of Polymer C produced
Base = pulp.LpVariable(name = "kg of Base", lowBound = 0) # Total kilorams of Base produced
# Objective function: Max profit
# In the explanation above we used k1, k2, k3 ... but since python uses zero-indexing in the code we use k0, k1, k2...
model += (p[0]*x1 + p[1]*x2 + p[2]*x3) - (A*k[0] + B*k[1] + C*k[2] + Base*k[3]), "total profit"
# Number of platforms produced
model += x1 >= n_orders[0], "minimum units of Airtex"
model += x2 >= n_orders[1], "minimum units of Extendex"
model += x3 >= n_orders[2], "minimum units of Resistex"
# For each kg of each product, the total kg of ingredients must be less or equal to their monthly production
# Polymer A
model += A == x1*w[0]*gpkg[0,0] + x2*w[1]*gpkg[1,0] + x3*w[2] *gpkg[0,2], "kg of Polymer A" # formula for the number of kg of polymer A
model += A <= M[0], "max. production of Polymer A"
# Polymer B
model += B == x1*w[0]*gpkg[0,1] + x2*w[1]*gpkg[1,1] + x3*w[2] *gpkg[1,2], "kg of Polymer B" # formula for the number of kg of polymer B
model += B <= M[1], "max. production of Polymer B"
#Polymer C
model += C == x1*w[0]*gpkg[0,2] + x2*w[1]*gpkg[1,2] + x3*w[2] *gpkg[2,2], "kg of Polymer C" # formula for the number of kg of polymer C
model += C <= M[2], "max. production of Polymer C"
# Base
model += Base == x1*w[0]*gpkg[0,3] + x2*w[1]*gpkg[1,3] + x3*w[2] *gpkg[2,3], "kg of Base" # formula for the number of kg of Base
model += Base <= M[3], "max. production of Base"
# The time in days must be less than 20
# The time in days is equal to the number of units produced divided by 100, plus the calibration time
model += (ct[0]*x1 + ct[1]*x2 + ct[2]*x3) <= total_calibration_time, "max. calibration time"
model += (x1+x2+x3)/units_per_day + (ct[0]*x1 + ct[1]*x2 + ct[2]*x3)/(24*60*60) <= machine_days, "max. days for the machine"
# Let's solve
# solve
model.solve()
# Print
print("------------------------------------")
print("Status: " + pulp.LpStatus[model.status])
# Do calculations
total_profit = p[0]*x1.varValue + p[1]*x2.varValue + p[2]*x3.varValue - (A.varValue*k[0] + B.varValue*k[1] + C.varValue*k[2] + Base.varValue*k[3])
total_cost = A.varValue*k[0] + B.varValue*k[1] + C.varValue*k[2] + Base.varValue*k[3]
print("The new profit is ${:.2f}".format(total_profit))
print("{0} Airtex platforms were produced".format(x1.varValue))
print("{0} Extendex platforms were produced".format(x2.varValue))
print("{0} Resistex platforms were produced".format(x3.varValue))
# Question 8
Solve the model for each new value of the Airtex price
# Create an array to store the results of Airtex units produced
airtex_units = []
for p_airtex in range(45, 61): # from 45 to 60
# create model
model = pulp.LpProblem(name = "ATLAS", sense = pulp.LpMaximize)
# define the variable
x1 = pulp.LpVariable(name = "units_of_airtex", lowBound = 0, cat = "Integer")
x2 = pulp.LpVariable(name = "units_of_extendex", lowBound = 0, cat = "Integer")
x3 = pulp.LpVariable(name = "units_of_resistex", lowBound = 0, cat = "Integer")
A = pulp.LpVariable(name = "kg of Polymer A", lowBound = 0) # Total kilorams of Polymer A produced
B = pulp.LpVariable(name = "kg of Polymer B", lowBound = 0) # Total kilorams of Polymer B produced
C = pulp.LpVariable(name = "kg of Polymer C", lowBound = 0) # Total kilorams of Polymer C produced
Base = pulp.LpVariable(name = "kg of Base", lowBound = 0) # Total kilorams of Base produced
# Objective function: Max profit
# In the explanation above we used k1, k2, k3 ... but since python uses zero-indexing in the code we use k0, k1, k2...
model += (p_airtex*x1 + p[1]*x2 + p[2]*x3) - (A*k[0] + B*k[1] + C*k[2] + Base*k[3]), "total profit"
# Number of platforms produced
model += x1 >= n_orders[0], "minimum units of Airtex"
model += x2 >= n_orders[1], "minimum units of Extendex"
model += x3 >= n_orders[2], "minimum units of Resistex"
# For each kg of each product, the total kg of ingredients must be less or equal to their monthly production
# Polymer A
model += A == x1*w[0]*gpkg[0,0] + x2*w[1]*gpkg[1,0] + x3*w[2] *gpkg[0,2], "kg of Polymer A" # formula for the number of kg of polymer A
model += A <= M[0], "max. production of Polymer A"
# Polymer B
model += B == x1*w[0]*gpkg[0,1] + x2*w[1]*gpkg[1,1] + x3*w[2] *gpkg[1,2], "kg of Polymer B" # formula for the number of kg of polymer B
model += B <= M[1], "max. production of Polymer B"
#Polymer C
model += C == x1*w[0]*gpkg[0,2] + x2*w[1]*gpkg[1,2] + x3*w[2] *gpkg[2,2], "kg of Polymer C" # formula for the number of kg of polymer C
model += C <= M[2], "max. production of Polymer C"
# Base
; model += Base == x1*w[0]*gpkg[0,3] + x2*w[1]*gpkg[1,3] + x3*w[2] *gpkg[2,3], "kg of Base" # formula for the number of kg of Base
; model += Base <= M[3], "max. production of Base"
# The time in days must be less than 20
# The time in days is equal to the number of units produced divided by 100, plus the calibration time
model += (ct[0]*x1 + ct[1]*x2 + ct[2]*x3) <= total_calibration_time, "max. calibration time"
model += (x1+x2+x3)/units_per_day + (ct[0]*x1 + ct[1]*x2 + ct[2]*x3)/(24*60*60) <= machine_days, "max. days for the machine"
# Let's solve
# solve
model.solve()
# Print
#print("Status for Price of Airtex = {0}: {1}".format(p_airtex, pulp.LpStatus[model.status]))
airtex_units.append(x1.varValue)
# Now, plot
plt.figure()
plt.plot(range(45,61), airtex_units)
plt.grid(True)
plt.xlabel('Price of Airtex platform')
plt.ylabel('Units of Airtex platform')
plt.title('Units of Airtex platform produced vs. Price')
plt.show()
# Question 9
n_orders = [200, 200, 200] # at least 200 for each platform
costs = []
profits = []
for machine_days in range(10, 21): # from 10 to 21
# create model
model = pulp.LpProblem(name = "ATLAS", sense = pulp.LpMaximize)
# define the variable
x1 = pulp.LpVariable(name = "units_of_airtex", lowBound = 0, cat = "Integer")
x2 = pulp.LpVariable(name = "units_of_extendex", lowBound = 0, cat = "Integer")
x3 = pulp.LpVariable(name = "units_of_resistex", lowBound = 0, cat = "Integer")
A = pulp.LpVariable(name = "kg of Polymer A", lowBound = 0) # Total kilorams of Polymer A produced
B = pulp.LpVariable(name = "kg of Polymer B", lowBound = 0) # Total kilorams of Polymer B produced
C = pulp.LpVariable(name = "kg of Polymer C", lowBound = 0) # Total kilorams of Polymer C produced
Base = pulp.LpVariable(name = "kg of Base", lowBound = 0) # Total kilorams of Base produced
; # Objective function: Max profit
# In the explanation above we used k1, k2, k3 ... but since python uses zero-indexing in the code we use k0, k1, k2...
model += (p_airtex*x1 + p[1]*x2 + p[2]*x3) - (A*k[0] + B*k[1] + C*k[2] + Base*k[3]), "total profit"
# Number of platforms produced
model += x1 >= n_orders[0], "minimum units of Airtex"
model += x2 >= n_orders[1], "minimum units of Extendex"
model += x3 >= n_orders[2], "minimum units of Resistex"
# For each kg of each product, the total kg of ingredients must be less or equal to their monthly production
# Polymer A
model += A == x1*w[0]*gpkg[0,0] + x2*w[1]*gpkg[1,0] + x3*w[2] *gpkg[0,2], "kg of Polymer A" # formula for the number of kg of polymer A
model += A <= M[0], "max. production of Polymer A"
# Polymer B
model += B == x1*w[0]*gpkg[0,1] + x2*w[1]*gpkg[1,1] + x3*w[2] *gpkg[1,2], "kg of Polymer B" # formula for the number of kg of polymer B
model += B <= M[1], "max. production of Polymer B"
#Polymer C
model += C == x1*w[0]*gpkg[0,2] + x2*w[1]*gpkg[1,2] + x3*w[2] *gpkg[2,2], "kg of Polymer C" # formula for the number of kg of polymer C
model += C <= M[2], "max. production of Polymer C"
# Base
model += Base == x1*w[0]*gpkg[0,3] + x2*w[1]*gpkg[1,3] + x3*w[2] *gpkg[2,3], "kg of Base" # formula for the number of kg of Base
model += Base <= M[3], "max. production of Base"
# The time in days must be less than 20
# The time in days is equal to the number of units produced divided by 100, plus the calibration time
model += (ct[0]*x1 + ct[1]*x2 + ct[2]*x3) <= total_calibration_time, "max. calibration time"
model += (x1+x2+x3)/units_per_day + (ct[0]*x1 + ct[1]*x2 + ct[2]*x3)/(24*60*60) <= machine_days, "max. days for the machine"
# Let's solve
# solve
model.solve()
# Print
print("Status for machine_days = {0}: {1}".format(machine_days, pulp.LpStatus[model.status]))
total_profit = p[0]*x1.varValue + p[1]*x2.varValue + p[2]*x3.varValue - (A.varValue*k[0] + B.varValue*k[1] + C.varValue*k[2] + Base.varValue*k[3])
total_cost = A.varValue*k[0] + B.varValue*k[1] + C.varValue*k[2] + Base.varValue*k[3]
costs.append(total_cost)
profits.append(total_profit)
# Now, plot
plt.figure()
plt.plot(range(10,21), costs, label = 'Total cost')
plt.plot(range(10,21), profits, label = 'Total profit')
plt.legend()
plt.grid(True)
plt.xlabel('Number of days the machine can work')
plt.ylabel('Cost/Profit ($)')
plt.title('Cost/Profit vs. number of days that the machine can work')
plt.show()
# Question 10
# We set the number max. of units of all platforms (except Airtex) to zero
# We reduce the machine_days and total_calibration_time by half
machine_days = 10
total_calibration_time = (45/2)*60*60
# Set the production of polymers to 10% of their original value
M2 = [x*0.1 for x in M]
# create model
model = pulp.LpProblem(name = "ATLAS", sense = pulp.LpMaximize)
# define the variable
x1 = pulp.LpVariable(name = "units_of_airtex", lowBound = 0, cat = "Integer")
x2 = pulp.LpVariable(name = "units_of_extendex", lowBound = 0, cat = "Integer")
x3 = pulp.LpVariable(name = "units_of_resistex", lowBound = 0, cat = "Integer")
A = pulp.LpVariable(name = "kg of Polymer A", lowBound = 0) # Total kilorams of Polymer A produced
B = pulp.LpVariable(name = "kg of Polymer B", lowBound = 0) # Total kilorams of Polymer B produced
C = pulp.LpVariable(name = "kg of Polymer C", lowBound = 0) # Total kilorams of Polymer C produced
Base = pulp.LpVariable(name = "kg of Base", lowBound = 0) # Total kilorams of Base produced
# Objective function: Max profit
# In the explanation above we used k1, k2, k3 ... but since python uses zero-indexing in the code we use k0, k1, k2...
model += (p[0]*x1 + p[1]*x2 + p[2]*x3) - (A*k[0] + B*k[1] + C*k[2] + Base*k[3]), "total profit"
# Number of platforms produced
model += x1 >= 0, "minimum units of Airtex"
model += x2 == 0, "minimum units of Extendex"
model += x3 == 0, "minimum units of Resistex"
# For each kg of each product, the total kg of ingredients must be less or equal to their monthly production
# Polymer A
model += A == x1*w[0]*gpkg[0,0] + x2*w[1]*gpkg[1,0] + x3*w[2] *gpkg[0,2], "kg of Polymer A" # formula for the number of kg of polymer A
model += A <= M2[0], "max. production of Polymer A"
# Polymer B
model += B == x1*w[0]*gpkg[0,1] + x2*w[1]*gpkg[1,1] + x3*w[2] *gpkg[1,2], "kg of Polymer B" # formula for the number of kg of polymer B
model += B <= M2[1], "max. production of Polymer B"
#Polymer C
model += C == x1*w[0]*gpkg[0,2] + x2*w[1]*gpkg[1,2] + x3*w[2] *gpkg[2,2], "kg of Polymer C" # formula for the number of kg of polymer C
model += C <= M2[2], "max. production of Polymer C"
# Base
model += Base == x1*w[0]*gpkg[0,3] + x2*w[1]*gpkg[1,3] + x3*w[2] *gpkg[2,3], "kg of Base" # formula for the number of kg of Base
model += Base <= M2[3], "max. production of Base"
# The time in days must be less than 20
# The time in days is equal to the number of units produced divided by 100, plus the calibration time
model += (ct[0]*x1 + ct[1]*x2 + ct[2]*x3) <= total_calibration_time, "max. calibration time"
model += (x1+x2+x3)/units_per_day + (ct[0]*x1 + ct[1]*x2 + ct[2]*x3)/(24*60*60) <= machine_days, "max. days for the machine"
# Let's solve
# solve
model.solve()
# Print
print("------------------------------------")
print("Status: " + pulp.LpStatus[model.status])
### Part a)
print("A total of {0:.0f} Airtex platforms are produced".format(x1.varValue))
### Part b)
For this case, we will declare and addditional variable $perc$ that will declare the percentage of production required to produce all platforms platform. This variable $perc$ will vary between 0 and 1.0
Our objective function will be to minimize the percentage production
We will also need an additional constraint that declares the minimum amount of platforms to be produced. That constraint is:
$$x_{1}+x_{2}+x_{3} \geq E$$
# create model
model = pulp.LpProblem(name = "ATLAS", sense = pulp.LpMinimize)
# define the variable
x1 = pulp.LpVariable(name = "units_of_airtex", lowBound = 0, cat = "Integer")
x2 = pulp.LpVariable(name = "units_of_extendex", lowBound = 0, cat = "Integer")
x3 = pulp.LpVariable(name = "units_of_resistex", lowBound = 0, cat = "Integer")
A = pulp.LpVariable(name = "kg of Polymer A", lowBound = 0) # Total kilorams of Polymer A produced
B = pulp.LpVariable(name = "kg of Polymer B", lowBound = 0) # Total kilorams of Polymer B produced
C = pulp.LpVariable(name = "kg of Polymer C", lowBound = 0) # Total kilorams of Polymer C produced
Base = pulp.LpVariable(name = "kg of Base", lowBound = 0) # Total kilorams of Base produced
perc = pulp.LpVariable(name = "Percentage of production", lowBound = 0) # Total kilorams of Base produced
# Objective function: Minimize percentage of production
# In the explanation above we used k1, k2, k3 ... but since python uses zero-indexing in the code we use k0, k1, k2...
model += perc, "Minimum percentage of production"
# Number of platforms produced
model += x1 >= 0, "minimum units of Airtex"
model += x2 >= 0, "minimum units of Extendex"
model += x3 >= 0, "minimum units of Resistex"
# Number of platforms produced
model += (x1+x2+x3) >= M[4], "total platforms"
# Max. percentage
model += perc <= 1.0, "max. percentage of production"
# For each kg of each product, the total kg of ingredients must be less or equal to their monthly production
# Polymer A
model += A == x1*w[0]*gpkg[0,0] + x2*w[1]*gpkg[1,0] + x3*w[2] *gpkg[0,2], "kg of Polymer A" # formula for the number of kg of polymer A
model += A <= perc*M[0], "max. production of Polymer A"
# Polymer B
model += B == x1*w[0]*gpkg[0,1] + x2*w[1]*gpkg[1,1] + x3*w[2] *gpkg[1,2], "kg of Polymer B" # formula for the number of kg of polymer B
model += B <= perc*M[1], "max. production of Polymer B"
#Polymer C
model += C == x1*w[0]*gpkg[0,2] + x2*w[1]*gpkg[1,2] + x3*w[2] *gpkg[2,2], "kg of Polymer C" # formula for the number of kg of polymer C
model += C <= perc*M[2], "max. production of Polymer C"
# Base
model += Base == x1*w[0]*gpkg[0,3] + x2*w[1]*gpkg[1,3] + x3*w[2] *gpkg[2,3], "kg of Base" # formula for the number of kg of Base
model += Base <= perc*M[3], "max. production of Base"
# The time in days must be less than 20
# The time in days is equal to the number of units produced divided by 100, plus the calibration time
model += (ct[0]*x1 + ct[1]*x2 + ct[2]*x3) <= total_calibration_time, "max. calibration time"
model += (x1+x2+x3)/units_per_day + (ct[0]*x1 + ct[1]*x2 + ct[2]*x3)/(24*60*60) <= machine_days, "max. days for the machine"
# Let's solve
# solve
model.solve()
# print
print("The minimum percentage of production required is: {:.2f}%".format(perc.varValue*100.0))