【问题标题】:Minimize total distance between two sets of points in Python最小化Python中两组点之间的总距离
【发布时间】:2016-12-25 07:16:35
【问题描述】:

给定 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() 函数计算集的所有点对之间的距离。

从那里,我可能可以测试每一行中单个元素的每个排列,并找到最小值。

我想到的应用程序涉及 3 维空间中相当少量的数据点,所以蛮力方法可能很好,但我想我会先检查一下是否有人知道更有效或更优雅的解决方案.

【问题讨论】:

  • 所以这个问题似乎与算法有关,与语言无关?
  • 这两个集合的大小总是相等的?
  • 这个问题不是linear sum assignment问题的一个实例吗?
  • @moooeeeep 主要对 python 答案感兴趣,但如果有一个简单的算法解决方案,我也会对此感兴趣;就尺寸而言,我对这两种情况都感兴趣——一种是集合大小相同,另一种是一组比另一组大。一种或两种解决方案都会有用。
  • @Stelios 感谢您向我指出这一点;我以前没听说过。看起来它正在尝试解决同样的问题。您认为您可以发布一个在两组点的上下文中应用它的答案吗?

标签: python scipy euclidean-distance


【解决方案1】:

将一组点的元素分配(映射)到另一组点的元素的示例,以使欧几里得距离之和最小化。

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

【讨论】:

  • 谢谢!将此标记为解决方案,因为 Stelios 是第一个建议使用 scipy.optimize.linear_sum_assignment 的人,以及从头到尾演示应用程序的详细代码示例。
【解决方案2】:

有一个已知的算法,The Hungarian Method For Assignment,它可以在 O(n3) 时间内工作。

在 SciPy 中,您可以在 scipy.optimize.linear_sum_assignment 中找到一个实现

【讨论】:

  • 看起来不错!明确一点——linear_sum_assigment() 接受一个 cost 矩阵,在这种情况下,它是scipy.spatial.distance.cdist() 的输出,而不是原始数据点本身,对吗?
  • @KeithHughitt 绝对。你可能想看看幻灯片,顺便说一句,它们的可读性很强。
猜你喜欢
  • 2021-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-07
  • 1970-01-01
  • 1970-01-01
  • 2021-01-30
  • 1970-01-01
相关资源
最近更新 更多