【问题标题】:Improve tuple distance computation algorithm for time efficiency改进元组距离计算算法以提高时间效率
【发布时间】:2017-06-21 16:04:35
【问题描述】:

我有一个算法可以计算每个点p(我的坐标值以一个元组表示)到我的元组列表中的每个其他元组的距离。

点列表:

centerList = [(54, 2991),
            (1717, 2989),
            (1683, 2991),
            (1604, 2991),
            (114, 2991),
            (919,222),
            (930,233)]

距离函数:

def getDistance(p0, p1):
    return math.sqrt((p0[0] - p1[0])**2 + (p0[1] - p1[1])**2)

计算点p 到元组列表中每个其他点的距离的算法。

i = 0
distanceList = []
for p in range(len(centerList)):
    while i < len(centerList):
        print centerList[p], centerList[i], getDistance(centerList[p], centerList[i])
        distance = getDistance(centerList[p], centerList[i])
        if distance < 20:
            distanceList.append(distance)
        i += 1
    i = p + 2

我当前的算法以一种并非多余的方式递增,但在当前状态下,它对于实际应用程序来说太粗暴了。我的问题在于我的实际centerList 包含数千个元组。

可以做些什么来提高这种元组比较算法的时间效率?

【问题讨论】:

  • 看起来您正在尝试计算每对点之间的距离。这本质上是 O(n^2),所以你可能想要并行化这个
  • 对于初学者,您可以放弃 sqrt。
  • 我猜你的算法有问题。 distance = getDistance(centerList[p], centerList[i]) 第一次迭代比较 centerList[0]centerlist[0]。这不会发生在 i 将是 i = p + 2 的后续迭代中。第一次迭代:getDistance(centerList[0], centerList[0]),第二次迭代:getDistance(centerList[1], centerList[2])... 为什么?从数学上讲,比较与同一点的距离为零。如果 x 和 y 以及 x=y 的距离,则 x 到 y 的距离为零。
  • 是的,很好。这就是我运行if distance &lt; 20 and distance &gt; 0 的原因

标签: python algorithm list distance point


【解决方案1】:

您可以将sklearn.metrics.euclidean_distancesnumpy 的布尔索引结合起来进行计算:

>>> from sklearn.metrics import euclidean_distances
>>> import numpy as np
>>> centerList = np.array(centerList)
>>> distances = euclidean_distances(centerList)
>>> distances[distances<20]
array([  0.        ,   0.        ,   0.        ,   0.        ,
         0.        ,   0.        ,  15.55634919,  15.55634919,   0.        ])

距离的计算使用以高速 C 语言开发的 numpy 矩阵代数。文档还强调了底层数学技术的效率:

出于效率原因,一对行之间的欧式距离 向量 x 和 y 计算为:

dist(x, y) = sqrt(dot(x, x) - 2 * dot(x, y) + dot(y, y))

与其他计算方式相比,此公式有两个优点 距离。首先,它在处理时具有计算效率 稀疏数据。其次,如果一个论点发生变化,但另一个仍然存在 不变,则可以预先计算 dot(x, x) 和/或 dot(y, y)。

【讨论】:

  • @DaOnlyOwner 不是复杂性的问题,更多的是 CPU 运行时间。
  • 效果很好!如果使用这种方法距离小于 20,有没有办法可以从 centerList 中删除其中一个元组?
  • 探戈需要两个人。一个坐标与一个坐标的距离可能小于 20,而与另一个坐标的距离大于 20。
【解决方案2】:

仅限numpy

import numpy

centerList = [(54, 2991), (1717, 2989), (1683, 2991), (1604, 2991), (114, 2991), (919,222), (930,233)]
centerList = numpy.array(centerList)

def getDistance(p0,p1):
    return numpy.linalg.norm(p0-p1)

将返回与您的 getDistance 函数相同的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-10
    • 2014-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多