在 Java 中生成泊松到达
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9832919/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Generate Poisson Arrival in Java
提问by user1287257
I would like to create a function in Java that generates Poisson arrivals given the mean arrival rate (lambda) and the mean service rate (mu).
我想在 Java 中创建一个函数,在给定平均到达率 (lambda) 和平均服务率 (mu) 的情况下生成泊松到达。
In my example I have: 2,2 requests/day, in other words 2,2 arrivals/day and a mean service time of 108 hours. Considering that my program starts at t=0 minutes, I would like to create a function that returns arrivals[], which will contain, t1, t2, and a possible t3. T1,t2 and t3 are the instants (in minutes) during the day where this arrivals occur. I have the following restrictions:
在我的示例中,我有:2,2 个请求/天,换句话说,2,2 个到达/天和 108 小时的平均服务时间。考虑到我的程序从 t=0 分钟开始,我想创建一个返回到达 [] 的函数,该函数将包含 t1、t2 和一个可能的 t3。T1、t2 和 t3 是一天中发生这种到达的时刻(以分钟为单位)。我有以下限制:
t1 < t2 < t3 < 1440 minutes (24 hours*60 minutes/hour)
t1 < t2 < t3 < 1440 minutes (24 hours*60 minutes/hour)
t2-t1 > 108 minutes
t2-t1 > 108 minutes
t3-t2 > 108 minutes
t3-t2 > 108 minutes
t3+ 108 minutes < 1440 minutes
t3+ 108 minutes < 1440 minutes
Can someone please help me?
有人可以帮帮我吗?
Thank you,
谢谢,
Ana
安娜
回答by mikera
Here's some simplified code to generate a poisson number with a given mean:
下面是一些生成具有给定均值的泊松数的简化代码:
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;
}
You should be able to use this or something similar to generate your arrival numbers for each time period: the input should be the mean number of arrivals you expect in the period.
您应该能够使用这个或类似的东西来生成每个时间段的到达数字:输入应该是您期望在该时期内到达的平均数量。
Note that if your mean is very large (say 500+) you will want to approximate the number of arrivals with a normal distribution instead. This is more efficient, plus it avoid numerical overflow issues inherent in the code above (at some point Math.exp(-mean) gets rounded to zero......ooops!)
请注意,如果您的均值非常大(比如 500+),您将需要使用正态分布来近似估计到达次数。这更有效,而且它避免了上面代码中固有的数值溢出问题(在某些时候 Math.exp(-mean) 被四舍五入为零......哎呀!)
回答by Adam Zalcman
You can use this algorithm proposed by D. Knuth:
您可以使用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;
}
To understand how this works note that after kiterations the loop condition becomes
要了解这是如何工作的,请注意在k次迭代后,循环条件变为
p1* p2* ... * pk> L
p 1* p 2* ... * p k> L
which is equivalent to
这相当于
-ln(p1)/mean -ln(p2)/mean ... -ln(pk)/mean > 1
-ln(p 1)/均值 -ln(p 2)/均值 ... -ln(p k)/均值 > 1
Note that if pis uniformly distributed then -ln(p)/mean has exponential distribution with a given mean. A random variable with Poisson distribution is equal to the number of times a given event occurs within a fixed interval when the lengths of the intervals between events are independent random variables with exponential distribution. Since we use the mean of the Poisson distribution as the mean of the exponential distribution for the intervals between events, the fixed internal in which we count occurrences is unit length. Thus, the loop condition sums up the lengths of the intervals between events and checks whether we have gone beyond the unit interval. If we have gone beyond the unit interval while counting kth event, then k-1 events occurred within the interval and so we return k-1.
请注意,如果p是均匀分布的,则 -ln(p)/mean 具有给定均值的指数分布。具有泊松分布的随机变量等于给定事件之间的间隔长度为指数分布的独立随机变量时在固定间隔内发生的次数。由于我们使用泊松分布的均值作为事件间隔的指数分布的均值,因此我们计算出现次数的固定内部是单位长度。因此,循环条件将事件之间的间隔长度相加,并检查我们是否超出了单位间隔。如果我们在计算第 k 个事件时超出了单位间隔,则在该间隔内发生了 k-1 个事件,因此我们返回 k-1。
回答by jdbertron
I found this solution, using inverse transform sampling:
我找到了这个解决方案,使用逆变换采样:
http://preshing.com/20111007/how-to-generate-random-timings-for-a-poisson-process
http://preshing.com/20111007/how-to-generate-random-timings-for-a-poisson-process
It doesn't use a rejection sampling approach, is efficient and accurate.
它不使用拒绝采样方法,高效且准确。
It uses the fact that the distribution of the time between events is an exponential distribution, with parameter lambda which is the arrival rate. The Exponential distribution is lambda exp(-lambda x). In order to sample values from that distribution and avoid rejection sampling, it is easier to use its Cumulative Distribution Function (CDF): 1 - exp(-lambda x). The CDF is a function that starts at 0.0 and grows to 1.0 with larget parameters. Intuitively, the probability that you will get an event increases as time passes.
它利用事件之间的时间分布是指数分布的事实,参数 lambda 是到达率。指数分布是 lambda exp(-lambda x)。为了从该分布中采样值并避免拒绝采样,更容易使用其累积分布函数 (CDF):1 - exp(-lambda x)。CDF 是一个函数,它从 0.0 开始,并随着大参数增长到 1.0。直觉上,随着时间的推移,您获得事件的可能性会增加。
To sample the CDF, and again avoid rejection sampling, it is easier to pick a uniform random number U between [0,1] and to plug that value in the inverse function of the CDF, which gives: nextEvent = - Ln(U)/lambda. Because Ln(0) is undefined, and most random number generators include 0.0 and exclude 1.0, it is safer to use: nextEvent = -Ln(1.0-U)/lambda. If your code uses a millisecond based time/sleep function you can use:
为了对 CDF 进行采样,并再次避免拒绝采样,更容易选择 [0,1] 之间的均匀随机数 U 并将该值插入 CDF 的反函数中,这给出: nextEvent = - Ln(U) /拉姆达。因为 Ln(0) 是未定义的,并且大多数随机数生成器都包含 0.0 并排除 1.0,所以使用更安全:nextEvent = -Ln(1.0-U)/lambda。如果您的代码使用基于毫秒的时间/睡眠函数,您可以使用:
double rate = 20.0/1000.0; // 20 per second on average
双倍率 = 20.0/1000.0;// 平均每秒 20 个
sleep(floor(-1.0 * log(1.0 - rand()*1.0/RAND_MAX) / rate) );
睡眠(地板(-1.0 *日志(1.0 - rand()* 1.0/RAND_MAX)/率));
回答by abolfazl bazghandi
you can add this to build.gradle
您可以将其添加到 build.gradle
implementation 'org.kie.modules:org-apache-commons-math:6.5.0.Final'
and use class PoissonDistribution more detail
并使用类 PoissonDistribution更详细