Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何修改Johnson';限制最大循环长度的基本循环算法?_Python_Algorithm_Graph Algorithm_Networkx - Fatal编程技术网

Python 如何修改Johnson';限制最大循环长度的基本循环算法?

Python 如何修改Johnson';限制最大循环长度的基本循环算法?,python,algorithm,graph-algorithm,networkx,Python,Algorithm,Graph Algorithm,Networkx,我想修改Johnson算法中查找图中所有基本圈的部分(也复制如下),这样就不会搜索大于某个最大长度的圈 def simple_cycles(G): def _unblock(thisnode,blocked,B): stack=set([thisnode]) while stack: node=stack.pop() if node in blocked: blocked.re

我想修改Johnson算法中查找图中所有基本圈的部分(也复制如下),这样就不会搜索大于某个最大长度的圈

def simple_cycles(G):
    def _unblock(thisnode,blocked,B):
        stack=set([thisnode])
        while stack:
            node=stack.pop()
            if node in blocked:
                blocked.remove(node)
                stack.update(B[node])
                B[node].clear()

    # Johnson's algorithm requires some ordering of the nodes.
    # We assign the arbitrary ordering given by the strongly connected comps
    # There is no need to track the ordering as each node removed as processed.
    subG = type(G)(G.edges_iter()) # save the actual graph so we can mutate it here
                              # We only take the edges because we do not want to
                              # copy edge and node attributes here.
    sccs = list(nx.strongly_connected_components(subG))
    while sccs:
        scc=sccs.pop()
        # order of scc determines ordering of nodes
        startnode = scc.pop()
        # Processing node runs "circuit" routine from recursive version
        path=[startnode]
        blocked = set() # vertex: blocked from search?
        closed = set() # nodes involved in a cycle
        blocked.add(startnode)
        B=defaultdict(set) # graph portions that yield no elementary circuit
        stack=[ (startnode,list(subG[startnode])) ]  # subG gives component nbrs
        while stack:
            thisnode,nbrs = stack[-1]
            if nbrs:
                nextnode = nbrs.pop()
#                    print thisnode,nbrs,":",nextnode,blocked,B,path,stack,startnode
#                    f=raw_input("pause")

                if nextnode == startnode:
                    yield path[:]
                    closed.update(path)
#                        print "Found a cycle",path,closed
                elif nextnode not in blocked:
                    path.append(nextnode)
                    stack.append( (nextnode,list(subG[nextnode])) )
                    closed.discard(nextnode)
                    blocked.add(nextnode)
                    continue
            # done with nextnode... look for more neighbors
            if not nbrs:  # no more nbrs
                if thisnode in closed:
                    _unblock(thisnode,blocked,B)
                else:
                    for nbr in subG[thisnode]:
                        if thisnode not in B[nbr]:
                            B[nbr].add(thisnode)
                stack.pop()
                assert path[-1]==thisnode
                path.pop()

        # done processing this node
        subG.remove_node(startnode)
        H=subG.subgraph(scc)  # make smaller to avoid work in SCC routine
        sccs.extend(list(nx.strongly_connected_components(H)))
当然,我也会接受一个与上述实现不同但运行时间相似的建议。此外,我的项目使用networkx,因此可以随意使用该库中的任何其他函数,例如
最短路径

(注意:不是家庭作业!)

编辑 Dorijan Cirkveni建议(如果我理解正确的话):

然而,这是行不通的。下面是一个反例:

G = nx.DiGraph()
G.add_edge(1, 2)
G.add_edge(2, 3)
G.add_edge(3, 1)
G.add_edge(3, 2)
G.add_edge(3, 4)

my_cycles = list(simple_cycles(G, limit = 3)) # Modification
nx_cycles = list(nx.simple_cycles(G)) # Original networkx code
print("MY:", my_cycles)
print("NX:", nx_cycles)
将输出

MY: [[2, 3]]
NX: [[1, 2, 3], [2, 3]]

此外,如果我们用
堆栈
路径
替换
阻塞的
,则此示例的结果将是正确的,但对于其他图形将给出错误的答案

您只需更改两件事:

  • 定义行(显然)

    def简单循环(G,极限):

  • 在下一个节点处理器的某处添加覆盖条件(下面的示例:)

    好处:使用
    =
    而不是
    =
    将导致函数运行,因为使用负值时没有限制,而不是不返回任何节点


  • 这是这段代码的一个经过高度修改的版本,但至少它可以工作

    def simple_cycles(G, limit):
        subG = type(G)(G.edges())
        sccs = list(nx.strongly_connected_components(subG))
        while sccs:
            scc = sccs.pop()
            startnode = scc.pop()
            path = [startnode]
            blocked = set()
            blocked.add(startnode)
            stack = [(startnode, list(subG[startnode]))]
    
            while stack:
                thisnode, nbrs = stack[-1]
    
                if nbrs and len(path) < limit:
                    nextnode = nbrs.pop()
                    if nextnode == startnode:
                        yield path[:]
                    elif nextnode not in blocked:
                        path.append(nextnode)
                        stack.append((nextnode, list(subG[nextnode])))
                        blocked.add(nextnode)
                        continue
                if not nbrs or len(path) >= limit:
                    blocked.remove(thisnode)
                    stack.pop()
                    path.pop()
            subG.remove_node(startnode)
            H = subG.subgraph(scc)
            sccs.extend(list(nx.strongly_connected_components(H)))
    
    def简单循环(G,极限):
    subG=类型(G)(G.边()
    sccs=列表(nx.强连接组件(subG))
    而SCC:
    scc=sccs.pop()
    startnode=scc.pop()
    路径=[startnode]
    blocked=set()
    已阻止。添加(startnode)
    stack=[(startnode,list(subG[startnode]))]
    堆栈时:
    此节点,nbrs=堆栈[-1]
    如果NBR和len(路径)<限制:
    nextnode=nbrs.pop()
    如果nextnode==startnode:
    屈服路径[:]
    elif nextnode未被阻止:
    append(nextnode)
    append((nextnode,list(subG[nextnode]))
    已阻止。添加(下一个节点)
    持续
    如果不是NBR或len(路径)>=限制:
    已阻止。删除(此节点)
    stack.pop()
    path.pop()
    子g.删除节点(开始节点)
    H=子g.子图(scc)
    扩展(列表(nx.强连接组件(H)))
    
    对不起-我不明白你在“奖金”评论中的意思。你能改写一下吗?这也是我的第一反应,但它不起作用。我将用更多细节更新我的问题。非常感谢。在我看来,这就像将
    if-nbrs
    更改为
    if-nbrs和len(path)@Joel一样简单,不幸的是,这仍然导致了与Dorijan Cirkveni的答案相同的答案。为了获得更好的性能,我建议使用这个库:graph-tool.skewed.de
    
            ...
            if blocked.size>=limit+1:
                pass
            elif if nextnode == startnode:
                yield path[:] ...
    
    def simple_cycles(G, limit):
        subG = type(G)(G.edges())
        sccs = list(nx.strongly_connected_components(subG))
        while sccs:
            scc = sccs.pop()
            startnode = scc.pop()
            path = [startnode]
            blocked = set()
            blocked.add(startnode)
            stack = [(startnode, list(subG[startnode]))]
    
            while stack:
                thisnode, nbrs = stack[-1]
    
                if nbrs and len(path) < limit:
                    nextnode = nbrs.pop()
                    if nextnode == startnode:
                        yield path[:]
                    elif nextnode not in blocked:
                        path.append(nextnode)
                        stack.append((nextnode, list(subG[nextnode])))
                        blocked.add(nextnode)
                        continue
                if not nbrs or len(path) >= limit:
                    blocked.remove(thisnode)
                    stack.pop()
                    path.pop()
            subG.remove_node(startnode)
            H = subG.subgraph(scc)
            sccs.extend(list(nx.strongly_connected_components(H)))