用Java生成Poisson到达

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

在我的例子中,我有: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

有人可以帮帮我吗?

谢谢,

安娜

您可以使用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; } 

要理解这是如何工作的,请注意在k次迭代之后循环条件变为

p 1 * p 2 * … * p k > L.

这相当于

-ln(p 1 )/ mean -ln(p 2 )/ mean … -ln(p k )/ mean> 1

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

我找到了这个解决方案,使用逆变换采样:

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。 如果您的代码使用基于毫秒的时间/睡眠function,您可以使用:

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

睡觉(楼层(-1.0 * log(1.0 – rand()* 1.0 / RAND_MAX)/ rate));

这是一些生成带有给定均值的泊松数的简化代码:

 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)被舍入为零…… ooops!)