排隊論作為研究隨機服務系統的重要工具,專門研究系統中客戶到達、排隊、服務和離開的過程。排隊論的核心目的是透過數學建模和分析,研究系統的效能指標,如平均等待時間、佇列長度、系統的吞吐量等。雖然排隊論提供了強大的數學工具來分析隨機服務系統,但在許多複雜的實際問題中,精確的數學模型可能難以建立。這時候,模擬與模擬技術便成為了研究和最佳化系統的重要方法。
模擬是透過計算機程式對一個真實系統進行近似模擬的過程。透過在模擬中引入隨機變數,可以對系統的隨機行為進行研究,從而評估系統在不同條件下的效能表現。模擬不僅可以用於驗證理論模型,還能用於探索無法透過解析方法解決的複雜系統。與排隊論的解析模型不同,模擬與模擬更靈活,可以處理非標準的、複雜的排隊系統。一個典型的應用場景是機場的安檢系統。乘客到達安檢口的時間、安檢速度、安檢通道數量等因素都具有隨機性。透過模擬技術,可以對不同配置方案下的乘客等待時間、系統吞吐量等效能指標進行估計,從而為決策者提供最佳化方案。
單服務檯 | 多服務檯 |
---|---|
一、Python模擬庫概述
模擬庫名 | 用途 | 概述 | 功能特點 |
---|---|---|---|
SimPy | 離散事件模擬 | 簡單易用的離散事件模擬庫,適合模擬排隊系統、生產線、交通系統等。 | 支援併發程序,簡單易用,適用於大多數離散事件模擬需求。 |
DEAP | 蒙特卡洛模擬、遺傳演算法模擬 | 用於演化計算的庫,適合用於遺傳演算法、遺傳規劃、模擬進化過程、解決最佳化問題等。 | 支援遺傳演算法、演化策略等,支援分散式計算,適合最佳化問題、複雜的決策系統。 |
PyDSTool | 動力學系統模擬 | 適用於連續和混合動力系統模擬的工具庫。 | 支援符號數學和自動微分,適合科學研究和複雜系統的模擬。 |
SALib | 敏感性分析、蒙特卡洛模擬 | 用於敏感性分析的庫,常與蒙特卡洛模擬結合使用。 | 支援全域性和區域性敏感性分析,可以用於評估輸入引數對模型輸出的影響,常與其他模擬庫結合使用。 |
PySim | 系統建模與模擬 | 通用的模擬框架,適合模擬各種物理系統。 | 支援多學科系統模擬,支援FMI標準,適用於複雜的工程模擬需求。 |
AnyLogic | 系統動力學、離散事件、Agent-Based模擬 | 商業化的模擬平臺,提供Python介面來進行定製化模擬。 | 提供Python介面來擴充套件模擬能力,適合大規模工業模擬,可用於供應鏈管理、物流、生產製造等領域。 |
Gym | 強化學習模擬 | 用於強化學習的模擬環境庫。 | 預設了多種模擬環境,適合強化學習和動態系統模擬,靈活的介面,可以自定義模擬環境。 |
Mesa | 基於Agent的模擬 | 基於Agent的模擬框架,適合用於模擬複雜系統中的個體行為和互動。 | 易於使用的API,快速構建多智慧體模型,提供圖形化介面和視覺化工具,適合社會學、經濟學、生態學等領域。 |
二、M/M/1排隊系統模型模擬
2.1 M/M/1排隊系統的績效指標
在M/M/1排隊模型中,系統只有一個服務機構,顧客到達的時間間隔和服務時間都服從指數分佈。透過M/M/1模型,可以計算系統的各項效能指標。下面我們先給出6個常見的效能指標的計算公式,然後提供一個Python程式來計算這些指標。
常用符號
- λ: 到達率(每單位時間內的平均顧客到達數量)
- μ: 服務率(每單位時間內的平均服務數量)
- ρ: 系統的利用率(利用率 = λ/μ)
績效指標及公式
- 系統利用率 \(ρ (ρ = λ/μ)\):系統中伺服器被佔用的比例。
- 系統中平均客戶數 \(L (L = ρ / (1 - ρ))\):系統中的平均客戶數,包括排隊和正在接受服務的客戶。
- 佇列中的平均客戶數 \(L_q (L_q = ρ^2 / (1 - ρ))\):系統中正在排隊的平均客戶數,不包括正在服務的客戶。
- 系統中客戶的平均逗留時間 \(W (W = 1 / (μ - λ))\):系統中每個客戶的平均停留時間,包括等待和服務時間。
- 客戶在佇列中的平均等待時間 \(W_q (W_q = ρ / (μ - λ))\):每個客戶在排隊中等待的平均時間,不包括服務時間。
- 空閒機率 $P_0 (P_0 = 1 - ρ):系統處於空閒狀態(即無客戶到達或正在服務)的機率。
# 定義計算效能指標的函式
def mm1_performance(lmbda, mu):
# 系統利用率 rho
rho = lmbda / mu
if rho >= 1:
raise ValueError("系統利用率不能大於或等於1,說明到達率必須小於服務率。")
# 系統中平均客戶數 L
L = rho / (1 - rho)
# 佇列中的平均客戶數 Lq
Lq = rho**2 / (1 - rho)
# 系統中客戶的平均逗留時間 W
W = 1 / (mu - lmbda)
# 客戶在佇列中的平均等待時間 Wq
Wq = rho / (mu - lmbda)
# 空閒機率 P0
P0 = 1 - rho
# 返回結果
return {
"系統利用率 (rho)": rho,
"系統中平均客戶數 (L)": L,
"佇列中的平均客戶數 (Lq)": Lq,
"系統中客戶的平均逗留時間 (W)": W,
"客戶在佇列中的平均等待時間 (Wq)": Wq,
"空閒機率 (P0)": P0
}
# 固定的到達率和服務率
lmbda = 3 # 到達率 λ
mu = 5 # 服務率 μ
# 計算並輸出各個效能指標,保留兩位小數
try:
performance = mm1_performance(lmbda, mu)
for key, value in performance.items():
print(f"{key}: {value:.2f}")
except ValueError as e:
print(e)
系統利用率 (rho): 0.60
系統中平均客戶數 (L): 1.50
佇列中的平均客戶數 (Lq): 0.90
系統中客戶的平均逗留時間 (W): 0.50
客戶在佇列中的平均等待時間 (Wq): 0.30
空閒機率 (P0): 0.40
2.2 M/M/1排隊系統模擬分析
import simpy
import random
import matplotlib.pyplot as plt
from matplotlib import rcParams
# 設定中文字型
rcParams['font.sans-serif'] = ['SimHei'] # 使用黑體
rcParams['axes.unicode_minus'] = False # 正常顯示負號
# 設定種子以確保模擬結果的可重複性
RANDOM_SEED = 42
random.seed(RANDOM_SEED)
# 定義全域性變數
lmbda = 3 # 到達率 λ (每單位時間的顧客到達數)
mu = 5 # 服務率 μ (每單位時間的服務能力)
SIM_TIME = 1000 # 模擬執行時間
class MM1Queue:
def __init__(self, env, mu):
self.env = env
self.server = simpy.Resource(env, capacity=1) # 1表示單個伺服器
self.mu = mu
self.total_waiting_time = 0.0
self.total_system_time = 0.0
self.total_customers = 0
self.system_size = 0 # 系統中顧客人數
self.time_data = [] # 時間點
self.size_data = [] # 系統中顧客人數
def serve(self, customer):
"""顧客服務時間"""
yield self.env.timeout(random.expovariate(self.mu))
def arrival(self, customer):
"""顧客到達"""
arrival_time = self.env.now
self.system_size += 1 # 系統中顧客人數 +1
self.record_data() # 記錄當前時刻的顧客人數
with self.server.request() as request:
yield request # 等待服務
waiting_time = self.env.now - arrival_time # 計算等待時間
self.total_waiting_time += waiting_time
self.total_customers += 1
yield self.env.process(self.serve(customer)) # 開始服務
self.system_size -= 1 # 系統中顧客人數 -1
self.record_data() # 記錄當前時刻的顧客人數
# 計算系統內停留時間
system_time = self.env.now - arrival_time
self.total_system_time += system_time
def record_data(self):
"""記錄當前模擬時間和系統中顧客人數"""
self.time_data.append(self.env.now)
self.size_data.append(self.system_size)
def run(self):
"""顧客不斷到達"""
customer_id = 0
while True:
yield self.env.timeout(random.expovariate(lmbda)) # 顧客到達時間間隔
customer_id += 1
self.env.process(self.arrival(customer_id))
def simulate_mm1():
# 初始化環境
env = simpy.Environment()
mm1_queue = MM1Queue(env, mu)
# 執行模擬
env.process(mm1_queue.run())
env.run(until=SIM_TIME)
# 計算系統效能指標
L = mm1_queue.total_system_time / SIM_TIME # 系統中平均客戶數
Lq = mm1_queue.total_waiting_time / SIM_TIME # 佇列中的平均客戶數
W = mm1_queue.total_system_time / mm1_queue.total_customers # 系統中客戶的平均逗留時間
Wq = mm1_queue.total_waiting_time / mm1_queue.total_customers # 客戶在佇列中的平均等待時間
# 輸出結果
print(f"系統中平均客戶數 (L): {L:.2f}")
print(f"佇列中的平均客戶數 (Lq): {Lq:.2f}")
print(f"系統中客戶的平均逗留時間 (W): {W:.2f}")
print(f"客戶在佇列中的平均等待時間 (Wq): {Wq:.2f}")
# 繪製時間-顧客人數曲線圖
plt.plot(mm1_queue.time_data, mm1_queue.size_data)
plt.xlabel('模擬時間')
plt.ylabel('系統中顧客人數')
plt.title('M/M/1 排隊系統模擬')
plt.grid(True)
plt.show()
# 執行模擬並輸出結果
simulate_mm1()
系統中平均客戶數 (L): 1.59
佇列中的平均客戶數 (Lq): 1.00
系統中客戶的平均逗留時間 (W): 0.54
客戶在佇列中的平均等待時間 (Wq): 0.34
三、M/M/c排隊系統模擬分析
3.1 M/M/c排隊系統的績效指標
對於 M/M/c 系統,常見的6個效能指標及其計算公式如下:
常用符號
- λ: 到達率(每單位時間內的平均顧客到達數量)
- μ: 服務率(每單位時間內的平均服務數量)
- c: 為服務檯的數量
績效指標及公式
- 系統利用率 $ \rho(\rho = \frac{\lambda}{c\mu} $):表示系統的平均工作負荷,或是所有服務檯的平均佔用率。
- 佇列中的平均顧客數 \(L_q(L_q = \frac{P_0 (\lambda/\mu)^c \rho}{c! (1 - \rho)^2})\):表示在佇列中等待服務的平均顧客數量。這裡,\(P_0\) 是系統空閒時的機率。
- 系統中平均顧客數 $L(L = L_q + \frac{\lambda}{\mu} $):表示在整個系統(包括正在接受服務的顧客)中的平均顧客數量。
- 顧客在佇列中的平均等待時間 $ W_q (W_q = \frac{L_q}{\lambda} $):表示顧客在佇列中等待服務的平均時間。
- 顧客在系統中的平均逗留時間 $ W ( W = W_q + \frac{1}{\mu} $):表示顧客在整個系統中(包括服務時間)的平均逗留時間。
- 系統空閒的機率 $ P_0( P_0 = \left[ \sum_{n=0}^{c-1} \frac{(\lambda/\mu)^n}{n!} + \frac{(\lambda/\mu)^c}{c!(1 - \rho)} \right]^{-1} $):表示系統中沒有顧客時的機率,即所有服務檯均空閒的機率。
import math
# 輸入資料
lmbda = 0.9 # 到達率 λ (人/分鐘)
mu = 0.4 # 服務率 μ (人/分鐘)
c = 3 # 售票視窗數
# 系統利用率 ρ
rho = lmbda / (c * mu)
# 計算 P0 (系統空閒的機率)
def calculate_P0(lmbda, mu, c):
sum_terms = sum((lmbda / mu) ** n / math.factorial(n) for n in range(c))
last_term = ((lmbda / mu) ** c) / (math.factorial(c) * (1 - rho))
P0 = 1 / (sum_terms + last_term)
return P0
# 計算 Lq (佇列中的平均顧客數)
def calculate_Lq(lmbda, mu, c, rho, P0):
numerator = P0 * (lmbda / mu) ** c * rho
denominator = math.factorial(c) * (1 - rho) ** 2
Lq = numerator / denominator
return Lq
# 計算各項指標
P0 = calculate_P0(lmbda, mu, c) # 系統空閒的機率
Lq = calculate_Lq(lmbda, mu, c, rho, P0) # 佇列中的平均顧客數
L = Lq + lmbda / mu # 系統中平均顧客數
Wq = Lq / lmbda # 顧客在佇列中的平均等待時間
W = Wq + 1 / mu # 顧客在系統中的平均逗留時間
# 輸出結果
print(f"系統利用率 (ρ): {rho:.2f}")
print(f"系統空閒的機率 (P0): {P0:.4f}")
print(f"佇列中的平均顧客數 (Lq): {Lq:.2f}")
print(f"系統中平均顧客數 (L): {L:.2f}")
print(f"顧客在佇列中的平均等待時間 (Wq): {Wq:.2f} 分鐘")
print(f"顧客在系統中的平均逗留時間 (W): {W:.2f} 分鐘")
3.2 M/M/c排隊系統模擬分析
import simpy
import random
import matplotlib.pyplot as plt
from matplotlib import rcParams
# 設定中文字型支援
rcParams['font.sans-serif'] = ['SimHei'] # 使用黑體顯示中文
rcParams['axes.unicode_minus'] = False # 解決負號顯示問題
# 輸入資料
RANDOM_SEED = 42
lmbda = 0.9 # 到達率 λ (人/分鐘)
mu = 0.4 # 服務率 μ (人/分鐘)
c = 3 # 售票視窗數
SIM_TIME = 1000 # 模擬時間(分鐘)
random.seed(RANDOM_SEED)
class MMcQueue:
def __init__(self, env, num_servers, mu):
self.env = env
self.server = simpy.Resource(env, capacity=num_servers)
self.mu = mu
self.total_waiting_time = 0.0
self.total_system_time = 0.0
self.total_customers = 0
self.customers_in_queue = 0
self.queue_time = 0.0
self.system_customers = []
# 記錄模擬過程中各時刻的系統內顧客人數
self.time_data = []
self.num_customers_data = []
def serve(self, customer):
"""服務過程,顧客服務時間"""
service_time = random.expovariate(self.mu)
yield self.env.timeout(service_time)
def arrival(self, customer):
"""顧客到達"""
arrival_time = self.env.now
self.system_customers.append(len(self.server.queue) + len(self.server.users))
# 記錄當前時刻的顧客人數
self.record_customers_count()
# 顧客加入佇列
with self.server.request() as request:
yield request
waiting_time = self.env.now - arrival_time # 計算顧客等待時間
self.total_waiting_time += waiting_time
self.queue_time += len(self.server.queue)
self.total_customers += 1
# 開始服務
yield self.env.process(self.serve(customer))
# 系統內停留時間 = 當前時間 - 到達時間
system_time = self.env.now - arrival_time
self.total_system_time += system_time
# 記錄當前時刻的顧客人數
self.record_customers_count()
def record_customers_count(self):
"""記錄當前模擬時刻的系統內顧客人數"""
current_time = self.env.now
num_customers = len(self.server.queue) + len(self.server.users)
self.time_data.append(current_time)
self.num_customers_data.append(num_customers)
def run_simulation(env, num_servers, mu):
mmc_queue = MMcQueue(env, num_servers, mu)
def customer_arrivals():
customer_id = 0
while True:
# 顧客到達時間
inter_arrival_time = random.expovariate(lmbda)
yield env.timeout(inter_arrival_time)
customer_id += 1
env.process(mmc_queue.arrival(customer_id))
# 啟動顧客到達過程
env.process(customer_arrivals())
# 執行模擬
env.run(until=SIM_TIME)
# 計算系統效能指標
Lq = mmc_queue.total_waiting_time / SIM_TIME # 佇列中的平均顧客數
L = sum(mmc_queue.system_customers) / len(mmc_queue.system_customers) # 系統中平均顧客數
Wq = mmc_queue.total_waiting_time / mmc_queue.total_customers # 顧客在佇列中的平均等待時間
W = mmc_queue.total_system_time / mmc_queue.total_customers # 顧客在系統中的平均逗留時間
# 輸出結果
print(f"佇列中的平均顧客數 (Lq): {Lq:.2f}")
print(f"系統中平均顧客數 (L): {L:.2f}")
print(f"顧客在佇列中的平均等待時間 (Wq): {Wq:.2f} 分鐘")
print(f"顧客在系統中的平均逗留時間 (W): {W:.2f} 分鐘")
# 繪製時間-顧客人數曲線圖
plt.figure(figsize=(10, 6))
plt.plot(mmc_queue.time_data, mmc_queue.num_customers_data, label='系統內顧客人數', color='b')
plt.xlabel('模擬時間(分鐘)')
plt.ylabel('系統內顧客人數')
plt.title('M/M/3 排隊系統中各時刻的顧客人數')
plt.grid(True)
plt.legend()
plt.show()
# 執行模擬
env = simpy.Environment()
run_simulation(env, c, mu)
四、複雜排隊系統模擬
複雜排隊系統結構
這是一個多階段、並行處理的排隊模型,包含多個服務檯多個服務節點。具體而言,系統包含多個佇列和不同的服務率\(\mu\),包括:
\(\mu_r = 10\)\mu_b = 13 \mu_1 = 12 \mu_2 = 9 \mu_3 = 16
這是一個多通道、分層服務系統,常見於製造或物流場景。
模擬步驟:
- 顧客到達:顧客到達系統時可以進入不同的子系統。子系統包含兩個階段,分別透過 ( \mu_r ) 和 ( \mu_b ) 進行服務,之後可能進入下一個階段。
- 各階段的服務:根據不同的到達流,顧客在不同階段接受服務,每個階段有不同的服務率。
- 服務完畢:最終,顧客在系統中的最後一個節點完成所有服務。
#大模型編寫的程式,沒有驗證,執行沒有問題
import simpy
import random
import matplotlib.pyplot as plt
# 設定系統的服務率
mu_r = 10 # 紅色佇列服務率
mu_b = 13 # 藍色佇列服務率
mu1 = 12 # 第一個階段服務率 (2個服務檯)
mu2 = 9 # 第二個階段服務率 (3個服務檯)
mu3 = 16 # 第三個階段服務率 (3個服務檯)
SIM_TIME = 1000 # 模擬時間(分鐘)
# 隨機數種子
RANDOM_SEED = 42
random.seed(RANDOM_SEED)
class ComplexQueueSystem:
def __init__(self, env):
self.env = env
# 定義各個服務資源,設定相應的服務檯數量
self.server_r = simpy.Resource(env, capacity=1) # 紅色佇列1個服務檯
self.server_b = simpy.Resource(env, capacity=1) # 藍色佇列1個服務檯
self.server1 = simpy.Resource(env, capacity=2) # 階段1有2個服務檯
self.server2 = simpy.Resource(env, capacity=3) # 階段2有3個服務檯
self.server3 = simpy.Resource(env, capacity=3) # 階段3有3個服務檯
# 統計資料
self.total_waiting_time = 0
self.total_system_time = 0
self.total_customers = 0
self.customers_in_queue = 0
self.system_customers = []
def serve(self, mu):
"""服務過程,服務時間服從負指數分佈"""
service_time = random.expovariate(mu)
yield self.env.timeout(service_time)
def process_customer(self, customer):
arrival_time = self.env.now
# 顧客進入紅色或藍色佇列
if random.choice(['red', 'blue']) == 'red':
with self.server_r.request() as request:
yield request
yield self.env.process(self.serve(mu_r))
else:
with self.server_b.request() as request:
yield request
yield self.env.process(self.serve(mu_b))
# 第一個服務階段
with self.server1.request() as request:
yield request
yield self.env.process(self.serve(mu1))
# 第二個服務階段
with self.server2.request() as request:
yield request
yield self.env.process(self.serve(mu2))
# 第三個服務階段
with self.server3.request() as request:
yield request
yield self.env.process(self.serve(mu3))
# 計算總的系統停留時間
system_time = self.env.now - arrival_time
self.total_system_time += system_time
# 統計顧客總數
self.total_customers += 1
def customer_arrival(env, system, arrival_rate):
"""顧客到達過程,泊松到達"""
while True:
yield env.timeout(random.expovariate(arrival_rate))
customer_id = system.total_customers + 1
env.process(system.process_customer(customer_id))
def run_simulation():
env = simpy.Environment()
system = ComplexQueueSystem(env)
# 顧客到達率
arrival_rate = 5 # 每單位時間到達顧客數
# 啟動顧客到達過程
env.process(customer_arrival(env, system, arrival_rate))
# 執行模擬
env.run(until=SIM_TIME)
# 計算指標
L = system.total_system_time / SIM_TIME # 系統中的平均顧客數
W = system.total_system_time / system.total_customers # 顧客在系統中的平均逗留時間
print(f"系統中平均顧客數 (L): {L:.2f}")
print(f"顧客在系統中的平均逗留時間 (W): {W:.2f} 分鐘")
# 執行模擬
run_simulation()
總結
隨著大資料、人工智慧、物聯網等技術的發展,隨機服務系統、排隊論與模擬技術的應用前景將更加廣闊。一方面,透過融合大資料分析和機器學習演算法,可以更準確地預測系統中各類隨機事件的發生規律,從而提高系統的效率;另一方面,雲端計算和高效能運算技術的發展,也使得複雜系統的模擬成為可能。模擬與模擬是解決隨機服務系統實際問題的重要工具,透過理論分析和計算機模擬相結合的方式,研究人員和工程師可以最佳化系統的資源配置、提高服務效率,從而應對複雜系統中的隨機性和不確定性。在未來,隨著技術的進步,這些方法將會在更多領域得到廣泛應用,併為各行各業帶來更大的效益。
參考文獻
- 排隊模型和排隊系統模擬
- 用R語言模擬隨機服務排隊系統
- 排隊系統模擬python 排隊系統建模模擬