Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在两个具有最小距离的点列表中高效地找到点对?_Python_Math - Fatal编程技术网

Python 如何在两个具有最小距离的点列表中高效地找到点对?

Python 如何在两个具有最小距离的点列表中高效地找到点对?,python,math,Python,Math,pointListA和pointListB的长度几乎为5000或更多。我的任务是为pointListA中的每个点找到pointListB中的点,以便这两个点之间的距离最小。 我的问题是找到一个有效的方法来完成这项任务。我已经尝试了一些方法,比如遍历两个列表,但是速度太慢了。那么,有什么建议给我吗 编辑1: 我很抱歉刚才在标题中对我的描述。现在我将其修改为“如何有效地在两个具有最小距离的点列表中查找点对” 事实上,我想要这样的结果 pointListA = [(13,45),(33,78),...

pointListA和pointListB的长度几乎为5000或更多。我的任务是为pointListA中的每个点找到pointListB中的点,以便这两个点之间的距离最小。 我的问题是找到一个有效的方法来完成这项任务。我已经尝试了一些方法,比如遍历两个列表,但是速度太慢了。那么,有什么建议给我吗

编辑1: 我很抱歉刚才在标题中对我的描述。现在我将其修改为“如何有效地在两个具有最小距离的点列表中查找点对” 事实上,我想要这样的结果

pointListA = [(13,45),(33,78),...,(360,240)]
pointListB = [(20,36),(47,32),...,(265,322)]

假设您希望从具有相同索引的每个列表中获取两个点,您可以
zip
两个列表。如果您指的是从A和B中选择的任意点之间的最小距离,则应使用
itertools.product

minDistansceList = [((13,45),(a point in pointListB)),((33,78),(a point in pointListB)).....((360,240),(a point in pointListB))]
更新后:

>>> from itertools import starmap, product
>>> from math import sqrt, pow

>>> def distance(p1, p2):
...     return sqrt(pow(p2[1] - p1[1], 2) + pow(p2[0] - p1[0], 2))

>>> pointListA = [(13,45), (33,78), (360,240)]
>>> pointListB = [(20,36), (47,32), (265,322)]

>>> min(starmap(distance, product(pointListA, pointListB)))
11.40175425099138

假设您希望从具有相同索引的每个列表中获取两个点,您可以
zip
两个列表。如果您指的是从A和B中选择的任意点之间的最小距离,则应使用
itertools.product

minDistansceList = [((13,45),(a point in pointListB)),((33,78),(a point in pointListB)).....((360,240),(a point in pointListB))]
更新后:

>>> from itertools import starmap, product
>>> from math import sqrt, pow

>>> def distance(p1, p2):
...     return sqrt(pow(p2[1] - p1[1], 2) + pow(p2[0] - p1[0], 2))

>>> pointListA = [(13,45), (33,78), (360,240)]
>>> pointListB = [(20,36), (47,32), (265,322)]

>>> min(starmap(distance, product(pointListA, pointListB)))
11.40175425099138

尝试使用
str(pointListA/pointlistB)%str(pointListA/pointlistB)

尝试使用
str(pointListA/pointlistB)%str(pointListA/pointlistB)

您可以使用元组作为由距离填充的字典的键,然后从中提取最小值

>>> sorted(product(pointListA, pointListB), key=lambda t: distance(t[0], t[1]))
>>> [((13, 45), (20, 36)), ((13, 45), (47, 32)), ((33, 78), (20, 36)), ...]

可以将元组用作由距离填充的字典的键,然后从中提取最小值

>>> sorted(product(pointListA, pointListB), key=lambda t: distance(t[0], t[1]))
>>> [((13, 45), (20, 36)), ((13, 45), (47, 32)), ((33, 78), (20, 36)), ...]

我不确定,但您可以通过从使用结果得到的矩阵中提取结果,从而有效地做到这一点:

pointListA = ((0,1),(1,2),(3,4),(2,2))
pointListB = ((0,1),(1,2),(3,4),(2,2))
dists = {}
for p0 in pointListA:
    dists[p0] = {}
    for p1 in pointListB:
         d = 0
         for k in [0,1]:
             d += (p0[k]-p1[k])**2
         dists[p0][p1] = d**0.5

minDistPairs = tuple([(k,min(dists[k], key=dists[k].get)) for k in dists])
print minDistPairs
我们采用对角线的原因是因为
cdist
返回从a中的每个点到B中的每个点的距离矩阵。我关心的是,这将生成AxB中间结果以提取len(a)结果的向量。但它将在NumPy的低级(编译的二进制)代码中进行矢量化操作,并可能利用CPU自己的矢量指令集扩展(例如x86上的SSE)


我怀疑有某种方法可以消除额外的计算,但我知道的NumPy不够。

我不确定,但您可以从使用结果得到的矩阵中提取,从而有效地实现这一点:

pointListA = ((0,1),(1,2),(3,4),(2,2))
pointListB = ((0,1),(1,2),(3,4),(2,2))
dists = {}
for p0 in pointListA:
    dists[p0] = {}
    for p1 in pointListB:
         d = 0
         for k in [0,1]:
             d += (p0[k]-p1[k])**2
         dists[p0][p1] = d**0.5

minDistPairs = tuple([(k,min(dists[k], key=dists[k].get)) for k in dists])
print minDistPairs
我们采用对角线的原因是因为
cdist
返回从a中的每个点到B中的每个点的距离矩阵。我关心的是,这将生成AxB中间结果以提取len(a)结果的向量。但它将在NumPy的低级(编译的二进制)代码中进行矢量化操作,并可能利用CPU自己的矢量指令集扩展(例如x86上的SSE)


我怀疑有某种方法可以消除额外的计算,但我知道的NumPy不够。

作为一种优化,如果在距离0处找到一个点,您可以利用找到最近点的事实,并利用使平方距离最小的点使距离最小的事实:

#!/bin/python
import numpy as np
from scip.spatial.distance import cdist

pointListB = [(20,36),(47,32),(265,322)]
pointListA = [(13,45),(33,78),(360,240)]
A = np.array(pointListA)
B = np.array(pointListB)
distances = np.diagonal(cdist(A, B, 'euclidean'))
# Minimum distance:
min_dist = np.min(distances)
然后


在我2岁的笔记本电脑上大约需要18秒作为一种优化,如果在距离0处找到一个点,您可以利用找到最近点这一事实,并利用一个使距离平方最小的点:

#!/bin/python
import numpy as np
from scip.spatial.distance import cdist

pointListB = [(20,36),(47,32),(265,322)]
pointListA = [(13,45),(33,78),(360,240)]
A = np.array(pointListA)
B = np.array(pointListB)
distances = np.diagonal(cdist(A, B, 'euclidean'))
# Minimum distance:
min_dist = np.min(distances)
然后


在我2岁的笔记本电脑上花了大约18秒

我对刚才标题中的描述感到抱歉。现在,我更新了我的问题。那么,关于这个问题有什么想法吗?这不是我的操作,我会给你一个答案:-)是的,我忘了用min({},{}.get)来获取min键。。。关于这一点,我应该测试得更好…还有一个问题,两个列表的长度超过5000,我只是在我的电脑上用intel i7 core测试代码,它需要23秒来完成计算,有没有办法使它更有效?我很抱歉刚才在标题中描述了。现在,我更新了我的问题。所以,你知道这个问题吗?这不是我的职责,我会给你一个答案:-)是的,我忘了用min({},{}.get)来获取min键。。。关于这一点,我应该测试得更好…还有一个问题,两个列表的长度超过5000,我只是在我的电脑上用英特尔i7内核测试代码,需要23秒才能完成计算,有没有办法让它更有效?你不需要参加sqrt,因为你是在最小化是的,在我认为OP想要看到最小距离之前,不是按最小距离排列的配对列表。我是指从A和B中选择的任何点之间的最小距离。你不需要进行sqrt,因为你是最小的。是的,在我认为OP想要看到最小距离之前,不是按最小距离排序的配对列表。我的意思是从A和位中选择的任何点之间的最小距离在我的计算机上大约需要8秒,这是perfect@Elivis这个问题称为最近邻搜索。以预处理
pointListB
为代价,您应该能够将其归结为
O(n*log(n))
而不是
O(n^2)
。预处理看起来很重要,可能不值得,但如果这被证明是一个瓶颈,你可能需要研究更复杂的算法(比如使用k-d树的算法)。在我的计算机上大约需要8秒钟,这是很重要的perfect@Elivis这个问题称为最近邻搜索。以预处理
pointListB
为代价,您应该能够将其归结为
O(n*log(n))
而不是
O(n^2)
。预处理似乎很重要,可能不值得,但如果这被证明是一个瓶颈,您可能需要研究更复杂的算法(例如使用