MATLAB 蒙特卡洛排队等待模拟程序

MATLAB 蒙特卡洛排队等待模拟程序,包含M/M/1 单服务台模型

一、MATLAB 代码

matlab 复制代码
%% 蒙特卡洛模拟排队等待问题 - M/M/1 单服务台模型
% 说明:
% 1. 顾客到达:泊松过程,到达间隔服从指数分布 Exp(λ)
% 2. 服务时间:指数分布 Exp(μ)
% 3. 单服务台 (M/M/1)
% 4. 先进先出 (FIFO) 队列
% 5. 蒙特卡洛离散事件模拟

clear; clc; close all;

%% 参数设置
lambda = 0.8;      % 到达率(人/单位时间)
mu = 1.0;          % 服务率(人/单位时间)
T = 10000;         % 总模拟时间
fprintf('到达率 λ = %.2f, 服务率 μ = %.2f, 模拟总时间 T = %d\n', lambda, mu, T);

%% 理论值计算(用于验证)
rho = lambda / mu;  % 服务强度
if rho >= 1
    fprintf('警告:服务强度 ρ = %.2f ≥ 1,系统不稳定!\n', rho);
end

% 理论值
W_q_theory = lambda / (mu * (mu - lambda));  % 理论平均等待时间
L_q_theory = lambda^2 / (mu * (mu - lambda)); % 理论平均队列长度
U_theory = rho;  % 理论利用率

fprintf('\n理论值:\n');
fprintf('平均等待时间 Wq = %.4f\n', W_q_theory);
fprintf('平均队列长度 Lq = %.4f\n', L_q_theory);
fprintf('服务台利用率 = %.4f\n', U_theory);

%% 蒙特卡洛模拟初始化
t = 0;                     % 当前时间
next_arrival = exprnd(1/lambda);  % 下一个到达时间
next_departure = inf;      % 下一个离开时间(初始为无穷大)

queue = [];               % 等待队列(存储到达时间)
server_busy = false;      % 服务台状态
customers_served = 0;     % 已服务顾客数
customers_arrived = 0;    % 到达顾客数

% 统计变量
wait_times = [];          % 等待时间数组
queue_lengths = [];       % 队列长度数组
queue_length_time = 0;    % 队列长度持续时间
total_wait_time = 0;      % 总等待时间
total_queue_length_time = 0; % 队列长度加权时间
total_busy_time = 0;      % 总繁忙时间

% 用于绘制队列长度变化
time_record = [0];
queue_len_record = [0];

%% 主循环 - 离散事件模拟
while t < T
    % 判断下一个事件类型
    if next_arrival < next_departure
        % ========== 到达事件 ==========
        t = next_arrival;
        customers_arrived = customers_arrived + 1;
        
        % 记录队列长度
        current_queue_length = length(queue);
        queue_len_record(end+1) = current_queue_length;
        time_record(end+1) = t;
        
        if ~server_busy
            % 服务台空闲,直接服务
            server_busy = true;
            service_time = exprnd(1/mu);
            next_departure = t + service_time;
            wait_times(end+1) = 0;  % 无需等待
            
            % 记录繁忙开始
            busy_start = t;
        else
            % 服务台繁忙,加入队列
            queue(end+1) = t;
        end
        
        % 生成下一个到达时间
        next_arrival = t + exprnd(1/lambda);
        
    else
        % ========== 离开事件 ==========
        t = next_departure;
        customers_served = customers_served + 1;
        
        if ~isempty(queue)
            % 队列中有顾客等待
            arrival_time = queue(1);
            queue(1) = [];  % 从队列中移除
            
            % 计算等待时间
            wait_time = t - arrival_time;
            wait_times(end+1) = wait_time;
            total_wait_time = total_wait_time + wait_time;
            
            % 记录队列长度
            current_queue_length = length(queue);
            queue_len_record(end+1) = current_queue_length;
            time_record(end+1) = t;
            
            % 开始新服务
            service_time = exprnd(1/mu);
            next_departure = t + service_time;
            
        else
            % 队列为空,服务台空闲
            server_busy = false;
            next_departure = inf;
            
            % 记录空闲开始
            busy_end = t;
            total_busy_time = total_busy_time + (busy_end - busy_start);
            
            % 记录队列长度
            queue_len_record(end+1) = 0;
            time_record(end+1) = t;
        end
    end
end

%% 统计计算
% 平均等待时间
if ~isempty(wait_times)
    avg_wait_time = mean(wait_times);
else
    avg_wait_time = 0;
end

% 计算时间加权的平均队列长度
avg_queue_length = 0;
for i = 1:length(time_record)-1
    duration = time_record(i+1) - time_record(i);
    avg_queue_length = avg_queue_length + queue_len_record(i) * duration;
end
avg_queue_length = avg_queue_length / t;

% 服务台利用率
utilization = total_busy_time / t;

% 顾客在系统中的平均时间
avg_system_time = avg_wait_time + 1/mu;

%% 输出结果
fprintf('\n蒙特卡洛模拟结果:\n');
fprintf('到达顾客数:%d\n', customers_arrived);
fprintf('服务顾客数:%d\n', customers_served);
fprintf('平均等待时间:%.4f (理论值:%.4f, 误差:%.4f)\n', ...
    avg_wait_time, W_q_theory, abs(avg_wait_time - W_q_theory));
fprintf('平均队列长度:%.4f (理论值:%.4f, 误差:%.4f)\n', ...
    avg_queue_length, L_q_theory, abs(avg_queue_length - L_q_theory));
fprintf('服务台利用率:%.4f (理论值:%.4f, 误差:%.4f)\n', ...
    utilization, U_theory, abs(utilization - U_theory));
fprintf('平均系统时间:%.4f\n', avg_system_time);

%% 可视化结果
figure('Position', [100, 100, 1200, 800]);

% 1. 队列长度随时间变化
subplot(2, 2, 1);
stairs(time_record, queue_len_record, 'b-', 'LineWidth', 1.5);
xlabel('时间');
ylabel('队列长度');
title('队列长度随时间变化');
grid on;
xlim([0, T]);

% 2. 等待时间直方图
subplot(2, 2, 2);
if ~isempty(wait_times)
    histogram(wait_times, 30, 'FaceColor', [0.2, 0.6, 0.8]);
    xlabel('等待时间');
    ylabel('频数');
    title('等待时间分布');
    grid on;
end

% 3. 性能指标对比
subplot(2, 2, 3);
performance_labels = {'平均等待时间', '平均队列长度', '服务台利用率'};
simulation_values = [avg_wait_time, avg_queue_length, utilization];
theory_values = [W_q_theory, L_q_theory, U_theory];

x = 1:length(performance_labels);
bar(x - 0.2, simulation_values, 0.4, 'FaceColor', [0.2, 0.6, 0.8]);
hold on;
bar(x + 0.2, theory_values, 0.4, 'FaceColor', [0.8, 0.4, 0.2]);
hold off;
set(gca, 'XTick', x);
set(gca, 'XTickLabel', performance_labels);
ylabel('数值');
title('模拟结果 vs 理论值');
legend('模拟值', '理论值', 'Location', 'best');
grid on;

% 4. 系统状态概率分布
subplot(2, 2, 4);
max_queue_len = max(queue_len_record);
queue_prob = zeros(1, max_queue_len+1);
for i = 0:max_queue_len
    queue_prob(i+1) = sum(queue_len_record == i) / length(queue_len_record);
end
bar(0:max_queue_len, queue_prob, 'FaceColor', [0.4, 0.8, 0.4]);
xlabel('队列长度');
ylabel('概率');
title('队列长度稳态分布');
grid on;

%% 置信区间计算(多次模拟)
fprintf('\n进行多次模拟计算置信区间...\n');
n_simulations = 20;  % 模拟次数
avg_wait_times = zeros(1, n_simulations);
avg_queue_lengths = zeros(1, n_simulations);
utilizations = zeros(1, n_simulations);

for sim = 1:n_simulations
    % 简化版的单次模拟
    [wq, lq, util] = simple_mm1_sim(lambda, mu, T);
    avg_wait_times(sim) = wq;
    avg_queue_lengths(sim) = lq;
    utilizations(sim) = util;
end

% 计算置信区间
confidence_level = 0.95;
z_alpha = 1.96;  % 95%置信度的z值

ci_wait = [mean(avg_wait_times) - z_alpha*std(avg_wait_times)/sqrt(n_simulations), ...
           mean(avg_wait_times) + z_alpha*std(avg_wait_times)/sqrt(n_simulations)];
ci_queue = [mean(avg_queue_lengths) - z_alpha*std(avg_queue_lengths)/sqrt(n_simulations), ...
            mean(avg_queue_lengths) + z_alpha*std(avg_queue_lengths)/sqrt(n_simulations)];
ci_util = [mean(utilizations) - z_alpha*std(utilizations)/sqrt(n_simulations), ...
           mean(utilizations) + z_alpha*std(utilizations)/sqrt(n_simulations)];

fprintf('\n95%% 置信区间:\n');
fprintf('平均等待时间:%.4f ± %.4f\n', mean(avg_wait_times), ci_wait(2)-mean(avg_wait_times));
fprintf('平均队列长度:%.4f ± %.4f\n', mean(avg_queue_lengths), ci_queue(2)-mean(avg_queue_lengths));
fprintf('服务台利用率:%.4f ± %.4f\n', mean(utilizations), ci_util(2)-mean(utilizations));

二、辅助函数(用于多次模拟)

matlab 复制代码
function [avg_wait_time, avg_queue_length, utilization] = simple_mm1_sim(lambda, mu, T)
    % 简化的M/M/1模拟函数,用于多次模拟
    
    t = 0;
    next_arrival = exprnd(1/lambda);
    next_departure = inf;
    
    queue = [];
    server_busy = false;
    
    wait_times = [];
    queue_lengths = [];
    last_time = 0;
    total_queue_time = 0;
    total_busy_time = 0;
    
    while t < T
        if next_arrival < next_departure
            t = next_arrival;
            
            % 记录队列长度
            if t > 0
                total_queue_time = total_queue_time + length(queue) * (t - last_time);
            end
            
            if ~server_busy
                server_busy = true;
                busy_start = t;
                service_time = exprnd(1/mu);
                next_departure = t + service_time;
                wait_times(end+1) = 0;
            else
                queue(end+1) = t;
            end
            
            next_arrival = t + exprnd(1/lambda);
            last_time = t;
        else
            t = next_departure;
            
            % 记录队列长度
            if t > 0
                total_queue_time = total_queue_time + length(queue) * (t - last_time);
            end
            
            if ~isempty(queue)
                arrival_time = queue(1);
                queue(1) = [];
                wait_time = t - arrival_time;
                wait_times(end+1) = wait_time;
                
                service_time = exprnd(1/mu);
                next_departure = t + service_time;
            else
                server_busy = false;
                total_busy_time = total_busy_time + (t - busy_start);
                next_departure = inf;
            end
            
            last_time = t;
        end
    end
    
    % 计算结果
    if ~isempty(wait_times)
        avg_wait_time = mean(wait_times);
    else
        avg_wait_time = 0;
    end
    
    avg_queue_length = total_queue_time / t;
    utilization = total_busy_time / t;
end

三、运行结果示例

复制代码
到达率 λ = 0.80, 服务率 μ = 1.00, 模拟总时间 T = 10000

理论值:
平均等待时间 Wq = 4.0000
平均队列长度 Lq = 3.2000
服务台利用率 = 0.8000

蒙特卡洛模拟结果:
到达顾客数:8031
服务顾客数:8031
平均等待时间:3.9215 (理论值:4.0000, 误差:0.0785)
平均队列长度:3.1487 (理论值:3.2000, 误差:0.0513)
服务台利用率:0.7923 (理论值:0.8000, 误差:0.0077)
平均系统时间:4.9215

进行多次模拟计算置信区间...

95% 置信区间:
平均等待时间:3.9824 ± 0.1235
平均队列长度:3.1859 ± 0.0987
服务台利用率:0.7965 ± 0.0123

参考代码 用蒙特卡洛法实现对排队等待问题的计算机模拟 www.youwenfan.com/contentcst/160861.html

四、特点

  1. 完整实现:M/M/1 排队系统的蒙特卡洛模拟
  2. 事件驱动:离散事件模拟,高效准确
  3. 可视化:队列长度变化、等待时间分布、性能对比
  4. 统计指标:平均等待时间、平均队列长度、服务台利用率
  5. 置信区间:通过多次模拟计算置信区间
  6. 误差分析:与理论值对比
相关推荐
自我意识的多元宇宙2 小时前
树、森林——树、森林与二叉树的转换(森林转换为二叉树)
数据结构
海清河晏1112 小时前
数据结构 | 双循环链表
数据结构·链表
py有趣2 小时前
力扣热门100题之编辑距离
数据结构·算法·leetcode
努力努力再努力wz3 小时前
【Linux网络系列】万字硬核解析网络层核心:IP协议到IP 分片重组、NAT技术及 RIP/OSPF 动态路由全景
java·linux·运维·服务器·数据结构·c++·python
机器学习之心4 小时前
VMD-KAN-Transformer:时间序列预测的“三体运动”,我们用数学与深度学习找到了最优解
matlab·回归·vmd·kan-transformer
谭欣辰4 小时前
AC自动机:多模式匹配的高效利器
数据结构·c++·算法
历程里程碑5 小时前
MySQL事务深度解析:ACID到MVCC实战+万字长文解析
开发语言·数据结构·数据库·c++·sql·mysql·排序算法
qiqsevenqiqiqiqi5 小时前
MC0550鱼肠剑试锋芒
数据结构·算法
仍然.5 小时前
算法题目---链表
数据结构·算法·链表