Single server queue (M/M/1) is a fundamental concept in queuing theory, which studies the behavior of waiting lines or queues. In a single-server queue, there is only one server that processes incoming customers or tasks. The key components of a single-server queue include:
Arrival Process: This describes how customers arrive at the queue. It is often modeled using a Poisson process, where arrivals occur randomly over time.
Service Process: This describes how the server processes customers. The service times are often modeled using an exponential distribution, where the time taken to serve each customer is random but has a known average rate.
Performance Metrics: Key performance metrics for a single-server queue include:
Average delay in queue (dn)
Average number of customers in the queue (ǭn)
Proportion of time the server is busy (ມ)
Event List¶
# Static Arrival and Service time
Arrival = [0.4, 1.2, 0.5, 1.7, 0.2, 1.6, 0.2, 1.4, 1.9]
Service = [2.0, 0.7, 0.2, 1.1, 3.7, 0.6]
ServiceNum = len(Service)
# Random Arrival and Service time
# Exponential random interarrival and service times
# mean = 1 / lambda -> lambda = 1 / mean
# import random
# mean_interarrival = 1.0
# mean_service = 0.8
# Arrival = [round(random.expovariate(1 / mean_interarrival), 2) for _ in range(1000)]
# Service = [round(random.expovariate(1 / mean_service), 2) for _ in range(1000)]
# ServiceNum = len(Service)Initialization of States¶
# System state variables
server_status = 0 # 0 means idle, 1 means busy
number_in_queue = 0
times_of_arrival = []
time_of_last_event = 0.0
clock = 0.0
event_list_arrival = 0.0
event_list_departure = 0.0
# Statistical counters
number_delayed = 0
total_delay = 0.0
area_under_q = 0.0
area_under_b = 0.0
# Plotting variables
queue_times = [] # (time, number_in_queue)
server_status_times = [] # (time, server_status)Logic¶
import math
def handle_arrival():
global server_status, number_in_queue, total_delay, number_delayed, event_list_departure, clock, area_under_b, area_under_q
area_under_b += server_status * (clock - time_of_last_event)
area_under_q += number_in_queue * (clock - time_of_last_event)
if server_status == 0:
number_delayed += 1
server_status = 1
event_list_departure = clock + Service.pop(0)
else:
number_in_queue += 1
times_of_arrival.append(clock)
def handle_departure():
global server_status, number_in_queue, total_delay, number_delayed, event_list_arrival, event_list_departure, clock, area_under_b, area_under_q
area_under_b += server_status * (clock - time_of_last_event)
area_under_q += number_in_queue * (clock - time_of_last_event)
if number_in_queue == 0:
server_status = 0
event_list_departure = math.inf
else:
number_in_queue -= 1
delay = clock - times_of_arrival.pop(0)
total_delay += delay
number_delayed += 1
event_list_departure = clock + Service.pop(0)
def event_handler():
global clock, event_list_arrival, event_list_departure, time_of_last_event, queue_times, server_status_times
queue_times.append((clock, number_in_queue))
server_status_times.append((clock, server_status))
if not event_list_arrival and not event_list_departure:
event_list_arrival = clock + Arrival.pop(0) if Arrival else 0.0
time_of_last_event = clock
clock += event_list_arrival if Arrival else 0.0
return clock
if event_list_arrival and (not event_list_departure or event_list_arrival <= event_list_departure):
time_of_last_event = clock
clock = event_list_arrival
event_list_arrival = clock + Arrival.pop(0) if Arrival else 0.0
# Handle arrival event
handle_arrival()
else:
time_of_last_event = clock
clock = event_list_departure
# Handle departure event
handle_departure()
# queue_times.append((clock, number_in_queue))
iteration = 1
while number_delayed < ServiceNum:
event_handler()
print("-" * 100)
print(f"Iteration: {iteration}")
print("Clock:", clock)
print("Event List Arrival:", event_list_arrival)
print("Event List Departure:", event_list_departure)
print("Server Status:", server_status)
print("Number in Queue:", number_in_queue)
print("Times of Arrival:", times_of_arrival)
print("Number Delayed:", number_delayed)
print("Total Delay:", total_delay)
print("Area Under Q:", area_under_q)
print("Area Under B:", area_under_b)
iteration += 1----------------------------------------------------------------------------------------------------
Iteration: 1
Clock: 0.4
Event List Arrival: 0.4
Event List Departure: 0.0
Server Status: 0
Number in Queue: 0
Times of Arrival: []
Number Delayed: 0
Total Delay: 0.0
Area Under Q: 0.0
Area Under B: 0.0
----------------------------------------------------------------------------------------------------
Iteration: 2
Clock: 0.4
Event List Arrival: 1.6
Event List Departure: 2.4
Server Status: 1
Number in Queue: 0
Times of Arrival: []
Number Delayed: 1
Total Delay: 0.0
Area Under Q: 0.0
Area Under B: 0.0
----------------------------------------------------------------------------------------------------
Iteration: 3
Clock: 1.6
Event List Arrival: 2.1
Event List Departure: 2.4
Server Status: 1
Number in Queue: 1
Times of Arrival: [1.6]
Number Delayed: 1
Total Delay: 0.0
Area Under Q: 0.0
Area Under B: 1.2000000000000002
----------------------------------------------------------------------------------------------------
Iteration: 4
Clock: 2.1
Event List Arrival: 3.8
Event List Departure: 2.4
Server Status: 1
Number in Queue: 2
Times of Arrival: [1.6, 2.1]
Number Delayed: 1
Total Delay: 0.0
Area Under Q: 0.5
Area Under B: 1.7000000000000002
----------------------------------------------------------------------------------------------------
Iteration: 5
Clock: 2.4
Event List Arrival: 3.8
Event List Departure: 3.0999999999999996
Server Status: 1
Number in Queue: 1
Times of Arrival: [2.1]
Number Delayed: 2
Total Delay: 0.7999999999999998
Area Under Q: 1.0999999999999996
Area Under B: 2.0
----------------------------------------------------------------------------------------------------
Iteration: 6
Clock: 3.0999999999999996
Event List Arrival: 3.8
Event List Departure: 3.3
Server Status: 1
Number in Queue: 0
Times of Arrival: []
Number Delayed: 3
Total Delay: 1.7999999999999994
Area Under Q: 1.7999999999999994
Area Under B: 2.6999999999999997
----------------------------------------------------------------------------------------------------
Iteration: 7
Clock: 3.3
Event List Arrival: 3.8
Event List Departure: inf
Server Status: 0
Number in Queue: 0
Times of Arrival: []
Number Delayed: 3
Total Delay: 1.7999999999999994
Area Under Q: 1.7999999999999994
Area Under B: 2.9
----------------------------------------------------------------------------------------------------
Iteration: 8
Clock: 3.8
Event List Arrival: 4.0
Event List Departure: 4.9
Server Status: 1
Number in Queue: 0
Times of Arrival: []
Number Delayed: 4
Total Delay: 1.7999999999999994
Area Under Q: 1.7999999999999994
Area Under B: 2.9
----------------------------------------------------------------------------------------------------
Iteration: 9
Clock: 4.0
Event List Arrival: 5.6
Event List Departure: 4.9
Server Status: 1
Number in Queue: 1
Times of Arrival: [4.0]
Number Delayed: 4
Total Delay: 1.7999999999999994
Area Under Q: 1.7999999999999994
Area Under B: 3.1
----------------------------------------------------------------------------------------------------
Iteration: 10
Clock: 4.9
Event List Arrival: 5.6
Event List Departure: 8.600000000000001
Server Status: 1
Number in Queue: 0
Times of Arrival: []
Number Delayed: 5
Total Delay: 2.6999999999999997
Area Under Q: 2.6999999999999997
Area Under B: 4.0
----------------------------------------------------------------------------------------------------
Iteration: 11
Clock: 5.6
Event List Arrival: 5.8
Event List Departure: 8.600000000000001
Server Status: 1
Number in Queue: 1
Times of Arrival: [5.6]
Number Delayed: 5
Total Delay: 2.6999999999999997
Area Under Q: 2.6999999999999997
Area Under B: 4.699999999999999
----------------------------------------------------------------------------------------------------
Iteration: 12
Clock: 5.8
Event List Arrival: 7.199999999999999
Event List Departure: 8.600000000000001
Server Status: 1
Number in Queue: 2
Times of Arrival: [5.6, 5.8]
Number Delayed: 5
Total Delay: 2.6999999999999997
Area Under Q: 2.9
Area Under B: 4.8999999999999995
----------------------------------------------------------------------------------------------------
Iteration: 13
Clock: 7.199999999999999
Event List Arrival: 9.1
Event List Departure: 8.600000000000001
Server Status: 1
Number in Queue: 3
Times of Arrival: [5.6, 5.8, 7.199999999999999]
Number Delayed: 5
Total Delay: 2.6999999999999997
Area Under Q: 5.699999999999999
Area Under B: 6.299999999999999
----------------------------------------------------------------------------------------------------
Iteration: 14
Clock: 8.600000000000001
Event List Arrival: 9.1
Event List Departure: 9.200000000000001
Server Status: 1
Number in Queue: 2
Times of Arrival: [5.8, 7.199999999999999]
Number Delayed: 6
Total Delay: 5.700000000000001
Area Under Q: 9.900000000000006
Area Under B: 7.700000000000001
Report¶
print("Single-server Queueing System Simulation Results")
print("-" * 100)
print("Mean interarrival time:", clock / number_delayed)
print("Mean service time:", abs((clock - total_delay) / number_delayed))
print("Number of Customers:", number_delayed)
print()
print("Average Delay in Queue:", total_delay / number_delayed)
print("Average Number in Queue:", area_under_q / clock)
print("Server Utilization:", area_under_b / clock)
print("Time Simulation Ended:", clock)Single-server Queueing System Simulation Results
----------------------------------------------------------------------------------------------------
Mean interarrival time: 1.4333333333333336
Mean service time: 0.4833333333333334
Number of Customers: 6
Average Delay in Queue: 0.9500000000000002
Average Number in Queue: 1.151162790697675
Server Utilization: 0.8953488372093023
Time Simulation Ended: 8.600000000000001
import matplotlib.pyplot as plt
times, queue_lengths = zip(*queue_times)
plt.step(times, queue_lengths, where='post')
plt.xlabel('Time')
plt.ylabel('Number in Queue')
plt.title('Single-server Queue Length Over Time')
plt.grid()
times_b, server_statuses = zip(*server_status_times)
plt.figure()
plt.step(times_b, server_statuses, where='post')
plt.xlabel('Time')
plt.ylabel('Server Status (0=Idle, 1=Busy)')
plt.title('Single-server Server Status Over Time')
plt.grid()