在n维空间中给出两组点,一个地图如何从一个集合指向另一个集合,这样每个点只使用一次,并且这些点之间的欧几里德总距离最小化?
例如,
import matplotlib.pyplot as plt
import numpy as np
# create six points in 2d space; the first three belong to set "A" and the
# second three belong to set "B"
x = [1, 2, 3, 1.8, 1.9, 3.4]
y = [2, 3, 1, 2.6, 3.4, 0.4]
colors = ['red'] * 3 + ['blue'] * 3
plt.scatter(x, y, c=colors)
plt.show()
因此,在上面的示例中,目标是将每个红点映射到蓝点,使每个蓝点仅使用一次,并使点之间的距离之和最小化。
我遇到this question这有助于解决问题的第一部分 - 使用 从那里,我可以测试每行中单个元素的每个排列,并找到最小值。 我想到的应用程序涉及三维空间中相当少的数据点,所以蛮力方法可能没问题,但我想我会先查看是否有人知道更有效或更优雅的解决方案。 scipy.spatial.distance.cdist()
函数计算集中所有点之间的距离。< / p>
答案 0 :(得分:5)
将一组元素分配(映射)为指向另一组点的元素的一个示例,以便最小化欧几里得距离。
import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial.distance import cdist
from scipy.optimize import linear_sum_assignment
np.random.seed(100)
points1 = np.array([(x, y) for x in np.linspace(-1,1,7) for y in np.linspace(-1,1,7)])
N = points1.shape[0]
points2 = 2*np.random.rand(N,2)-1
C = cdist(points1, points2)
_, assigment = linear_sum_assignment(C)
plt.plot(points1[:,0], points1[:,1],'bo', markersize = 10)
plt.plot(points2[:,0], points2[:,1],'rs', markersize = 7)
for p in range(N):
plt.plot([points1[p,0], points2[assigment[p],0]], [points1[p,1], points2[assigment[p],1]], 'k')
plt.xlim(-1.1,1.1)
plt.ylim(-1.1,1.1)
plt.axes().set_aspect('equal')
答案 1 :(得分:2)
有一个已知的算法The Hungarian Method For Assignment,它在时间 O(n 3 )中有效。
在SciPy中,您可以在scipy.optimize.linear_sum_assignment