排队论经典程序MM1代码
- 格式:doc
- 大小:115.00 KB
- 文档页数:30
分组到达时间不是独立和指数分布的,而是一群一群地到达的(即分组有成群的特性)。
而用户发起访问某种网络资源的行为具有独立、随机的泊松特性,即会话到达过程仍服从泊松分布。
通常,网络性能评估的第一步是先进行理论上的评估,而这需要以一种较好的分析模型和分析方法为基础。
被广泛应用的排队论模型是用于分析网络性能最经典的理论之一。
其中,
M/M/1模型是分析分组交换网络性能的主要模型。
当使用M/M/1排队论模型分析网络性能时,
每个资源的利用率ρ=λ/μ,其中λ表示单位时间内到达的分组数,μ表示该资源单位时间内能够完成的分组数;每个处理中的平均分组数l=ρ/(1-ρ)= λ/(λ-μ);
平均系统时间S=1/(μ-λ);
每个处理的平均等待时间W=ρ/(μ-λ)
从这些计算各种性能指标的公可知,对结果影响最大的参数是分组平均到达率λ。
mm1n排队论模型参数
M/M/1 排队论模型是一种简单的排队系统模型,用于分析单一服务台、顾客到达服从泊松分布、服务时间服从指数分布的系统。
在M/M/1 模型中,有三个主要参数:
1. 到达率(λ):表示单位时间内到达系统的顾客数的期望值,服从参数为λ的泊松分布。
到达率决定了系统中的顾客数量变化速率。
2. 服务率(μ):表示单位时间内一个顾客被服务完成的期望值,服从参数为μ的指数分布。
服务率决定了系统中顾客等待服务的速度。
3. 顾客到达和服务时间是独立的:这个条件表明顾客的到达和服务的完成之间没有影响,使得模型更具有现实意义。
通过平衡方程法,可以对M/M/1 模型进行稳态分析,计算出以下几个重要性质:
1. 队长(Ls):表示系统中的顾客数(n)的期望值。
2. 排队长(Lq):表示系统中排队等待服务的顾客数(n)的期望值。
3. 逗留时间(Ws):指一个顾客在系统中的全部停留时间,为期望值。
4. 等待时间(Wq):指顾客在系统中等待服务的時間,为期望值。
了解这些参数后,可以对M/M/1 模型进行评估和优化,以提高系统的效率和服务质量。
M/M/1 模型虽然简单,但在实际应用中具有广泛的价值,如电话交换系统、计算机网络、银行窗口等。
掌握M/M/1 模型的基本原理和分析方法对于学习排队论和实际应用具有重要意义。
M/M/1排队系统实验报告一、实验目的本次实验要求实现M/M/1单窗口无限排队系统的系统仿真,利用事件调度法实现离散事件系统仿真,并统计平均队列长度以及平均等待时间等值,以与理论分析结果进行对比。
二、实验原理根据排队论的知识我们知道,排队系统的分类是根据该系统中的顾客到达模式、服务模式、服务员数量以及服务规则等因素决定的。
1、 顾客到达模式设到达过程是一个参数为λ的Poisson 过程,则长度为t 的时间内到达k 个呼叫的概率 服从Poisson 分布,即etkk k t t p λλ-=!)()(,⋅⋅⋅⋅⋅⋅⋅⋅⋅=,2,1,0k ,其中λ>0为一常数,表示了平均到达率或Poisson 呼叫流的强度。
2、 服务模式设每个呼叫的持续时间为i τ,服从参数为μ的负指数分布,即其分布函数为{}1,0t P X t e t μ-<=-≥3、 服务规则先进先服务的规则(FIFO ) 4、 理论分析结果在该M/M/1系统中,设λρμ=,则稳态时的平均等待队长为1Q ρλρ=-,顾客的平均等待时间为T ρμλ=-。
三、实验内容M/M/1排队系统:实现了当顾客到达分布服从负指数分布,系统服务时间也服从负指数分布,单服务台系统,单队排队,按FIFO (先入先出队列)方式服务。
四、采用的语言MatLab 语言 源代码:clear; clc;%M/M/1排队系统仿真SimTotal=input('请输入仿真顾客总数SimTotal='); %仿真顾客总数;Lambda=0.4; %到达率Lambda;Mu=0.9; %服务率Mu;t_Arrive=zeros(1,SimTotal);t_Leave=zeros(1,SimTotal);ArriveNum=zeros(1,SimTotal);LeaveNum=zeros(1,SimTotal);Interval_Arrive=-log(rand(1,SimTotal))/Lambda;%到达时间间隔Interval_Serve=-log(rand(1,SimTotal))/Mu;%服务时间t_Arrive(1)=Interval_Arrive(1);%顾客到达时间ArriveNum(1)=1;for i=2:SimTotalt_Arrive(i)=t_Arrive(i-1)+Interval_Arrive(i);ArriveNum(i)=i;endt_Leave(1)=t_Arrive(1)+Interval_Serve(1);%顾客离开时间LeaveNum(1)=1;for i=2:SimTotalif t_Leave(i-1)<t_Arrive(i)t_Leave(i)=t_Arrive(i)+Interval_Serve(i);elset_Leave(i)=t_Leave(i-1)+Interval_Serve(i);endLeaveNum(i)=i;endt_Wait=t_Leave-t_Arrive; %各顾客在系统中的等待时间t_Wait_avg=mean(t_Wait);t_Queue=t_Wait-Interval_Serve;%各顾客在系统中的排队时间t_Queue_avg=mean(t_Queue);Timepoint=[t_Arrive,t_Leave];%系统中顾客数随时间的变化Timepoint=sort(Timepoint);ArriveFlag=zeros(size(Timepoint));%到达时间标志CusNum=zeros(size(Timepoint));temp=2;CusNum(1)=1;for i=2:length(Timepoint)if (temp<=length(t_Arrive))&&(Timepoint(i)==t_Arrive(temp)) CusNum(i)=CusNum(i-1)+1;temp=temp+1;ArriveFlag(i)=1;elseCusNum(i)=CusNum(i-1)-1;endend%系统中平均顾客数计算Time_interval=zeros(size(Timepoint));Time_interval(1)=t_Arrive(1);for i=2:length(Timepoint)Time_interval(i)=Timepoint(i)-Timepoint(i-1);endCusNum_fromStart=[0 CusNum];CusNum_avg=sum(CusNum_fromStart.*[Time_interval 0] )/Timepoint(end);QueLength=zeros(size(CusNum));for i=1:length(CusNum)if CusNum(i)>=2QueLength(i)=CusNum(i)-1;elseQueLength(i)=0;endendQueLength_avg=sum([0 QueLength].*[Time_interval 0] )/Timepoint(end);%系统平均等待队长%仿真图figure(1);set(1,'position',[0,0,1000,700]);subplot(2,2,1);title('各顾客到达时间和离去时间');stairs([0 ArriveNum],[0 t_Arrive],'b');hold on;stairs([0 LeaveNum],[0 t_Leave],'y');legend('到达时间','离去时间');hold off;subplot(2,2,2);stairs(Timepoint,CusNum,'b')title('系统等待队长分布');xlabel('时间');ylabel('队长');subplot(2,2,3);title('各顾客在系统中的排队时间和等待时间');stairs([0 ArriveNum],[0 t_Queue],'b');hold on;stairs([0 LeaveNum],[0 t_Wait],'y');hold off;legend('排队时间','等待时间');%仿真值与理论值比较disp(['理论平均等待时间t_Wait_avg=',num2str(1/(Mu-Lambda))]);disp(['理论平均排队时间t_Wait_avg=',num2str(Lambda/(Mu*(Mu-Lambda)))]);disp(['理论系统中平均顾客数=',num2str(Lambda/(Mu-Lambda))]);disp(['理论系统中平均等待队长=',num2str(Lambda*Lambda/(Mu*(Mu-Lambda)))]);disp(['仿真平均等待时间t_Wait_avg=',num2str(t_Wait_avg)])disp(['仿真平均排队时间t_Queue_avg=',num2str(t_Queue_avg)])disp(['仿真系统中平均顾客数=',num2str(CusNum_avg)]);disp(['仿真系统中平均等待队长=',num2str(QueLength_avg)]);五、数据结构1.仿真设计算法(主要函数)利用负指数分布与泊松过程的关系,产生符合泊松过程的顾客流,产生符合负指数分布的随机变量作为每个顾客的服务时间:Interval_Arrive=-log(rand(1,SimTotal))/Lambda;%到达时间间隔,结果与调用exprnd(1/Lambda,m)函数产生的结果相同Interval_Serve=-log(rand(1,SimTotal))/Mu;%服务时间间隔t_Arrive(1)=Interval_Arrive(1);%顾客到达时间时间计算t_Wait=t_Leave-t_Arrive;%各顾客在系统中的等待时间t_Queue=t_Wait-Interval_Serve; %各顾客在系统中的排队时间由事件来触发仿真时钟的不断推进。
修理店仿真报告一.问题:①修理店空闲的概率;②店内有三个顾客的概率;③店内至少有一个顾客的概率;④在店内顾客的平均数;⑤顾客在店内的平均逗留时间;⑥顾客必须在店内消耗15分钟以上的概率。
二.求解问题的方法:①修理店空闲的概率:(sim_time-area_server_status) / sim_time);②店内有三个顾客的概率:area_3_in_q/sim_time);③店内至少有一个顾客的概率:abv_1/sim_time);④在店内顾客的平均数:area_num_in_h/sim_time);⑤顾客在店内的平均逗留时间:(total_of_delays+total_of_server)/ num_custs_delayed );⑥顾客必须在店内消耗15分钟以上概率:abv_15/num_custs_delayed);三。
求解过程中计算统计量的方法:①area_server_status += server_status * time_since_last_event;②//店内有三个顾客的概率if(server_status == BUSY)//服务台忙,则有队列中有两个顾客if(num_in_q == 2)area_3_in_q += time_since_last_event;③//店内至少有一个顾客的概率if(server_status == BUSY) //服务台忙,则店内至少有一个顾客abv_1 += time_since_last_event;④//在店内顾客的平均数if(server_status == BUSY) //服务台忙,总的顾客数为排队顾客数加一area_num_in_h += (num_in_q+1) * time_since_last_event;⑤total_of_server += time_next_event[2]-sim_time;//总的服务时间加一个服务时间为新的服务总时间delay = sim_time - time_arrival[1];//排队时间=当前时间-这个人来的时间total_of_delays += delay;⑥//离开时总的消耗时间大于15,必须在店内消耗15分钟以上的顾客数加一if((delay+time_next_event[2]-sim_time)>15)abv_15++;//到达时总的服务时间大于15,必须在店内消耗15分钟以上的顾客数加一if((time_next_event[2]-sim_time)>15)abv_15++;程序代码:/* External definitions for single-server queueing system. */#include <stdio.h>#include <math.h>/*#include "lcgrand.h" Header file for random-number generator. */#define Q_LIMIT 100 /* Limit on queue length.队伍最长100人*/ #define BUSY 1 /* Mnemonics for server's being busy 忙碌状态*/#define IDLE 0 /* and idle.空闲状态*/int next_event_type, //下一个事件类型num_custs_delayed, //已模拟的顾客数num_delays_required, //模拟的顾客数num_events,//事件数num_in_q, //队列中的顾客数server_status;//服务状态float area_num_in_q,//有顾客的时间area_server_status,//总的服务时间mean_interarrival,//平均顾客到达时间间隔mean_service,//平均服务时间sim_time, //模拟时间time_arrival[Q_LIMIT + 1], //到来的时间time_last_event, //上一个事件的时间time_next_event[3],//下一个事件的时间total_of_delays; //总的排队时间//////////////////////////////////////////////////////////////////////////////////////添加的变量float abv_15, //15分钟以上的顾客数量total_of_server, //所有顾客的总的服务时间area_3_in_q, //有3个顾客的时间abv_1, //至少有一个顾客的时间area_num_in_h; //顾客总数////////////////////////////////////////////////////////////////////////////////////FILE *infile, *outfile;/* The following 3 declarations are for use of the random-number generatorlcgrand and the associated functions lcgrandst and lcgrandgt for seed management. This file (named lcgrand.h) should be included in anyprogramusing these functions by executing #include "lcgrand.h"before referencing the functions. */float lcgrand(int stream);void lcgrandst(long zset, int stream); long lcgrandgt(int stream);void initialize(void);void timing(void);void arrive(void);void depart(void);void report(void);void update_time_avg_stats(void); float expon(float mean);main() /* Main function. */{/* Open input and output files. */infile = fopen("mm1.in", "r");outfile = fopen("mm1.out", "w");/* Specify the number of events for the timing function. */num_events = 2;//两种事件/* Read input parameters. */fscanf(infile, "%f %f %d", &mean_interarrival, &mean_service, &num_delays_required);/* Write report heading and input parameters. 输出*/fprintf(outfile, "Single-server queueing system\n\n");fprintf(outfile, "Mean interarrival time%11.3f minutes\n\n",mean_interarrival);fprintf(outfile, "Mean service time%16.3f minutes\n\n", mean_service);fprintf(outfile, "Number of customers%14d\n\n", num_delays_required);/* Initialize the simulation.初始化仿真*/initialize();//初始化/* Run the simulation while more delays are still needed.没服务完,仿真继续*/while (num_custs_delayed < num_delays_required) {//当已服务顾客数小于1000时/* Determine the next event. 确定下一事件*/timing();/* Update time-average statistical accumulators.时间记录更新*/update_time_avg_stats();/* Invoke the appropriate event function. 根据事件的不同,调用不同的函数*/switch (next_event_type) {case 1:arrive();//到达break;case 2:depart();//离开break;}}/* Invoke the report generator and end the simulation. */ report();fclose(infile);fclose(outfile);return 0;}void initialize(void) /* Initialization function. */{/* Initialize the simulation clock. 仿真时间置为0*/sim_time = 0.0;/* Initialize the state variables.最开始状态初始化*/server_status = IDLE;//服务空闲num_in_q = 0; //队伍里无人排队time_last_event = 0.0; //上一个事件的时间,最开始肯定是0开始/* Initialize the statistical counters. */num_custs_delayed = 0; //已经服务的人数total_of_delays = 0.0;//总的排队时间area_num_in_q = 0.0;//有顾客的时间area_server_status = 0.0;//总的服务时间///////////////////////////////////////////////////////////////////////////////////添加的变量的初始化area_3_in_q = 0.0;//有3个顾客的时间abv_1 = 0.0;//有顾客的时间area_num_in_h = 0.0;//顾客的总数total_of_server = 0.0;//所有顾客的所有的服务的时间abv_15 = 0.0;//消耗15分钟以上的顾客数//////////////////////////////////////////////////////////////////////////////////* Initialize event list. 初始化事件列表Since no customers are present, the departure(service completion) event is eliminated from consideration. 无顾客存在和离开*/time_next_event[1] = sim_time + expon(mean_interarrival);//下一事件是来的时间time_next_event[2] = 1.0e+30; //下一事件是离开的时间}void timing(void) /* Timing function. */{int i;float min_time_next_event = 1.0e+29; //像指针一样的对于当前服务的人来说下一个事件的时间next_event_type = 0;/* Determine the event type of the next event to occur.接下来将要发生的事件的类型*/for (i = 1; i <= num_events; ++i)if (time_next_event[i] < min_time_next_event) {//下一事件是来的时间跟离开时间比较min_time_next_event = time_next_event[i];next_event_type = i;}/* Check to see whether the event list is empty. */if (next_event_type == 0) {/* The event list is empty, so stop the simulation. 无事件,停止仿真过程*/fprintf(outfile, "\nEvent list empty at time %f", sim_time);exit(1);}/* The event list is not empty, so advance the simulation clock. 有事件,进行仿真过程*/sim_time = min_time_next_event; //仿真的时间就是当前事件的时间}void arrive(void) /* Arrival event function. */{float delay;/* Schedule next arrival.计划下一次的到来*/time_next_event[1] = sim_time + expon(mean_interarrival);/* Check to see whether server is busy. 检测是否在服务状态*/if (server_status == BUSY) {/* Server is busy, so increment number of customers in queue. 在服务则排队多一人*/++num_in_q;/* Check to see whether an overflow condition exists. 检测人数是否超出*/if (num_in_q > Q_LIMIT) {/* The queue has overflowed, so stop the simulation. */fprintf(outfile, "\nOverflow of the array time_arrival at");fprintf(outfile, " time %f", sim_time);exit(2);}/* There is still room in the queue, so store the time of arrival of thearriving customer at the (new) end of time_arrival. 队列中仍有空间时,记录新到达的时间*/time_arrival[num_in_q] = sim_time;//在这个时间的时候有这么多的排队人数,用于计算3顾客的问题}else { //服务空闲的状况/* Server is idle, so arriving customer has a delay of zero. (Thefollowing two statements are for program clarity and do not affectthe results of the simulation.) */delay = 0.0;total_of_delays += delay; //总的排队时间/* Increment the number of customers delayed, and make server busy. */++num_custs_delayed; //已经模拟的顾客数加1server_status = BUSY; //人到来,服务开始/* Schedule a departure (service completion). 服务完成*/time_next_event[2] = sim_time + expon(mean_service);//这个人离开的时间为现在时间+服务时间///////////////////////////////////////////////////////////////////////////////////总的服务时间加上当前服务时间,更新总的服务时间total_of_server += time_next_event[2]-sim_time;//总的服务时间加一个服务时间为新的服务总时间//总的服务时间大于15,必须在店内消耗15分钟以上的顾客数加一if((time_next_event[2]-sim_time)>15)//如果这个人服务时间超过15分钟则耗费15分钟人数加1abv_15++;/////////////////////////////////////////////////////////////////////////////////}}void depart(void) /* Departure event function. 讨论离开事件*/{int i;float delay;/* Check to see whether the queue is empty.检测队列是否为空*/if (num_in_q == 0) {/* The queue is empty so make the server idle and eliminate the departure (service completion) event from consideration. 队列空,服务空闲*/server_status = IDLE;time_next_event[2] = 1.0e+30; //离开的时间无限大(无人离开)}else {/* The queue is nonempty, so decrement the number of customers inqueue. 有人离开,队列人数减少*/--num_in_q;/* Compute the delay of the customer who is beginning serviceand updatethe total delay accumulator. */delay = sim_time - time_arrival[1];//排队时间=当前时间-这个人来的时间total_of_delays += delay;/* Increment the number of customers delayed, and schedule departure.已经服务人数+1 */++num_custs_delayed; //服务人数加1time_next_event[2] = sim_time + expon(mean_service);//当前接受服务的人的离开时间///////////////////////////////////////////////////////////////////////////////////总的服务时间加上当前服务时间,更新总的服务时间total_of_server += time_next_event[2]-sim_time;//总的消耗时间大于15,必须在店内消耗15分钟以上的顾客数加一if((delay+time_next_event[2]-sim_time)>15)abv_15++;//////////////////////////////////////////////////////////////////////////////////* Move each customer in queue (if any) up one place.有人离开,队列前移*/for (i = 1; i <= num_in_q; ++i)time_arrival[i] = time_arrival[i + 1];//人的到达时间也前移}}void report(void) /* Report generator function. */{/* Compute and write estimates of desired measures of performance. */fprintf(outfile, "\n\nAverage delay in queue%11.3f minutes\n\n",total_of_delays / num_custs_delayed);fprintf(outfile, "Average number in queue%10.3f\n\n",area_num_in_q / sim_time);fprintf(outfile, "Server utilization%15.3f\n\n",area_server_status / sim_time);fprintf(outfile, "Time simulation ended%12.3f minutes", sim_time);printf("统计量:\n");//////////////////////////////////////////////////////////////////////////总时间减去服务台忙的时间除以总时间,得到服务台空闲的概率printf("①修理店空闲的概率:%24.3f\n",(sim_time-area_server_status) / sim_time);printf("②店内有三个顾客的概率:%20.3f\n",area_3_in_q/sim_time);printf("③店内至少有一个顾客的概率:%16.3f\n",abv_1/sim_time);printf("④在店内顾客的平均数:%22.3f\n",area_num_in_h/sim_time);printf("⑤顾客在店内的平均逗留时间:%16.3f\n",(total_of_delays+total_of_server)/ num_custs_delayed );printf("⑥顾客必须在店内消耗15分钟以上概率:%8.3f\n\n", abv_15/num_custs_delayed);printf("仿真时间:%12.3f minutes\n\n", sim_time);//////////////////////////////////////////////////////////////////////}void update_time_avg_stats(void) /* Update area accumulators fortime-averagestatistics.更新时间平均时间统计*/{float time_since_last_event;/* Compute time since last event, and update last-event-time marker.上个事件到现在的时间并更新最后事件的标记*/time_since_last_event = sim_time - time_last_event;//两个事件的时间差time_last_event = sim_time;/* Update area under number-in-queue function. 有顾客的时间=队列中的人数*时间差*/area_num_in_q += num_in_q * time_since_last_event;/* Update area under server-busy indicator function. 总的服务时间=所有时间差相加*/area_server_status += server_status * time_since_last_event;///////////////////////////////////////////////////////////////////////////////////店内有三个顾客的概率if(server_status == BUSY) //服务台忙,则有队列中有两个顾客if(num_in_q == 2)area_3_in_q += time_since_last_event;//if(server_status == IDLE) //服务台空闲,则有队列中有三个顾客// if(num_in_q == 3)// area_3_in_q += time_since_last_event;//店内至少有一个顾客的概率if(server_status == BUSY) //服务台忙,则店内至少有一个顾客abv_1 += time_since_last_event;//if(server_status == IDLE) //服务台空闲,则有队列中至少有一个顾客// if(num_in_q>0)// abv_1 += time_since_last_event;//在店内顾客的平均数if(server_status == BUSY) //服务台忙,总的顾客数为排队顾客数加一area_num_in_h += (num_in_q+1) * time_since_last_event;//if(server_status == IDLE) //服务台空闲,总的顾客数为排队顾客数// area_num_in_h += num_in_q * time_since_last_event;/////////////////////////////////////////////////////////////////////////////////}float expon(float mean) /* Exponential variate generation function. */ {/* Return an exponential random variate with mean "mean". */return -mean * log(lcgrand(10));//自己学号的后两位}/* Prime modulus multiplicative linear congruential generator Z[i] = (630360016 * Z[i-1]) (mod(pow(2,31) - 1)), based on Marse and Roberts'portable FORTRAN random-number generator UNIRAN. Multiple(100) streams aresupported, with seeds spaced 100,000 apart. Throughout, input argument"stream" must be an int giving the desired stream number. The header filelcgrand.h must be included in the calling program (#include "lcgrand.h")before using these functions.Usage: (Three functions)1. To obtain the next U(0,1) random number from stream "stream," executeu = lcgrand(stream);where lcgrand is a float function. The float variable u will contain thenext random number.2. To set the seed for stream "stream" to a desired value zset, executelcgrandst(zset, stream);where lcgrandst is a void function and zset must be a long set to thedesired seed, a number between 1 and 2147483646 (inclusive). Defaultseeds for all 100 streams are given in the code.3. To get the current (most recently used) integer in the sequence beinggenerated for stream "stream" into the long variable zget, execute zget = lcgrandgt(stream);where lcgrandgt is a long function. *//* Define the constants. */#define MODLUS 2147483647#define MULT1 24112#define MULT2 26143/* Set the default seeds for all 100 streams. */static long zrng[] ={ 1,1973272912, 281629770, 20006270,1280689831,2096730329,1933576050,913566091, 246780520,1363774876, 604901985,1511192140,1259851944,824064364, 150493284, 242708531, 75253171,1964472944,1202299975,233217322,1911216000, 726370533, 403498145, 993232223,1103205531,762430696,1922803170,1385516923, 76271663, 413682397, 726466604,336157058,1432650381,1120463904, 595778810, 877722890,1046574445,68911991,2088367019, 748545416, 622401386,2122378830, 640690903,1774806513,2132545692,2079249579, 78130110, 852776735,1187867272,1351423507,1645973084,1997049139, 922510944,2045512870, 898585771,243649545,1004818771, 773686062, 403188473, 372279877,1901633463,498067494,2087759558, 493157915, 597104727,1530940798,1814496276,536444882,1663153658, 855503735, 67784357,1432404475, 619691088,119025595, 880802310, 176192644,1116780070, 277854671,1366580350,1142483975,2026948561,1053920743,786262391,1792203830,1494667770,1923011392,1433700034,1244184613,1147297105,539712780,1545929719,190641742,1645390429, 264907697, 620389253,1502074852, 927711160,364849192,2049576050, 638580085, 547070247 };/* Generate the next random number. */float lcgrand(int stream){long zi, lowprd, hi31;zi = zrng[stream];lowprd = (zi & 65535) * MULT1;hi31 = (zi >> 16) * MULT1 + (lowprd >> 16);zi = ((lowprd & 65535) - MODLUS) +((hi31 & 32767) << 16) + (hi31 >> 15);if (zi < 0) zi += MODLUS;lowprd = (zi & 65535) * MULT2;hi31 = (zi >> 16) * MULT2 + (lowprd >> 16);zi = ((lowprd & 65535) - MODLUS) +((hi31 & 32767) << 16) + (hi31 >> 15);if (zi < 0) zi += MODLUS;zrng[stream] = zi;return (zi >> 7 | 1) / 16777216.0;}void lcgrandst (long zset, int stream) /* Set the current zrng for stream"stream" to zset. */ {zrng[stream] = zset;}long lcgrandgt (int stream) /* Return the current zrng for stream "stream". */{return zrng[stream];}。
修理店仿真报告一.问题:①修理店空闲的概率;②店内有三个顾客的概率;③店内至少有一个顾客的概率;④在店内顾客的平均数;⑤顾客在店内的平均逗留时间;⑥顾客必须在店内消耗15分钟以上的概率。
二.求解问题的方法:①修理店空闲的概率:(sim_time-area_server_status) / sim_time);②店内有三个顾客的概率:area_3_in_q/sim_time);③店内至少有一个顾客的概率:abv_1/sim_time);④在店内顾客的平均数:area_num_in_h/sim_time);⑤顾客在店内的平均逗留时间:(total_of_delays+total_of_server)/num_custs_delayed );⑥顾客必须在店内消耗15分钟以上概率:abv_15/num_custs_delayed);三。
求解过程中计算统计量的方法:①area_server_status += server_status * time_since_last_event;②//店内有三个顾客的概率if(server_status == BUSY)//服务台忙,则有队列中有两个顾客if(num_in_q == 2)area_3_in_q += time_since_last_event;③//店内至少有一个顾客的概率if(server_status == BUSY) //服务台忙,则店内至少有一个顾客abv_1 += time_since_last_event;④//在店内顾客的平均数if(server_status == BUSY) //服务台忙,总的顾客数为排队顾客数加一area_num_in_h += (num_in_q+1) * time_since_last_event;⑤total_of_server += time_next_event[2]-sim_time;//总的服务时间加一个服务时间为新的服务总时间delay = sim_time - time_arrival[1];//排队时间=当前时间-这个人来的时间total_of_delays += delay;⑥//离开时总的消耗时间大于15,必须在店内消耗15分钟以上的顾客数加一if((delay+time_next_event[2]-sim_time)>15)abv_15++;//到达时总的服务时间大于15,必须在店内消耗15分钟以上的顾客数加一if((time_next_event[2]-sim_time)>15)abv_15++;程序代码:/* External definitions for single-server queueing system. */#include <stdio.h>#include <math.h>/*#include "lcgrand.h" Header file for random-number generator. */#define Q_LIMIT 100 /* Limit on queue length.队伍最长100人*/#define BUSY 1 /* Mnemonics for server's being busy 忙碌状态*/#define IDLE 0 /* and idle.空闲状态 */int next_event_type, //下一个事件类型num_custs_delayed, //已模拟的顾客数num_delays_required, //模拟的顾客数num_events,//事件数num_in_q, //队列中的顾客数server_status;//服务状态float area_num_in_q,//有顾客的时间area_server_status,//总的服务时间mean_interarrival,//平均顾客到达时间间隔mean_service,//平均服务时间sim_time, //模拟时间time_arrival[Q_LIMIT + 1], //到来的时间time_last_event, //上一个事件的时间time_next_event[3],//下一个事件的时间total_of_delays; //总的排队时间/////////////////////////////////////////////////////////// ///////////////////////////添加的变量float abv_15, //15分钟以上的顾客数量 total_of_server, //所有顾客的总的服务时间area_3_in_q, //有3个顾客的时间abv_1, //至少有一个顾客的时间area_num_in_h; //顾客总数////////////////////////////////////////////////////////////////////////////////////FILE *infile, *outfile;/* The following 3 declarations are for use of the random-number generatorlcgrand and the associated functions lcgrandst and lcgrandgt for seedmanagement. This file (named lcgrand.h) should be included in any programusing these functions by executing#include "lcgrand.h"before referencing the functions. */float lcgrand(int stream);void lcgrandst(long zset, int stream);long lcgrandgt(int stream);void initialize(void);void timing(void);void arrive(void);void depart(void);void report(void);void update_time_avg_stats(void);float expon(float mean);main() /* Main function. */{/* Open input and output files. */infile = fopen("mm1.in", "r");outfile = fopen("mm1.out", "w");/* Specify the number of events for the timing function. */num_events = 2;//两种事件/* Read input parameters. */fscanf(infile, "%f %f %d", &mean_interarrival, &mean_service,&num_delays_required);/* Write report heading and input parameters. 输出*/fprintf(outfile, "Single-server queueing system\n\n"); fprintf(outfile, "Mean interarrival time%11.3f minutes\n\n",mean_interarrival);fprintf(outfile, "Mean service time%16.3f minutes\n\n", mean_service);fprintf(outfile, "Number of customers%14d\n\n", num_delays_required);/* Initialize the simulation.初始化仿真 */initialize();//初始化/* Run the simulation while more delays are still needed.没服务完,仿真继续 */while (num_custs_delayed < num_delays_required) {//当已服务顾客数小于1000时/* Determine the next event. 确定下一事件*/timing();/* Update time-average statistical accumulators.时间记录更新 */update_time_avg_stats();/* Invoke the appropriate event function. 根据事件的不同,调用不同的函数*/switch (next_event_type) {case 1:arrive();//到达break;case 2:depart();//离开break;}}/* Invoke the report generator and end the simulation. */ report();fclose(infile);fclose(outfile);return 0;}void initialize(void) /* Initialization function. */{/* Initialize the simulation clock. 仿真时间置为0*/sim_time = 0.0;/* Initialize the state variables.最开始状态初始化 */server_status = IDLE;//服务空闲num_in_q = 0; //队伍里无人排队time_last_event = 0.0; //上一个事件的时间,最开始肯定是0开始/* Initialize the statistical counters. */num_custs_delayed = 0; //已经服务的人数total_of_delays = 0.0;//总的排队时间area_num_in_q = 0.0;//有顾客的时间area_server_status = 0.0;//总的服务时间/////////////////////////////////////////////////////////// ////////////////////////添加的变量的初始化area_3_in_q = 0.0;//有3个顾客的时间abv_1 = 0.0;//有顾客的时间area_num_in_h = 0.0;//顾客的总数total_of_server = 0.0;//所有顾客的所有的服务的时间abv_15 = 0.0;//消耗15分钟以上的顾客数/////////////////////////////////////////////////////////// ///////////////////////* Initialize event list. 初始化事件列表Since no customers are present, the departure(service completion) event is eliminated fromconsideration. 无顾客存在和离开*/time_next_event[1] = sim_time +expon(mean_interarrival);//下一事件是来的时间time_next_event[2] = 1.0e+30; //下一事件是离开的时间}void timing(void) /* Timing function. */{int i;float min_time_next_event = 1.0e+29; //像指针一样的对于当前服务的人来说下一个事件的时间next_event_type = 0;/* Determine the event type of the next event to occur.接下来将要发生的事件的类型 */for (i = 1; i <= num_events; ++i)if (time_next_event[i] < min_time_next_event) {//下一事件是来的时间跟离开时间比较min_time_next_event = time_next_event[i];next_event_type = i;}/* Check to see whether the event list is empty. */if (next_event_type == 0) {/* The event list is empty, so stop the simulation. 无事件,停止仿真过程*/fprintf(outfile, "\nEvent list empty at time %f",sim_time);exit(1);}/* The event list is not empty, so advance the simulationclock. 有事件,进行仿真过程*/sim_time = min_time_next_event; //仿真的时间就是当前事件的时间}void arrive(void) /* Arrival event function. */{float delay;/* Schedule next arrival.计划下一次的到来 */time_next_event[1] = sim_time + expon(mean_interarrival);/* Check to see whether server is busy. 检测是否在服务状态*/if (server_status == BUSY) {/* Server is busy, so increment number of customers in queue. 在服务则排队多一人*/++num_in_q;/* Check to see whether an overflow condition exists.检测人数是否超出*/if (num_in_q > Q_LIMIT) {/* The queue has overflowed, so stop the simulation. */fprintf(outfile, "\nOverflow of the array time_arrival at");fprintf(outfile, " time %f", sim_time);exit(2);}/* There is still room in the queue, so store the time of arrival of thearriving customer at the (new) end of time_arrival. 队列中仍有空间时,记录新到达的时间*/time_arrival[num_in_q] = sim_time;//在这个时间的时候有这么多的排队人数,用于计算3顾客的问题}else { //服务空闲的状况/* Server is idle, so arriving customer has a delay of zero. (Thefollowing two statements are for program clarity and do not affectthe results of the simulation.) */delay = 0.0;total_of_delays += delay; //总的排队时间/* Increment the number of customers delayed, and make server busy. */++num_custs_delayed; //已经模拟的顾客数加1server_status = BUSY; //人到来,服务开始/* Schedule a departure (service completion). 服务完成*/time_next_event[2] = sim_time + expon(mean_service);//这个人离开的时间为现在时间+服务时间/////////////////////////////////////////////////////////// ////////////////////////总的服务时间加上当前服务时间,更新总的服务时间total_of_server += time_next_event[2]-sim_time;//总的服务时间加一个服务时间为新的服务总时间//总的服务时间大于15,必须在店内消耗15分钟以上的顾客数加一if((time_next_event[2]-sim_time)>15)//如果这个人服务时间超过15分钟则耗费15分钟人数加1abv_15++;/////////////////////////////////////////////////////////// //////////////////////}}void depart(void) /* Departure event function. 讨论离开事件*/{int i;float delay;/* Check to see whether the queue is empty.检测队列是否为空 */if (num_in_q == 0) {/* The queue is empty so make the server idle and eliminate thedeparture (service completion) event from consideration. 队列空,服务空闲*/server_status = IDLE;time_next_event[2] = 1.0e+30; //离开的时间无限大(无人离开)}else {/* The queue is nonempty, so decrement the number of customers inqueue. 有人离开,队列人数减少*/--num_in_q;/* Compute the delay of the customer who is beginning service and updatethe total delay accumulator. */delay = sim_time - time_arrival[1];//排队时间=当前时间-这个人来的时间total_of_delays += delay;/* Increment the number of customers delayed, and schedule departure.已经服务人数+1 */++num_custs_delayed; //服务人数加1time_next_event[2] = sim_time + expon(mean_service);//当前接受服务的人的离开时间/////////////////////////////////////////////////////////// ////////////////////////总的服务时间加上当前服务时间,更新总的服务时间total_of_server += time_next_event[2]-sim_time;//总的消耗时间大于15,必须在店内消耗15分钟以上的顾客数加一if((delay+time_next_event[2]-sim_time)>15)abv_15++;/////////////////////////////////////////////////////////// ///////////////////////* Move each customer in queue (if any) up one place.有人离开,队列前移 */for (i = 1; i <= num_in_q; ++i)time_arrival[i] = time_arrival[i + 1];//人的到达时间也前移}}void report(void) /* Report generator function. */{/* Compute and write estimates of desired measures of performance. */fprintf(outfile, "\n\nAverage delay in queue%11.3f minutes\n\n",total_of_delays / num_custs_delayed);fprintf(outfile, "Average number in queue%10.3f\n\n",area_num_in_q / sim_time);fprintf(outfile, "Server utilization%15.3f\n\n",area_server_status / sim_time);fprintf(outfile, "Time simulation ended%12.3f minutes", sim_time);printf("统计量:\n");/////////////////////////////////////////////////////////// ///////////////总时间减去服务台忙的时间除以总时间,得到服务台空闲的概率printf("①修理店空闲的概率:%24.3f\n",(sim_time-area_server_status) / sim_time);printf("②店内有三个顾客的概率:%20.3f\n",area_3_in_q/sim_time);printf("③店内至少有一个顾客的概率:%16.3f\n",abv_1/sim_time);printf("④在店内顾客的平均数:%22.3f\n",area_num_in_h/sim_time);printf("⑤顾客在店内的平均逗留时间:%16.3f\n",(total_of_delays+total_of_server)/num_custs_delayed );printf("⑥顾客必须在店内消耗15分钟以上概率:%8.3f\n\n", abv_15/num_custs_delayed);printf("仿真时间:%12.3f minutes\n\n", sim_time);/////////////////////////////////////////////////////////// ///////////}void update_time_avg_stats(void) /* Update area accumulators for time-averagestatistics.更新时间平均时间统计 */{float time_since_last_event;/* Compute time since last event, and update last-event-time marker.上个事件到现在的时间并更新最后事件的标记 */time_since_last_event = sim_time - time_last_event;//两个事件的时间差time_last_event = sim_time;/* Update area under number-in-queue function. 有顾客的时间=队列中的人数*时间差*/area_num_in_q += num_in_q * time_since_last_event;/* Update area under server-busy indicator function. 总的服务时间=所有时间差相加*/area_server_status += server_status * time_since_last_event;/////////////////////////////////////////////////////////// ////////////////////////店内有三个顾客的概率if(server_status == BUSY) //服务台忙,则有队列中有两个顾客if(num_in_q == 2)area_3_in_q += time_since_last_event;//if(server_status == IDLE) //服务台空闲,则有队列中有三个顾客// if(num_in_q == 3)// area_3_in_q += time_since_last_event;//店内至少有一个顾客的概率if(server_status == BUSY) //服务台忙,则店内至少有一个顾客abv_1 += time_since_last_event;//if(server_status == IDLE) //服务台空闲,则有队列中至少有一个顾客// if(num_in_q>0)// abv_1 += time_since_last_event;//在店内顾客的平均数if(server_status == BUSY) //服务台忙,总的顾客数为排队顾客数加一area_num_in_h += (num_in_q+1) * time_since_last_event;//if(server_status == IDLE) //服务台空闲,总的顾客数为排队顾客数// area_num_in_h += num_in_q * time_since_last_event;/////////////////////////////////////////////////////////// //////////////////////}float expon(float mean) /* Exponential variate generation function. */{/* Return an exponential random variate with mean "mean". */return -mean * log(lcgrand(10));//自己学号的后两位}/* Prime modulus multiplicative linear congruential generator Z[i] = (630360016 * Z[i-1]) (mod(pow(2,31) - 1)), based on Marse and Roberts'portable FORTRAN random-number generator UNIRAN. Multiple (100) streams aresupported, with seeds spaced 100,000 apart. Throughout, input argument"stream" must be an int giving the desired stream number. The header filelcgrand.h must be included in the calling program (#include "lcgrand.h")before using these functions.Usage: (Three functions)1. To obtain the next U(0,1) random number from stream "stream," executeu = lcgrand(stream);where lcgrand is a float function. The float variable u will contain thenext random number.2. To set the seed for stream "stream" to a desired value zset, executelcgrandst(zset, stream);where lcgrandst is a void function and zset must be a long set to thedesired seed, a number between 1 and 2147483646 (inclusive). Defaultseeds for all 100 streams are given in the code.3. To get the current (most recently used) integer in the sequence beinggenerated for stream "stream" into the long variable zget, executezget = lcgrandgt(stream);where lcgrandgt is a long function. *//* Define the constants. */#define MODLUS 2147483647#define MULT1 24112#define MULT2 26143/* Set the default seeds for all 100 streams. */static long zrng[] ={ 1,1973272912, 281629770, 20006270,1280689831,2096730329,1933576050,913566091, 246780520,1363774876, 604901985,1511192140,1259851944,824064364, 150493284, 242708531,75253171,1964472944,1202299975,233217322,1911216000, 726370533, 403498145, 993232223,1103205531,762430696,1922803170,1385516923, 76271663, 413682397, 726466604,336157058,1432650381,1120463904, 595778810, 877722890,1046574445,68911991,2088367019, 748545416, 622401386,2122378830, 640690903,1774806513,2132545692,2079249579, 78130110, 852776735,1187867272,1351423507,1645973084,1997049139, 922510944,2045512870, 898585771,243649545,1004818771, 773686062, 403188473, 372279877,1901633463,498067494,2087759558, 493157915, 597104727,1530940798,1814496276,536444882,1663153658, 855503735, 67784357,1432404475, 619691088,119025595, 880802310, 176192644,1116780070, 277854671,1366580350,1142483975,2026948561,1053920743,786262391,1792203830,1494667770,1923011392,1433700034,1244184613,1147297105,539712780,1545929719,190641742,1645390429, 264907697, 620389253,1502074852, 927711160,364849192,2049576050, 638580085, 547070247 };/* Generate the next random number. */float lcgrand(int stream){long zi, lowprd, hi31;zi = zrng[stream];lowprd = (zi & 65535) * MULT1;hi31 = (zi >> 16) * MULT1 + (lowprd >> 16);zi = ((lowprd & 65535) - MODLUS) +((hi31 & 32767) << 16) + (hi31 >> 15);if (zi < 0) zi += MODLUS;lowprd = (zi & 65535) * MULT2;hi31 = (zi >> 16) * MULT2 + (lowprd >> 16);zi = ((lowprd & 65535) - MODLUS) +((hi31 & 32767) << 16) + (hi31 >> 15);if (zi < 0) zi += MODLUS;zrng[stream] = zi;return (zi >> 7 | 1) / 16777216.0;}void lcgrandst (long zset, int stream) /* Set the current zrng for stream"stream" to zset. */{zrng[stream] = zset;}long lcgrandgt (int stream) /* Return the current zrng for stream "stream". */{return zrng[stream];}。