找到d维空间中一组n个点的直径

时间:2014-12-11 01:47:21

标签: algorithm computational-geometry

我很有兴趣在128个维度中找到两个点集的直径。第一个有10000点,第二个1000000。因此我想做一些比O(n²)的天真方法更好的东西。该算法将能够处理任意数量的点和维度,但我目前对这两个特定的数据集非常感兴趣。

我非常有兴趣获得速度超过准确性,因此,基于this,我会找到点集的(近似)边界框,通过计算每个坐标的最小值和最大值,因此O( n * d)时间。然后,如果我找到此框的直径,问题就解决了

在3d情况下,我可以找到一侧的直径,因为我知道两条边,然后,我可以将毕达哥拉斯定理应用于另一边,这是垂直于这一边。但我不确定这一点,当然,我看不出如何将它推广到d维。


可以找到一个有趣的答案here,但它似乎特定于3个维度,我想要一个d维方法。

有趣的论文:计算高维欧氏空间中点集的直径。 Link。但是,在这个阶段,对我来说实现算法似乎太多了。

3 个答案:

答案 0 :(得分:3)

针对此问题的经典2近似算法(运行时间为O(nd))是选择任意点,然后将最大距离返回到另一个点。直径不小于此值,且不大于此值的两倍。

答案 1 :(得分:2)

我想添加评论,但没有足够的声誉......

我只想警告其他读者,“边界框”解决方案非常不准确。以半径为1的欧几里德球为例。该组的直径为2,但其边界框为[-1,1] ^ d,其直径为d的平方根的两倍。对于d = 128,这已经是一个非常糟糕的近似值。

粗略估计,我会留下David Eisenstat的回答。

答案 2 :(得分:1)

有一种基于精度的算法在任何维度上都能很好地运行,它基于计算轴向边界框的尺寸。

这个想法是可以找到轴边界框长度函数的下边界和上边界,因为它的偏导数是有限的,并且取决于轴之间的角度。

2d空间中两个轴之间的局部最大值导数的极限可以计算为:

sin(a / 2)*(1 + tan(a / 2)) 这意味着,例如,对于轴之间的90度,边界是1.42(sqrt(2))

当a =>时减少到a / 2; 0,所以上边界与角度成正比。

对于多维情况,公式略有不同,但仍然很容易计算。

因此,局部最小值的搜索在对数时间内进行卷积。

好消息是我们可以并行搜索这样的局部最大值。 此外,我们可以根据迄今为止取得的最佳结果以及点本身过滤出搜索区域,这些点本身也是最差区域内搜索的下限。

算法的最坏情况是所有点都放在球体表面上。

这可以进一步改进:当我们检测到仅在几个点上运行的本地搜索时,我们将交换到该特定轴的暴力。它工作得很快,因为我们只需要受特定局部搜索影响的点,这些点可以确定为由共享同一轴的特定角度的两个相对球面实际约束的点。

很难找出大O符号,因为它取决于所需的精度和点的分布(当大多数点在球体表面上时很差)。

我使用的算法在这里:

  1. 设置初始角度a = pi / 2.
  2. 为每个维度选择一个轴。角度和轴形成初始“桶”
  3. 对于每个轴,通过将所有点投影到轴上,并在轴上找到坐标的最小值和最大值来计算该轴上的跨度。
  4. 计算有趣的直径的上限和下限。它基于以下公式:sin(a / 2)*(1 + tan(a / 2))并乘以测量系数,根据当前轴投影的长度计算。
  5. 下一步,同时杀死每个维度下限范围内的所有点。
  6. 对于每个exis,如果高于上限的点数小于某个合理数量(通过实验计算),则在所讨论的点集上使用强力(N ^ 2)计算,并调整下限,并杀死下一步的轴。
  7. 下一步,杀死所有的轴,它们的所有点都在下限之下。
  8. 如果精度令人满意(上限 - 下限)< epsilon,然后返回上限作为结果。
  9. 对于所有幸存的轴,在该轴上有一个虚拟圆锥(实际上是两个相对的圆锥),它覆盖虚拟球体上包围立方体面的某个区域。如果我没弄错的话,它的角度将是* sqrt(2)。将新角度设置为/ sqrt(2)。创建一整桶新轴(2 *维数),因此新的锥形区域将覆盖初始锥形区域。这对我来说很难,因为我对n> 3维案例的想象力不够。
  10. 从步骤(3)继续。
  11. 你可以对程序进行并列化,同步目前为(5)到(7)中的点计算的限制。