我目前正在用python编写一个简单的程序来模拟1+1维的SU(2) yang mills理论。对于SU(2)的情况,存在用于更新链接变量的特定热浴算法。然而,为了实现这个算法,我需要生成一个随机实数X,使得X根据P(x) = sqrt(1-X^2)*e^(k*X)
分布,其中k是从负无穷大到无穷大的实数。
幸运的是,有一种算法可以根据上述分布生成X。使用我有限的python技能,我实现了这样一个算法。下面是代码。我在这里只用了numpy。
def algorithm(k):
count = 0
while 1 != 0:
r1,r2,r3,r4 = np.random.uniform(low=0,high=1),np.random.uniform(low=0,high=1),np.random.uniform(low=0,high=1),np.random.uniform(low=0,high=1)
L1 = -1/(2*k)*(np.log(r1)+np.log(r3)*np.cos(2*np.pi*r2)**2)
if r4**2 <= 1 - L1:
X = 1 -2*L1
break
else:
count = count + 1
continue
print(count)
return X
基本上,如果我们在0到1的区间内取三个均匀分布的随机数,我们可以生成一个随机变量l1,它是这三个随机数的函数。
如果1- L1大于或等于第四个随机数的平方(在区间0到1中均匀分布),我们接受此值L1。否则,我们循环回到开头,重新做一次。我们一直这样做,直到我们接受L1的值。在我们接受L1之后,我们计算X为1- 2*L1。此算法确保X遵循所需的分布。
在我的程序中,我将不得不生成一个二维数组的X,这在我目前的实现中是相当慢的。所以我的问题是:有没有一种更简单的方法来使用任何预设的numpy包来做到这一点?如果这样的方法不存在,有没有一种方法可以向量化这个函数来生成随机X的二维网格,而不是简单地用for循环迭代它?
发布于 2018-08-07 04:55:35
我不知道是否存在一个内置函数,可以精确地返回您想要的分布,但我相信向量化您的代码应该不难。只需使用沃伦提到的size
parameter of the uniform
function生成r1
、r2
、r3
和r4
向量,然后执行这些操作。正如DSM所提到的,您也可以只使用一个元组作为size
参数,并通过一个调用完成所有操作。
您可以保留循环并以某种方式重复操作,直到获得N
值,但我只需删除循环,只保留满足条件的数字。这会产生比N
数字更少的结果,但对代码来说很简单。
这样的代码可能就是您想要的:
def algorithm_2(k, N):
r1,r2,r3,r4 = np.random.uniform(low=0,high=1, size=(4,N))
L1 = -1/(2*k)*(np.log(r1)+np.log(r3)*np.cos(2*np.pi*r2)**2)
reduced_L1 = L1[r4**2 <= 1 - L1]
return 1-2*reduced_L1
运行它会带来以下好处:
>>> algorithm_2(1, 50)
array([-0.21110547, -0.70285195, 0.0475383 , -0.20860877, -0.07776909,
-0.21907097, 0.70566776, 0.3207524 , 0.71130986, 0.45789795,
0.15865965, -0.13757757, 0.04306286, 0.46003952])
如果您想要一个始终精确返回N
-ary向量的函数,您可以编写一个包装器来不断调用上面的函数,然后连接这些数组。如下所示:
def algorithm_3(k, N):
total_size =0
random_arrays = []
while total_size < N:
random_array = algorithm_2(k, N)
total_size += len(random_array)
random_arrays.append(random_array)
return np.hstack(random_arrays)[:N]
https://stackoverflow.com/questions/51715173
复制相似问题