python networkx获得唯一的匹配组合

时间:2018-08-20 14:31:59

标签: python graph networkx matching

我有一个节点图,这些节点可能是项目的潜在重复项,我正在尝试找到所有可能的匹配组合。如果连接了两个节点,则意味着它们可能是同一项目,但是没有一个节点可以匹配超过一次。

例如,如果我使用以下简单图形:

T = nx.Graph()

T.add_edge('A','B')
T.add_edge('A','C')
T.add_edge('B','D')
T.add_edge('D','A')

enter image description here

在此示例中,我的输出可能是:

[{A:B},{A:C,B:D},{A:D}]

如何创建唯一组合列表?一些图有约20个节点,因此无法通过所有组合进行强行使用。

1 个答案:

答案 0 :(得分:1)

似乎您正在寻找的是找到G的匹配项,即没有两个边共享同一顶点的边集合。
特别是,您正在寻找G的最大匹配项

Networkx提供功能maximal_matching。您可以扩展此功能以获得所有最大匹配。
一种实现方法可能是以下方法。您从部分匹配的列表开始,每个匹配由一条边组成。然后将每个部分匹配扩展到最大匹配,即直到不能扩展为更大基数的匹配为止。

如果可以使用边缘(u,v)将部分匹配的 m 扩展为更大的一个,则 m'= m∪{(u ,v)} 添加到部分匹配列表中。否则,将 m 添加到最大匹配项列表中。

以下代码可以通过多种方式进行改进以提高效率。一种方法是在添加到部分匹配列表之前进行检查。实际上,该列表将包含表示同一项的部分匹配项(即[{i,j},{u,v}]和[{u,v},{i,j}]))。

import networkx as nx
import itertools

def all_maximal_matchings(T):

    maximal_matchings = []
    partial_matchings = [{(u,v)} for (u,v) in T.edges()]

    while partial_matchings:
        # get current partial matching
        m = partial_matchings.pop()
        nodes_m = set(itertools.chain(*m))

        extended = False
        for (u,v) in T.edges():
            if u not in nodes_m and v not in nodes_m:
                extended = True
                # copy m, extend it and add it to the list of partial matchings
                m_extended = set(m)
                m_extended.add((u,v))
                partial_matchings.append(m_extended)

        if not extended and m not in maximal_matchings:
            maximal_matchings.append(m)

    return maximal_matchings

T = nx.Graph()

T.add_edge('A','B')
T.add_edge('A','C')
T.add_edge('B','D')
T.add_edge('D','A')

print(all_maximal_matchings(T))