【问题标题】:Minimize sum of distances between mutually disjoint bipartite pair of points最小化相互不相交的二分对点之间的距离总和
【发布时间】:2021-02-05 12:20:11
【问题描述】:

我有一个多维数组,表示两组点之间的距离(分别用蓝色和红色着色)。

import numpy as np
distance=np.array([[30,18,51,55],
                   [35,15,50,49],
                   [36,17,40,32],
                   [40,29,29,17]])

每列代表红点,行代表蓝点。该矩阵中的值表示红点和蓝点之间的距离。这是一个草图,可以理解它的样子:

问题:如何求互不相交的(蓝、红)对之间距离之和的最小值?

尝试

我希望在上图中找到 1=1、2=2、3=3 和 4=4。但是,如果我使用简单的 argmin numpy 函数,例如:

for liste in distance:
    np.argmin(liste)

结果是

1
1
1
3

因为2个红点是1,2和3个蓝点中最接近的。

有没有办法在这种情况下做一些通用的事情来让事情变得更好?我的意思是不使用大量 if 语句和 while 函数。

【问题讨论】:

  • 为什么 1,1,1,3 不是预期的输出?如果你顺序处理蓝色点1,2,3,4的距离并删除找到的点,为什么不是2,1,4,3?
  • @BillHuang 我相信 OP 要求的是最小化总成对距离的对应关系。
  • 因为两个点不能在同一个地方。这里不能将 2 个红点分配给 1、2 和 3 个蓝点。我不能按顺序执行,因为点的顺序可能会改变,我希望每个红点都分配给它最近的蓝点。
  • @Panda50 你想如何处理两个红点与最近的蓝点相同的情况?
  • @Eshan 假设第二个红点与蓝点 1 和 2 等距。红点 1 是最近的蓝点 1,所以蓝点 1 不能是红点二!正如 Quang Hoang 所说,我想知道是否有一种简单的方法来计算最小的成对距离!

标签: python arrays numpy multidimensional-array scipy


【解决方案1】:

该问题在运营管理中称为assignment problem,可以通过Hungarian Algorithm 有效解决。在您的情况下,距离可以被视为一种“成本”函数,它将在总体上最小化。

幸运的是,scipy 实现了一个不错的linear_sum_assignment()(请参阅official docs and example),因此您不必重新发明轮子。该函数返回匹配的索引。

from scipy.optimize import linear_sum_assignment
distance=np.array([[30,18,51,55],
                   [35,15,50,49],
                   [36,17,40,32],
                   [40,29,29,17]])

row_ind, col_ind = linear_sum_assignment(distance)

# result
col_ind
Out[79]: array([0, 1, 2, 3])
row_ind
Out[80]: array([0, 1, 2, 3])

【讨论】:

  • 非常感谢 Bill 的解决方案,感谢文档和 wiki 页面!!!
【解决方案2】:

您可以使用itertools.permutations 找到所有可能的解决方案。然后,您计算哪个解决方案使总成对距离最小。

import itertools
import numpy as np

distance=np.array([[30,18,51,55],[35,15,50,49],[36,17,40,32],[40,29,29,17]])

permutation=[x for x in itertools.permutations([0,1,2,3],4)]
x_opt=permutation[0]
d_opt=sum([distance[i,x_opt[i]] for i in range(len(distance[0]))])
for x in permutation:
    d=sum([distance[i,x[i]] for i in range(len(distance[0]))])
    if d<d_opt:
        (d_opt,x_opt)=(d,x)
print(x_opt)

结果将是这种情况:

(0,1,2,3)

【讨论】:

  • 这真的是大材小用
  • 谢谢Lauriane,它可以工作,但写起来有点困难。
  • 注意:n 个红点有多少种可能的解决方案?有n!,还有15! &gt; 1.3 trillion
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-21
  • 2016-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-28
相关资源
最近更新 更多