使用Java模拟Grocery Store Line Queue

时间:2015-03-03 23:21:03

标签: java random simulation probability

所以我有一个问题我现在已经被大脑震荡了一周左右。情况是:

  

考虑一下杂货店的结账台。任何给定的   第二,新客户加入生产线的概率是0.02(没有   在任何给定的秒数内,不止一个客户加入生产线。该   结帐职员在20秒到75之间随机抽取一段时间   为每个客户服务的秒数。编写程序来模拟这个   场景大约一千万秒并打印出平均值   客户在此之前排队等候的秒数   店员开始为顾客服务。请注意,因为你不知道   在任何给定时间可能排队的最大客户数量,   你应该使用ArrayList而不是数组。

预计平均等待时间应介于500到600秒之间。但是,我没有得到接近这个范​​围的答案。鉴于线路中新客户的概率仅为2%,我预计线路中的线路数量永远不会超过1人,因此平均等待时间约为45-50秒。我问了一个朋友(他是一名数学专业)他对这个问题的看法,他同意45秒是一个合理的平均值给出2%的概率。到目前为止我的代码是:

package grocerystore;

import java.util.ArrayList;
import java.util.Random;

public class GroceryStore {

private static ArrayList<Integer> line = new ArrayList();    
private static Random r = new Random();

public static void addCustomer() {        
    int timeToServe = r.nextInt(56) + 20;
    line.add(timeToServe);        
}    

public static void removeCustomer() {
    line.remove(0);
}

public static int sum(ArrayList<Integer> a) {
    int sum = 0;
    for (int i = 0; i < a.size(); i++) {
        sum += a.get(i);
    }
    return sum;
}

public static void main(String[] args) {
      int waitTime = 0;
      int duration = 10000;
      for (int i = 0; i < duration; i++) {              
          double newCust = r.nextDouble();

          if (newCust < .02) {
              addCustomer();
          }

          try {
              for (int j = 0; j < line.get(0); j++) {                                          
                  waitTime = waitTime + sum(line);                      
              }
          } catch (IndexOutOfBoundsException e) {}                

          if (line.isEmpty()) {}
          else {
              removeCustomer();
          }
      }
      System.out.println(waitTime/duration);
}

}

对此有任何建议将不胜感激。

3 个答案:

答案 0 :(得分:1)

这是一些帮助你计划的伪代码

for each second that goes by:
    generate probability

    if probability <= 0.02
        add customer

    if wait time is 0
        if line is not empty
            remove customer
            generate a new wait time
    else
        decrement wait time

答案 1 :(得分:1)

实际上,单个服务器排队系统的实施非常简单,您不需要ArrayListQueue来存储排队的客户。它基于下面描述的简单递归关系。

您需要知道到达间次'分布,即一次到达与下一次之间的时间分布。你的时间步长被描述为在时钟的给定刻度中新到达0.02的概率。这相当于Geometric distribution p = 0.02。您已经知道服务时间分布 - Uniform(20,75)。

通过这两条信息和一点点思考,您可以推断,对于任何给定的客户,到达时间是先前客户的到达时间加上(生成的)到达时间;该客户可以在其到达时间或先前客户的出发时间(以较晚者为准)开始提供服务;他们完成了服务器,并在他们的开始服务时间和(生成的)服务时间离开。你需要初始化一个想象中的第0个客户的到达时间和出发时间来启动整个事情,但是这是一个计算重现的简单循环。

因为这看起来像家庭作业,所以我给你一个Ruby实现。如果您不了解Ruby,请将其视为伪代码。您可以非常直接地转换为Java。我遗漏了如何生成分布的详细信息,但我实际上已经完成了这个的完整实现,用统计结果替换了注释行,并且它给出了大约500的平均等待时间。

interarrival_time = Geometric.new(p_value)
service_time = Uniform.new(service_min, service_max)
arrival_time = depart_time = 0.0        # initialize zeroth customer
loop do
   arrival_time += interarrival_time.generate
   break if arrival_time > 10_000_000
   start_time = [arrival_time, depart_time].max
   depart_time = start_time + service_time.generate
   delay_in_queue = start_time - arrival_time
   # do anything you want with the delay_in_queue value:
   #   print it, tally it for averaging, whatever...
end

请注意,这种方法会在没有任何事情发生的大片时间内跳过,所以与通过时间步进模拟时钟的每个滴答并将内容存储在动态大小的容器中相比,它是一个非常有效的小程序。

最后一点注意事项 - 由于初始化偏差,您可能希望忽略前几百或一千个观测值。仿真模型通常需要一个“预热”期,以消除程序上必要的变量初始化对任意值的影响。

答案 2 :(得分:0)

Queue可能更适合管理客户,而不是使用ArrayList。另外,删除try / catch子句和throws IndexOutOfBoundsException到主函数定义。