在Java中生成泊松到达

问题描述:

我想创建一个Java中的函数,根据平均到达率(lambda)和平均服务率(mu)生成泊松到达。在Java中生成泊松到达

在我的例子中,我有:2,2次/天,换句话说2,2次到达/日,平均服务时间为108小时。考虑到我的程序从t = 0分钟开始,我想创建一个返回到达[]的函数,它将包含t1,t2和一个可能的t3。 T1,t2和t3是这些到达发生当天的瞬间(以分钟为单位)。我有以下限制:

t1 < t2 < t3 < 1440 minutes (24 hours*60 minutes/hour)

t2-t1 > 108 minutes

t3-t2 > 108 minutes

t3+ 108 minutes < 1440 minutes

有人可以帮我吗?

谢谢

安娜

+2

什么是阻止你这样做的具体问题? – 2012-03-23 01:20:23

+0

[模拟泊松等待时间 - Java]的可能的副本(http://*.com/questions/6527345/simulating-poisson-waiting-times-java) – duffymo 2012-03-23 01:21:26

+1

欢迎来到SO。请阅读[常见问题]和[问]以了解如何在此发布问题的详细信息。如果没有证据表明您已经尝试解决问题,则会被视为超出范围。 SO用户提供特定问题的答案,但通常不会为您完成工作。此外,您希望在发布之前在网上和SO上搜索答案。 – 2012-03-23 01:22:36

下面是一些简单的代码来生成与给定平均泊​​松号:

private static int poisson(double mean) { 
    int r = 0; 
    double a = random.nextDouble(); 
    double p = Math.exp(-mean); 

    while (a > p) { 
     r++; 
     a = a - p; 
     p = p * mean/r; 
    } 
    return r; 
} 

您应该能够使用这种或类似的东西来生成每个时间段的到达数量:输入应该是期间到达的平均数量。

请注意,如果您的平均值非常大(比如500+),您将希望用正态分布来近似到达的数量。这是更有效的,再加上它避免在上面的代码中固有的数值溢出的问题(在某些时候Math.exp(-mean)被四舍五入为零......哎呀!)

您可以使用this algorithm proposed by D. Knuth

private static int getPoissonRandom(double mean) { 
    Random r = new Random(); 
    double L = Math.exp(-mean); 
    int k = 0; 
    double p = 1.0; 
    do { 
     p = p * r.nextDouble(); 
     k++; 
    } while (p > L); 
    return k - 1; 
} 

要理解它是如何工作的注意,之后ķ迭代循环条件变得

p * p * ...... * p ķ>大号

这相当于

-ln(P )/平均-ln(P )/平均... -ln(P ķ)/平均> 1

请注意,如果p是均匀分布的,则-ln(p)/ mean具有给定均值的指数分布。具有泊松分布的随机变量等于事件之间的间隔长度为具有指数分布的独立随机变量时在给定事件发生在固定间隔内的次数。由于我们使用泊松分布的平均值作为事件之间间隔的指数分布的均值,因此我们统计事件的固定内部是单位长度。因此,循环条件总结了事件间隔的长度并检查我们是否超出了单位间隔。如果我们在计数第k个事件时已经超出了单位间隔,那么k-1个事件在间隔内发生,因此我们返回k-1。

+0

这是Knuth的方法。如果您可以接受生成时间来等待下一个事件,那么您可以使用此:[http://*.com/a/15307412/1650437](http://*.com/a/15307412/1650437) – jdbertron 2013-03-09 05:10:59

我发现这个解决方案,使用逆变换采样:

http://preshing.com/20111007/how-to-generate-random-timings-for-a-poisson-process

它不使用拒绝采样方法,是有效的和准确的。

它使用这样一个事实,即事件之间的时间分布是指数分布,参数lambda是到达率。 指数分布是lambda exp(-lambda x)。 为了从该分布中采样值并避免拒收采样,使用其累积分布函数(CDF)更容易:1-exp(-lambda x)。 CDF是一个函数,它从0.0开始并使用larget参数增长到1.0。直觉上,随着时间的推移,你会得到一个事件的概率会增加。为了对CDF进行采样,并且再次避免拒绝采样,在[0,1]之间选择均匀的随机数U并且将该值插入到CDF的反函数中更容易,其给出:nextEvent = - LN(U)/λ。 因为Ln(0)是未定义的,并且大多数随机数生成器包含0.0并且不包括1.0,所以使用: nextEvent = -Ln(1.0-U)/ lambda更安全。 如果您的代码使用基于毫秒的时间/睡眠功能,您可以使用:

双倍率= 20.0/1000.0; //平均每秒20次

sleep(floor(-1.0 * log(1.0 - rand()* 1.0/RAND_MAX)/ rate));

+0

由远远是最好的方法 – 2014-03-26 18:31:05