簡體   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