C 或 Python 中的快速最大二分匹配
Posted
技术标签:
【中文标题】C 或 Python 中的快速最大二分匹配【英文标题】:Fast maximum bipartite matching in C or Python 【发布时间】:2018-09-06 13:46:27 【问题描述】:在 C 或 Python 中是否有快速现成的最大基数二分匹配实现?
我试过networkx
,但是很慢。我有一个两层图,每层大约有 1000 个节点。密度不同。此设置的预计时间是多少?
我看到这个帖子Fast max-flow min-cut library for Python,但是有什么更快的吗?
【问题讨论】:
【参考方案1】:SciPy,从版本 1.4.0 开始,在scipy.sparse.csgraph.maximum_bipartite_matching
中包含一个 Hopcroft--Karp 的实现,在性能方面与 NetworkX 相媲美。该功能也存在于以前的版本中,但假设完美匹配;这个假设在 1.4.0 中被取消了。
它的性能究竟如何取决于二分图的结构,但仅通过随机图(并忽略 NetworkX 初始化底层数据结构所需的时间),我获得了大约 200 倍的性能提升:
import networkx as nx
from scipy.sparse import rand
from scipy.sparse.csgraph import maximum_bipartite_matching
n = 5000
graph = rand(n, n, density=.1, format='csr', random_state=42)
G = nx.algorithms.bipartite.from_biadjacency_matrix(graph)
>>> %timeit maximum_bipartite_matching(graph, perm_type='column')
8.95 ms ± 183 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
>>> %timeit nx.algorithms.bipartite.maximum_matching(G, top_nodes=range(n))
2.01 s ± 118 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
【讨论】:
【参考方案2】:好吧,如果您打算使用网络流方法,那么所有可用算法的时间复杂度似乎都至少是 O(|V||E|)
的一个因素,在大多数情况下甚至更高(例如 O(|V|^2|E|)
)。
如果您有一个包含 2000 个节点的图,即使边数 |E|
与顶点数 |V|
成线性关系,时间复杂度为 O(|V|^2|E|)
的算法也会导致执行时间很长在一台普通的日常计算机中只需几分钟。如果图是密集的,并且 |E|与|V|^2
成线性关系,则可能需要几天时间才能执行。
解决这个二分最大匹配问题的替代算法可能是Hopcroft-Karp algorithm。它首先有一个空集M
用于二分匹配,并尝试通过在给定图中查找增广路径来扩展M
。该算法的复杂度为O(|E|√|V|)
,优于 Push Relabel 或 Edmonds-Karp 等网络流风格的算法。
另外,a Python library 已经实现了 Hopcroft-Karp 算法,我相信这是您正在寻找的另一件事。
【讨论】:
NetworkX 在networkx.algorithms.bipartite.matching.hopcroft_karp_matching
中也有一个 Hopcroft--Karp 的实现(并且从 2015 年开始就有了)。以上是关于C 或 Python 中的快速最大二分匹配的主要内容,如果未能解决你的问题,请参考以下文章