U
    ?h.                     @   s   d Z ddlZddlmZ dddddd	gZejed
dd Zed
dddZed
dd Z	ed
dd Z
ed
dd Zed
ddd	ZdS )zStrongly connected components.    N)not_implemented_for$number_strongly_connected_componentsstrongly_connected_componentsis_strongly_connected'strongly_connected_components_recursive&kosaraju_strongly_connected_componentscondensationZ
undirectedc                 #   sn  i }i }t  }g }d} fdd D } D ]:}||kr,|g}|r,|d }	|	|krd|d }|||	< d}
||	 D ]}||krp|| d}
 qqp|
r@||	 ||	<  |	 D ]N}||kr|| ||	 krt||	 || g||	< qt||	 || g||	< q|  ||	 ||	 kr\|	h}|rJ||d  ||	 krJ| }|| q|| |V  q@||	 q@q,dS )	a  Generate nodes in strongly connected components of graph.

    Parameters
    ----------
    G : NetworkX Graph
        A directed graph.

    Returns
    -------
    comp : generator of sets
        A generator of sets of nodes, one for each strongly connected
        component of G.

    Raises
    ------
    NetworkXNotImplemented
        If G is undirected.

    Examples
    --------
    Generate a sorted list of strongly connected components, largest first.

    >>> G = nx.cycle_graph(4, create_using=nx.DiGraph())
    >>> nx.add_cycle(G, [10, 11, 12])
    >>> [
    ...     len(c)
    ...     for c in sorted(nx.strongly_connected_components(G), key=len, reverse=True)
    ... ]
    [4, 3]

    If you only want the largest component, it's more efficient to
    use max instead of sort.

    >>> largest = max(nx.strongly_connected_components(G), key=len)

    See Also
    --------
    connected_components
    weakly_connected_components
    kosaraju_strongly_connected_components

    Notes
    -----
    Uses Tarjan's algorithm[1]_ with Nuutila's modifications[2]_.
    Nonrecursive version of algorithm.

    References
    ----------
    .. [1] Depth-first search and linear graph algorithms, R. Tarjan
       SIAM Journal of Computing 1(2):146-160, (1972).

    .. [2] On finding the strongly connected components in a directed graph.
       E. Nuutila and E. Soisalon-Soinen
       Information Processing Letters 49(1): 9-14, (1994)..

    r   c                    s   i | ]}|t  | qS  )iter.0vGr	   c/var/www/html/venv/lib/python3.8/site-packages/networkx/algorithms/components/strongly_connected.py
<dictcomp>O   s      z1strongly_connected_components.<locals>.<dictcomp>   TFN)setappendminpopaddupdate)r   ZpreorderZlowlinkZ	scc_foundZ	scc_queueiZ	neighborssourcequeuer   donewscckr	   r   r   r      sH    ;


c                 #   sj   t tj| jdd|d}t  |rf| }| kr6q t| |} fdd|D } | |V  q dS )a	  Generate nodes in strongly connected components of graph.

    Parameters
    ----------
    G : NetworkX Graph
        A directed graph.

    Returns
    -------
    comp : generator of sets
        A generator of sets of nodes, one for each strongly connected
        component of G.

    Raises
    ------
    NetworkXNotImplemented
        If G is undirected.

    Examples
    --------
    Generate a sorted list of strongly connected components, largest first.

    >>> G = nx.cycle_graph(4, create_using=nx.DiGraph())
    >>> nx.add_cycle(G, [10, 11, 12])
    >>> [
    ...     len(c)
    ...     for c in sorted(
    ...         nx.kosaraju_strongly_connected_components(G), key=len, reverse=True
    ...     )
    ... ]
    [4, 3]

    If you only want the largest component, it's more efficient to
    use max instead of sort.

    >>> largest = max(nx.kosaraju_strongly_connected_components(G), key=len)

    See Also
    --------
    strongly_connected_components

    Notes
    -----
    Uses Kosaraju's algorithm.

    F)copy)r   c                    s   h | ]}| kr|qS r	   r	   r   seenr	   r   	<setcomp>   s      z9kosaraju_strongly_connected_components.<locals>.<setcomp>N)listnxZdfs_postorder_nodesreverser   r   Zdfs_preorder_nodesr   )r   r   postrcnewr	   r"   r   r   r   s    0
c                 #   sP    fddi i i d}g  D ]}|kr.||E dH  q.dS )a!  Generate nodes in strongly connected components of graph.

    Recursive version of algorithm.

    Parameters
    ----------
    G : NetworkX Graph
        A directed graph.

    Returns
    -------
    comp : generator of sets
        A generator of sets of nodes, one for each strongly connected
        component of G.

    Raises
    ------
    NetworkXNotImplemented
        If G is undirected.

    Examples
    --------
    Generate a sorted list of strongly connected components, largest first.

    >>> G = nx.cycle_graph(4, create_using=nx.DiGraph())
    >>> nx.add_cycle(G, [10, 11, 12])
    >>> [
    ...     len(c)
    ...     for c in sorted(
    ...         nx.strongly_connected_components_recursive(G), key=len, reverse=True
    ...     )
    ... ]
    [4, 3]

    If you only want the largest component, it's more efficient to
    use max instead of sort.

    >>> largest = max(nx.strongly_connected_components_recursive(G), key=len)

    To create the induced subgraph of the components use:
    >>> S = [G.subgraph(c).copy() for c in nx.weakly_connected_components(G)]

    See Also
    --------
    connected_components

    Notes
    -----
    Uses Tarjan's algorithm[1]_ with Nuutila's modifications[2]_.

    References
    ----------
    .. [1] Depth-first search and linear graph algorithms, R. Tarjan
       SIAM Journal of Computing 1(2):146-160, (1972).

    .. [2] On finding the strongly connected components in a directed graph.
       E. Nuutila and E. Soisalon-Soinen
       Information Processing Letters 49(1): 9-14, (1994)..

    c                 3   s   || < || < |d7 } |   |  D ]:}|krF||E d H  |kr*t|  | | < q*|  |  krĈ|  | < | h}d | kr }|  |< || q|  |V  d S )Nr   r   )r   r   r   r   remove)r   cntr   Ztmpcr   	componentrootstackvisitvisitedr	   r   r2      s$    

z6strongly_connected_components_recursive.<locals>.visitr   Nr	   )r   r-   r   r	   r.   r   r      s    ?c                 C   s   t dd t| D S )a  Returns number of strongly connected components in graph.

    Parameters
    ----------
    G : NetworkX graph
       A directed graph.

    Returns
    -------
    n : integer
       Number of strongly connected components

    Raises
    ------
    NetworkXNotImplemented
        If G is undirected.

    Examples
    --------
    >>> G = nx.DiGraph([(0, 1), (1, 2), (2, 0), (2, 3), (4, 5), (3, 4), (5, 6), (6, 3), (6, 7)])
    >>> nx.number_strongly_connected_components(G)
    3

    See Also
    --------
    strongly_connected_components
    number_connected_components
    number_weakly_connected_components

    Notes
    -----
    For directed graphs only.
    c                 s   s   | ]
}d V  qdS )r   Nr	   )r   r   r	   r	   r   	<genexpr>/  s     z7number_strongly_connected_components.<locals>.<genexpr>)sumr   r   r	   r	   r   r     s    #c                 C   s.   t | dkrtdt tt| t | kS )aW  Test directed graph for strong connectivity.

    A directed graph is strongly connected if and only if every vertex in
    the graph is reachable from every other vertex.

    Parameters
    ----------
    G : NetworkX Graph
       A directed graph.

    Returns
    -------
    connected : bool
      True if the graph is strongly connected, False otherwise.

    Examples
    --------
    >>> G = nx.DiGraph([(0, 1), (1, 2), (2, 3), (3, 0), (2, 4), (4, 2)])
    >>> nx.is_strongly_connected(G)
    True
    >>> G.remove_edge(2, 3)
    >>> nx.is_strongly_connected(G)
    False

    Raises
    ------
    NetworkXNotImplemented
        If G is undirected.

    See Also
    --------
    is_weakly_connected
    is_semiconnected
    is_connected
    is_biconnected
    strongly_connected_components

    Notes
    -----
    For directed graphs only.
    r   z-Connectivity is undefined for the null graph.)lenr&   ZNetworkXPointlessConceptnextr   r   r	   r	   r   r   2  s
    +c                    s   |dkrt | }i i }t  }|jd< t| dkr<|S t|D ](\ }|| <  fdd|D  qD d }|t| |	fdd| 
 D  t ||d |S )	a  Returns the condensation of G.

    The condensation of G is the graph with each of the strongly connected
    components contracted into a single node.

    Parameters
    ----------
    G : NetworkX DiGraph
       A directed graph.

    scc:  list or generator (optional, default=None)
       Strongly connected components. If provided, the elements in
       `scc` must partition the nodes in `G`. If not provided, it will be
       calculated as scc=nx.strongly_connected_components(G).

    Returns
    -------
    C : NetworkX DiGraph
       The condensation graph C of G.  The node labels are integers
       corresponding to the index of the component in the list of
       strongly connected components of G.  C has a graph attribute named
       'mapping' with a dictionary mapping the original nodes to the
       nodes in C to which they belong.  Each node in C also has a node
       attribute 'members' with the set of original nodes in G that
       form the SCC that the node in C represents.

    Raises
    ------
    NetworkXNotImplemented
        If G is undirected.

    Examples
    --------
    Contracting two sets of strongly connected nodes into two distinct SCC
    using the barbell graph.

    >>> G = nx.barbell_graph(4, 0)
    >>> G.remove_edge(3, 4)
    >>> G = nx.DiGraph(G)
    >>> H = nx.condensation(G)
    >>> H.nodes.data()
    NodeDataView({0: {'members': {0, 1, 2, 3}}, 1: {'members': {4, 5, 6, 7}}})
    >>> H.graph['mapping']
    {0: 0, 1: 0, 2: 0, 3: 0, 4: 1, 5: 1, 6: 1, 7: 1}

    Contracting a complete graph into one single SCC.

    >>> G = nx.complete_graph(7, create_using=nx.DiGraph)
    >>> H = nx.condensation(G)
    >>> H.nodes
    NodeView((0,))
    >>> H.nodes.data()
    NodeDataView({0: {'members': {0, 1, 2, 3, 4, 5, 6}}})

    Notes
    -----
    After contracting all strongly connected components to a single node,
    the resulting graph is a directed acyclic graph.

    Nmappingr   c                 3   s   | ]}| fV  qd S Nr	   )r   n)r   r	   r   r4     s     zcondensation.<locals>.<genexpr>r   c                 3   s2   | ]*\}} |  | kr |  | fV  qd S r9   r	   )r   ur   )r8   r	   r   r4     s     members)r&   r   ZDiGraphgraphr6   	enumerater   Zadd_nodes_fromrangeZadd_edges_fromedgesZset_node_attributes)r   r   r<   Cr/   Znumber_of_componentsr	   )r   r8   r   r   e  s$    >

)N)N)__doc__Znetworkxr&   Znetworkx.utils.decoratorsr   __all__Z	_dispatchr   r   r   r   r   r   r	   r	   r	   r   <module>   s,   
a<
\
%
2