图解匈牙利算法(含python代码)

匈牙利算法解析
本文介绍了解决分配问题的经典算法——匈牙利算法。通过详细步骤解析和Python实现示例,帮助读者理解如何以较低的时间复杂度求解工人与工作任务的最佳匹配。

分配问题

分配问题/指派问题(Assignment Problem)作为线性规划问题的一个特例,在运筹学研究中占有重要的地位,一直受到广泛的重视。

假如有n个工人和n项工作,每个工人只能执行一个工作,并且每个工作只能分配给一个工人,每个工人做不同类型工作的成本是不同的。如何将这n项工作分配给这n个工人,从而使得总体成本最低。

用矩阵 C ( i , j ) C(i,j) C(i,j)来表示n个工人中每个个工人执行不同工作的成本。分配问题就是将工作分配给工人,以使总成本最小化。1

在这里插入图片描述
如果想找到成本最低的分配,最直观的方法是运用暴力穷举。对于nxn的矩阵来说,第一行有n个选择,第二行有n-1个选择,以此类推,总共有 n ! n! n!种可能的选择,时间复杂度在指数级,计算成本太高。

所以,James Munkre在1950年代提出匈牙利算法,用于解决分配问题/指派问题,时间复杂度在多项式级,最坏情况下的O(n3)2

匈牙利算法

算法步骤

步骤0: 创建一个称为成本矩阵的nxm矩阵,其中每个元素代表将n个工人之一分配给m个工作之一的成本。旋转矩阵,以便至少有与行一样多的列,并令K= min(n,m)。
在这里插入图片描述

步骤1: 对于矩阵的每一行,找到最小的元素,并将其从其行中的每个元素中减去。转到步骤2。
在这里插入图片描述

步骤2: 在生成的矩阵中找到0(Z)。如果其行或列中没有加星号的零,请加星号Z。对矩阵中的每个元素重复此操作。转到步骤3。
在这里插入图片描述

步骤3: 覆盖有0*的每一列。如果覆盖了K列,则加星号的零表示完整的唯一赋值集。在这种情况下,请转到“完成”,否则,请转到步骤4。步骤3是贪婪方法的示例。如果最小值全部在不同的行中,则它们的位置表示最小的成对分配。
在这里插入图片描述

步骤4: 找到一个未覆盖的零并将其准备好。如果包含0 *的行中没有准备好的0’,请转到步骤5。否则,覆盖该行并找出包含0 *的列。继续以这种方式进行操作,直到没有剩余的零为止。保存最小的发现值,然后转到步骤6。
在这里插入图片描述

步骤5:构造如下一系列交替的填色和加星号的零:
令Z0代表在步骤4中发现的未覆盖的准备好的零 0’。
令Z1表示Z0列中的星号零 0*(如果有的话)。
令Z2表示Z1行中的准备好的零 0’(始终为1个)。
继续直到0’所在列没有星标零 0*,终止该序列。取消对每个已加星标的零的星标,对系列中的每个0’加星标,去除所有的’和覆盖线。 步骤5是增强路径算法(稳定婚姻问题)的示例。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
返回步骤3。
返回步骤3。
在这里插入图片描述
在这里插入图片描述

步骤6: 将在第4步中找到的最小值添加到每个覆盖行的每个元素中,并将其从每个未覆盖列的每个元素中减去。返回第4步,而不更改任何星号,或遮盖线。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

完成: 分配对由成本矩阵中加星号的零的位置指示。如果C(i,j)为星号零,则将与行i关联的元素分配给与列j关联的元素。

在这里插入图片描述

算法实现

python版本

scipy中有对应的接口scipy.optimize.linear_sum_assignment3,输入代价矩阵,即可得到分配问题的结果:

    >>> cost = np.array([[4, 1, 3], [2, 0, 5], [3, 2, 2]])
    >>> from scipy.optimize import linear_sum_assignment
    >>> row_ind, col_ind = linear_sum_assignment(cost)
    >>> col_ind
    array([1, 0, 2])
    >>> cost[row_ind, col_ind].sum()
    5

scipy.optimize.linear_sum_assignment的源码如下4

# Hungarian algorithm (Kuhn-Munkres) for solving the linear sum assignment
# problem. Taken from scikit-learn. Based on original code by Brian Clapper,
# adapted to NumPy by Gael Varoquaux.
# Further improvements by Ben Root, Vlad Niculae and Lars Buitinck.
#
# Copyright (c) 2008 Brian M. Clapper <bmc@clapper.org>, Gael Varoquaux
# Author: Brian M. Clapper, Gael Varoquaux
# License: 3-clause BSD

import numpy as np


def linear_sum_assignment(cost_matrix):
    """Solve the linear sum assignment problem.
    The linear sum assignment problem is also known as minimum weight matching
    in bipartite
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值