列出有向图的顶点属于单个群集的所有路径

时间:2019-06-05 08:06:38

标签: python graph networkx graph-theory

我需要单个有向图的所有子图/路径,这些有向图的顶点属于特定簇,如下面的代码所述。

g = nx.DiGraph()

# cluster to vertices mapping, so [a, b, c] vertices 
# belongs to cluster 1 and so on..
cluster = {
    1: ['a', 'b', 'c'],
    2: ['d', 'e'],
    3: ['f', 'g'],
    4: ['h'],
    5: ['i'],
    6: ['j'],
}

g.add_edge('a', 'd')
g.add_edge('a', 'e')
g.add_edge('b', 'd')
g.add_edge('b', 'e')
g.add_edge('c', 'd')
g.add_edge('c', 'e')
g.add_edge('d', 'f')
g.add_edge('e', 'g')
g.add_edge('d', 'h')
g.add_edge('e', 'h')
g.add_edge('h', 'i')
g.add_edge('j', 'h')

pos = {}
pos['a'] = [0, 1]
pos['b'] = [0, 2]
pos['c'] = [0, 3]
pos['d'] = [2, 3]
pos['e'] = [2, 2]
pos['f'] = [3, 3]
pos['g'] = [3, 2]
pos['h'] = [2, -2]
pos['i'] = [0, -2]
pos['j'] = [4, -2]

nx.draw_networkx(g, pos)

## expected paths
# [a-e, e-g, e-h, h-i, j-h]
# [a-d, d-f, d-h, h-i, j-h]
# .
# .
# [c-e, e-g, e-h, h-i, j-h]

我的输入

enter image description here

我想要的输出内容

enter image description here enter image description here

有12种这样的路径/子图感兴趣。

我可以想到修改后的DFS搜索,但仅限于从集群中选择下一个节点,但不确定如何进行。请给我一些指针/算法/伪代码,以了解如何实现所需的输出。

1 个答案:

答案 0 :(得分:0)

函数nx.subgraph(G, nodes)返回在给定节点集上归纳的G的子图。根据您的评论,您想要给定群集之间的边缘,因此对于群集1和2,我们正在讨论以下边缘:

enter image description here

有很多方法可以获得这些优势。在下面的解决方案中,我将它们计算为在两个聚类的并集上诱导子图并减去在单个聚类上诱导的子图时剩余的边。

import networkx as nx

g = nx.DiGraph()

# cluster to vertices mapping, so [a, b, c] vertices belongs to cluster 1 and so on..
cluster = {
    1: ['a', 'b', 'c'],
    2: ['d', 'e'],
    3: ['f', 'g'],
    4: ['h'],
    5: ['i'],
    6: ['j'],
}

g.add_edge('a', 'd')
g.add_edge('a', 'e')
g.add_edge('b', 'd')
g.add_edge('b', 'e')
g.add_edge('c', 'd')
g.add_edge('c', 'e')
g.add_edge('d', 'f')
g.add_edge('e', 'g')
g.add_edge('d', 'h')
g.add_edge('e', 'h')
g.add_edge('h', 'i')
g.add_edge('j', 'h')

pos = {}
pos['a'] = [0, 1]
pos['b'] = [0, 2]
pos['c'] = [0, 3]
pos['d'] = [2, 3]
pos['e'] = [2, 2]
pos['f'] = [3, 3]
pos['g'] = [3, 2]
pos['h'] = [2, -2]
pos['i'] = [0, -2]
pos['j'] = [4, -2]

nx.draw_networkx(g, pos)

# --------------------------------------------------------------------------------
# my answer using cluster 1 and 2 as examples

def get_subgraph_between_clusters(g, cluster_1, cluster_2):
    """Returns the subgraph induced on g that contains all edges between
    the clusters 1 and 2.

    Arguments:
    ----------
    g -- networkx graph object
        The graph

    cluster_1 / cluster_2 : iterable of nodes
        The node clusters. Clusters are assumed to be disjoint,
        i.e. any node in cluster 1 is assumed to be absent from cluster 2.

    Returns:
    h -- networkx graph object
        The induced subgraph
    """

    # get subgraph induced on individual clusters, and compute union of subgraphs
    g_1 = nx.subgraph(g, cluster_1)
    g_2 = nx.subgraph(g, cluster_2)
    g_1_g_2 = nx.union(g_1, g_2)

    # get subgraph induced on union of cluster node sets
    g_12 = nx.subgraph(g, set(cluster_1) | set(cluster_2))

    # compute difference
    h = nx.difference(g_12, g_1_g_2)

    return h


h = get_subgraph_between_clusters(g, cluster[1], cluster[2])
nx.draw_networkx_edges(h, pos, edge_color='red', )