2点之间平均距离的期望值偏差'on '一个球体
Deviation from expected value of mean distance between 2 points 'on ' a sphere
我试图通过取多个随机案例的平均值来验证各种 3-D 和 2-D 结构中两点之间的平均距离。几乎一直以来,除了球体表面上的点外,我都获得了相当不错的准确度。我的代码使用受 this answer 启发的高斯分布(请参阅投票第二多的答案)
这里是 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 here
可以说绝对差别不是很大。但是在任何 运行 上与预期值的百分比偏差约为 1%。另一方面,在具有其他形状和相同数量随机案例的所有其他类似程序中,百分比偏差平均约为 0.05%。
另外,代码returns的值总是小于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)
两个点的初始随机值包含在立方体中,而不是球体中。每个向量按 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
正如所解释的那样,这个小型 MC 模拟的随机抽样没有以正确的方式完成。
您想提取均匀分布在球体表面的随机点。最简单的方法是使用极坐标并随机选择角度 theta(0-pi)和 phi(0-2pi)。
如果您想保持笛卡尔坐标系,您必须使用已知的变换矩阵将您的分布从笛卡尔坐标系转换为 3-d 极坐标系。
我试图通过取多个随机案例的平均值来验证各种 3-D 和 2-D 结构中两点之间的平均距离。几乎一直以来,除了球体表面上的点外,我都获得了相当不错的准确度。我的代码使用受 this answer 启发的高斯分布(请参阅投票第二多的答案)
这里是 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 here
可以说绝对差别不是很大。但是在任何 运行 上与预期值的百分比偏差约为 1%。另一方面,在具有其他形状和相同数量随机案例的所有其他类似程序中,百分比偏差平均约为 0.05%。
另外,代码returns的值总是小于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)
两个点的初始随机值包含在立方体中,而不是球体中。每个向量按 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
正如所解释的那样,这个小型 MC 模拟的随机抽样没有以正确的方式完成。
您想提取均匀分布在球体表面的随机点。最简单的方法是使用极坐标并随机选择角度 theta(0-pi)和 phi(0-2pi)。
如果您想保持笛卡尔坐标系,您必须使用已知的变换矩阵将您的分布从笛卡尔坐标系转换为 3-d 极坐标系。