我试图在半圆内均匀地生成一组点。
size = 1000
t = np.random.random(size)*np.pi*2
u = np.random.random(size) + np.random.random(size)
r = np.where(u > 1, 2 - u, u)
x = r*cos(t)
y = r*sin(t)
coor = (x,y)
for idx, value in enumerate(y):
if value<0:
x[idx]=-3
y[idx]=-3
f, ax = plt.subplots(figsize = (3,3))
plt.scatter(x, y)
这段代码有2个错误。
由于点比其他点更位于中心,因此以下所示的图不是统一的。
另一个如下所示的图可以看作是统一的。
任何解决错误的想法都会受到赞赏。
答案 0 :(得分:6)
您应生成均匀分布的角度phi
,并考虑均匀生成的半径sqrt
的{{1}}(考虑到我们要在区域均匀采样< / em>,请参见下面的说明),以确保您在半圆上均匀地采样点。
r
要在(半)圆上生成均匀分布的点,我们必须确保每个无限小区域或线段都以相同的概率“命中”。我们可以简单地从均匀随机分布import numpy as np
import matplotlib.pyplot as plt
# sample
size = 10000
R = 1
phi = np.random.random(size=size) * np.pi
r = np.sqrt(np.random.random(size=size)) * R
# transform
x = r * np.cos(phi)
y = r * np.sin(phi)
# plot
f = plt.figure(figsize=(12,12))
a = f.add_subplot(111)
a.scatter(x, y, marker='.')
a.set_aspect('equal')
plt.show()
乘以phi
(所以[0, 1)
)中抽取np.pi
,因为所有角度都应具有相同的概率被采样。但是,如果我们从[0, pi)
中的均匀随机分布中采样r
,则由于 area 的生长像{ {1}}。考虑到这一事实,我们必须相应地对采样的半径进行偏置,在这种情况下,我们可以通过简单地取平方根([0, 1)
)来应用偏置,以将正确的权重应用于采样的半径值,并考虑到较大的外圈面积。
在这里可以找到更好,更详尽的解释:https://stackoverflow.com/a/50746409/1170207
由于此方法基本上是一种反转采样方法,因此我们对其进行比较 性能的拒绝采样算法。
r**2
使用拒绝抽样方法,我们还不能确保我们选择一定数量的变量,因此我们必须重复该过程,直到有了为止。除非我们接受对太多的值进行采样并丢弃其他值,否则不能很好地将其向量化。
答案 1 :(得分:2)
在R中:
runif_in_semicircle <- function(n, radius=1){
theta <- runif(n, 0, pi)
r <- radius * sqrt(runif(n))
cbind(r*cos(theta), r*sin(theta))
}
sims <- runif_in_semicircle(1000)
plot(sims[,1], sims[,2], asp=1, pch=19)
我们可以通过评估一个积分来检查它是否有效。
# integrand example
f <- function(x) x[1]^2 + exp(x[2])
set.seed(666)
sims <- runif_in_semicircle(10000)
fsims <- apply(sims, 1, f)
mean(fsims)*pi/2 # approximates the integral of f over the half-disk
# 2.890905
现在,我们用数字评估f
的积分。
library(SphericalCubature)
adaptIntegrateBallPolar(f, n=2, lowerLimit = 0, upperLimit = pi)
# $integral
# [1] 2.880598
答案 2 :(得分:1)
您应该在封闭的矩形中生成点,并删除不在半圆中的点
# generate about n points in a half-circle with
# given center (x, y) and given radius, and y>0
points <- function(x, y, radius, n) {
n2 = n * 4 / pi # each point has pi/4 probability to survive
# make [-1, 1] * [-1, 1] square
xs = runif(n2, -1, 1)
ys = runif(n2, 0, 1) # or just runif(n2)
points = cbind(xs, ys)
# keep only points in circle with center (0,0) and radius 1 with y>0
ind = (xs**2 + ys**2 <= 1) # the condition ys>=0 is obeyed already
points = points[ind,]
# move/stretch to given center and radius
points = points * radius
points[,1] = points[,1] + x
points[,2] = points[,2] + y
}
# generate about 1000 points with center(1,1) and radius 3
points = f(1, 1, 3, 1000)
# plot them, making them smaller for better visibility
plot(points, cex=0.3)
答案 3 :(得分:0)
您可以在R中尝试以下方法:
size <- 1000
maxRad <- 1 #maximum radius of the half-circle
r <- runif(1000,0,maxRad) #generate random radius
phi <- runif(size,0,pi) #generate angle for polarcoordinates (between 0 and pi since you want a halfcircle)
x <- r*cos(phi) #polarcoordinates
y <- r*sin(phi)
plot(x,y)
您可以将其放在函数中
halfCircle <- function(size, maxRad) {
r <- runif(1000,0,maxRad)
phi <- runif(size,0,1)*pi
x <- r*cos(phi)
y <- r*sin(phi)
plot(x,y)
}
并尝试它是否可以为您提供“更可接受的随机”结果。
答案 4 :(得分:0)
此方法使用Python
和拒绝算法。
首先在一个正方形中创建均匀分布的变量。然后拒绝所有您感兴趣的半圆之外的点。在这里,我选择了最简单的情况,但是如果您添加这些点的旋转,缩放和平移,它可以扩展到任何半圆。
代码如下:
import numpy as np
import matplotlib.pyplot as plt
n = 10000
r = 3 # radius
uniform_square = np.random.uniform(-r,r,(int(2.65*n),2))
radius = np.sqrt(uniform_square[:,0]**2 + uniform_square[:,1]**2)
uniform_circle = uniform_square[radius<=r,:]
uniform_half_circle = uniform_circle[uniform_circle[:,0]>=0,:]
final_points = uniform_half_circle[0:n,:]
fig, axs = plt.subplots(1, 1)
axs.scatter(final_points[:,0], final_points[:,1], marker='.')
axs.set_aspect('equal', 'box')
plt.show()
由于它对所有步骤都使用numpy,因此相对较快。要获得固定数量的点,请生成比您最初需要的更多的内容,并缩小数组的大小。由于我从一个完美的正方形(面积= 4)开始并且只需要一个半圆(面积= pi / 2),所以我们需要生成的点数是最后所需的大约2.6倍。
python中的for循环不是很快,因此请尝试仅使用numpy
函数和操作。
答案 5 :(得分:0)
不确定您的意思是“统一”。
这是一种沿x和y轴生成“均匀”分布点的方法,但效率不高
import numpy as np
import matplotlib.pyplot as plt
x = np.random.random(size) * 2 - 1
y = np.random.random(size)
r = np.sqrt(x**2 + y**2)
x[r > 1] = -3
y[r > 1] = -3
plt.plot(x, y, 'o')
plt.show()