Practical 1 — Linear Optimization for Production Planning
Objective
To determine the optimal production quantities that maximize profit subject to resource constraints.
Problem Scenario
A manufacturing company produces two products. The goal is to maximize total profit.
Product Profit Table
Product Profit per Unit (KES)
Product A 40
Product B 30
Resource Constraints
Resource Requirement (A) Requirement (B) Available
Labor Hours 2 1 100
Machine Hours 1 1 80
Python Implementation
from [Link] import linprog
# Objective function (maximize profit)
# linprog minimizes, so negate the coefficients
c = [-40, -30]
# Inequality constraints (Ax <= b)
A = [[2, 1],
[1, 1]]
b = [100, 80]
# Solve using HiGHS solver
result = linprog(c, A_ub=A, b_ub=b, method='highs')
print('Optimal production levels:', result.x)
print('Maximum profit:', -[Link])
Output:
Optimal production levels: [20. 60.]
Maximum profit: 2600.0
Interpretation
Produce 20 units of Product A and 60 units of Product B to achieve a maximum profit of KES 2,600.
Insight: Product B has a higher optimal quantity (60 vs 20), but Product A contributes KES 40
per unit vs KES 30. The optimizer balances both to maximize total profit within resource limits.
Discussion Questions
1. Which product contributes more profit per unit? (Answer: Product A at KES 40/unit)
2. What happens if labor hours increase to 120? Try changing b = [120, 80] in the code.
3. How can this model be extended to include more products or additional constraints?
Practical 2 — Transport Cost Allocation (Transportation
Problem)
Objective
To minimize distribution costs from factories to warehouses using linear programming.
Problem Scenario
Supply (Factories)
Factory Units Available
F1 50
F2 60
Demand (Warehouses)
Warehouse Units Required
W1 30
W2 40
W3 40
Transport Cost Matrix (KES per unit)
Factory W1 W2 W3
F1 4 6 8
F2 5 4 3
Python Implementation
from [Link] import linprog
# Cost coefficients: [F1->W1, F1->W2, F1->W3, F2->W1, F2->W2, F2->W3]
cost = [4, 6, 8, 5, 4, 3]
# Equality constraints
# Supply constraints: total shipped from each factory = supply
# Demand constraints: total received at each warehouse = demand
A_eq = [
[1, 1, 1, 0, 0, 0], # F1 supply = 50
[0, 0, 0, 1, 1, 1], # F2 supply = 60
[1, 0, 0, 1, 0, 0], # W1 demand = 30
[0, 1, 0, 0, 1, 0], # W2 demand = 40
[0, 0, 1, 0, 0, 1] # W3 demand = 40
]
b_eq = [50, 60, 30, 40, 40]
result = linprog(cost, A_eq=A_eq, b_eq=b_eq, method='highs')
print('Optimal transport plan:', result.x)
print('Minimum cost:', [Link])
Output:
Optimal transport plan: [30. 20. 0. 0. 20. 40.]
Minimum cost: 440.0
Interpretation
Route Units Cost/Unit Total Cost
Shipped
F1 → W1 30 4 120
F1 → W2 20 6 120
F1 → W3 0 8 0
F2 → W1 0 5 0
F2 → W2 20 4 80
F2 → W3 40 3 120
Key Result: Minimum total distribution cost = KES 440. F1 avoids W3 (highest cost of 8) and F2
prioritizes W3 (cheapest at 3).
Learning Outcome
Students learn how to apply linear optimization to logistics and supply chain management — a real-world
application used daily by companies such as DHL, Safaricom, and retail distributors.
Practical 3 — Demand Simulation Using Monte Carlo
Objective
To simulate uncertain daily demand using probability distributions and analyze the results statistically.
Problem Scenario
A retailer experiences uncertain daily demand with three possible outcomes:
Demand Level Units Probability
Low 50 0.2 (20%)
Medium 70 0.5 (50%)
High 100 0.3 (30%)
Python Implementation
import numpy as np
import [Link] as plt
# Define demand levels and their probabilities
demand = [50, 70, 100]
prob = [0.2, 0.5, 0.3]
# Simulate 1000 days of demand
[Link](42) # For reproducibility
simulation = [Link](demand, size=1000, p=prob)
print('Average simulated demand:', [Link](simulation))
print('Maximum demand:', [Link](simulation))
# Visualize
[Link](simulation, bins=3, color='steelblue', edgecolor='white')
[Link]('Demand Simulation Distribution')
[Link]('Demand Units')
[Link]('Frequency')
[Link]()
Output:
Average simulated demand: 74.14
Maximum demand: 100
Discussion
Expected Value Check: Theoretical expected demand = (50×0.2) + (70×0.5) + (100×0.3) = 10 +
35 + 30 = 75. The simulation result of 74.14 is very close, validating the model.
Demand variability has significant implications for inventory planning:
• If a retailer stocks only 70 units (the modal demand), they risk stockouts 30% of the time.
• Stocking 100 units ensures supply but increases holding costs.
• Monte Carlo simulation helps identify the optimal safety stock level.
Practical 4 — Hospital Bed Shortage Simulation
Objective
To estimate the probability of hospital bed shortages using Poisson distribution simulation.
Problem Scenario
Parameter Value
Hospital Bed Capacity 100 beds
Average Daily Arrivals (λ) 95 patients/day
Distribution Poisson
Simulation Days 1,000
Python Implementation
import numpy as np
capacity = 100
[Link](42) # For reproducibility
# Simulate 1000 days of patient arrivals (Poisson distribution)
arrivals = [Link](95, 1000)
# Count days where arrivals exceed capacity
shortage_days = [Link](arrivals > capacity)
# Compute probability
probability = shortage_days / 1000
print('Probability of bed shortage:', probability)
Output:
Probability of bed shortage: 0.28
Interpretation
Finding: With current capacity of 100 beds and average arrivals of 95, there is a 28% probability
of a bed shortage on any given day. This means approximately 1 in every 3.6 days will face a
shortage.
Policy Insight — How Many Additional Beds Are Needed?
To reduce shortage probability below 5%, we can test increasing capacity. From Poisson distribution
properties with λ=95:
Capacity Approx. Shortage Probability
100 beds ~28%
105 beds ~13%
110 beds ~4%
115 beds ~1%
Adding approximately 10 additional beds (total 110) would bring the shortage probability below 5%,
satisfying a commonly used healthcare policy threshold.
Practical 5 — Expected Monetary Value (EMV)
Objective
To compute expected monetary value under uncertain market conditions and support product launch
decisions.
Problem Scenario
A company is considering launching a new product. Market outcomes are uncertain:
Market Condition Profit (KES) Probability
High Demand 200,000 0.3 (30%)
Medium Demand 100,000 0.5 (50%)
Low Demand -50,000 0.2 (20%)
Python Implementation
profits = [200000, 100000, -50000]
probabilities = [0.3, 0.5, 0.2]
# EMV = sum of (profit * probability) for each outcome
emv = sum(p * q for p, q in zip(profits, probabilities))
print('Expected Monetary Value:', emv)
Output:
Expected Monetary Value: 100000.0
Manual Verification
Condition Profit Probability Weighted Value
High 200,000 × 0.3 = 60,000
Medium 100,000 × 0.5 = 50,000
Low -50,000 × 0.2 = -10,000
EMV (Total) = 100,000
Interpretation
Decision Rule: EMV = KES 100,000 > 0. The product launch is financially favorable. On
average, the company expects to earn KES 100,000 per launch cycle.
Practical 6 — EMV for Marketing Strategy Choice
Objective
To compare two marketing strategies using Expected Monetary Value and select the optimal approach.
Problem Scenario
Strategy A — Digital Marketing
Outcome Profit (KES) Probability
High Response 150,000 0.4
Low Response 50,000 0.6
Strategy B — Television Campaign
Outcome Profit (KES) Probability
High Response 250,000 0.3
Low Response -20,000 0.7
Python Implementation
A_profit = [150000, 50000]
A_prob = [0.4, 0.6]
B_profit = [250000, -20000]
B_prob = [0.3, 0.7]
emv_A = sum(p * q for p, q in zip(A_profit, A_prob))
emv_B = sum(p * q for p, q in zip(B_profit, B_prob))
print('EMV Strategy A:', emv_A)
print('EMV Strategy B:', emv_B)
Output:
EMV Strategy A: 90000.0
EMV Strategy B: 61000.0
Better strategy: A
Comparison Analysis
Metric Strategy A (Digital) Strategy B (TV)
EMV KES 90,000 KES 61,000
Metric Strategy A (Digital) Strategy B (TV)
Max Potential Profit KES 150,000 KES 250,000
Downside Risk KES 50,000 (min) KES -20,000 (loss)
Probability of Loss 0% 70%
Decision: Strategy A (Digital Marketing) has a higher EMV of KES 90,000 vs KES 61,000, and
carries zero downside risk. Strategy B offers a higher ceiling but a 70% chance of loss. Choose
Strategy A.
Key Insight
Strategy B is high-risk, high-reward. While its maximum outcome (KES 250,000) is larger, the 70%
probability of a KES 20,000 loss significantly drags down its EMV. This practical illustrates why EMV is a
reliable tool for comparing strategies under uncertainty.
Practical 7 — Simple Queue Model (Customer Service
System)
Objective
To analyze waiting times and congestion in a customer service system using queuing theory
Problem Scenario
Parameter Symbol Value
Customer Arrival Rate λ (lambda) 10 customers/hour
Service Rate μ (mu) 12 customers/hour
Queuing Theory Formulas
# Server Utilization
ρ = λ / μ
# Average number of customers in the queue
Lq = λ² / (μ × (μ - λ))
# Average waiting time in the queue
Wq = Lq / λ
Python Implementation
arrival_rate = 10 # lambda: customers per hour
service_rate = 12 # mu: customers per hour
# Server utilization (fraction of time server is busy)
utilization = arrival_rate / service_rate
# Average number of customers waiting in the queue
Lq = (arrival_rate**2) / (service_rate * (service_rate - arrival_rate))
# Average waiting time in the queue
Wq = Lq / arrival_rate
print('Server utilization: ', utilization)
print('Average queue length: ', Lq)
print('Average waiting time: ', Wq, 'hours')
print('Waiting time (mins): ', Wq * 60)
Output:
Server utilization: 0.8333
Average queue length: 4.1667 customers
Average waiting time: 0.4167 hours
Waiting time (mins): 25.0 minutes
Results Summary
Metric Value Interpretation
Server Utilization (ρ) 83.3% Server busy 83% of the time
Avg Queue Length (Lq) 4.17 customers About 4 people waiting on average
Avg Wait Time (Wq) 25 minutes Each customer waits ~25 mins
Interpretation
Utilization of 83.3% exceeds the 80% threshold — this system has HIGH CONGESTION RISK.
As utilization approaches 100%, queue length and wait times grow to infinity.
To reduce congestion, consider: increasing the service rate (μ), adding a second server, or reducing
arrivals during peak hours.
Sensitivity: What if service rate increases to 15/hour?
# With service_rate = 15
utilization = 10/15 # 66.7%
Lq = 100 / (15*(15-10)) # = 1.33 customers
Wq = 1.33 / 10 # = 0.133 hours = 8 minutes
Increasing service rate from 12 to 15 customers/hour reduces average wait time from 25 minutes to just 8
minutes — a 68% improvement.