简体   繁体   English

如何在 Python 和 function 中实现计算环面上两个任意点之间的欧几里得距离

[英]How to implement in Python a function to compute the Euclidean distance between two arbitrary points on a torus

Given a 10x10 grid (2d-array) filled randomly with numbers, either 0, 1 or 2 .给定一个 10x10 网格(二维数组),随机填充数字, 0, 12 How can I find the Euclidean distance (the l2-norm of the distance vector) between two given points considering periodic boundaries?考虑到周期性边界,如何找到两个给定点之间的欧几里得距离(距离向量的 l2 范数)?

Let us consider an arbitrary grid point called centre .让我们考虑一个称为centre的任意网格点。 Now, I want to find the nearest grid point containing the same value as centre .现在,我想找到包含与centre相同值的最近网格点。 I need to take periodic boundaries into account, such that the matrix/grid can be seen rather as a torus instead of a flat plane.我需要考虑周期性边界,这样矩阵/网格可以被看作是一个圆环而不是一个平面。 In that case, say the centre = matrix[0,2] , and we find that there is the same number in matrix[9,2] , which would be at the southern boundary of the matrix.在这种情况下,假设centre = matrix[0,2] ,我们发现matrix[9,2]中存在相同的数字,它将位于矩阵的南边界。 The Euclidean distance computed with my code would be for this example np.sqrt(0**2 + 9**2) = 9.0 .使用我的代码计算的欧几里得距离将用于此示例np.sqrt(0**2 + 9**2) = 9.0 However, because of periodic boundaries, the distance should actually be 1 , because matrix[9,2] is the northern neighbour of matrix[0,2] .但是,由于周期性边界,距离实际上应该是1 ,因为matrix[9,2]matrix[0,2]的北邻。 Hence, if periodic boundary values are implemented correctly, distances of magnitude above 8 should not exist.因此,如果正确实现了周期性边界值,则不应存在幅度大于 8 的距离。

So, I would be interested on how to implement in Python a function to compute the Euclidean distance between two arbitrary points on a torus by applying a wrap-around for the boundaries.因此,我会对如何在 Python 中实现 function 感兴趣,以通过对边界应用环绕来计算环面上两个任意点之间的欧几里得距离。

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]))

For each axis, you can check whether the distance is shorter when you wrap around or when you don't.对于每个轴,您可以检查环绕时或不环绕时距离是否较短。 Consider the row axis, with rows i and j .考虑行轴,行ij

  • When not wrapping around, the difference is abs(i - j) .当不环绕时,区别是abs(i - j)
  • When wrapping around, the difference is "flipped", as in 10 - abs(i - j) .环绕时,差异是“翻转”的,如10 - abs(i - j) In your example with i == 0 and j == 9 you can check that this correctly produces a distance of 1.在您使用i == 0j == 9的示例中,您可以检查这是否正确产生了 1 的距离。

Then simply take whichever is smaller:然后只需取较小的那个:

delta_row = same[0][i] - 0 #row coord of centre
delta_row = min(delta_row, 10 - delta_row)

And similarly for delta_column .同样对于delta_column

The final dist[i] calculation needs no changes.最终的dist[i]计算不需要更改。

I have a working 'sketch' of how this could work.我有一个关于它如何工作的工作“草图”。 In short, I calculate the distance 9 times, 1 for the normal distance, and 8 shifts to possibly correct for a closer 'torus' distance.简而言之,我计算了 9 次距离,1 次表示正常距离,8 次移位可能纠正更近的“环面”距离。

As n is getting larger, the calculation costs can go sky high as the numbers go up.随着n越来越大,计算成本可能会随着数字 go 的增加而变得非常高。 But, the torus effect, is probably not needed as there is always a point nearby without 'wrap around'.但是,可能不需要环面效应,因为附近总是有一个点没有“环绕”。

You can easily test this, because for a grid of size 1, if a point is found of distance 1/2 or closer, you know there is not a closer torus point (right?)您可以轻松地对此进行测试,因为对于大小为 1 的网格,如果找到距离为 1/2 或更近的点,您就知道没有更近的圆环点(对吗?)

import numpy as np

n=10000

np.random.seed(1)

A = np.random.randint(low=0, high=10, size=(n,n))

I create 10000x10000 points, and store the location of the 1's in ONES .我创建 10000x10000 点,并将 1 的位置存储在ONES中。

ONES = np.argwhere(A == 0)

Now I define my torus distance, which is trying which of the 9 mirrors is the closest.现在我定义了我的环面距离,即尝试 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)
%%time

distance_on_torus([2,3])

It is slow, the above takes 15 minutes.... For n = 1000 less than a second.它很慢,上面需要 15 分钟....对于n = 1000不到一秒。


A optimisation would be to first consider the none-torus distance, and if the minimum distance is possibly not the smallest, calculate with only the minimum set of extra 'blocks' around.优化将首先考虑非环面距离,如果最小距离可能不是最小的,则仅使用最小的额外“块”集进行计算。 This will greatly increase speed.这将大大提高速度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用欧几里得距离计算两点之间的距离? - How to calculate the distance between two points using Euclidean distance? 计算python中序列点的欧式距离 - Compute euclidean distance of sequance points in python Pyspark上两点之间的欧几里得距离 - Euclidean Distance between two points on Pyspark Scipy Euclidean两点之间的距离 - Scipy Euclidean distance between two points 如何计算 Python OpenCV 中两个 ndarray 之间的欧几里得距离 - How to calculate euclidean distance between two ndarrays in Python OpenCV Python:如何找到最小化两个系列之间的欧几里得距离的偏移量? - Python: how to find the offset that minimizes the euclidean distance between two series? 计算两个python数组之间的欧几里德距离 - Calculate Euclidean distance between two python arrays 计算两个熊猫数据帧的行之间的欧几里德距离 - Compute Euclidean distance between rows of two pandas dataframes 如何使用python比较大圆距离与两个球面点的欧氏距离? - How to compare great circle distance with euclidean distance of two sphere points using python? 如何有效地计算大量点和任意函数之间的距离? - How to efficiently calculate the distance between a large set of points and an arbitrary function?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM