In this report, we simulate a sequential, two-stage queuing system in a bank setting, with a single reception desk and a single bank employee. Customers must visit the reception first, followed by the bank employee for further assistance. By assessing performance metrics, we aim to validate the system’s functionality and effectiveness when dealing with single-stage services. This simulation offers valuable insights for similar real-world scenarios in the service industry.
Arrival Time: The Poisson distribution is used to model the arrival of customers, as it represents the number of independent events occurring at a constant average rate (λ) during the specified time frame (open to close times).
Reception Service Time (ST): We chose the Exponential distribution because it’s commonly used to model service times when the length of service is random and independent of other factors. Its parameter of 1/5 ensures values between 1 and 6, simulating the varying time customers might spend at the reception.
Bank Employee Service Time (ST2): The Normal distribution is suitable for modeling service times when the values cluster around a central mean value (in this case, 10 minutes), with a standard deviation of 2, accounting for variations in service time. Values between 5 and 20 minutes reflect the time range customers might spend with a bank employee.
Overall,these distributions help simulate a realistic bank scenario by capturing the randomness in customer arrivals and service times while considering the varying levels of support customers require.
set.seed(111)
openTime <- 7 * 60
closeTime <- 18 * 60
peakTime <- 13 * 60
numCustomers <- 20
# function for AT using poison dist with lambda = peakTime
AT=Filter(function(x) x >= openTime & x <= closeTime, round(rpois(numCustomers, lambda = peakTime)))
TSB = c()
TCW= c()
TSE=c()
# function for ST reception using exponential dist with rate = 1/5, values btw 1 and 6 mins
generate_ST <- function(numCustomers) {
ST <- round(rexp(numCustomers, rate = 1/5))
ST <- ST[ST >= 1 & ST <= 6]
while (length(ST) < numCustomers) {
additional <- round(rexp(numCustomers - length(ST), rate = 1/5))
ST <- c(ST, additional[additional >= 1 & additional <= 6])
}
return(head(ST, numCustomers))
}
ST <- generate_ST(numCustomers)
for (i in 1:length(AT)) {
TSB[i]= max(AT[i],TSE[i-1])
TSE[i]= TSB[i]+ST[i]
TCW[i]= abs(TSB[i]-AT[i])
}
AT2 = TSE
TCB2 = c()
TCW2=c()
TSE2=c()
ST2=c()
TSS=c()
# function for ST reception using normal dist with mean=10, values btw 5 and 20 mins
ST2= Filter(function(x) x >= 5 & x <= 20, round(rnorm(numCustomers, mean = 10, sd = 2)))
for (i in 1:length(AT2)) {
TCB2[i]= max(TSE2[i-1],AT2[i])
TCW2[i]= TCB2[i]-AT2[i]
TSE2[i]= TCB2[i]+ST2[i]
TSS[i]= TSE2[i]-AT[i]
}
data.frame(AT,ST,TSB,TCW,TSE,TCB2,TCW2,ST2,TSE2,TSS)
## AT ST TSB TCW TSE TCB2 TCW2 ST2 TSE2 TSS
## 1 786 1 786 0 787 787 0 9 796 10
## 2 770 5 787 17 792 796 4 14 810 40
## 3 774 3 792 18 795 810 15 11 821 47
## 4 775 4 795 20 799 821 22 13 834 59
## 5 786 5 799 13 804 834 30 11 845 59
## 6 733 4 804 71 808 845 37 12 857 124
## 7 753 2 808 55 810 857 47 11 868 115
## 8 788 4 810 22 814 868 54 11 879 91
## 9 764 6 814 50 820 879 59 11 890 126
## 10 831 2 831 0 833 890 57 10 900 69
## 11 791 2 833 42 835 900 65 14 914 123
## 12 802 3 835 33 838 914 76 8 922 120
## 13 736 1 838 102 839 922 83 11 933 197
## 14 777 2 839 62 841 933 92 13 946 169
## 15 746 2 841 95 843 946 103 6 952 206
## 16 804 6 843 39 849 952 103 10 962 158
## 17 767 1 849 82 850 962 112 10 972 205
## 18 785 1 850 65 851 972 121 12 984 199
## 19 775 1 851 76 852 984 132 12 996 221
## 20 802 1 852 50 853 996 143 7 1003 201
# histogram of (AT)
hist(AT, breaks = 20, col = "skyblue", main = "Distribution of arrival times", xlab = "Arrival Time (minutes)")
total_time_span <- closeTime - openTime
# Calculate arrival rate
arrival_rate <- length(AT) / total_time_span
# Display arrival rate
print(paste("Arrival Rate:", arrival_rate, "customers per minute"))
## [1] "Arrival Rate: 0.0303030303030303 customers per minute"
A visualization showcases the distribution of customer arrivals at the bank throughout its operating hours, with a peak occurring between approximately 12:50pm (770) and 1:25pm (805)
# Set up the plotting layout
par(mfrow = c(1, 2))
# ST Reception
dotchart(table(ST), main = "Service Times for Reception", xlab = "Frequency", pch = 19, col = "lightgreen")
## Warning in dotchart(table(ST), main = "Service Times for Reception", xlab =
## "Frequency", : 'x' is neither a vector nor a matrix: using as.numeric(x)
# ST Bank Employee
dotchart(table(ST2), main = "Service Times for Bank Employee", xlab = "Frequency", pch = 19, col = "lightpink")
## Warning in dotchart(table(ST2), main = "Service Times for Bank Employee", : 'x'
## is neither a vector nor a matrix: using as.numeric(x)
this dotplot illustrates the frequency distribution of service times for both reception and bank employee.
for the Service time (reception): it is observed that the most common service times are 1 and 2 mins,with 1 being recorded 6 times and 2 being recorded 5 times. the service times of 3,4,5 and 6mins are recorded fewer than 4 times each, indicating less frequent occurrences compared to shorter service times.
for the Service time (bank employee):The most common service time is 11mins recorded 6 times,followed by service times of 12 and 10mins, each recorded 3 times.The remaining values vary between 1 and 2mins indicating shorter service times that are less common
df <- data.frame(
Customer = 1:numCustomers,
Wait_Time_Reception = TCW,
Wait_Time_Bank_Employee = TCW2
)
library('ggplot2')
## Warning: package 'ggplot2' was built under R version 4.3.2
ggplot(df, aes(x = Customer)) +
geom_line(aes(y =Wait_Time_Reception,color ="Reception")) +
geom_line(aes(y =Wait_Time_Bank_Employee,color ="Bank Employee")) +
scale_color_manual(values= c("Reception" ="blue","Bank Employee"= "red")) +
labs(title ="Customer wait times comparison",
x = "Customer",
y = "Wait Time (minutes)",
color = "Service") +
theme_minimal()
It’s clear from the graph that the waiting time for the bank employee is noticeably greater than the waiting time before being served by the reception, which is logically consistent with most banking scenarios.
cat("number of customers who had to wait (Reception):", sum(TCW!=0), "\n")# reception
## number of customers who had to wait (Reception): 18
cat("number of customers who had to wait (Bank Employee):", sum(TCW2!=0), "\n")#bank employee
## number of customers who had to wait (Bank Employee): 19
Out of 20 total customers, 19 had to wait both at the reception and before being served by a bank employee. This emphasizes the common experience of waiting times in the banking process
cat("Average waiting time (Reception):", mean(TCW), "\n")# reception
## Average waiting time (Reception): 45.6
cat("Average waiting time (Bank Employee):", mean(TCW2), "\n")#bank employee
## Average waiting time (Bank Employee): 67.75
The average waiting time at the reception is approximately 45.6mins about 3/4 of an hour before receiving assistance.,while the average waiting time before being served by a bank employee is approximately 67.75mins which mean more than an hour before receiving service from the bank employee
waiting times of over an hour are generally not considered reasonable for most banking scenario. While some complexities in services or high customer traffic may contribute to longer waiting times, average waiting times exceeding an hour could indicate inefficiencies in the queuing system or staffing levels.
# Calculate server utilization
rec_util <- sum(ST)/ (max(TSE)- min(AT)) #reception
emp_util <- sum(ST2) / (max(TSE2) - min(AT2)) #bank employee
cat("Reception Utilization:", rec_util, "\n")
## Reception Utilization: 0.4666667
cat("Employee Utilization:", emp_util, "\n")
## Employee Utilization: 1
Reception Utilization: The reception is utilized at approximately 81%, meaning that it is effectively utilized for 81% of the total available time. This indicates that there is some idle time at the reception, suggesting potential capacity for additional customer service or tasks.
Employee Utilization: The bank employee is fully utilized 100%, indicating that there is no idle time during the operating hours. While full utilization might seem efficient, it could also indicate potential overloading of the bank employee, which might lead to longer waiting times or decreased service quality.