排隊論——隨機服務系統模擬精解

郝hai發表於2024-09-20

排隊論作為研究隨機服務系統的重要工具,專門研究系統中客戶到達、排隊、服務和離開的過程。排隊論的核心目的是透過數學建模和分析,研究系統的效能指標,如平均等待時間、佇列長度、系統的吞吐量等。雖然排隊論提供了強大的數學工具來分析隨機服務系統,但在許多複雜的實際問題中,精確的數學模型可能難以建立。這時候,模擬與模擬技術便成為了研究和最佳化系統的重要方法。
模擬是透過計算機程式對一個真實系統進行近似模擬的過程。透過在模擬中引入隨機變數,可以對系統的隨機行為進行研究,從而評估系統在不同條件下的效能表現。模擬不僅可以用於驗證理論模型,還能用於探索無法透過解析方法解決的複雜系統。與排隊論的解析模型不同,模擬與模擬更靈活,可以處理非標準的、複雜的排隊系統。一個典型的應用場景是機場的安檢系統。乘客到達安檢口的時間、安檢速度、安檢通道數量等因素都具有隨機性。透過模擬技術,可以對不同配置方案下的乘客等待時間、系統吞吐量等效能指標進行估計,從而為決策者提供最佳化方案。

單服務檯 多服務檯

一、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

這是一個多通道、分層服務系統,常見於製造或物流場景。

模擬步驟:

  1. 顧客到達:顧客到達系統時可以進入不同的子系統。子系統包含兩個階段,分別透過 ( \mu_r ) 和 ( \mu_b ) 進行服務,之後可能進入下一個階段。
  2. 各階段的服務:根據不同的到達流,顧客在不同階段接受服務,每個階段有不同的服務率。
  3. 服務完畢:最終,顧客在系統中的最後一個節點完成所有服務。
#大模型編寫的程式,沒有驗證,執行沒有問題
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()

總結

隨著大資料、人工智慧、物聯網等技術的發展,隨機服務系統、排隊論與模擬技術的應用前景將更加廣闊。一方面,透過融合大資料分析和機器學習演算法,可以更準確地預測系統中各類隨機事件的發生規律,從而提高系統的效率;另一方面,雲端計算和高效能運算技術的發展,也使得複雜系統的模擬成為可能。模擬與模擬是解決隨機服務系統實際問題的重要工具,透過理論分析和計算機模擬相結合的方式,研究人員和工程師可以最佳化系統的資源配置、提高服務效率,從而應對複雜系統中的隨機性和不確定性。在未來,隨著技術的進步,這些方法將會在更多領域得到廣泛應用,併為各行各業帶來更大的效益。

排隊論——隨機服務系統模擬精解

參考文獻

  1. 排隊模型和排隊系統模擬
  2. 用R語言模擬隨機服務排隊系統
  3. 排隊系統模擬python 排隊系統建模模擬

相關文章