0

我试图通过取多个随机案例的平均值来验证各种 3-D 和 2-D 结构中 2 点之间的平均距离。几乎在所有时间里,除了球体表面上的点的情况外,我都获得了相当不错的精度。我的代码使用受此答案启发的高斯分布(请参阅投票最多的第二个答案)

这是python代码:

import math as m
from random import uniform as u
sum = 0
for i in range(10000):
    x1 = u(-1, 1)
    y1 = u(-1, 1)
    x2 = u(-1, 1)
    y2 = u(-1, 1)
    z1 = u(-1, 1)
    z2 = u(-1, 1)
    if x1 == y1 == z1 == 0:
        sum += m.sqrt((x2) ** 2 + (y2) ** 2 + (z2) ** 2)
    elif x2 == y2 == z2 == 0:
        sum += m.sqrt((x1) ** 2 + (y1) ** 2 + (z1) ** 2)
    else:
        x1 /= m.sqrt(x1 ** 2 + y1 ** 2 + z1 ** 2)
        y1 /= m.sqrt(x1 ** 2 + y1 ** 2 + z1 ** 2)
        z1 /= m.sqrt(x1 ** 2 + y1 ** 2 + z1 ** 2)
        x2 /= m.sqrt(x2 ** 2 + y2 ** 2 + z2 ** 2)
        y2 /= m.sqrt(x2 ** 2 + y2 ** 2 + z2 ** 2)
        z2 /= m.sqrt(x2 ** 2 + y2 ** 2 + z2 ** 2)
        sum += m.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2 + (z1-z2) ** 2)
print(sum/10000)

预期值为 4/3,此处显示

可以说绝对差异不是很大。但是在任何运行中,与预期值的百分比偏差都在 1% 左右。另一方面,在所有其他具有其他形状和相同数量随机案例的类似程序中,平均偏差百分比约为 0.05%。

此外,代码返回的值始终小于 4/3。这是我最关心的问题。

我的猜测是我以错误的方式实现了算法。任何帮助表示赞赏。

编辑:

在意识到之前方法的错误之后,我现在,首先使用拒绝采样来获取位于球体内的点。这将确保在用它们的范数划分点向量后,得到的单位向量分布是均匀的。尽管如此,我得到了一个不同的结果,出乎意料地比前一个结果更偏离预期。更准确地说,该算法的极限接近 1.25。

这是代码:

sum2 = 0
size = 0
for t in range(10000):  # Attempt 2
    x1 = u(-1, 1)
    y1 = u(-1, 1)
    x2 = u(-1, 1)
    y2 = u(-1, 1)
    z1 = u(-1, 1)
    z2 = u(-1, 1)
    if (x1**2 + y1**2 + z1**2)>1 or (x2**2 + y2**2 + z2**2)>1 or x1==y1==z1==0 or x2==y2==z2==0: continue
    size += 1
    x1 /= m.sqrt(x1 ** 2 + y1 ** 2 + z1 ** 2)
    y1 /= m.sqrt(x1 ** 2 + y1 ** 2 + z1 ** 2)
    z1 /= m.sqrt(x1 ** 2 + y1 ** 2 + z1 ** 2)
    x2 /= m.sqrt(x2 ** 2 + y2 ** 2 + z2 ** 2)
    y2 /= m.sqrt(x2 ** 2 + y2 ** 2 + z2 ** 2)
    z2 /= m.sqrt(x2 ** 2 + y2 ** 2 + z2 ** 2)
    sum2 += m.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2 + (z1 - z2) ** 2)
print(size)
print(sum2/size)
4

2 回答 2

1

两个点的初始随机值包含在立方体中,而不是球体中。将每个向量缩放 1/length 后,向量在单位球体上,但它们并不均匀分布在球体表面。

与每个面的中心相比,您将倾向于在立方体的角附近获得更多矢量。由于向量倾向于在区域中聚集,因此它们之间的距离平均值小于 4/3。

这可以解决问题: https ://mathworld.wolfram.com/SpherePointPicking.html


这段代码对我有用:

from math import sqrt
from random import uniform


sum2 = 0
size = 0
while size < 100000:
    x1 = uniform(-1, 1)
    y1 = uniform(-1, 1)
    x2 = uniform(-1, 1)
    y2 = uniform(-1, 1)
    z1 = uniform(-1, 1)
    z2 = uniform(-1, 1)

    r1 = sqrt(x1**2 + y1**2 + z1**2)
    r2 = sqrt(x2**2 + y2**2 + z2**2)
    if r1 > 1 or r2 > 1 or x1==y1==z1==0 or x2==y2==z2==0: continue
    size += 1
    x1 /= r1
    y1 /= r1
    z1 /= r1
    x2 /= r2
    y2 /= r2
    z2 /= r2
    sum2 += sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2 + (z1 - z2) ** 2)
print(sum2/size)

输出是:

1.3337880809331075
于 2020-06-03T16:14:37.757 回答
0

正如所解释的,这个小型 MC 模拟的随机抽样没有以正确的方式完成。

您想提取均匀分布在球体表面上的随机点。最简单的方法是使用极坐标并随机选择角度 theta(0-pi)和 phi(0-2pi)。

如果你想保持笛卡尔坐标,你必须使用已知的从笛卡尔坐标系到 3-d 极坐标系的变换矩阵来变换你的分布。

于 2020-06-03T16:20:20.000 回答