我正在尝试做一个简单的“人群”模型,并且需要在2D区域内分配随机点。这个半伪代码是我最好的尝试,但是在我运行它之前我就能看到很大的问题,因为对于密集的人群来说,新点太近的可能性会很快变得非常高,这使得效率非常低且容易发生失败,除非价值被微调。可能也会出现签名值,但为了简单起见,我将其留下。
int numPoints = 100;
int x[numPoints];
int y[numPoints];
int testX, testY;
tooCloseRadius = 20;
maxPointChecks = 100;
pointCheckCount = 0;
for (int newPoint = 0; newPoint < numPoints; newPoint++ ){
//Keep checking random points until one is found with no other points in close proximity, or maxPointChecks reached.
while (pointCheckCount < maxPointChecks){
tooClose = false;
// Make a new random point and check against all previous points
testX = random(1000);
testY = random(1000);
for ( testPoint = 0; testPoint < newPoint; testPoint++ ){
if ( (isTooClose (x[testPoint] , y[testPoint], textX, testY, tooCloseRadius) ) {
tooClose = true;
break; // (exit for loop)
}
if (tooClose == false){
// Yay found a point with some space!
x[newPoint] = testX;
y[newPoint] = testY;
break; // (exit do loop)
}
//Too close to one of the points, start over.
pointCheckCount++;
}
if (tooClose){
// maxPointChecks reached without finding a point that has some space.
// FAILURE DEPARTMENT
} else {
// SUCCESS
}
}
// Simple Trig to check if a point lies within a circle.
(bool) isTooClose(centerX, centerY, testX, testY, testRadius){
return (testX - centreX)^2 + (testY - centreY)^2) < testRadius ^2
}
在Google搜索主题后,我相信我所做的就是拒绝采样(?),自适应拒绝采样可能是更好的方法,但数学太复杂了。
是否有任何优雅的方法可以实现这一目标,而不需要统计学位?
答案 0 :(得分:5)
对于您提出的生成随机样本的最佳方法的问题是使用Poisson Disk Sampling。
https://www.jasondavies.com/poisson-disc
现在,如果您想以简单的方式对矩形中的随机点进行采样。只是 从0到最大尺寸的长度每个点采样两个值。
如果表示较小维度的值大于该维度,则抛弃该对,然后重试。
伪代码:
while (need more points)
begin
range = max (rect_width, rect_height);
x = uniform_random(0,range);
y = uniform_random(0,range);
if (x > rect_width) or (y > rect_height)
continue;
else
insert point(x,y) into point_list;
end
您采样两个长度中较大者的原因是,当长度不同时,使统一选择标准等效。
例如假设一侧长度为K而另一侧长度为10K。并假设使用的数字类型的分辨率为K的1/1000,然后对于较短的一侧,只有1000个可能的值,而对于较长的一侧,有10000个可能的值可供选择。 1/1000的概率与1/10000不同。简单地说,短边的坐标值比长边的坐标值高10倍 - 这意味着采样不是真正均匀的。
您希望确保生成的点与任何已生成点之间的距离不近的场景的伪代码:
while (need more points)
begin
range = max (rect_width, rect_height)
x = uniform_random(0,range);
y = uniform_random(0,range);
if (x > rect_width) or (y > rect_height)
continue;
new_point = point(x,y);
too_close = false;
for (p : all points)
begin
if (distance(p, new_point) < minimum_distance)
begin
too_close = true;
break;
end
end
if (too_close)
continue;
insert point(x,y) into point_list;
end
答案 1 :(得分:0)
虽然Poisson Disk解决方案通常很好而且花花公子,但我想指出一种使用准随机数的替代方案。对于准随机Sobol序列,有一个陈述表明点之间的最小正距离达到0.5 * sqrt(d)/ N,其中d
是问题的维度(在你的情况下为2),并且N
是在超立方体中采样的点数。该男子自己撰写的论文http://www.sciencedirect.com/science/article/pii/S0378475406002382。
为什么我认为它应该是Python?对不起这是我的错。对于最适合调用GSL的C类语言,函数名称为gsl_qrng_sobol
。在d = 2时使用它的示例与here