在这个帖子中,@Thomas Lux提供了一个很好的解决方案,可以生成半径为r=1的n维球内的均匀随机点。但是现在我想生成笛卡尔坐标为整数的点。我不知道除了在立方体中生成随机点并扔掉范数大于1的点之外还有什么方法。
我不知道是否简单地使用randint
或将np.floor()
推入向量中就可以做到。
在这个帖子中,@Thomas Lux提供了一个很好的解决方案,可以生成半径为r=1的n维球内的均匀随机点。但是现在我想生成笛卡尔坐标为整数的点。我不知道除了在立方体中生成随机点并扔掉范数大于1的点之外还有什么方法。
我不知道是否简单地使用randint
或将np.floor()
推入向量中就可以做到。
对于均匀的实数样本,简单地使用round()
几乎可以达到目的。但是球边附近的整数点出现的概率会更低。因为在球内采样时,某个点上的超立方体邻居不足一半都被包含在内。
然而有一个简单的解决方法。在一个完全包含所有此类超立方体的球中生成实数样本,半径 r+sqrt(n)/2
应该足够,然后应用四舍五入,最后丢弃距离r
之外的整数点。
当然,外球的大小可能比内球大得多,这取决于r
和n
,但丢弃率应该会更好。
n
的增长,外球应该呈指数级增长。这意味着大多数尝试都会失败(请参见我上面的评论)。我想这应该比在超立方体中进行朴素探测好一些,如果球体的半径很大的话。事实上,在半径为 r
的 D
-超球体中找到一个点的概率是 (r/(r+1))**D
。这意味着只要 r
不小且 D
不是很大,这个解决方案就很好。例如,当 r=5
和 D=15
时,6% 的点将在内部超球体中。当 D=40
时,0.07%。r=100,n=10
和r=10,n=100
的情况可能需要不同的算法。不知道OP需要哪种情况。 - Karolis Juodelė(r/(r+D**0.5/2))**D
。因此,先前的示例分别为0.7%和0.0000003%。D
应该很小。当r > O(D**1.5)
时,您的解决方案很好。当r
相当小时,问题非常难以解决,而D
很大(看起来像非线性整数优化)。无论如何,这是一个有趣的解决方案。 - Jérôme Richardr
很小而D
很大,那么整数坐标几乎都是0,只有少数几组相似的点以多种方式排列。例如,如果r=3
,则球中的所有整数点要么是3,0...,要么是2,2,1,0...,要么是2,1,1,1,1,1,0...,要么是1,1,1,1,1,1,1,1,1,0...,或者它们的任何子集,或者带有一些负号。这不是一个巨大的家族,很容易看出每个家族有多大,也很容易从中取样。 - Karolis Juodelė
randint
解决方案应该可以工作,但是当D很大时,nD球体积比其边界框的体积慢得多,因此非常低效。np.floor
可能不起作用,因为它应该会引入分布偏差(除非您进行一些非平凡的校正,否则不再完全随机)。据我所知,这是一个相当复杂的问题。除此之外,你是指笛卡尔坐标系吗? - Jérôme RichardD
很大时,这种朴素方法确实不太有效。请参阅 https://en.wikipedia.org/wiki/Volume_of_an_n-ball 了解更多信息。在二维空间中,圆盘占随机二维正方形空间的78%。在三维空间中,它是51%。但在15D中,它只有0.001%,非常小。这意味着100_000个整数中会有99_999个被过滤掉。事实上,所需测试点的数量随着D
的增加呈指数级增长。当D>40
时,这种方法甚至无法在合理的时间内(即至少几周)找到一个超球体中的点。 - Jérôme Richard