Python中笛卡尔坐标列表的高效操作 背景:
我正在写一个程序,处理大量与各种规则形状的顶点网络相关的数据。我有一个工作生成器,它根据一系列用户输入参数生成与所述形状顶点对应的笛卡尔坐标列表。然后,数据被传递到过滤器,过滤器清除重复的条目、对数据进行排序和各种其他功能,从中清理的数据被馈送到画布模块,画布模块循环并绘制顶点 问题: 我需要实现一个新的过滤器,有效地在坐标中循环,将每一对与其他每一对进行比较,即Python中笛卡尔坐标列表的高效操作 背景:,python,algorithm,list,python-2.7,coordinates,Python,Algorithm,List,Python 2.7,Coordinates,我正在写一个程序,处理大量与各种规则形状的顶点网络相关的数据。我有一个工作生成器,它根据一系列用户输入参数生成与所述形状顶点对应的笛卡尔坐标列表。然后,数据被传递到过滤器,过滤器清除重复的条目、对数据进行排序和各种其他功能,从中清理的数据被馈送到画布模块,画布模块循环并绘制顶点 问题: 我需要实现一个新的过滤器,有效地在坐标中循环,将每一对与其他每一对进行比较,即(x1,y1)->(x2,y2)到(x1,y1)(xn,yn)(x2,y2)(x3,y3)到(x2,y2)(xn,yn)(xn,yn)
(x1,y1)
->(x2,y2)
到(x1,y1)
(xn,yn)
(x2,y2)(x3,y3)
到(x2,y2)
(xn,yn)
(xn,yn)
,例如,如果(x1,y1)
和(x5,y5)
之间的关系符合[(x5-x1)^2+(y5-y1)^2]=顶点间距^2
,那么这两组坐标将与其各自的列表条目编号配对,并附加到一个新列表中,其中一个条目的形式为:[(x1,y1),(x5,y5),0,4]
例如。实现这一目标最有效的方法是什么
我的尝试:
我已经在这里和各种指南中介绍了很多处理列表的方法。我尝试了嵌套的“for”和“if”循环,但发现虽然这种方法可以工作,但它会导致运行时间过长,并试图将问题分解为许多较小的for循环
进一步说明:
这样做的最终目的是为前端接口元素使用生成的坐标,并根据需要保存和导入。[(x1,y1),(x5,y5),0,4]
中的列表位置0和4的功能是使界面能够对坐标进行分组,以便以后在画布对象中使用。该方法应该能够处理潜在的数千个坐标
提前感谢您的帮助,我当然愿意改进我提供的措辞/信息和/或添加示例代码,如果不清楚我在任何方面的要求-我对此还是很陌生的!) 您基本上要检查的是:
对于每个顶点v
,查找所有顶点u
,使u
位于v
周围的半径圆顶点间距
上
如果您的积分分布不是所有的积分都很接近,我想有两种方法可以加快搜索速度:
加速此过程的最简单方法是按x坐标对点进行排序。这样,您就可以跳过许多比较。作为一个简单的示例,假设x坐标为[1,2,10,15,18,20,21]
和顶点间距=5
。您只需要将第一个顶点与第二个顶点进行比较,因为所有其他顶点都明显位于第一个顶点周围的圆之外
请注意,如果所有点都靠得很近,则此方法无效。换句话说,如果顶点间距=25
,则不能跳过任何比较
按照同样的思路,您可以使用二维图形。这相当于排序方法,但有两个维度。给定一个顶点(x,y)
和顶点间距=v
,您必须检查范围内的所有点([x-v,x+v],[y-v,y+v])
。使用与前面相同的示例,假设第一个点具有坐标(1,0)
,第二个点具有坐标(2,10)
,则无需将第一个顶点与任何东西进行比较
这两种方法都是启发式的,不会对最坏情况下的运行时间进行任何改进(恰恰相反:排序/构建k-d树的开销也很大),但如果顶点通常至少相隔顶点空间
,这可以大大加快搜索速度。加快搜索速度的一种方法是使用某种空间索引,这样就可以排除明显相距较远的搜索点。下面是一个可能有用的模块:。另请参见。我的速度太慢,无法超过Heuster对算法的描述,但下面是按x坐标排序方法的实现:
def pairs(coords, vertex_spacing):
results = []
vsquared = vertex_spacing * vertex_spacing
coords = sorted(coords)
for ia, (xa, ya) in enumerate(coords):
for ib, (xb, yb) in enumerate(coords[ia:]):
dx = xb - xa
if dx > vertex_spacing:
break
dy = yb - ya
if dx * dx + dy * dy == vsquared:
results.append([(xa, ya), (xb, yb), ia, ia + ib])
return results
。。。这就是行动:
>>> coords = list((x, y) for x in range(100) for y in range(100))
>>> p = pairs(coords, 5)
>>> from random import choice
>>> choice(p)
[(93, 36), (96, 40), 9336, 9640]
>>> choice(p)
[(9, 57), (13, 54), 957, 1354]
>>> choice(p)
[(46, 69), (46, 74), 4669, 4674]
在我的机器上,对(坐标,5)
检查10000个坐标对需要1.5秒(检查2500个坐标对需要0.15秒)
编辑:我忘了将ia
添加到ib
以补偿在切片上的枚举-现在已修复。算法最慢的部分是单独处理x和y坐标以及斜边计算。使用Python的本机复数类型可以加快这两种速度:
>>> from itertools import starmap
>>> parray = list(starmap(complex, [(5, 1), (8.5, 3), (3.75, 4.25)]))
>>> a = parray[0]
>>> b = parray[1]
>>> a
(5+1j)
>>> b
(8.5+3j)
>>> a-b
(-3.5-2j)
>>> abs(a-b)
4.031128874149275
祝贺你提出了一个很好的问题!问题在于,简单的方法(将每一对与所有其他对进行比较)会导致二次运行时间。你的积分分布情况如何?如果它们都在一个相对较小的空间中(小的顺序是顶点间距
),这将是一个困难的问题,否则您可以进行一些简单的优化(我将根据分布将它们作为答案发布)。谢谢!)我注意到情况确实如此,我意识到这会发生,尽管我想不出解决这个问题的办法。顶点间距本身的值默认设置为60,但由于它是用户定义的,理论上可以是任何大小。数据也基于倍数和使用顶点间距的三角恒等式进行计算。本质上,顶点间距是我的数据中的基本单位。我希望我理解你的意思,谢谢你的帮助!这是一个好问题。我认为决策树是一种可行的方法,我查看了维基百科条目中的“最近点对问题”,因为这似乎是该问题的一个扩展(?)后面的问题