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
四、特点
- 完整实现:M/M/1 排队系统的蒙特卡洛模拟
- 事件驱动:离散事件模拟,高效准确
- 可视化:队列长度变化、等待时间分布、性能对比
- 统计指标:平均等待时间、平均队列长度、服务台利用率
- 置信区间:通过多次模拟计算置信区间
- 误差分析:与理论值对比