用Java模拟杂货店排队

用Java模拟杂货店排队,java,random,simulation,probability,Java,Random,Simulation,Probability,所以我有一个问题,我已经绞尽脑汁一个星期了。情况是: 考虑在杂货店排队结账。在任何时候 其次,新客户加入该行的概率为0.02(否 在任何给定的时间内,都有多个客户加入生产线)。这个 收银台职员需要20秒到75秒之间的随机时间 为每位客户服务的时间为秒。编写一个程序来模拟这种情况 模拟大约一千万秒,然后打印出平均值 客户排队等待的秒数 店员开始为顾客服务。请注意,由于您不知道 在任何给定时间排队的最大客户数, 您应该使用ArrayList,而不是数组 预期的平均等待时间应在500到600秒之间。然

所以我有一个问题,我已经绞尽脑汁一个星期了。情况是:

考虑在杂货店排队结账。在任何时候 其次,新客户加入该行的概率为0.02(否 在任何给定的时间内,都有多个客户加入生产线)。这个 收银台职员需要20秒到75秒之间的随机时间 为每位客户服务的时间为秒。编写一个程序来模拟这种情况 模拟大约一千万秒,然后打印出平均值 客户排队等待的秒数 店员开始为顾客服务。请注意,由于您不知道 在任何给定时间排队的最大客户数, 您应该使用ArrayList,而不是数组

预期的平均等待时间应在500到600秒之间。然而,我还没有得到一个接近这个范围的答案。考虑到排队等候新客户的概率仅为2%,我预计排队人数不会超过1人,因此平均等待时间约为45-50秒。我问过一位朋友(他主修数学),他对这个问题的看法是什么,他同意,考虑到2%的概率,45秒是一个合理的平均值。到目前为止,我的代码是:

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);
}

}
包装杂货店;
导入java.util.ArrayList;
导入java.util.Random;
公共级杂货店{
私有静态ArrayList行=新建ArrayList();
私有静态随机r=新随机();
公共静态void addCustomer(){
int timeToServe=r.nextInt(56)+20;
行。添加(timeToServe);
}    
公共静态void removeCustomer(){
行。删除(0);
}
公共静态整数和(ArrayList a){
整数和=0;
对于(int i=0;i

如果您对此有任何建议,我们将不胜感激

这里有一些伪代码可以帮助您规划它

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
对于经过的每一秒:
生成概率

如果概率而不是使用ArrayList,则a可能更适合管理客户。另外,删除try/catch子句,一个
会向主函数定义抛出IndexOutOfBoundsException

实际上有一个非常简单的单服务器排队系统实现,您不需要
数组列表
队列
来隐藏排队的客户。它基于下面描述的简单递归关系

您需要知道到达时间之间的分布,即一次到达和下一次到达之间的时间分布。你的被描述为时间步进的方式,在给定的时钟滴答声中有一个新到达的概率为0.02。这相当于a与
p=0.02
。您已经知道服务时间分布-统一(20,75)

通过这两条信息和一点思考,您可以推断出,对于任何给定的客户,到达时间都是前一个客户的到达时间加上(生成的)间隔时间;该客户可以在其到达时间或前一客户的离开时间开始接受服务,以较晚者为准;他们在服务器上结束,在开始服务时间加上(生成的)服务时间离开。您需要初始化一个假想的第零位客户的到达时间和离开时间,以启动整个过程,但是计算重复性是一个简单的循环

因为这看起来像是家庭作业,所以我给你一个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
请注意,这种方法跳过了大部分时间,在这些时间里什么都没有发生,因此与时间步进模拟时钟的每一个滴答声并将东西存储在动态大小的容器中相比,它是一个相当有效的小程序


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

您可以将
放在
行前面。isEmpty()
将其取反,这样,如果你真的不应该捕获
IndexOutOfBounds
的话,你就不会有空块了。平均处理时间(47.5秒)比平均到达时间(50秒)稍微短一点。所以我想通常会有人排队等候。您可以尝试改变问题的参数,看看会发生什么。如果处理时间多多少少,对等待时间有什么影响?如果到达间隔时间(相当于到达概率)或多或少会产生什么影响?