Python 列出顶点属于单个簇的有向图中的所有路径

Python 列出顶点属于单个簇的有向图中的所有路径,python,graph,networkx,graph-theory,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'],

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

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]
我的输入:

我想要的输出:

我感兴趣的路径/子图有12个


我可以考虑修改DFS搜索,只从集群中选择下一个节点,但不确定如何继续。请给我一些指针/算法/伪代码,说明如何实现所需的输出。

函数
nx。子图(G,节点)
返回给定节点集上导出的G的子图。根据您的评论,您需要给定簇之间的边,因此对于簇1和簇2,我们将讨论这些边:

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

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', )

函数
nx.subgraph(G,nodes)
返回给定节点集上导出的G的子图。根据您的评论,您需要给定簇之间的边,因此对于簇1和簇2,我们将讨论这些边:

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

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', )

澄清一下:你想要a)与你的簇相对应的子图(例如,
nx.子图(g,簇[1])
,或者b)由簇之间的边组成的子图?a)没有得到,当我做
list(nx.子图(g,簇[1])=['b','a','c']
b)是的,簇之间的边像[('a','d'),('d','f'),('d','h'),('h','i'),('j','h')]澄清:你想要a)与你的簇相对应的子图(例如,
nx.子图(g,簇[1])
,或者b)由簇之间的边组成的子图?a)没有得到,当我得到
列表(nx.子图(g,簇[1])=['b','a','c']
b)是的,群集节点之间的边,如[('a','d','d','f',('d','h'),('h','i'),('j','h')]谢谢你的回答,但我不想要2个簇之间的所有边,而是子图/路径通过所有簇单点。我更新了关于我的输出预期的问题,很抱歉在原始问题中造成任何混乱。谢谢你的回答,但我不想要2个簇之间的所有边,而是子图/路径通过所有簇单点。我更新了我关于输出期望的问题,对于原始问题中造成的任何混乱,我深表歉意。