排队论MM1与MMN的java仿真(含源代码)(美赛17年D题所用到)

做美赛练习的时候有用到。
嗯。。。练习做完了自己又把代码重新更新了一下。
两个类,一个是MM1类,一个是MMN类,MMN类继承的MM1类,改了一下方法
测试类我又写了一遍,这样就可以对大家所用了,还把代码里的内容注释也蛮详细的。
唯一要注意一点的是,有时候队列时间是-1.1546319456101628E-14这种,其实是0,java在比较的时候有精度会出现一点点小问题,无伤大雅。
要注意的第二点就是,这里如果你给的langda和miu值如果比下来趋近于1的话就代表排队时间很长(就是服务效率慢),这时候你的仿真结果旧跟数据集有关,我做过一个数据集的图像,可供参考。此图的下标1,2,3,4,5打错了,是2,3,4,5,6。
数据集大小与仿真,理论的关系
第三点是,算法在仿真数据集为10万时最接近理论值,但是这时候的仿真计算的平均队长时间会比较慢,可能需要等30秒,如果是100万,可能需要等2,3分钟。

源代码如下:

/*
 * 完整版排队论仿真模型(MM1与MMN)
 * 所需要的其他都可在此基础上更改
 * 2018.1.21-2017.1.28陆续修改而成
 * from 济民宝宝
 */
import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;
class MM1
{
/*
 * MM1所具有的函数有以下几个:
 * MM1:构造函数,知道langda和miu以及number仿真总人数就可以进行仿真
 * Produce:通过负指数分布landa的值产生到达人群的时间间隔,计算得出时间点(泊松分布是产生人群,与到达人群是无关的)
 * Leave:通过负指数分布miu的值计算服务时间,队列时间以及等待时间
 * Print_need:打印出所需要的平均逗留时间,平均队列时间,平均服务时间与平均队长(这是仿真模型,打印出来的是仿真结果)
 * Print_people:打印出编号为x的人的到达时间,队列时间,服务时间与离开时间
 * Print_time:打印出时间为T时的队列人数,此时的平均服务时间,到达该窗口的累计人数,当前窗口人数
*/
    double in;//in为langda,一秒钟到来了几个人
    double out;//out为miu,人离开的速率,完成速率

    double[] arrive_time;//到达时间间隔
    double[] arrivetime;//顾客到达时间
    double[] serve_time;//服务时间
    double[] leave_time;//离开时间
    double[] wait_time;//等待(在服务窗的总时间)时间
    double[] queue_time;//排队时间

    MM1(double in,double out,int number)
    {
        arrive_time=new double[number];//到达时间间隔
        arrivetime=new double[number];//顾客到达时间
        serve_time=new double[number];//服务时间
        leave_time=new double[number];//顾客离开时间
        wait_time=new double[number];//等待时间,(在服务窗的总时间)
        queue_time=new double[number];//排队时间
        this.in=in;
        this.out=out;
    }
    void Produce(int number)
    {
        for(int i=0;i<number;i++)
        {
            Random random=new java.util.Random();// 定义随机类
            double result=random.nextDouble();// 返回0到1之间的小数
            arrive_time[i]=Math.log(result)*-1/in;//负指数分布函数产生到达时间间隔
        }
        arrivetime[0]=arrive_time[0];
        for(int i=1;i<number;i++)
        {
            arrivetime[i]=arrivetime[i-1]+arrive_time[i];//通过到达时间间隔计算出到达时间
        }

    }
    void Leave(int number)
    {
        for(int i=0;i<number;i++)
        {
            Random random=new java.util.Random();// 定义随机类
            double result=random.nextDouble();// 返回0到1之间的小数
            if(result<0)    result*=-1;
            serve_time[i]=Math.log(result)*-1/out;
        }
        leave_time[0]=serve_time[0]+arrivetime[0];
/*
 * 离开时间的计算方法:
 * 如果前面那个人的离开时间大于我,我的离开时间等于他的离开时间加上我的服务时间
 * 如果前面那个人的离开时间小于我,我的离开时间等于我的到达时间加上我的服务时间
*/
        for(int i=1;i<number;i++)
        {
            if(leave_time[i-1]<arrivetime[i])
                leave_time[i]=arrivetime[i]+serve_time[i];
            else
                leave_time[i]=leave_time[i-1]+serve_time[i];
        }

        for(int i=0;i<number;i++)
        {
            queue_time[i]=leave_time[i]-arrivetime[i]-serve_time[i];//队列时间的计算
            wait_time[i]=leave_time[i]-arrivetime[i];//等待时间的计算
        }   
    }
    void Print_people_x(int x)//x是编号
    {
        System.out.println("第"+x+"个人的数据如下:");
        System.out.println("到达时间:"+arrivetime[x]);
        System.out.println("队列时间:"+queue_time[x]);
        System.out.println("服务时间:"+serve_time[x]);
        System.out.println("离开时间:"+leave_time[x]);
    }
    void Print_need(int x)//x是规模
    {
        double[] line_wait;//当前队长(包括正在服务的)

        double sum_wait=0,sum_queue=0,sum_serve=0,sum_line=0;
        for(int i=0;i<x;i++)
        {
            sum_wait+=wait_time[i];
            sum_queue+=queue_time[i];
            sum_serve+=serve_time[i];
        }
        sum_wait/=x;
        sum_queue/=x;
        sum_serve/=x;
        System.out.println("平均逗留时间为:"+sum_wait);
        System.out.println("平均队列时间为:"+sum_queue);
        System.out.println("平均服务时间为:"+sum_serve);

        double last_time=leave_time[x-1];
        line_wait=new double[(int)last_time+1];
        int time=0;
        for(time=0;time<last_time;time++)
        {
            for(int i=0;i<x;i++)
            {
                if(time>arrivetime[i]&&time<leave_time[i])
                {
                    line_wait[time]++;
                }
            }
            sum_line+=line_wait[time];
        }
        sum_line/=time;
        System.out.println("平均队长为:"+sum_line);
    }
    void Print_time(double time,int number)
    {

        int queue_people=0;
        int arrive_people=0;
        int leave_people=0;
        double servertime=0;
        for(int i=0;i<number;i++)
        {
            if(arrivetime[i]<time&&leave_time[i]>time)
                queue_people++;
            if(arrivetime[i]<time)
                arrive_people++;
            if(leave_time[i]<time)
                leave_people++;
        }
        servertime=(time-arrive_time[0])/(leave_people+1);
        System.out.println("第"+time+"时间的数据如下:");
        System.out.println("此时队列人数有:"+queue_people);
        System.out.println("此时的平均服务时间"+servertime);
        System.out.println("到达该窗口累计人数:"+arrive_people);
        System.out.println("离开此窗口的累计人数:"+leave_people);
    }
}

class MMN extends MM1
{
    int N;
    MMN(double in, double out, int number,int N) {
        super(in, out, number);
        this.N=N;
        // TODO Auto-generated constructor stub
    }
    void Leave(int number)
    {
        for(int i=0;i<number;i++)
        {
            Random random=new java.util.Random();// 定义随机类
            double result=random.nextDouble();// 返回0到1之间的小数
            if(result<0)    result*=-1;
            serve_time[i]=Math.log(result)*-1/out;

        }

        double[]leave_x=new double[N];
        for(int i=0;i<N;i++)    
        {
            leave_time[i]=serve_time[i]+arrivetime[i];
            leave_x[i]=leave_time[i];
        }

        for(int i=N;i<number;i++)
        {
            Arrays.sort(leave_x);
            if(leave_x[0]<arrivetime[i])//到达时间比最小的都大时
            {
                leave_time[i]=arrivetime[i]+serve_time[i];
                leave_x[0]=leave_time[i];
            }   
            else if(leave_x[0]>arrivetime[i]){
                leave_time[i]=leave_x[0]+serve_time[i];
                leave_x[0]=leave_time[i];
            }
        }

        for(int i=0;i<number;i++)
        {
            queue_time[i]=leave_time[i]-arrivetime[i]-serve_time[i];
            wait_time[i]=leave_time[i]-arrivetime[i];
        }   
    }
}
public class Queue {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int number=10000;
        int flag=0;
        while(flag!=5){
        System.out.println("济民宝宝为郭阳小姐姐服务:");
        System.out.println("本系统提供如下服务:");
        System.out.println("1.提供Print_need的测试样例,输入1回车可见(具体代码见Queue类的注释1部分)");
        System.out.println("2.提供Print_time的测试样例,输入2回车可见(具体代码见Queue类的注释2部分)");
        System.out.println("3.提供Print_people的测试样例,输入3回车可见(具体代码见Queue类的注释3部分)");
        System.out.println("4.提供排队论仿真模型(可自行输入输出),输入4回车可见(具体代码见Queue类的注释4部分)");
        System.out.println("5.结束");
        Scanner in =new Scanner(System.in);
        flag=in.nextInt();


/*
 * 注释1
 * 函数的具体功能见MM1类的注释
 * 包含MM1和MM3的Print_need
 */
        if(flag==1){
        System.out.println("这是一个测试类:测试数据集为10000,langda=0.2,miu=0.5的MM1模型");
        MM1 test1=new MM1(0.2,0.5,number);
        test1.Produce(number);
        test1.Leave(number);
        test1.Print_need(number);

        System.out.println("\n--------------OvO华丽的分割线QAQ-------------\n");

        System.out.println("这是一个测试类:测试数据集为10000,langda=0.2,miu=0.5的MM3模型");
        MMN test2=new MMN(0.2,0.5,number,3);
        test2.Produce(number);
        test2.Leave(number);
        test2.Print_need(number);
        }
/*
 * 注释2
 * 包含MM1和MM3的Print_time
 */ 
        if(flag==2){
        System.out.println("这是一个测试类:测试数据集为10000,langda=0.2,miu=0.5的MM1模型");
        MM1 test1=new MM1(0.2,0.5,number);
        double time=100.0;
        test1.Produce(number);
        test1.Leave(number);
        test1.Print_time(time, number);

        System.out.println("\n--------------OvO华丽的分割线QAQ-------------\n");

        System.out.println("这是一个测试类:测试数据集为10000,langda=0.2,miu=0.5的MM3模型");
        MMN test2=new MMN(0.2,0.5,number,3);
        test2.Produce(number);
        test2.Leave(number);
        test2.Print_time(time, number);
        }

/*
 * 注释3
 * 包含MM1和MM3的Print_people
 */ 
        if(flag==3){
        System.out.println("这是一个测试类:测试数据集为10000,langda=0.2,miu=0.5的MM1模型");
        MM1 test1=new MM1(0.2,0.5,number);
        double time=100.0;
        test1.Produce(number);
        test1.Leave(number);
        test1.Print_people_x(100);

        System.out.println("\n--------------OvO华丽的分割线QAQ-------------\n");

        System.out.println("这是一个测试类:测试数据集为10000,langda=0.2,miu=0.5的MM3模型");
        MMN test2=new MMN(0.2,0.5,number,3);
        test2.Produce(number);
        test2.Leave(number);
        test2.Print_time(time, number);
        test2.Print_people_x(100);
        }
/*
 * 注释4
 * 自选输入输出
 */ 
        if(flag==4){
        System.out.println("请选择你想模拟的是MM1还是MMN");
        System.out.println("MM1的话输入1换行,MMN的话输入2换行");
        Scanner one=new Scanner(System.in);
        int flag_one=one.nextInt();
        System.out.println("请输入langda:");
        double langda=one.nextDouble();
        System.out.println("请输入miu:");
        double miu=one.nextDouble();
        System.out.println("请输入仿真数量集:");
        number=one.nextInt();
        System.out.println("请输入你想仿真的方法:");
        System.out.println("1.Print_need,输入1回车");
        System.out.println("2.Print_people,输入2回车");
        System.out.println("3.Print_time,输入3回车");
        int method=one.nextInt();

        if(flag_one==1){
        MM1 test1=new MM1(langda,miu,number);
        test1.Produce(number);
        test1.Leave(number);
        switch(method)
        {
        case 1:
            test1.Print_need(number);
            break;
        case 2:
            System.out.println("请输入你想print_people的编号(不能大于你给的数据集):");
            int people=one.nextInt();
            test1.Print_people_x(people);
            break;
        case 3:
            System.out.println("请输入你想print_time的时间(不能大于你给的数据集的最后一个人的离开时间):");
            double time_one=one.nextDouble();
            test1.Print_time(time_one, number);
            break;
        }
        System.out.println("\n--------------OvO华丽的分割线QAQ-------------\n");
        }
        else if(flag_one==2){
            System.out.println("请输入你想输入的窗口数");
            int window_number=one.nextInt();
            MMN test1=new MMN(langda,miu,number,window_number);
            test1.Produce(number);
            test1.Leave(number);
            switch(method)
            {
            case 1:
                test1.Print_need(number);
                break;
            case 2:
                System.out.println("请输入你想print_people的编号(不能大于你给的数据集):");
                int people=one.nextInt();
                test1.Print_people_x(people);
                break;
            case 3:
                System.out.println("请输入你想print_time的时间(不能大于你给的数据集的最后一个人的离开时间):");
                double time_one=one.nextDouble();
                test1.Print_time(time_one, number);
                break;
            }
        }
        }
        System.out.println("5秒后返回主菜单");
        for(int i=0;i<3;i++)
            System.out.println();//清屏
        try {
            Thread.sleep(5000);
           } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
           }
        }
    }
}
  • 9
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
MATLAB是一款非常强大的数学软件,可以用来进行各种科学计算和数据分析。排队论是MATLAB中的一个重要应用领域,可以用来模拟和分析各种排队系统,如MM1排队系统。 以下是一个简单的MATLAB代码示例,用于模拟MM1排队系统: ```matlab % MM1 Queue Simulation % Number of customers to simulate numCustomers = 100; % Inter-arrival times (exponential distribution) interArrivalTimes = exprnd(5, 1, numCustomers); % Service times (exponential distribution) serviceTimes = exprnd(4, 1, numCustomers); % Arrival times arrivalTimes = zeros(1, numCustomers); for i = 2:numCustomers arrivalTimes(i) = arrivalTimes(i-1) + interArrivalTimes(i); end % Service start times serviceStartTimes = zeros(1, numCustomers); for i = 2:numCustomers serviceStartTimes(i) = max(arrivalTimes(i), serviceStartTimes(i-1) + serviceTimes(i-1)); end % Service end times serviceEndTimes = serviceStartTimes + serviceTimes; % Waiting times waitingTimes = serviceStartTimes - arrivalTimes; % Total time in system totalTimes = serviceEndTimes - arrivalTimes; % Average waiting time avgWaitingTime = mean(waitingTimes); % Average total time in system avgTotalTime = mean(totalTimes); disp(['Average waiting time: ' num2str(avgWaitingTime)]); disp(['Average total time in system: ' num2str(avgTotalTime)]); ``` 该代码可以模拟一个包100个顾客的MM1排队系统,并计算平均等待时间和平均总时间。具体实现过程可以参考代码注释。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值