ó žÃÒYc@sÃdZddlmZddlmZddlmZddlZddl m Z ddl m Z e Z djd gƒZd gZe d ƒdd „ƒZd „Zd„Zd„Zd„ZdS(s, Moody and White algorithm for k-components iÿÿÿÿ(t defaultdict(t combinations(t itemgetterN(tnot_implemented_for(t edmonds_karps s%Jordi Torrents t k_componentstdirectedcCsettƒ}|dkr!t}nxItj|ƒD]8}t|ƒ}t|ƒdkr1|dj|ƒq1q1Wttj |ƒƒ}x@|D]8}t|ƒ}t|ƒdkr‰|dj|ƒq‰q‰Wx“|D]‹}t|ƒdkrêqÌntj |d|ƒ} | dkr+|| jt|j ƒƒƒnttj |d| d|ƒƒ} | t || | ƒfg} xí| rV| d\} } yµt| ƒ}|j|ƒ}tj |d|ƒ}|| krë|dkrë||jt|j ƒƒƒnttj |d|d|ƒƒ} | r4| j|t || |ƒfƒnWqjtk rR| jƒqjXqjWqÌ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 iit flow_functkiÿÿÿÿN(RtlisttNonetdefault_flow_functnxtconnected_componentstsettlentappendtbiconnected_component_subgraphstnode_connectivitytnodest all_node_cutst_generate_partitiontnexttsubgrapht StopIterationtpopt_reconstruct_k_components(tGRRt componenttcompt bicomponentst bicomponenttbicomptBRtcutststacktparent_kt partitionRtCtthis_k((s‚/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/connectivity/kcomponents.pyRsDY         !   !&  c#s›tjƒ}d„t|ƒDƒ‰|jˆƒ|j‡‡fd†tˆdƒDƒƒx<tj|ƒD]+}tjg|D]}ˆ|^q{ŒVqhWdS(ssMerge 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. cSsi|]\}}||“qS(((t.0tits((s‚/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/connectivity/kcomponents.pys «s c3s?|]5\}}tˆ|ˆ|@ƒˆkr||fVqdS(N(R(R(tutv(RR(s‚/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/connectivity/kcomponents.pys ­s iN( R tGrapht enumeratetadd_nodes_fromtadd_edges_fromRR Rtunion(tsetsRRRtn((RRs‚/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/connectivity/kcomponents.pyt _consolidatežs  )c #sd„}g}‡fd†|jƒDƒd„|Dƒ}|j|ƒ}xtj|ƒD]~}t|ƒ}xA|D]9} x0| D](} ||| |ƒr~|j| ƒq~q~WqqWt|ƒ|jƒkrX|j|ƒqXqXWx t |ˆdƒD] }|VqîWdS(NcSs)x"||D]}||kr tSq WtS(N(tTruetFalse(RtnodeR%R3((s‚/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/connectivity/kcomponents.pythas_nbrs_in_partition´s cs(h|]\}}|ˆkr|’qS(((R(R3td(R(s‚/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/connectivity/kcomponents.pys ºs cSs#h|]}|D] }|’qqS(((R(tcutR3((s‚/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/connectivity/kcomponents.pys »s i( tdegreeRR R RtaddRtorderRR4( RR"RR8t componentsRtHtccRR:R7((Rs‚/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/connectivity/kcomponents.pyR³s    cs0tƒ}t|ƒ}xttd|dƒƒD]ù}||kratt|||ƒƒ||Ós( tdicttmaxtreversedtrangeR R4RR1tany(tk_compstresulttmax_kRtctto_add((RAs‚/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/connectivity/kcomponents.pyRÉs      $=$!cCsei}xXt|jƒdtdƒƒD]8\}}x)|D]!}x|D]}|||s   ‰