繁体   English   中英

根据最近距离找到最佳唯一邻居对

[英]Find optimal unique neighbour pairs based on closest distance

一般问题

首先让我们更一般地解释这个问题。 我有一组具有 x,y 坐标的点,并希望找到最佳的唯一邻居对,以使所有对中的邻居之间的距离最小化,但点不能用于一对以上。

一些简单的例子

注意:点不是有序的,x 和 y 坐标都将在 0 到 1000 之间变化,但为了简单起见,在下面的示例中 x==y 并且项目是有序的。

首先,假设我有以下点矩阵:

matrix1 = np.array([[1, 1],[2, 2],[5, 5],[6, 6]])

对于此数据集,output 应为[0,0,1,1] ,因为点 1 和 2 彼此最接近,点 3 和 4 提供对 0 和 2。

其次,两点不能有相同的伙伴。 如果我们有矩阵:

matrix2 = np.array([[1, 1],[2, 2],[4, 4],[6, 6]])

这里 pt1 和 pt3 最接近 pt2,但 pt1 相对更近,所以 output 应该再次为[0,0,1,1]

第三,如果我们有矩阵:

matrix3 = np.array([[1, 1],[2, 2],[3, 3],[4, 4]])

现在 pt1 和 pt3 再次最接近 pt2 但现在它们的距离相同。 现在 output 应该再次为[0,0,1,1] ,因为 pt4 最接近 pt3。

四、点数奇数的情况下,最远的点应设为nan,例如

matrix4 = np.array([[1, 1],[2, 2],[4,4]])

应该给 output [0,0,nan]

第五,在三个或更多点的距离完全相同的情况下,配对可以是随机的,例如

matrix5 = np.array([[1, 1],[2, 2],[3, 3]])

'[0,0,nan] and [nan,0,0]' 的 output 都应该没问题。

我的努力

使用 sklearn:

import numpy as np
from sklearn.neighbors import NearestNeighbors
data = matrix3
nbrs = NearestNeighbors(n_neighbors=len(data), algorithm="ball_tree")
nbrs = nbrs.fit(data)
distances,indices = nbrs.kneighbors(data)

这输出实例:

array([[0, 1, 2, 3],
       [1, 2, 0, 3],
       [2, 1, 3, 0],
       [3, 2, 1, 0]]))

第二列提供最近的点:

nearinds = `indices[:,1]`

接下来,如果列表中有重复项,我们需要找到最近的距离:

if len(set(nearinds) != len(nearinds):
    dupvals = [i for i in set(nearinds) if list(nearinds).count(i) > 1]
    for dupval in dupvals:
        dupinds = [i for i,j in enumerate(nearinds) if j == dupval]
        dupdists = distances[dupinds,1]

使用这些 dupdists,我将能够发现一个比另一个更接近 pt:

       if len(set(dupdists))==len(dupdists):
            duppriority = np.argsort(dupdists)

使用duppriority值,我们可以提供更接近的 pt 其正确配对。 但是要给另一个点,它的配对将取决于它的第二个最近配对以及所有其他点到同一点的距离。此外,如果两个点到它们最近点的距离相同,我还需要 go 一个更深一层:

        if len(set(dupdists))!=len(dupdists):
            dupdists2 = [distances[i,2] for i,j in enumerate(inds) if j == dupval]```
            if len(set(dupdists2))==len(dupdists2):
                duppriority2 = np.argsort(dupdists2)  

ETC..

我有点卡在这里,也觉得这种方式效率不高,特别是对于比 4 个点更复杂的条件,并且多个点与一个或多个最近的、第二最近的点的距离相似。

我还发现 scipy 有一个类似的单行命令可用于获取距离和索引:

from scipy.spatial import cKDTree
distances,indices = cKDTree(matrix3).query(matrix3, k=len(matrix3))

所以我想知道一个人是否会更好地继续与另一个人相比。

我想解决的更具体的问题

我有一个点列表,需要将它们与之前的点列表进行最佳匹配。 点的数量通常是有限的,范围从 2 到 10,但随着时间的推移通常是一致的(即随着时间的推移,它不会在值之间跳跃太多)。 数据往往看起来像:

prevdat = {'loc': [(300, 200), (425, 400), (400, 300)], 'contid': [0, 1, 2]}
currlocs = [(435, 390), (405, 295), (290, 215),(440,330)]`

时间点通常比与他人更接近。 因此,我应该能够随着时间的推移链接点的身份。 然而,有许多并发症需要克服:

  1. 有时当前点和以前的点数不相等
  2. 点通常具有相同的最近邻居,但不应分配相同的身份
  3. 点有时与最近邻居的距离相同(但不太可能与第二、第三最近邻居等)。

任何有助于解决我的问题的建议将不胜感激。 我希望我上面的例子和努力会有所帮助。 谢谢!

这可以表述为混合 integer 线性规划问题。

在 python 中,您可以 model 并使用cvxpy解决此类问题。

def connect_point_cloud(points):
    '''
    Given a set of points computes return pairs of points that
    whose added distance is minimised
    '''
    N = points.shape[0];
    I, J = np.indices((N, N))
    d = np.sqrt(sum((points[I, i] - points[J, i])**2 for i in range(points.shape[1])));
    
    use = cvxpy.Variable((N, N), integer=True)
    # each entry use[i,j] indicates that the point i is connected to point j
    # each pair may count 0 or 1 times
    constraints = [use >= 0, use <= 1];
    # point i must be used in at most one connection
    constraints += [sum(use[i,:]) + sum(use[:, i]) <= 1 for i in range(N)]
    # at least floor(N/2) connections must be presented
    constraints += [sum(use[i,j] for i in range(N) for j in range(N)) >= N//2];
    
    # let the solver  to handle the problem
    P = cvxpy.Problem(cvxpy.Minimize(sum(use[i,j] * d[i,j] for i in range(N) for j in range(N))), constraints)
    dist = P.solve()
    return use.value

这是一段代码,用于可视化 2D 问题的结果

# create a random set with 50 points
p = np.random.rand(50, 2)
# find the pairs to with minimum distance
pairs = connect_point_cloud(p)

# plot all the points with circles
plt.plot(p[:, 0], p[:, 1], 'o')

# plot lines connecting the points
for i1, i2 in zip(*np.nonzero(pairs)):
    plt.plot([p[i1,0], p[i2,0]], [p[i1,1], p[i2,1]])

在此处输入图像描述

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM