【问题标题】:Simulating a Grocery Store Line Queue using Java使用 Java 模拟杂货店排队队列
【发布时间】:2015-05-04 19:41:27
【问题描述】:

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

考虑在杂货店排队结账。在任何给定的 第二,新客户加入该行的概率为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);
}

}

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

【问题讨论】:

  • 你可以在line.isEmpty()前面加上一个!来否定它,这样你就不会有空的if块
  • 你真的不应该追IndexOutOfBounds
  • 平均处理时间 (47.5 s) 比平均到达时间 (50 s) 略短。所以我预计通常会有一条等候线。您可以尝试改变问题的参数,看看会发生什么。如果处理时间或多或少,对等待时间有何影响?如果到达间隔时间(相当于到达概率)或多或少会有什么影响?

标签: java random simulation probability


【解决方案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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      实际上,单服务器排队系统的实现非常简单,您不需要ArrayListQueue 来隐藏排队的客户。它基于一个简单的递归关系,如下所述。

      您需要知道到达间隔次的分布,即一次到达和下一次到达之间的时间分布。你的以时间步长的方式被描述为在给定的时钟滴答中新到达的概率为 0.02。这相当于Geometric distributionp = 0.02。您已经知道服务时间分布 - Uniform(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
      

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

      最后一点 - 由于初始化偏差,您可能希望忽略前几百或几千个观察结果。模拟模型通常需要一个“预热”期来消除以编程方式将变量初始化为任意值的影响。

      【讨论】:

        猜你喜欢
        • 2012-03-29
        • 1970-01-01
        • 2012-10-30
        • 2013-03-06
        • 2013-08-21
        • 1970-01-01
        • 2023-03-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多