您能否详细说明您是如何得出答案的?
嗯,主要问题在于获得一种公平的方式来采样坐标 X 的非均匀分布。
从初等几何来看,上三角形x0部分的面积为:(1/2) * (x0 + 1)2。由于这个上三角形的总面积等于 2,因此上三角形内 (X 0) 的累积概率 P 为:P = (1/4) * (x 0 + 1)2.
所以,倒置最后一个公式,我们有:x0 = 2*sqrt(P) - 1
现在,根据Inverse Transform Sampling 定理,我们知道我们可以通过重新解释 P 作为随机变量 U0公平抽样 /sub> 均匀分布在 0 和 1 之间。
在 Python 中,这给了我们:
u0 = random.uniform(0.0, 1.0)
x = (2*math.sqrt(u0)) - 1.0
或等效:
u0 = random.random()
x = (2 * math.sqrt(u0)) - 1.0
请注意,这与@SamMason 的出色答案基本相同。那件事来自一般统计原理。它也可以用来证明 3D 球体上纬度的公平采样由 arcsin(2*u - 1) 给出。
所以现在我们有了 x,但我们仍然需要 y。底层的二维密度是均匀的,因此对于给定的 x,y 的所有可能值都是均匀分布的。
y 的可能值区间为 [-x, 1]。因此,如果 U1 是另一个均匀分布在 0 和 1 之间的独立随机变量,则可以从等式中得出 y:
y = (1+x) * u1 - x
在 Python 中由以下方式渲染:
u1 = random.random()
y = (1+x)*u1 - x
总的来说,Python代码可以这样写:
import math
import random
import matplotlib.pyplot as plt
def mySampler():
u0 = random.random()
u1 = random.random()
x = 2*math.sqrt(u0) - 1.0
y = (1+x)*u1 - x
return (x,y)
#--- Main program:
points = (mySampler() for _ in range(10000)) # an iterator object
xx, yy = zip(*points)
plt.scatter(xx, yy, s=0.2)
plt.show()
从图形上看,结果看起来足够好:
旁注:更便宜的临时解决方案:
总是有可能在整个正方形中均匀采样,而拒绝 x+y 和恰好为负的点。但这有点浪费。通过注意“坏”区域与“好”区域具有相同的形状和面积,我们可以得到一个更优雅的解决方案。
所以如果我们得到一个“坏”点,而不是仅仅拒绝它,我们可以用它关于 x+y=0 分割线的对称点来替换它。这可以使用以下 Python 代码完成:
def mySampler2():
x0 = random.uniform(-1.0, 1.0)
y0 = random.uniform(-1.0, 1.0)
s = x0+y0
if (s >= 0):
return (x0, y0) # good point
else:
return (x0-s, y0-s) # symmetric of bad point
这也很好用。这可能是关于 CPU 时间的最便宜的解决方案,因为我们不拒绝任何内容,而且我们不需要计算平方根。