ó
 ,µ[c           @   sÃ   d  Z  d d l m Z d d l m Z d d l m Z d d l Z d d l	 m
 Z
 d d l m Z e Z d j d	 g ƒ Z d
 g Z e
 d ƒ d d „ ƒ Z d „  Z d „  Z d „  Z d „  Z d S(   s,   
Moody and White algorithm for k-components
iÿÿÿÿ(   t   defaultdict(   t   combinations(   t
   itemgetterN(   t   not_implemented_for(   t   edmonds_karps   
s%   Jordi Torrents <jtorrents@milnou.net>t   k_componentst   directedc         C   se  t  t ƒ } | d k r! t } n  xI t j |  ƒ D]8 } t | ƒ } t | ƒ d k r1 | d j | ƒ q1 q1 Wt t j	 |  ƒ ƒ } x@ | D]8 } t | ƒ } t | ƒ d k r‰ | d j | ƒ q‰ q‰ Wx“| D]‹} t | ƒ d k rê qÌ n  t j
 | d | ƒ}	 |	 d k r+| |	 j t | j ƒ  ƒ ƒ n  t t j | d |	 d | ƒƒ }
 |	 t | |
 |	 ƒ f g } xí | rV| d \ } } yµ t | ƒ } | j | ƒ } t j
 | d | ƒ} | | k rë| d k rë| | j t | j ƒ  ƒ ƒ n  t t j | d | d | ƒƒ }
 |
 r4| j | t | |
 | ƒ f ƒ n  Wqjt k
 rR| j ƒ  qjXqjWqÌ Wt | ƒ S(   s8  Returns the k-component structure of a graph G.

    A `k`-component is a maximal subgraph of a graph G that has, at least,
    node connectivity `k`: we need to remove at least `k` nodes to break it
    into more components. `k`-components have an inherent hierarchical
    structure because they are nested in terms of connectivity: a connected
    graph can contain several 2-components, each of which can contain
    one or more 3-components, and so forth.

    Parameters
    ----------
    G : NetworkX graph

    flow_func : function
        Function to perform the underlying flow computations. Default value
        :meth:`edmonds_karp`. This function performs better in sparse graphs with
        right tailed degree distributions. :meth:`shortest_augmenting_path` will
        perform better in denser graphs.

    Returns
    -------
    k_components : dict
        Dictionary with all connectivity levels `k` in the input Graph as keys
        and a list of sets of nodes that form a k-component of level `k` as
        values.

    Raises
    ------
    NetworkXNotImplemented:
        If the input graph is directed.

    Examples
    --------
    >>> # Petersen graph has 10 nodes and it is triconnected, thus all
    >>> # nodes are in a single component on all three connectivity levels
    >>> G = nx.petersen_graph()
    >>> k_components = nx.k_components(G)

    Notes
    -----
    Moody and White [1]_ (appendix A) provide an algorithm for identifying
    k-components in a graph, which is based on Kanevsky's algorithm [2]_
    for finding all minimum-size node cut-sets of a graph (implemented in
    :meth:`all_node_cuts` function):

        1. Compute node connectivity, k, of the input graph G.

        2. Identify all k-cutsets at the current level of connectivity using
           Kanevsky's algorithm.

        3. Generate new graph components based on the removal of
           these cutsets. Nodes in a cutset belong to both sides
           of the induced cut.

        4. If the graph is neither complete nor trivial, return to 1;
           else end.

    This implementation also uses some heuristics (see [3]_ for details)
    to speed up the computation.

    See also
    --------
    node_connectivity
    all_node_cuts
    biconnected_components : special case of this function when k=2
    k_edge_components : similar to this function, but uses edge-connectivity
        instead of node-connectivity

    References
    ----------
    .. [1]  Moody, J. and D. White (2003). Social cohesion and embeddedness:
            A hierarchical conception of social groups.
            American Sociological Review 68(1), 103--28.
            http://www2.asanet.org/journals/ASRFeb03MoodyWhite.pdf

    .. [2]  Kanevsky, A. (1993). Finding all minimum-size separating vertex
            sets in a graph. Networks 23(6), 533--541.
            http://onlinelibrary.wiley.com/doi/10.1002/net.3230230604/abstract

    .. [3]  Torrents, J. and F. Ferraro (2015). Structural Cohesion:
            Visualization and Heuristics for Fast Computation.
            https://arxiv.org/pdf/1503.04476v1

    i   i   t	   flow_funct   kiÿÿÿÿN(   R    t   listt   Nonet   default_flow_funct   nxt   connected_componentst   sett   lent   appendt   biconnected_component_subgraphst   node_connectivityt   nodest   all_node_cutst   _generate_partitiont   nextt   subgrapht   StopIterationt   popt   _reconstruct_k_components(   t   GR   R   t	   componentt   compt   bicomponentst   bicomponentt   bicompt   BR   t   cutst   stackt   parent_kt	   partitionR   t   Ct   this_k(    (    sK   lib/python2.7/site-packages/networkx/algorithms/connectivity/kcomponents.pyR      sD    Y	 !	 !&	c         #   s›   t  j ƒ  } d „  t |  ƒ Dƒ ‰ | j ˆ ƒ | j ‡  ‡ f d †  t ˆ d ƒ Dƒ ƒ x< t  j | ƒ D]+ } t j g  | D] } ˆ | ^ q{ Œ  Vqh Wd S(   ss  Merge sets that share k or more elements.

    See: http://rosettacode.org/wiki/Set_consolidation

    The iterative python implementation posted there is
    faster than this because of the overhead of building a
    Graph and calling nx.connected_components, but it's not
    clear for us if we can use it in NetworkX because there
    is no licence for the code.

    c         S   s   i  |  ] \ } } | | “ q S(    (    (   t   .0t   it   s(    (    sK   lib/python2.7/site-packages/networkx/algorithms/connectivity/kcomponents.pys
   <dictcomp>«   s   	 c         3   s?   |  ]5 \ } } t  ˆ | ˆ | @ƒ ˆ  k r | | f Vq d  S(   N(   R   (   R(   t   ut   v(   R   R   (    sK   lib/python2.7/site-packages/networkx/algorithms/connectivity/kcomponents.pys	   <genexpr>­   s    	i   N(	   R   t   Grapht	   enumeratet   add_nodes_fromt   add_edges_fromR   R   R   t   union(   t   setsR   R   R   t   n(    (   R   R   sK   lib/python2.7/site-packages/networkx/algorithms/connectivity/kcomponents.pyt   _consolidatež   s    )c         #   s  d „  } g  } ‡  f d †  |  j  ƒ  Dƒ d „  | Dƒ } |  j | ƒ } x t j | ƒ D]~ } t | ƒ } xA | D]9 }	 x0 |	 D]( }
 | |  |
 | ƒ r~ | j |
 ƒ q~ q~ Wqq Wt | ƒ |  j ƒ  k  rX | j | ƒ qX qX Wx  t	 | ˆ  d ƒ D] } | Vqî Wd  S(   Nc         S   s)   x" |  | D] } | | k r t  Sq Wt S(   N(   t   Truet   False(   R   t   nodeR%   R3   (    (    sK   lib/python2.7/site-packages/networkx/algorithms/connectivity/kcomponents.pyt   has_nbrs_in_partition´   s    c            s(   h  |  ] \ } } | ˆ  k r | ’ q S(    (    (   R(   R3   t   d(   R   (    sK   lib/python2.7/site-packages/networkx/algorithms/connectivity/kcomponents.pys	   <setcomp>º   s   	 c         S   s#   h  |  ] } | D] } | ’ q q S(    (    (   R(   t   cutR3   (    (    sK   lib/python2.7/site-packages/networkx/algorithms/connectivity/kcomponents.pys	   <setcomp>»   s   	 i   (
   t   degreeR   R   R   R   t   addR   t   orderR   R4   (   R   R"   R   R8   t
   componentsR   t   Ht   ccR   R:   R7   (    (   R   sK   lib/python2.7/site-packages/networkx/algorithms/connectivity/kcomponents.pyR   ³   s    	c            s0  t  ƒ  } t |  ƒ } xt t d | d ƒ ƒ D]ù } | | k ra t t |  | | ƒ ƒ | | <q/ | |  k r‘ t t | | d | ƒ ƒ | | <q/ t j |  | Œ  ‰  g  | | d D]( } t ‡  f d †  | Dƒ ƒ r³ | ^ q³ } | rt t |  | | | ƒ ƒ | | <q/ t t |  | | ƒ ƒ | | <q/ W| S(   Ni   c         3   s   |  ] } | ˆ  k Vq d  S(   N(    (   R(   R3   (   t
   nodes_at_k(    sK   lib/python2.7/site-packages/networkx/algorithms/connectivity/kcomponents.pys	   <genexpr>Ó   s    (	   t   dictt   maxt   reversedt   rangeR	   R4   R   R1   t   any(   t   k_compst   resultt   max_kR   t   ct   to_add(    (   RA   sK   lib/python2.7/site-packages/networkx/algorithms/connectivity/kcomponents.pyR   É   s    	  $=$!c         C   se   i  } xX t  |  j ƒ  d t d ƒ ƒD]8 \ } } x) | D]! } x | D] } | | | <qE Wq8 Wq% W| S(   Nt   keyi    (   t   sortedt   itemsR   (   t   kcompsRH   R   t   compsR   R7   (    (    sK   lib/python2.7/site-packages/networkx/algorithms/connectivity/kcomponents.pyt   build_k_number_dictÛ   s    +(   t   __doc__t   collectionsR    t	   itertoolsR   t   operatorR   t   networkxR   t   networkx.utilsR   t   networkx.algorithms.flowR   R   t   joint
   __author__t   __all__R
   R   R4   R   R   RQ   (    (    (    sK   lib/python2.7/site-packages/networkx/algorithms/connectivity/kcomponents.pyt   <module>   s   		‰			