
    hQ                     V   S r SSKrSSKJr  SSKrSSKJrJ	r	  / SQr
\	" S5      \R                  S 5       5       r\	" S5      \R                  S 5       5       rS	 r\	" S
5      \	" S5      \R                  S 5       5       5       r " S S5      rSS jrS r\R                  " SS9S 5       rg)aw  
Algorithms for finding k-edge-connected components and subgraphs.

A k-edge-connected component (k-edge-cc) is a maximal set of nodes in G, such
that all pairs of node have an edge-connectivity of at least k.

A k-edge-connected subgraph (k-edge-subgraph) is a maximal set of nodes in G,
such that the subgraph of G defined by the nodes has an edge-connectivity at
least k.
    N)partial)arbitrary_elementnot_implemented_for)k_edge_componentsk_edge_subgraphsbridge_componentsEdgeComponentAuxGraph
multigraphc                 x   US:  a  [        S5      eU R                  5       (       aB  US:X  a  [        R                  " U 5      $ [        R                  U 5      nUR                  U5      $ US:X  a  [        R                  " U 5      $ US:X  a  [        U 5      $ [        R                  U 5      nUR                  U5      $ )a  Generates nodes in each maximal k-edge-connected component in G.

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

k : Integer
    Desired edge connectivity

Returns
-------
k_edge_components : a generator of k-edge-ccs. Each set of returned nodes
   will have k-edge-connectivity in the graph G.

See Also
--------
:func:`local_edge_connectivity`
:func:`k_edge_subgraphs` : similar to this function, but the subgraph
    defined by the nodes must also have k-edge-connectivity.
:func:`k_components` : similar to this function, but uses node-connectivity
    instead of edge-connectivity

Raises
------
NetworkXNotImplemented
    If the input graph is a multigraph.

ValueError:
    If k is less than 1

Notes
-----
Attempts to use the most efficient implementation available based on k.
If k=1, this is simply connected components for directed graphs and
connected components for undirected graphs.
If k=2 on an efficient bridge connected component algorithm from _[1] is
run based on the chain decomposition.
Otherwise, the algorithm from _[2] is used.

Examples
--------
>>> import itertools as it
>>> from networkx.utils import pairwise
>>> paths = [
...     (1, 2, 4, 3, 1, 4),
...     (5, 6, 7, 8, 5, 7, 8, 6),
... ]
>>> G = nx.Graph()
>>> G.add_nodes_from(it.chain(*paths))
>>> G.add_edges_from(it.chain(*[pairwise(path) for path in paths]))
>>> # note this returns {1, 4} unlike k_edge_subgraphs
>>> sorted(map(sorted, nx.k_edge_components(G, k=3)))
[[1, 4], [2], [3], [5, 6, 7, 8]]

References
----------
.. [1] https://en.wikipedia.org/wiki/Bridge_%28graph_theory%29
.. [2] Wang, Tianhao, et al. (2015) A simple algorithm for finding all
    k-edge-connected components.
    http://journals.plos.org/plosone/article?id=10.1371/journal.pone.0136264
   k cannot be less than 1   )	
ValueErroris_directednxstrongly_connected_componentsr	   	constructr   connected_componentsr   )Gk	aux_graphs      c/var/www/html/env/lib/python3.13/site-packages/networkx/algorithms/connectivity/edge_kcomponents.pyr   r      s    B 	1u233}}633A66 .77:I..q116**1--!V$Q''-77:I..q11    c                     US:  a  [        S5      eU R                  5       (       a  US::  a  [        X5      $ [        X5      $ US::  a  [        X5      $ [        X5      $ )u=  Generates nodes in each maximal k-edge-connected subgraph in G.

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

k : Integer
    Desired edge connectivity

Returns
-------
k_edge_subgraphs : a generator of k-edge-subgraphs
    Each k-edge-subgraph is a maximal set of nodes that defines a subgraph
    of G that is k-edge-connected.

See Also
--------
:func:`edge_connectivity`
:func:`k_edge_components` : similar to this function, but nodes only
    need to have k-edge-connectivity within the graph G and the subgraphs
    might not be k-edge-connected.

Raises
------
NetworkXNotImplemented
    If the input graph is a multigraph.

ValueError:
    If k is less than 1

Notes
-----
Attempts to use the most efficient implementation available based on k.
If k=1, or k=2 and the graph is undirected, then this simply calls
`k_edge_components`.  Otherwise the algorithm from _[1] is used.

Examples
--------
>>> import itertools as it
>>> from networkx.utils import pairwise
>>> paths = [
...     (1, 2, 4, 3, 1, 4),
...     (5, 6, 7, 8, 5, 7, 8, 6),
... ]
>>> G = nx.Graph()
>>> G.add_nodes_from(it.chain(*paths))
>>> G.add_edges_from(it.chain(*[pairwise(path) for path in paths]))
>>> # note this does not return {1, 4} unlike k_edge_components
>>> sorted(map(sorted, nx.k_edge_subgraphs(G, k=3)))
[[1], [2], [3], [4], [5, 6, 7, 8]]

References
----------
.. [1] Zhou, Liu, et al. (2012) Finding maximal k-edge-connected subgraphs
    from a large graph.  ACM International Conference on Extending Database
    Technology 2012 480-–491.
    https://openproceedings.org/2012/conf/edbt/ZhouLYLCL12.pdf
r   r   r   )r   r   r   _k_edge_subgraphs_nodes)r   r   s     r   r   r   n   sa    z 	1u233}}6 %Q***1006 %Q***100r   c              #   f   #    [        X5       H  n[        UR                  5       5      v   M      g7f)zaHelper to get the nodes from the subgraphs.

This allows k_edge_subgraphs to return a generator.
N)general_k_edge_subgraphssetnodes)r   r   Cs      r   r   r      s&     
 &a+!'')n ,s   /1directedc              #      #    U R                  5       nUR                  [        R                  " U 5      5        [        R                  " U5       Sh  vN   g N7f)au  Finds all bridge-connected components G.

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

Returns
-------
bridge_components : a generator of 2-edge-connected components


See Also
--------
:func:`k_edge_subgraphs` : this function is a special case for an
    undirected graph where k=2.
:func:`biconnected_components` : similar to this function, but is defined
    using 2-node-connectivity instead of 2-edge-connectivity.

Raises
------
NetworkXNotImplemented
    If the input graph is directed or a multigraph.

Notes
-----
Bridge-connected components are also known as 2-edge-connected components.

Examples
--------
>>> # The barbell graph with parameter zero has a single bridge
>>> G = nx.barbell_graph(5, 0)
>>> from networkx.algorithms.connectivity.edge_kcomponents import bridge_components
>>> sorted(map(sorted, bridge_components(G)))
[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]
N)copyremove_edges_fromr   bridgesr   )r   Hs     r   r   r      s=     N 	
A

1&&&q)))s   AAAAc                   4    \ rS rSrSr\S 5       rS rS rSr	g)r	      a  A simple algorithm to find all k-edge-connected components in a graph.

Constructing the auxiliary graph (which may take some time) allows for the
k-edge-ccs to be found in linear time for arbitrary k.

Notes
-----
This implementation is based on [1]_. The idea is to construct an auxiliary
graph from which the k-edge-ccs can be extracted in linear time. The
auxiliary graph is constructed in $O(|V|\cdot F)$ operations, where F is the
complexity of max flow. Querying the components takes an additional $O(|V|)$
operations. This algorithm can be slow for large graphs, but it handles an
arbitrary k and works for both directed and undirected inputs.

The undirected case for k=1 is exactly connected components.
The undirected case for k=2 is exactly bridge connected components.
The directed case for k=1 is exactly strongly connected components.

References
----------
.. [1] Wang, Tianhao, et al. (2015) A simple algorithm for finding all
    k-edge-connected components.
    http://journals.plos.org/plosone/article?id=10.1371/journal.pone.0136264

Examples
--------
>>> import itertools as it
>>> from networkx.utils import pairwise
>>> from networkx.algorithms.connectivity import EdgeComponentAuxGraph
>>> # Build an interesting graph with multiple levels of k-edge-ccs
>>> paths = [
...     (1, 2, 3, 4, 1, 3, 4, 2),  # a 3-edge-cc (a 4 clique)
...     (5, 6, 7, 5),  # a 2-edge-cc (a 3 clique)
...     (1, 5),  # combine first two ccs into a 1-edge-cc
...     (0,),  # add an additional disconnected 1-edge-cc
... ]
>>> G = nx.Graph()
>>> G.add_nodes_from(it.chain(*paths))
>>> G.add_edges_from(it.chain(*[pairwise(path) for path in paths]))
>>> # Constructing the AuxGraph takes about O(n ** 4)
>>> aux_graph = EdgeComponentAuxGraph.construct(G)
>>> # Once constructed, querying takes O(n)
>>> sorted(map(sorted, aux_graph.k_edge_components(k=1)))
[[0], [1, 2, 3, 4, 5, 6, 7]]
>>> sorted(map(sorted, aux_graph.k_edge_components(k=2)))
[[0], [1, 2, 3, 4], [5, 6, 7]]
>>> sorted(map(sorted, aux_graph.k_edge_components(k=3)))
[[0], [1, 2, 3, 4], [5], [6], [7]]
>>> sorted(map(sorted, aux_graph.k_edge_components(k=4)))
[[0], [1], [2], [3], [4], [5], [6], [7]]

The auxiliary graph is primarily used for k-edge-ccs but it
can also speed up the queries of k-edge-subgraphs by refining the
search space.

>>> import itertools as it
>>> from networkx.utils import pairwise
>>> from networkx.algorithms.connectivity import EdgeComponentAuxGraph
>>> paths = [
...     (1, 2, 4, 3, 1, 4),
... ]
>>> G = nx.Graph()
>>> G.add_nodes_from(it.chain(*paths))
>>> G.add_edges_from(it.chain(*[pairwise(path) for path in paths]))
>>> aux_graph = EdgeComponentAuxGraph.construct(G)
>>> sorted(map(sorted, aux_graph.k_edge_subgraphs(k=3)))
[[1], [2], [3], [4]]
>>> sorted(map(sorted, aux_graph.k_edge_components(k=3)))
[[1, 4], [2], [3]]
c                   ^ [        S5      " S 5      " U5        U4S jmUR                  5       nUR                  UR                  5       5        UR	                  UR                  5       SS9  [        R                  " 5       nUR                  5       S:  a;  [        UR                  5       5      n[        UR                  5       5      nT" X#XE5        U " 5       nX6l        X&l        U$ )a  Builds an auxiliary graph encoding edge-connectivity between nodes.

Notes
-----
Given G=(V, E), initialize an empty auxiliary graph A.
Choose an arbitrary source node s.  Initialize a set N of available
nodes (that can be used as the sink). The algorithm picks an
arbitrary node t from N - {s}, and then computes the minimum st-cut
(S, T) with value w. If G is directed the minimum of the st-cut or
the ts-cut is used instead. Then, the edge (s, t) is added to the
auxiliary graph with weight w. The algorithm is called recursively
first using S as the available nodes and s as the source, and then
using T and t. Recursion stops when the source is the only available
node.

Parameters
----------
G : NetworkX graph
r
   c                     U $ N )r   s    r   <lambda>1EdgeComponentAuxGraph.construct.<locals>.<lambda>Q  s    Ar   c                 ^  > U1U:X  a  g [        X21-
  5      n[        R                  " XU5      u  nu  pgU R                  5       (       a%  [        R                  " XU5      u  nu  pX:  a  XU	pvnUR	                  X$US9  T" XX#R                  U5      5        T" XXCR                  U5      5        g )N)weight)r   r   minimum_cutr   add_edgeintersection)r&   AsourceavailsinkvalueSTvalue_T_S__recursive_builds              r   r>   9EdgeComponentAuxGraph.construct.<locals>._recursive_buildS  s    x5 $UX%56DNN1d;ME6A}}#%>>!6#B >"(baEJJvEJ2Q6+=+=a+@AQ4););A)>?r   r   )capacityr   )r   	__class__add_nodes_fromr   add_edges_fromedgesr   Graphnumber_of_nodesr   r   r4   r&   )r	   r   r&   r4   r5   r6   selfr>   s          @r   r   EdgeComponentAuxGraph.construct;  s    , 	L)+6q9	@( KKM	#	Q/ HHJ "&qwwy1F	NE Q61 %&r   c              #   p  ^#    TS:  a  [        S5      eU R                  n[        R                  " US5      n[        R                  " 5       nUR                  UR                  5       5        UR                  U4S jUR                  5        5       5        [        R                  " U5       Sh  vN   g N7f)a  Queries the auxiliary graph for k-edge-connected components.

Parameters
----------
k : Integer
    Desired edge connectivity

Returns
-------
k_edge_components : a generator of k-edge-ccs

Notes
-----
Given the auxiliary graph, the k-edge-connected components can be
determined in linear time by removing all edges with weights less than
k from the auxiliary graph.  The resulting connected components are the
k-edge-ccs in the original graph.
r   r   r0   c              3   <   >#    U  H  u  pUT:  d  M  Uv   M     g 7fr+   r,   .0ewr   s      r   	<genexpr>:EdgeComponentAuxGraph.k_edge_components.<locals>.<genexpr>       E':tqa1f':   	N)
r   r4   r   get_edge_attributesrE   rB   r   rC   itemsr   )rG   r   r4   aux_weightsRs    `   r   r   'EdgeComponentAuxGraph.k_edge_components  s     & q5677FF ,,Q9HHJ	#	E{'8'8':EE **1---s   B+B6.B4/B6c              #     ^#    TS:  a  [        S5      eU R                  nU R                  n[        R                  " US5      n[        R
                  " 5       nUR                  UR                  5       5        UR                  U4S jUR                  5        5       5        [        R                  " U5       HG  n[        U5      T:  a  U H  nU1v   M
     M"  UR                  U5      n[        UT5       Sh  vN   MI     g N	7f)a  Queries the auxiliary graph for k-edge-connected subgraphs.

Parameters
----------
k : Integer
    Desired edge connectivity

Returns
-------
k_edge_subgraphs : a generator of k-edge-subgraphs

Notes
-----
Refines the k-edge-ccs into k-edge-subgraphs. The running time is more
than $O(|V|)$.

For single values of k it is faster to use `nx.k_edge_subgraphs`.
But for multiple values of k, it can be faster to build AuxGraph and
then use this method.
r   r   r0   c              3   <   >#    U  H  u  pUT:  d  M  Uv   M     g 7fr+   r,   rK   s      r   rO   9EdgeComponentAuxGraph.k_edge_subgraphs.<locals>.<genexpr>  rQ   rR   N)r   r&   r4   r   rS   rE   rB   r   rC   rT   r   lensubgraphr   )	rG   r   r&   r4   rU   rV   ccnoder    s	    `       r   r   &EdgeComponentAuxGraph.k_edge_subgraphs  s     * q5677FFFF ,,Q9HHJ	#	E{'8'8':EE ))!,B2w{D&L  JJrN+Aq111 - 2s   C6D9D:
D)r4   r&   N)
__name__
__module____qualname____firstlineno____doc__classmethodr   r   r   __static_attributes__r,   r   r   r	   r	      s+    EP A AF.B*2r   r	   c              #   |  #    U R                  5       (       a~  [        5       nU R                  U5       H!  u  pEXQ:  d  M  UR                  U5        Uv   M#     U R	                  U5       H(  u  pEXC;  d  M  XQ:  d  M  UR                  U5        Uv   M*     gU R                  U5       H  u  pEXQ:  d  M  Uv   M     g7f)z1Helper for finding nodes with degree less than k.N)r   r   
out_degreeadd	in_degreedegree)r   r   nbunchseenr^   rk   s         r   _low_degree_nodesrn     s      	}}uLL0LDz
 1 KK/LDFJ
 0 HHV,LDz
 -s   9B<2B<5B<<3B<3	B<c              #   "  #    U R                  5       n[        [        X!5      5      nU(       a  [        [        R                  R                  [        UR                  U5      5      5      nUR                  U5        UR                  U5        U H  nU1v   M
     [        [        X!U5      5      nU(       a  M  U R                  5       (       a  [        R                  " U5       Sh  vN   g[        R                  " U5       Sh  vN   g N$ N7f)zHelper for filtering components that can't be k-edge-connected.

Removes and generates each node with degree less than k.  Then generates
remaining components where all nodes have degree at least k.
N)r#   r   rn   itchainfrom_iterablemap	neighborsdifference_updateremove_nodes_fromr   r   r   r   )r   r   r&   
singletonsrl   r^   s         r   _high_degree_componentsrx     s      	
A&q,-J
RXX++CZ,HIJ  ,	J'D&L *189
 * 	}}33A666**1--- 	7-s*   B4D8.D&D'DDDDT)returns_graphc              #     #    US:  a  [        S5      e[        [        US9nU R                  5       U:  a:  U R	                  5        H%  nU R                  U/5      R                  5       v   M'     gU" U 5       Vs1 s H!  o@R                  U5      R                  5       iM#     nnU(       a  UR                  5       nUR                  5       S:X  a  Uv   Oy[        R                  " U5      n[        U5      nX:  aO  UR                  U5        U" U5       H1  nUR                  UR                  U5      R                  5       5        M3     OUv   U(       a  M  ggs  snf 7f)u  General algorithm to find all maximal k-edge-connected subgraphs in `G`.

Parameters
----------
G : nx.Graph
   Graph in which all maximal k-edge-connected subgraphs will be found.

k : int

Yields
------
k_edge_subgraphs : Graph instances that are k-edge-subgraphs
    Each k-edge-subgraph contains a maximal set of nodes that defines a
    subgraph of `G` that is k-edge-connected.

Notes
-----
Implementation of the basic algorithm from [1]_.  The basic idea is to find
a global minimum cut of the graph. If the cut value is at least k, then the
graph is a k-edge-connected subgraph and can be added to the results.
Otherwise, the cut is used to split the graph in two and the procedure is
applied recursively. If the graph is just a single node, then it is also
added to the results. At the end, each result is either guaranteed to be
a single node or a subgraph of G that is k-edge-connected.

This implementation contains optimizations for reducing the number of calls
to max-flow, but there are other optimizations in [1]_ that could be
implemented.

References
----------
.. [1] Zhou, Liu, et al. (2012) Finding maximal k-edge-connected subgraphs
    from a large graph.  ACM International Conference on Extending Database
    Technology 2012 480-–491.
    https://openproceedings.org/2012/conf/edbt/ZhouLYLCL12.pdf

Examples
--------
>>> from networkx.utils import pairwise
>>> paths = [
...     (11, 12, 13, 14, 11, 13, 14, 12),  # a 4-clique
...     (21, 22, 23, 24, 21, 23, 24, 22),  # another 4-clique
...     # connect the cliques with high degree but low connectivity
...     (50, 13),
...     (12, 50, 22),
...     (13, 102, 23),
...     (14, 101, 24),
... ]
>>> G = nx.Graph(it.chain(*[pairwise(path) for path in paths]))
>>> sorted(len(k_sg) for k_sg in k_edge_subgraphs(G, k=3))
[1, 1, 1, 4, 4]
r   r   )r   N)r   r   rx   rF   r   r\   r#   popr   minimum_edge_cutr[   r$   ri   )	r   r   find_ccsr^   r]   R0G1	cut_edges	cut_values	            r   r   r     s#    l 	1u233 .!4H 	QGGID**dV$))++  +31+	6+B**R.


+B	6
VVX1$H ++B/III}$$Y/"2,BFF2;;r?//12 '  " 
7s   A8E:(E"B2EEr+   )rd   	itertoolsrp   	functoolsr   networkxr   networkx.utilsr   r   __all___dispatchabler   r   r   r   r	   rn   rx   r   r,   r   r   <module>r      s   	    A \"O2  #O2d \"J1  #J1Z Z \"&*  # !&*RX2 X2v*.2 %T &Tr   