Making Chappie¶
Try me¶
Problem definition¶
The company Tetravaal located in Johannesburg manufactures two types of robots, Model \(P_{1}\) and Model \(P_{2}\). The production plant is consisted of four different sections: metal machining, plastic moulding, electrical work and assembly. The metal machining section has a capacity of 7500 units of \(P_{1}\) or 6000 units of \(P_{2}\) per month.
Plastic moulding can process 5000 units of \(P_{1}\) or 9000 units of \(P_{2}\) per month.
Electrical work can process 6000 units of \(P_{1}\) or 7000 units of \(P_{2}\) per month.
In Assembly, there are two assembly lines that work in parallel, one per each robot model.
The first assembly line can process 4000 units of \(P_{1}\) per month
The second assembly line can process 5000 units of \(P_{2}\) per month
Knowing that the unitary profit of \(P_{1}\) is 500€ and that the unitary profit of \(P_{2}\) is 600€, and that both robots have a great demand and therefore all manufactured robots are sold, Michelle Bradley, CEO of Tetravaal, asks his engineering team:
Calculate the number of units of each robot that needs to be manufactured to maximise profit for the company.
Model¶
We want to maximise the company profits:
\(\max z = 500x_{1} + 600x_{2}\)
where z represents the profits (€). The decision variables are:
\(x_{1}:\) units of \(P_{1}\) per month \(x_{2}:\) units of \(P_{2}\) per month
The objective function is subject to the following constraints:
\(x_{1}/7500+x_{2}/6000 \leq 1\) Metal machining constraint
\(x_{1}/5000+x_{2}/9000 \leq 1\) Plastic moulding constraint
\(x_{1}/6000 + x_{2}/7000 \leq 1\) Electrical work constraint
\(x_{1} \leq 4000\) First assembly line constraint
\(x_{2} \leq 5000\) Second assembly line constraint
Solution using PuLP¶
[1]:
import pandas as pd
import numpy as np
from IPython.display import display, Markdown
import pulp
model = pulp.LpProblem("Maximising profits for Tetravaal", pulp.LpMaximize)
variable_names = ['P1', 'P2']
variables = pulp.LpVariable.dicts("Units per month",
(i for i in variable_names),
lowBound=0,
cat='Continuous')
coefficients = [500, 600]
# Objective function
model += (
pulp.lpSum([
coefficients[i] * variables[variable_names[i]]
for i in range(len(variable_names))])
), "Profit"
# And the constraints, the Matrix A
A=[[1/7500, 1/6000], #Coefficients of the first constraint
[1/5000, 1/9000], #Coefficients of the second constraint
[1/6000, 1/7000],
[1/4000, 0], #Coefficients of the second constraint
[0, 1/5000]] #Coefficients of the third constraint
A = A
# And vector b
b = [1, 1, 1, 1, 1] #limits of the three constraints
constraint_names = ['Metal machining', 'Plastic moulding', 'Electrical work', 'Assembly 1', 'Assembly 2']
# Constraints
for i in range(len(A)):
model += pulp.lpSum([
A[i][j] * variables[variable_names[j]]
for j in range(len(variable_names))]) <= b[i] , constraint_names[i]
# Solve our problem
model.solve()
pulp.LpStatus[model.status]
C:\Users\franc\PycharmProjects\operations-research-notebooks\venv\Lib\site-packages\pulp\pulp.py:1316: UserWarning: Spaces are not permitted in the name. Converted to '_'
warnings.warn("Spaces are not permitted in the name. Converted to '_'")
[1]:
'Optimal'
[2]:
total_profit = pulp.value(model.objective)
display(Markdown("Total profit is %0.2f €"%total_profit))
display(Markdown("The following table shows the decision variables: "))
var_df = pd.DataFrame.from_dict(variables, orient="index",
columns = ["Variables"])
# First we add the solution. We apply a lambda function to get only two decimals:
var_df["Solution"] = var_df["Variables"].apply(lambda item: item.varValue)
# We do the same for the reduced cost:
var_df["Reduced cost"] = var_df["Variables"].apply(lambda item: item.dj)
display(var_df)
const_dict = dict(model.constraints)
con_df = pd.DataFrame.from_records(list(const_dict.items()), exclude=["Expression"], columns=["Constraint", "Expression"])
#Now we add columns for the solution, the slack and shadow price
con_df["Right Hand Side"] = con_df["Constraint"].apply(lambda item: -const_dict[item].constant)
con_df["Slack"] = con_df["Constraint"].apply(lambda item: const_dict[item].slack)
con_df["Shadow Price"] = con_df["Constraint"].apply(lambda item: const_dict[item].pi)
display(Markdown("The following table shows the constraints: "))
display(con_df)
Total profit is 3654545.43 €
The following table shows the decision variables:
| Variables | Solution | Reduced cost | |
|---|---|---|---|
| P1 | Units_per_month_P1 | 2727.2727 | 0.000000e+00 |
| P2 | Units_per_month_P2 | 3818.1818 | -6.394885e-14 |
The following table shows the constraints:
| Constraint | Right Hand Side | Slack | Shadow Price | |
|---|---|---|---|---|
| 0 | Metal_machining | 1.0 | -0.000000 | 3272727.30 |
| 1 | Plastic_moulding | 1.0 | 0.030303 | -0.00 |
| 2 | Electrical_work | 1.0 | -0.000000 | 381818.18 |
| 3 | Assembly_1 | 1.0 | 0.318182 | -0.00 |
| 4 | Assembly_2 | 1.0 | 0.236364 | -0.00 |
[ ]:

