Making Chappie

Try me

Open In ColabBinder

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
[ ]: