"""
Draws a random number from given probability density function.
Parameters
----------
pdf -- the function pointer to a probability density function of form P = pdf(x)
interval -- the resulting random number is restricted to this interval
pdfmax -- the maximum of the probability density function
integers -- boolean, indicating if the result is desired as integer
max_iterations -- maximum number of 'tries' to find a combination of random numbers (rand_x, rand_y) located below the function value calc_y = pdf(rand_x).
returns a single random number according the pdf distribution.
"""
def draw_random_number_from_pdf(pdf, interval, pdfmax = 1, integers = False, max_iterations = 10000):
for i in range(max_iterations):
if integers == True:
rand_x = np.random.randint(interval[0], interval[1])
else:
rand_x = (interval[1] - interval[0]) * np.random.random(1) + interval[0] #(b - a) * random_sample() + a
rand_y = pdfmax * np.random.random(1)
calc_y = pdf(rand_x)
if(rand_y <= calc_y ):
return rand_x
raise Exception("Could not find a matching random number within pdf in " + max_iterations + " iterations.")
一般来说,你需要一个逆累积概率密度函数。一旦有了它,就可以简单地沿分布生成随机数:
或者,如果使用NumPy:
在这两种情况下,
icdf
是反向累积分布函数,它接受0到1之间的值,并从分布中输出相应的值。为了说明
icdf
的性质,我们将以值10和12之间的简单均匀分布为例:概率分布函数在10到12之间为0.5,其他地方为零
累积分布函数为0小于10(10以下无样本),1大于12(12以上无样本),且在值之间线性增加(PDF的整数)
反向累积分布函数仅定义在0和1之间。在0时为10,在12时为1,并且在值之间线性变化
当然,最困难的部分是求逆累积密度函数。它实际上取决于你的分布,有时你可能有一个分析函数,有时你可能想诉诸插值。数值方法可能是有用的,因为数值积分可用于创建CDF,插值可用于反转CDF。
这是我的函数,用于检索根据给定概率密度函数分布的单个随机数。我用了蒙特卡罗的方法。当然,可以通过调用这个函数n次来生成随机数。
在我看来,如果不必检索大量随机变量,这个解决方案的性能比其他解决方案要好。另一个好处是,您只需要PDF并避免计算CDF、逆CDF或权重。
相关问题 更多 >
编程相关推荐