+1 (315) 557-6473 

Python Program to Create Production Planning Details Assignment Solution.


Objective

Write a python assignment program to create production planning details in python.

Requirements and Specifications

Production Planning Details
Hindle Hifi make acoustic isolation hifi platforms out of a revolutionary mix of hi-tech polymers. They manufacture three different densities of the platforms, depending on the type of hifi equipment the platform will be placed underneath. The Extendex and Resistex platforms weigh 1kg each, but the Airtex is lighter at 500 grams. All the polymers, including the base polymer, are produced in-house by Hindle Hifi.
Airtex (a light platform for CD players, streamers and other digital source equipment)
Extendex (a heavier platform for amplifiers and solid-state equipment)
Resistex (a harder platform for mono-blocks, speakers and subwoofers)
All three products require the same four ingredients – three special proprietary chemical polymers and a standard base. Everything is made on-site. The amounts of each ingredient are given in below:

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

  1. What is the expected cost of supplying exactly the confirmed orders next month?
  2. What is the expected profit associated with the confirmed orders next month?
  3. 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?
  4. 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.]

  5. What would the maximum profit be, and how many of the three platforms should they make?
  6. 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?
  7. 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?
  8. 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?
  9. 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.
  10. 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.
  11. 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.
  12. 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.
    1. How many Airtex platforms can be made under these reduced production conditions?
    2. 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?

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))