N球上生成均匀分布随机点的算法

时间:2018-10-15 02:11:50

标签: python math

我还没有在Python上找到这种算法的实现

类似这样的东西:

有两个输入参数:

  • n-空间尺寸。
  • m-n-1球面上的点数。

我需要将它们大致均匀地排列在n球的表面上。

坐标轴位于n-1个球体的中心。 例如,在3D规则球体上,可以定位点like this

我认为,斐波那契算法在视觉上非常好。 我不知道n球是否存在类似的东西。 我有512D空间,我要在其中放置1000点甚至10,000点。

如何在python中执行此操作?

2 个答案:

答案 0 :(得分:2)

有一种简单的Muller and Marsaglia方法可以在超球面上生成均匀的分布。

生成具有高斯分布的n个变量(此处列出l)。它们形成一些向量。

找到该矢量的长度并对其分量进行归一化以提供单位长度结果

示例显示了在10d空间中在球体上生成一个点,并在视觉上检查了圆上的点包的均匀性(在2d中的球体,hystogram值应接近)

import random, math

#muller-marsaglia method
def spherepicking(n):
    while True:           #to get rid off [0,0,0,0] case
        l = [random.gauss(0, 1) for i in range(n)]
        sumsq = sum([x * x for x in l])
        if sumsq > 0:
            break
    norm = 1.0 / math.sqrt(sumsq)
    pt = [x * norm for x in l]
    return pt

print(spherepicking(10))

cnt = [0] * 18
for i in range(10000):
   pt = spherepicking(2)
   an = math.atan2(pt[1], pt[0]) + math.pi / 2
   cnt[math.floor(an * 9 / math.pi)] += 1
print(cnt)

-0.31811419572739935, 0.2845442135156396, -0.2849019746359018,
-0.1326796017012003, 0.7388447238721524, -0.287062305232526, 
-0.08794741714783766, 0.131707880836534, 0.22059937624019868, 
-0.13047162618106062]

[554, 560, 529, 589, 534, 538, 550, 558, 578, 556, 522, 553, 561, 513, 592, 583, 593, 537]

答案 1 :(得分:1)

使用与MBo相同的参数:(Muller 1959,Marsaglia 1972)-[https://mathworld.wolfram.com/HyperspherePointPicking.html]我使用numpy在python中展示了我的实现:

import numpy as np

def getRandomSamplesOnNSphere(N , R , numberOfSamples):
    # Return 'numberOfSamples' samples of vectors of dimension N 
    # with an uniform distribution on the (N-1)-Sphere surface of radius R.
    # RATIONALE: https://mathworld.wolfram.com/HyperspherePointPicking.html
    
    X = np.random.default_rng().normal(size=(numberOfSamples , N))

    return R / np.sqrt(np.sum(X**2, 1, keepdims=True)) * X

On the surface 而且,如果您需要在N-Sphere内内部生成点,则可以执行此操作(参考:https://math.stackexchange.com/q/87238

import numpy as np

def getRandomSamplesInNSphere(N , R , numberOfSamples):
    # Return 'numberOfSamples' samples of vectors of dimension N 
    # with an uniform distribution inside the N-Sphere of radius R.
    # RATIONALE: https://math.stackexchange.com/q/87238
    
    randomnessGenerator = np.random.default_rng()
    
    X = randomnessGenerator.normal(size=(numberOfSamples , N))
    U = randomnessGenerator.random((numberOfSamples , 1)) 
    
    return R * U**(1/N) / np.sqrt(np.sum(X**2, 1, keepdims=True)) * X

Inside the circle of radius 1