Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.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_Python 3.x_Numpy_Matrix_Euclidean Distance - Fatal编程技术网

如何在Python中实现计算圆环体上任意两点之间欧氏距离的函数

如何在Python中实现计算圆环体上任意两点之间欧氏距离的函数,python,python-3.x,numpy,matrix,euclidean-distance,Python,Python 3.x,Numpy,Matrix,Euclidean Distance,给定一个10x10网格(2d数组),随机填充数字,0、1或2。在考虑周期边界的情况下,如何找到两个给定点之间的欧几里德距离(距离向量的l2范数) 让我们考虑一个任意的网格点,叫做中心< /代码>。现在,我想找到与中心值相同的最近的网格点。我需要考虑周期性边界,这样矩阵/网格可以被看作是一个圆环体而不是一个平面。在这种情况下,假设中心=矩阵[0,2],我们发现矩阵[9,2]中有相同的数字,它将位于矩阵的南部边界。使用我的代码计算的欧几里德距离在本例中为np.sqrt(0**2+9**2)=9.0。

给定一个10x10网格(2d数组),随机填充数字,
0、1
2
。在考虑周期边界的情况下,如何找到两个给定点之间的欧几里德距离(距离向量的l2范数)

让我们考虑一个任意的网格点,叫做<代码>中心< /代码>。现在,我想找到与

中心
值相同的最近的网格点。我需要考虑周期性边界,这样矩阵/网格可以被看作是一个圆环体而不是一个平面。在这种情况下,假设
中心=矩阵[0,2]
,我们发现
矩阵[9,2]
中有相同的数字,它将位于矩阵的南部边界。使用我的代码计算的欧几里德距离在本例中为
np.sqrt(0**2+9**2)=9.0
。然而,由于周期性边界,距离实际上应该是
1
,因为
矩阵[9,2]
矩阵[0,2]
的北部邻居。因此,如果正确执行周期性边界值,则不应存在大于8级的距离

因此,我感兴趣的是如何在Python中实现一个函数,通过对边界应用环绕来计算圆环体上任意两点之间的欧几里德距离

import numpy as np

matrix = np.random.randint(0,3,(10,10))
centre = matrix[0,2]

#rewrite the centre to be the number 5 (to exclude itself as shortest distance)
matrix[0,2] = 5

#find the points where entries are same as centre
same = np.where((matrix == centre) == True)
idx_row, idx_col = same

#find distances from centre to all values which are of same value 
dist = np.zeros(len(same[0]))
for i in range(0,len(same[0])):
    delta_row = same[0][i] - 0 #row coord of centre
    delta_col = same[1][i] - 2 #col coord of centre
    dist[i] = np.sqrt(delta_row**2 + delta_col**2)

#retrieve the index of the smallest distance
idx = dist.argmin() 
print('Centre value: %i. The nearest cell with same value is at (%i,%i)' 
      % (centre, same[0][idx],same[1][idx]))

对于每个轴,可以检查环绕或不环绕时距离是否较短。考虑行轴,用行<代码> i < /代码>和<代码> j< /代码> ./p>
  • 当不环绕时,区别是abs(i-j)
  • 环绕时,差异被“翻转”,如
    10-abs(i-j)
    。在使用
    i==0
    j==9
    的示例中,您可以检查这是否正确地生成了1的距离
  • 然后只需取较小者:

    delta_row = same[0][i] - 0 #row coord of centre
    delta_row = min(delta_row, 10 - delta_row)
    
    对于
    delta_列
    也是如此


    最后的
    dist[i]
    计算不需要更改。

    我有一个工作的“草图”,说明这是如何工作的。简言之,我计算了9次距离,1次为正常距离,8次偏移可能会修正更近的“圆环”距离

    随着
    n
    越来越大,随着数字的增加,计算成本可能会越来越高。但是,可能不需要环面效应,因为附近总是有一个点没有“环绕”

    您可以很容易地对此进行测试,因为对于大小为1的栅格,如果发现距离为1/2或更近的点,您知道没有更近的圆环点(对吗?)

    我创建10000x1000点,并将1的位置存储在
    ONES

    ONES = np.argwhere(A == 0)
    
    现在我定义了环面距离,这是在尝试9个镜像中哪一个是最近的

    def distance_on_torus( point=[500,500] ):
        index_diff = [[1],[1],[0],[0],[0,1],[0,1],[0,1],[0,1]]
        coord_diff = [[-1],[1],[-1],[1],[-1,-1],[-1,1],[1,-1],[1,1]]
        
        tree = BallTree( ONES, leaf_size=5*n, metric='euclidean')
        
        dist, indi = tree.query([point],k=1, return_distance=True )
    
        distances = [dist[0]]
    
        for indici_to_shift, coord_direction in zip(index_diff, coord_diff):
            MIRROR = ONES.copy()
            for i,shift in zip(indici_to_shift,coord_direction):
                MIRROR[:,i] = MIRROR[:,i] + (shift * n)
    
            tree = BallTree( MIRROR, leaf_size=5*n, metric='euclidean')
            dist, indi = tree.query([point],k=1, return_distance=True )
            
            distances.append(dist[0])
            
        
        return np.min(distances)
    
    速度很慢,上面的过程需要15分钟。。。。对于
    n=1000
    小于一秒



    优化是首先考虑无环面距离,如果最小距离可能不是最小的,则只计算最小的一组额外的“块”。这将大大提高速度。

    如果x和y边界分别“环绕”到另一侧,则它在拓扑上不是球体,而是圆环体。在一个球体上,整个顶部边缘将被视为同一点,即北极,同样,底部边缘也被视为同一点。此外,球体上不存在欧几里德距离。欧几里德距离定义为平面(或高维或低维欧几里德空间)。对不起,我的错误,我指的是圆环。只是相应地编辑了问题。关于欧几里德距离,我的意思是我对差分向量的l2范数感兴趣。谢谢你澄清@Thomas,我相信其中一个非常相似。循环性符合你的条件是正确的吗?@user3184950谢谢你的链接,我之前查看过那篇文章,但我无法完全理解内容和想法,这可能不是我所需要的。不过,那篇文章中的循环边界条件符合我的需要。然而,在我的例子中,我需要为每个指定的数字找到相同类型的最近邻,交换彼此的值,然后再次执行相同的循环。我将尝试下面的答案,看看瓶颈会有多严重。谢谢你的建议。我最初正试图实现这一点,但后来应用此过程时,网格的大小实际上是1000x1000甚至10000x1000。正因为如此,我担心这会导致瓶颈,所以我在考虑如何在不检查哪一个较短的情况下实现此环绕。您认为,这种方法会显著降低性能吗?如果它成为瓶颈,您可能会更改代码以使用更多矢量化。但是(取决于您的数据),我认为真正的性能改进将来自于不搜索所有这些1亿个元素以找到最接近的单个元素;相反,你可以在一个圆形或螺旋形中进行搜索,直到找到匹配的元素。我需要在包含该特定值的每个单元格上循环,这是不可避免的,但实际上我不需要计算所有的距离,我只需要找到同一类型中最近的一个。因此,在圆周运动中搜索可能更有效,因为我可以在找到一条后续注释后立即停止:我实现了这种方法,并运行了10次代码,粗略估计了100x100网格的例行程序所需的时间。与我采用随机选择的实现相比,完成相同的计算所花费的时间大约要长5倍。
    def distance_on_torus( point=[500,500] ):
        index_diff = [[1],[1],[0],[0],[0,1],[0,1],[0,1],[0,1]]
        coord_diff = [[-1],[1],[-1],[1],[-1,-1],[-1,1],[1,-1],[1,1]]
        
        tree = BallTree( ONES, leaf_size=5*n, metric='euclidean')
        
        dist, indi = tree.query([point],k=1, return_distance=True )
    
        distances = [dist[0]]
    
        for indici_to_shift, coord_direction in zip(index_diff, coord_diff):
            MIRROR = ONES.copy()
            for i,shift in zip(indici_to_shift,coord_direction):
                MIRROR[:,i] = MIRROR[:,i] + (shift * n)
    
            tree = BallTree( MIRROR, leaf_size=5*n, metric='euclidean')
            dist, indi = tree.query([point],k=1, return_distance=True )
            
            distances.append(dist[0])
            
        
        return np.min(distances)
    
    %%time
    
    distance_on_torus([2,3])