(G)
Adapted from networkx: http://networkx.github.io/
    Parameters
    ----------
    G : DiGraph
    Returns
    -------
    cycle_generator: generator
       A generator that produces elementary cycles of the graph.
       Each cycle is represented by a list of nodes along the cycle.
Adapted from networkx: http://networkx.github.io/
    Parameters
    ----------
    G : DiGraph
    Returns
    -------
    cycle_generator: generator
       A generator that produces elementary cycles of the graph.
       Each cycle is represented by a list of nodes along the cycle.
Adapted from networkx : http : // networkx . github . io / Parameters ---------- G : DiGraph Returns ------- cycle_generator : generator A generator that produces elementary cycles of the graph . Each cycle is represented by a list of nodes along the cycle .
def simple_cycles(G):  # noqa: C901
    '''
    Adapted from networkx: http://networkx.github.io/
    Parameters
    ----------
    G : DiGraph
    Returns
    -------
    cycle_generator: generator
       A generator that produces elementary cycles of the graph.
       Each cycle is represented by a list of nodes along the cycle.
    '''

    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.
    # 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.
    subG = G.subgraph(G.nodes())
    sccs = list(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.neighbors(startnode)))]
        while stack:
            thisnode, nbrs = stack[-1]
            if nbrs:
                nextnode = nbrs.pop()
                if nextnode == startnode:
                    yield path[:]
                    closed.update(path)
                elif nextnode not in blocked:
                    path.append(nextnode)
                    stack.append((nextnode, list(subG.neighbors(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.neighbors(thisnode):
                        if thisnode not in B[nbr]:
                            B[nbr].add(thisnode)
                stack.pop()
                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(strongly_connected_components(H)))
def simple_cycles ( G ) : # noqa: C901 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. # 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. subG = G . subgraph ( G . nodes ( ) ) sccs = list ( 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 . neighbors ( startnode ) ) ) ] while stack : thisnode , nbrs = stack [ - 1 ] if nbrs : nextnode = nbrs . pop ( ) if nextnode == startnode : yield path [ : ] closed . update ( path ) elif nextnode not in blocked : path . append ( nextnode ) stack . append ( ( nextnode , list ( subG . neighbors ( 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 . neighbors ( thisnode ) : if thisnode not in B [ nbr ] : B [ nbr ] . add ( thisnode ) stack . pop ( ) 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 ( strongly_connected_components ( H ) ) )