Post

Solving linear programming problems

At work a presentation on an optimization problem was made by researches working in the local hospital. They were looking to minimizing staffing resources given certain variables and constraints.

The field which studies such problems is called Linear Programming (LP). I remember studying this vaguely during my bachelors in industrial engineering, but since then I have forgotten the basics of it.

Consider a case of staffing a hospital. Nurses and doctors are expected to working in shifts, but as the rest of us they too may have personal commitments which have to be taken into consideration when planning for resource planning. Some of them may be specialists in one form of care so they cannot not easily be replaced by others from the resource pool.

Now such problems are where linear programming can be useful.

In the above case, we are trying to maximize resource utilization while considering the dynamic nature of resource availability and skills. We also need to adhere to the constraint of minimum required resources for smooth operations.

A visual representation of components involved in linear programming.


---
title: Components within linear programming
---
stateDiagram-v2 
direction LR
[*]--> Decision_Variables
note left of Decision_Variables
    Output influencing variables
end note
[*]--> Constraints
note left of Constraints
    Defined limitations
end note
Decision_Variables --> Objective_Function 
note right of Objective_Function
    Quantitatively calculable
end note
Constraints --> Objective_Function
Objective_Function -->Optimal_Solution:Linear Solver
note right of Optimal_Solution
    Solution given the other three components
end note
Optimal_Solution -->[*]


In summary, linear programming is used to find an optimal solution given the variables of the system and adhering to the constraints which define the limitations within the system. The end goal is to either maximize or minimize an objective function.

Modules in python

PluP, Docplex, Pyomo and Gekko are some of the well known python modules used to solve linear programming problems.

LP solvers are independent of the python modules, as many LP solvers are openly available and the python modules have built an api over these solvers to make it easier to integrate in python.

Example problems

Solving some problems without external help. I tested my understanding after watching videos to learn the concept. Problem 1 and Problem 2 are credited to Byjus. Although, I am not totally certain about the origin of these questions (may not be a primary source).

Problem 1 - Vitamin blending

A doctor wishes to mix two types of Dishes in such a way that the vitamin contents of the mixture contain at least 8 units of vitamin A and 10 units of vitamin C. Dish 1 contains 2 units/kg of vitamin A and 1 unit/kg of vitamin C. Dish 2 contains 1 unit/kg of vitamin A and 2 units/kg of vitamin C. It costs Kr 50 per kg to purchase Dish 1 and Kr 70 per kg to purchase Dish 2. Formulate this problem as a linear programming problem to minimize the cost of such a mixture

Intuition

Formulating the problem. Before we do that we create a table to make this easier. This video was of good to understand and build an intuition.

 Vitamin A (units)Vitamin C (units)Cost (Kr)
Dish 12150
Dish 21270
Daily need810 

For simplicity Vitamin A = x Vitamin C = y

Variables x, y daily feed in units

Objective function: f(x, y) = 50*x + 70*y –> Minimzation problem

Subject to constraints:

1
2
3
4
2*x + 1*y >= 8
1*x + 2*y >= 10
x >=0
y >= 0

Python implementation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import pulp   

# Creating LP problem
"""
Here we are looking to minimize the cost while getting the enough of vitamin a and c in the diet. This is therefore a minimization LP problem.
"""
vitamin_mix_lp = pulp.LpProblem("vitamin_mix_lp", pulp.LpMinimize)

# Creating LPvariables
x = pulp.LpVariable("Dish 1", lowBound=0, cat='Integer')
y = pulp.LpVariable("Dish 2", lowBound=0, cat='Integer')

# Creating Constraints: Mixture contain at least 8 units of vitamin A and 10 units of vitamin C
vitamin_mix_lp += 2*x + 1*y >=8
vitamin_mix_lp += 1*x + 2*y >= 10
vitamin_mix_lp += x >= 0
vitamin_mix_lp += y >=0

# Creating the objective function: f(x, y) = 50*x + 70*y
vitamin_mix_lp += 50*x + 70*y

# Solving the objective function
solution = vitamin_mix_lp.solve()

# Printing the results and optimal variable values
print("Status:", solution) # 1: Optimal solution exists
print("Optimal Solution Value:", vitamin_mix_lp.objective.value(), "Kr.")
for var in vitamin_mix_lp.variables():
    print(var.name, "=", var.varValue, "units")

Output from the above problem results in 2 units of dish 1 and 4 units of dish 2, which results in the minimum cost of 380 kroner while adhering to the set constraints.

1
2
3
4
Status: 1 (optimal solution exists)
Optimal Solution Value: 380.0 Kr.
Dish_1 = 2.0 units
Dish_2 = 4.0 units

Problem 2 - Bakery case

One kind of cake requires 200g of flour and 25g of fat, and another kind of cake requires 100g of flour and 50g of fat. Formulate this problem as a linear programming problem to find the maximum number of cakes that can be made from 5kg of flour and 1 kg of fat assuming that there is no shortage of the other ingredients used in making the cakes.

Intuition

Formulating the problem. We here are trying maximize the amount of cakes baked given the limited supplies.

 Flour (grams)Fat (grams)
Cake A20025
Cake B10050
Availability50001000

For simplicity Flour = x & Fat = y

Variables x, y in grams

Objective function: f(x, y) = SUM((200*x + 100*y),(25*x + 50*y)) –> Maximization problem

Subject to constraints:

1
2
3
4
200*x + 100*y <= 5000
25*x + 50*y <= 1000
x >=0
y >= 0

Python implementation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import pulp   

# Creating LP problem: Here we are looking to maximize the objective function.
bakery_lp = pulp.LpProblem("bakery_lp", pulp.LpMaximize)

# Creating LPvariables
x = pulp.LpVariable("Cake A", lowBound=0, cat='Integer')
y = pulp.LpVariable("Cake B", lowBound=0, cat='Integer')

# Creating Constraints:number of cakes that can be made from 5kg of flour and 1 kg of fat
bakery_lp += 200*x + 100*y <= 5000
bakery_lp += 25*x + 50*y <= 1000
bakery_lp += x >= 0
bakery_lp += y >=0

# Creating the objective function: f(x, y) = (200*x + 100*y)+(25*x + 50*y)
bakery_lp += (200*x + 100*y)+(25*x + 50*y)

# Solving the objective function
solution = bakery_lp.solve()

# Printing the results and optimal variable values
print("Status:", solution) # 1: Optimal solution exists
print("Optimal Solution Value:", bakery_lp.objective.value())
for var in bakery_lp.variables():
    print(var.name, "=", var.varValue, "units")

Output from the above problem results in 20 units of cake 1 and 10 units of cake 2, which results in the maximum revenue of 6000 kroner while adhering to the set constraints. Totally 30 cakes need to be baked by the baker.

1
2
3
4
Status: 1
Optimal Solution Value: 6000 kr.
Cake_A = 20.0 units
Cake_B = 10.0 units

Problem 3 - Protein intake

This problem is sourced from Brilliant.org

An amateur bodybuilder is looking for supplement protein bars to build his muscle fast, and there are 2 available products: protein bar A and protein bar B. Each protein bar A contains 15 g of protein and 30 g of carbohydrates and has total 200 calories. On the other hand, each protein bar B contains 30 g of protein and 20 g of carbohydrates and has total 240 calories. According to his nutritional plan, this bodybuilder needs at least 20,000 calories from these supplements over the month, which must comprise of at least 1,800 g of protein and at least 2,200 g of carbohydrates. If each protein bar A costs $3 and each protein bar B costs $4, what is the least possible amount of money (in $) he can spend to meet all his one-month requirements?

Intuition

Formulating the problem. We here are trying maximize the amount of cakes baked given the limited supplies.

 Protein (grams)Carbohydrates (grams)CaloriesCost ($)
Protein A15302003
Protein B30202404
Need1800220020000 

For simplicity Protein A = x & Protein B = y

Variables x, y

Objective function: f(x, y) = (3*x + 4*y) –> Minimization problem

Subject to constraints:

1
2
3
4
5
15*x + 30*y >= 1800
30*x + 20*y >= 2200
200*x + 240*y >= 20000
x >= 0
y >= 0

Python implementation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import pulp   

# Creating LP problem: Here we are looking to minimize the objective function.
bodybuilderdiet_lp = pulp.LpProblem("bodybuilderdiet_lp", pulp.LpMinimize)

# Creating LPvariables
x = pulp.LpVariable("Protein", lowBound=0, cat='Integer')
y = pulp.LpVariable("Carbohydrates", lowBound=0, cat='Integer')

# Creating Constraints
bodybuilderdiet_lp += 15*x + 30*y >= 1800
bodybuilderdiet_lp += 30*x + 20*y >= 2200
bodybuilderdiet_lp += 200*x + 240*y >= 20000
bodybuilderdiet_lp += x >= 0
bodybuilderdiet_lp += y >=0

# Creating the objective function: f(x, y) = (3*x + 4*y)
bodybuilderdiet_lp += 3*x + 4*y

# Solving the objective function
solution = bodybuilderdiet_lp.solve()

# Printing the results and optimal variable values
print("Status:", solution) # 1: Optimal solution exists
print("Optimal Solution Value:", bodybuilderdiet_lp.objective.value())
for var in bodybuilderdiet_lp.variables():
    print(var.name, "=", var.varValue, "units")

Output from the above problem results in 25 units of Carbohydrates and 70 units of Protein, which results in the minimum expense of 310 dollars while adhering to the set constraints.

1
2
3
4
Status: 1
Optimal Solution Value: 310.0 $
Carbohydrates = 25.0 units
Protein = 70.0 units

Resources

Here are some of the resources which helped me learn the concepts of linear programming with no specific order.

I enjoyed reading this to dig deeper into the workings of LP: https://www.uky.edu/~dsianita/300/online/LP.pdf

Video tutorials on linear programming

A deep dive into concepts behind linear programming

Using PulP in python

Going forward, when I come across an interesting LP problem, I will update this post. For now, LP was fun learning. I have barely scratched the surface here.

More fun to be had!

This post is licensed under CC BY 4.0 by the author.