查询R ^ N中的大量多维点

时间:2015-08-10 17:34:18

标签: algorithm data-structures

我正在考虑列出/计算R ^ N(在欧几里德空间意义上)中的整数点的数量,在某些几何形状内,例如圆形和椭圆形,受各种条件限制,对于小N.我的意思是N< 5,条件是多项式不等式。

作为一个具体的例子,取R ^ 2。我可能想要运行的一个查询是“椭圆中有多少个整数点(由x = 4 cos(theta)参数化,y = 3 sin(theta)),这样y * x ^ 2 - x * y = 4?“

我可以在Haskell中实现这个:

ghci> let latticePoints = [(x,y) | x <- [-4..4], y <-[-3..3], 9*x^2 + 16*y^2 <= 144, y*x^2 - x*y == 4]

然后我会:

ghci> latticePoints
[(-1,2),(2,2)]

这确实回答了我的问题。

当然,这是一个非常天真的实现,但它展示了我正在努力实现的目标。 (我也只是在这里使用Haskell,因为我觉得它最直接地表达了潜在的数学思想。)

现在,如果我有类似“在R ^ 5中,在半径为1,000,000的4球中有多少个整数点,满足x ^ 3 - y + z = 20?”,我可能会尝试这样的事情:

ghci> :{
Prelude| let latticePoints2 = [(x,y,z,w,v) | x <-[-1000..1000], y <- [-1000..1000],
Prelude|                      z <- [-1000..1000], w <- [-1000..1000], v <-[1000..1000],
Prelude|                      x^2 + y^2 + z^2 + w^2 + v^2 <= 1000000, x^3 - y + z == 20]
Prelude| :}

所以,如果我现在输入:

ghci> latticePoints2

不会发生太多......

我想这个问题是因为它有效地循环了2000 ^ 5(32千万亿!)点,而且我期望计算机处理这个问题显然是不合理的。我无法想象在Python或C中执行类似的实现也会有所帮助。

因此,如果我想以这种方式解决大量问题,那么在通用算法或数据结构方面,最好的选择是什么呢?我在另一个线程(Count number of points inside a circle fast)中看到,有人提到了四叉树以及K-D树,但我不知道如何实现它们,也不知道如何在实现后对其进行适当的查询。

我知道其中一些数字相当大,但是我要处理的最大的圆圈,椭圆等是半径10 ^ 12(一万亿),我当然不需要处理R ^ N,其中N> 5.如果上述情况不可能,我有兴趣知道哪种数字可行?

3 个答案:

答案 0 :(得分:2)

没有一般方法可以解决这个问题。找到代数方程的整数解(这种方程称为Diophantine equations)的问题是不可判定的。显然,你可以编写这种方程式,这样求解方程最终等同于决定给定的图灵机是否会停止给定的输入。

在您列出的示例中,您始终将点限制在一些表现良好的形状上,如椭圆或球体。虽然这类特殊问题绝对是可以判断的,但我怀疑你能否有效地解决这些问题以获得更复杂的曲线。我怀疑有可能构造一些简短的公式来描述大多数是空的但有一个巨大的边界框的曲线。

如果你碰巧知道更多关于你试图解决的问题的结构 - 例如,如果你总是处理球体或省略号 - 那么你可能能够找到快速的算法这个问题。但总的来说,我并不认为你能比蛮力做得更好。我愿意承认(事实上,希望有人)会证明我错了。

答案 1 :(得分:0)

kd-tree方法背后的想法是你递归细分搜索框并尝试一次排除整个框。给定当前框,使用一些方法,或者(a)声明框中的所有点都与谓词匹配(b)声明框中的任何点都不匹配谓词(c)不做声明(一种可能性,可能特别是在哈斯克尔方便:interval arithmetic)。在(c)中,将盒子切成两半(比如沿着最长尺寸)并递归计数。显然,这种方法可以随时选择(c),这就是蛮力;这里的目标是尽可能地做(a)或(b)。

此方法的性能非常依赖于它的实例化方式。尝试一下 - 它不应该超过几十行代码。

答案 2 :(得分:0)

对于连接良好的区域,假设您的形状明显小于包含的搜索空间,并且给定种子点,您可以执行增长/构建算法:

Given a seed point:
Push seed point into test-queue
while test-queue has items:
    Pop item from test-queue
    If item tests to be within region (eg using a callback function):
        Add item to inside-set
        for each neighbour point (generated on the fly):
            if neighbour not in outside-set and neighbour not in inside-set:
               Add neighbour to test-queue
    else:
        Add item to outside-set
return inside-set

诀窍是找到函数内部的初始种子点。

确保您的set实施提供O(1)重复检查。当表面积超过体积时,这种方法最终将以大量尺寸分解,但对于5个尺寸应该没问题。