Python 有向图中的最大公共子图

Python 有向图中的最大公共子图,python,python-3.x,graph,networkx,Python,Python 3.x,Graph,Networkx,我试图将一组句子表示为一个有向图,其中一个单词由一个节点表示。如果一个单词被重复,则该节点不重复,将使用先前存在的节点。让我们将此图称为MainG 接下来,我用一个新句子,创建这个句子的有向图(称这个图为SubG),然后在MainG中查找SubG的最大公共子图 我正在使用Python 3.5中的NetworkX api。我知道这是正常图的NP完全问题,但对于有向图,这是一个线性问题。我提到的其中一个链接: 我尝试执行以下代码: import networkx as nx import pand

我试图将一组句子表示为一个有向图,其中一个单词由一个节点表示。如果一个单词被重复,则该节点不重复,将使用先前存在的节点。让我们将此图称为
MainG

接下来,我用一个新句子,创建这个句子的有向图(称这个图为
SubG
),然后在
MainG
中查找
SubG
的最大公共子图

我正在使用Python 3.5中的NetworkX api。我知道这是正常图的NP完全问题,但对于有向图,这是一个线性问题。我提到的其中一个链接:

我尝试执行以下代码:

import networkx as nx
import pandas as pd
import nltk

class GraphTraversal:
    def createGraph(self, sentences):
        DG=nx.DiGraph()
        tokens = nltk.word_tokenize(sentences)
        token_count = len(tokens)
        for i in range(token_count):
            if i == 0:
                continue
            DG.add_edges_from([(tokens[i-1], tokens[i])], weight=1)
        return DG


    def getMCS(self, G_source, G_new):
        """
        Creator: Bonson
        Return the MCS of the G_new graph that is present 
        in the G_source graph
        """
        order =  nx.topological_sort(G_new)
        print("##### topological sort #####")
        print(order)

        objSubGraph = nx.DiGraph()

        for i in range(len(order)-1):

            if G_source.nodes().__contains__(order[i]) and G_source.nodes().__contains__(order[i+1]):
                print("Contains Nodes {0} -> {1} ".format(order[i], order[i+1]))
                objSubGraph.add_node(order[i])
                objSubGraph.add_node(order[i+1])
                objSubGraph.add_edge(order[i], order[i+1])
            else:
                print("Does Not Contains Nodes {0} -> {1} ".format(order[i], order[i+1]))
                continue


obj_graph_traversal = GraphTraversal()
SourceSentences = "A series of escapades demonstrating the adage that what is good for the goose is also good for the gander , some of which occasionally amuses but none of which amounts to much of a story ."
SourceGraph = obj_graph_traversal.createGraph(SourceSentences)

TestSentence_1 = "not much of a story"    #ThisWorks
TestSentence_1 = "not much of a story of what is good"    #This DOES NOT Work
TestGraph = obj_graph_traversal.createGraph(TestSentence_1)

obj_graph_traversal.getMCS(SourceGraph, TestGraph)
当我尝试进行拓扑排序时,第二个排序不起作用


将有兴趣了解解决此问题的可能方法。

以下代码从有向图中获取最大公共子图:

def getMCS(self, G_source, G_new):
    matching_graph=nx.Graph()

    for n1,n2,attr in G_new.edges(data=True):
        if G_source.has_edge(n1,n2) :
            matching_graph.add_edge(n1,n2,weight=1)

    graphs = list(nx.connected_component_subgraphs(matching_graph))

    mcs_length = 0
    mcs_graph = nx.Graph()
    for i, graph in enumerate(graphs):

        if len(graph.nodes()) > mcs_length:
            mcs_length = len(graph.nodes())
            mcs_graph = graph

    return mcs_graph

Bonson答案的编辑队列已满,但它不再适用于networkx 2.4,并且有一些可能的改进:

  • networkx 2.4中删除了
    connected_component_子图
    ,应改用返回一组节点的
    connected_components

  • 因为只有节点的数量才能找到最大的组件,这可以大大简化

  • 这不再是专门针对初始问题定制的,因为这是搜索“有向图中的最大公共子图”的最佳选择,我需要它来完成完全不同的任务

我的改编版本是:

def getMCS(g1、g2):
匹配图=networkx.graph()
对于g2.边()中的n1和n2:
如果g1.有_边(n1,n2):
匹配图。添加边(n1,n2)
组件=网络x.连接的组件(匹配图)
最大组件=最大(组件,键=len)
返回networkx.诱导子图(匹配子图,最大子图分量)

如果最后一行被替换为
返回networkx.induced\u子图(g1,最大的\u分量)
它也应该正常工作并返回一个有向图。

到底是什么失败了?您的标记化很可能会产生重复的数据(“of”),因此,如果您采取措施确保数据是唯一的,那么它可能会成功。例如,您可以考虑图形对<代码>(index,令牌),< /代码>,其中索引仅仅是令牌的基于0的索引。(
对于i,tok in enumerate(tokens):…
)@Austin Hastings感谢您的回复。创建的图形是循环的,就像句子中的单词可以重复一样。在SourceGraph中也是一样的,我们在其中也有循环。记住这一点,我们必须找到最大公共子图。我今天有点忙。为什么需要拓扑排序?为什么你不能只过滤公共边,然后计算出最大的连通分量呢?@Paul谢谢你的想法/评论。这让我思考。已经发布了我的解决方案。好笑。那是在那天喝第一杯咖啡之前,所以我真的不相信我的思维过程。很高兴它有帮助。我收到了以下错误:
AttributeError:module'networkx'没有属性'connected\u component\u subgraphs'
。我正在使用Networkx2.4。