
    sh"_                     >   S r SSKJrJrJrJr  SSKrSSKJr  SSK	J
r
  SSKJr  / SQr\R                  rS r\R"                  " S	S
S9      SS j5       rS r\R"                  " S
SS0S
S9 SSS.S jj5       r\r\R"                  " S
SS0S
S9 SSS.S jj5       rg)z3Provides functions for computing minors of a graph.    )chaincombinationspermutationsproductN)density)NetworkXException)arbitrary_element)contracted_edgecontracted_nodesequivalence_classesidentified_nodesquotient_graphc                     / nU  HJ  nU H/  n[        U5      nU" XS5      (       d  M  UR                  U5          M6     UR                  U/5        ML     U Vs1 s H  n[        U5      iM     sn$ s  snf )ak  Returns equivalence classes of `relation` when applied to `iterable`.

The equivalence classes, or blocks, consist of objects from `iterable`
which are all equivalent. They are defined to be equivalent if the
`relation` function returns `True` when passed any two objects from that
class, and `False` otherwise. To define an equivalence relation the
function must be reflexive, symmetric and transitive.

Parameters
----------
iterable : list, tuple, or set
    An iterable of elements/nodes.

relation : function
    A Boolean-valued function that implements an equivalence relation
    (reflexive, symmetric, transitive binary relation) on the elements
    of `iterable` - it must take two elements and return `True` if
    they are related, or `False` if not.

Returns
-------
set of frozensets
    A set of frozensets representing the partition induced by the equivalence
    relation function `relation` on the elements of `iterable`. Each
    member set in the return set represents an equivalence class, or
    block, of the partition.

    Duplicate elements will be ignored so it makes the most sense for
    `iterable` to be a :class:`set`.

Notes
-----
This function does not check that `relation` represents an equivalence
relation. You can check that your equivalence classes provide a partition
using `is_partition`.

Examples
--------
Let `X` be the set of integers from `0` to `9`, and consider an equivalence
relation `R` on `X` of congruence modulo `3`: this means that two integers
`x` and `y` in `X` are equivalent under `R` if they leave the same
remainder when divided by `3`, i.e. `(x - y) mod 3 = 0`.

The equivalence classes of this relation are `{0, 3, 6, 9}`, `{1, 4, 7}`,
`{2, 5, 8}`: `0`, `3`, `6`, `9` are all divisible by `3` and leave zero
remainder; `1`, `4`, `7` leave remainder `1`; while `2`, `5` and `8` leave
remainder `2`. We can see this by calling `equivalence_classes` with
`X` and a function implementation of `R`.

>>> X = set(range(10))
>>> def mod3(x, y):
...     return (x - y) % 3 == 0
>>> equivalence_classes(X, mod3)  # doctest: +SKIP
{frozenset({1, 4, 7}), frozenset({8, 2, 5}), frozenset({0, 9, 3, 6})}
)r	   append	frozenset)iterablerelationblocksyblockxs         z/Users/tiagomarins/Projetos/claudeai/copy_bank/venv/lib/python3.13/site-packages/networkx/algorithms/minors/contraction.pyr   r      sp    v F E!%(A~~Q	  MM1#  +11&Ie&111s   A/weightT)
edge_attrsreturns_graphc           
      .   [        U5      (       aW  [        X5      n[        R                  R	                  X5      (       d  [        R
                  " S5      e[        U UUUUUUU5      $ [        U[        5      (       a  [        UR                  5       5      n[        5       R                  " U6 n[        U5      [        U 5      :w  a  U R                  U5      n [        R                  R	                  X5      (       d  [        S5      e[        U UUUUUUU5      $ )a!  Returns the quotient graph of `G` under the specified equivalence
relation on nodes.

Parameters
----------
G : NetworkX graph
    The graph for which to return the quotient graph with the
    specified node relation.

partition : function, or dict or list of lists, tuples or sets
    If a function, this function must represent an equivalence
    relation on the nodes of `G`. It must take two arguments *u*
    and *v* and return True exactly when *u* and *v* are in the
    same equivalence class. The equivalence classes form the nodes
    in the returned graph.

    If a dict of lists/tuples/sets, the keys can be any meaningful
    block labels, but the values must be the block lists/tuples/sets
    (one list/tuple/set per block), and the blocks must form a valid
    partition of the nodes of the graph. That is, each node must be
    in exactly one block of the partition.

    If a list of sets, the list must form a valid partition of
    the nodes of the graph. That is, each node must be in exactly
    one block of the partition.

edge_relation : Boolean function with two arguments
    This function must represent an edge relation on the *blocks* of
    the `partition` of `G`. It must take two arguments, *B* and *C*,
    each one a set of nodes, and return True exactly when there should be
    an edge joining block *B* to block *C* in the returned graph.

    If `edge_relation` is not specified, it is assumed to be the
    following relation. Block *B* is related to block *C* if and
    only if some node in *B* is adjacent to some node in *C*,
    according to the edge set of `G`.

node_data : function
    This function takes one argument, *B*, a set of nodes in `G`,
    and must return a dictionary representing the node data
    attributes to set on the node representing *B* in the quotient graph.
    If None, the following node attributes will be set:

    * 'graph', the subgraph of the graph `G` that this block
      represents,
    * 'nnodes', the number of nodes in this block,
    * 'nedges', the number of edges within this block,
    * 'density', the density of the subgraph of `G` that this
      block represents.

edge_data : function
    This function takes two arguments, *B* and *C*, each one a set
    of nodes, and must return a dictionary representing the edge
    data attributes to set on the edge joining *B* and *C*, should
    there be an edge joining *B* and *C* in the quotient graph (if
    no such edge occurs in the quotient graph as determined by
    `edge_relation`, then the output of this function is ignored).

    If the quotient graph would be a multigraph, this function is
    not applied, since the edge data from each edge in the graph
    `G` appears in the edges of the quotient graph.

weight : string or None, optional (default="weight")
    The name of an edge attribute that holds the numerical value
    used as a weight. If None then each edge has weight 1.

relabel : bool
    If True, relabel the nodes of the quotient graph to be
    nonnegative integers. Otherwise, the nodes are identified with
    :class:`frozenset` instances representing the blocks given in
    `partition`.

create_using : NetworkX graph constructor, optional (default=nx.Graph)
   Graph type to create. If graph instance, then cleared before populated.

Returns
-------
NetworkX graph
    The quotient graph of `G` under the equivalence relation
    specified by `partition`. If the partition were given as a
    list of :class:`set` instances and `relabel` is False,
    each node will be a :class:`frozenset` corresponding to the same
    :class:`set`.

Raises
------
NetworkXException
    If the given partition is not a valid partition of the nodes of
    `G`.

Examples
--------
The quotient graph of the complete bipartite graph under the "same
neighbors" equivalence relation is `K_2`. Under this relation, two nodes
are equivalent if they are not adjacent but have the same neighbor set.

>>> G = nx.complete_bipartite_graph(2, 3)
>>> same_neighbors = lambda u, v: (u not in G[v] and v not in G[u] and G[u] == G[v])
>>> Q = nx.quotient_graph(G, same_neighbors)
>>> K2 = nx.complete_graph(2)
>>> nx.is_isomorphic(Q, K2)
True

The quotient graph of a directed graph under the "same strongly connected
component" equivalence relation is the condensation of the graph (see
:func:`condensation`). This example comes from the Wikipedia article
*`Strongly connected component`_*.

>>> G = nx.DiGraph()
>>> edges = [
...     "ab",
...     "be",
...     "bf",
...     "bc",
...     "cg",
...     "cd",
...     "dc",
...     "dh",
...     "ea",
...     "ef",
...     "fg",
...     "gf",
...     "hd",
...     "hf",
... ]
>>> G.add_edges_from(tuple(x) for x in edges)
>>> components = list(nx.strongly_connected_components(G))
>>> sorted(sorted(component) for component in components)
[['a', 'b', 'e'], ['c', 'd', 'h'], ['f', 'g']]
>>>
>>> C = nx.condensation(G, components)
>>> component_of = C.graph["mapping"]
>>> same_component = lambda u, v: component_of[u] == component_of[v]
>>> Q = nx.quotient_graph(G, same_component)
>>> nx.is_isomorphic(C, Q)
True

Node identification can be represented as the quotient of a graph under the
equivalence relation that places the two nodes in one block and each other
node in its own singleton block.

>>> K24 = nx.complete_bipartite_graph(2, 4)
>>> K34 = nx.complete_bipartite_graph(3, 4)
>>> C = nx.contracted_nodes(K34, 1, 2)
>>> nodes = {1, 2}
>>> is_contracted = lambda u, v: u in nodes and v in nodes
>>> Q = nx.quotient_graph(K34, is_contracted)
>>> nx.is_isomorphic(Q, C)
True
>>> nx.is_isomorphic(Q, K24)
True

The blockmodeling technique described in [1]_ can be implemented as a
quotient graph.

>>> G = nx.path_graph(6)
>>> partition = [{0, 1}, {2, 3}, {4, 5}]
>>> M = nx.quotient_graph(G, partition, relabel=True)
>>> list(M.edges())
[(0, 1), (1, 2)]

Here is the sample example but using partition as a dict of block sets.

>>> G = nx.path_graph(6)
>>> partition = {0: {0, 1}, 2: {2, 3}, 4: {4, 5}}
>>> M = nx.quotient_graph(G, partition, relabel=True)
>>> list(M.edges())
[(0, 1), (1, 2)]

Partitions can be represented in various ways:

0. a list/tuple/set of block lists/tuples/sets
1. a dict with block labels as keys and blocks lists/tuples/sets as values
2. a dict with block lists/tuples/sets as keys and block labels as values
3. a function from nodes in the original iterable to block labels
4. an equivalence relation function on the target iterable

As `quotient_graph` is designed to accept partitions represented as (0), (1) or
(4) only, the `equivalence_classes` function can be used to get the partitions
in the right form, in order to call `quotient_graph`.

.. _Strongly connected component: https://en.wikipedia.org/wiki/Strongly_connected_component

References
----------
.. [1] Patrick Doreian, Vladimir Batagelj, and Anuska Ferligoj.
       *Generalized Blockmodeling*.
       Cambridge University Press, 2004.

z?Input `partition` is not an equivalence relation for nodes of Gz4each node must be in exactly one part of `partition`)callabler   nx	communityis_partitionr   _quotient_graph
isinstancedictlistvaluessetunionlensubgraph)	G	partitionedge_relation	node_data	edge_datar   relabelcreate_usingpartition_nodess	            r   r   r   c   s   X 	'5	||((66&&Q  	
 		
 )T""))+,	
 ekk9-O
?s1v%JJ'<<$$Q22 VWW		 	    c                   ^ ^^^^ Uc  T R                  5       nO[        R                  " SU5      nTc  U 4S jmU V	s/ s H  n	[        U	5      PM     nn	UR	                  U4S jU 5       5        Tc  U 4S jmTc  U U4S jmUR                  5       (       a  [        US5      O[        US5      n
UR                  5       (       a  [        U U4S jU
 5       5      nOUU4S jU
 5       nUR                  U5        U(       a5  [        U5       VV	s0 s H  u  pX_M	     nnn	[        R                  " X5      nU$ s  sn	f s  sn	nf )	z<Construct the quotient graph assuming input has been checkedr   c                 t   > TR                  U 5      nU[        U5      UR                  5       [        U5      S.$ )N)graphnnodesnedgesr   )r)   r(   number_of_edgesr   )bSr*   s     r   r-   "_quotient_graph.<locals>.node_datag  s7    

1Aa&++-"1:	 r2   c              3   6   >#    U  H  oT" U5      4v   M     g 7fN ).0r9   r-   s     r   	<genexpr>"_quotient_graph.<locals>.<genexpr>r  s     :	11&	s   c                 @   > [        U4S j[        X5       5       5      $ )Nc              3   8   >#    U  H  u  pUTU   ;   v   M     g 7fr=   r>   )r?   uvr*   s      r   r@   9_quotient_graph.<locals>.edge_relation.<locals>.<genexpr>}  s     ;]TQqAaDy]s   )anyr   )r9   cr*   s     r   r,   &_quotient_graph.<locals>.edge_relation|  s    ;WQ];;;r2   c                 r   >^ ^ U U4S jTR                  T T-  SS9 5       nS[        U4S jU 5       5      0$ )Nc              3   f   >#    U  H&  u  pnUT;   a  UT;   d  UT;   d  M  UT;   d  M"  Uv   M(     g 7fr=   r>   )r?   rD   rE   dr9   rH   s       r   r@   5_quotient_graph.<locals>.edge_data.<locals>.<genexpr>  s=      8GA!FqAv16 671f 8s   11	1Tdatar   c              3   F   >#    U  H  oR                  TS 5      v   M     g7f)   N)get)r?   rL   r   s     r   r@   rM     s     !EHq%%"2"2Hs   !)edgessum)r9   rH   edgedatar*   r   s   `` r   r.   "_quotient_graph.<locals>.edge_data  s;     wwq1u4w8H
 c!EH!EEFFr2      c              3   ~   >^^#    U  H0  u  mmT" TT5      (       d  M  UUU4S  j[        TT5       5       v   M2     g7f)c           	   3   d   >#    U  H%  u  pUTU   ;   d  M  TTTR                  X0 S 94v   M'     g7f))defaultN)get_edge_data)r?   rD   rE   r*   r9   rH   s      r   r@   ,_quotient_graph.<locals>.<genexpr>.<genexpr>  s;      )DA!9 :AqqR89)s   00N)r   )r?   r9   rH   r*   r,   s    @@r   r@   rA     sB      
 $1Q" #AqM 
 $s   ==c              3   Z   >#    U  H   u  pT" X5      (       d  M  XT" X5      4v   M"     g 7fr=   r>   )r?   r9   rH   r.   r,   s      r   r@   rA     s)      
2=qAT#Q9Q?#+s   ++)	__class__r   empty_graphr   add_nodes_fromis_directedr   r   is_multigraphchainiadd_edges_from	enumeraterelabel_nodes)r*   r+   r,   r-   r.   r   r/   r0   Hr9   block_pairsrS   ilabelss   ` ````        r   r!   r!   [  s+    KKMNN1l+ 	 (11y!1yI1:	:: 	<
 	G )*,q!$\!Q=OK 	 
 $
 

2=
 U  $-Y#78#741!$#78Q'Hq 2l 9s   D8D=znot copy   )preserve_all_attrsmutates_inputr   contraction)store_contraction_asc                L   U(       a  U R                  5       OU nUR                  5       (       a)  [        U R                  USS9U R	                  USS95      nOU R                  USS9nU(       d  [        U5      nUR                  U   nUR                  U5        USL=n	(       a  Un
U H  u  pnX:w  a  UOUnX:w  a  UOUnX1X1:X  a	  U(       d  M)  UR                  X5      (       a  U R                  5       (       a  UR                  " X40 UD6  Mi  U	(       d  Mr  W
UR
                  X4   ;   a  XR
                  X4   U
   X4'   M  X4U0UR
                  X4   U
'   M     U	(       a<  W
UR                  U   ;   a  XR                  U   U
   U'   U$ X(0UR                  U   U
'   U$ )a  Returns the graph that results from contracting `u` and `v`.

Node contraction identifies the two nodes as a single node incident to any
edge that was incident to the original two nodes.

Parameters
----------
G : NetworkX graph
    The graph whose nodes will be contracted.

u, v : nodes
    Must be nodes in `G`.

self_loops : Boolean
    If this is True, any edges joining `u` and `v` in `G` become
    self-loops on the new node in the returned graph.

copy : Boolean
    If this is True (default True), make a copy of
    `G` and return that instead of directly changing `G`.

store_contraction_as : str or None, default="contraction"
    Name of the node/edge attribute where information about the contraction
    should be stored. By default information about the contracted node and
    any contracted edges is stored in a ``"contraction"`` attribute on the
    resulting node and edge. If `None`, information about the contracted
    nodes/edges and their data are not stored.

Returns
-------
Networkx graph
    If Copy is True,
    A new graph object of the same type as `G` (leaving `G` unmodified)
    with `u` and `v` identified in a single node. The right node `v`
    will be merged into the node `u`, so only `u` will appear in the
    returned graph.
    If copy is False,
    Modifies `G` with `u` and `v` identified in a single node.
    The right node `v` will be merged into the node `u`, so
    only `u` will appear in the returned graph.

Notes
-----
For multigraphs, the edge keys for the realigned edges may
not be the same as the edge keys for the old edges. This is
natural because edge keys are unique only within each pair of nodes.

For non-multigraphs where `u` and `v` are adjacent to a third node
`w`, the edge (`v`, `w`) will be contracted into the edge (`u`,
`w`) with its attributes stored into a "contraction" attribute.

This function is also available as `identified_nodes`.

Examples
--------
Contracting two nonadjacent nodes of the cycle graph on four nodes `C_4`
yields the path graph (ignoring parallel edges):

>>> G = nx.cycle_graph(4)
>>> M = nx.contracted_nodes(G, 1, 3)
>>> P3 = nx.path_graph(3)
>>> nx.is_isomorphic(M, P3)
True

>>> G = nx.MultiGraph(P3)
>>> M = nx.contracted_nodes(G, 0, 2)
>>> M.edges
MultiEdgeView([(0, 1, 0), (0, 1, 1)])

>>> G = nx.Graph([(1, 2), (2, 2)])
>>> H = nx.contracted_nodes(G, 1, 2, self_loops=False)
>>> list(H.nodes())
[1]
>>> list(H.edges())
[(1, 1)]

In a ``MultiDiGraph`` with a self loop, the in and out edges will
be treated separately as edges, so while contracting a node which
has a self loop the contraction will add multiple edges:

>>> G = nx.MultiDiGraph([(1, 2), (2, 2)])
>>> H = nx.contracted_nodes(G, 1, 2)
>>> list(H.edges())  # edge 1->2, 2->2, 2<-2 from the original Graph G
[(1, 1), (1, 1), (1, 1)]
>>> H = nx.contracted_nodes(G, 1, 2, self_loops=False)
>>> list(H.edges())  # edge 2->2, 2<-2 from the original Graph G
[(1, 1), (1, 1)]

See Also
--------
contracted_edge
quotient_graph

TrN   N)copyra   r   in_edges	out_edgesrS   r$   nodesremove_nodehas_edgerb   add_edge)r*   rD   rE   
self_loopsrq   ro   rg   edges_to_remapv_data_store_contractionrn   prev_wprev_xrL   wr   s                   r   r   r     s   J aA 	}}qzz!$z7QT9RS. n-WWQZFMM! 3$>??*+kFqkFq&
zz!1??#4#4JJq!q! aggqfo-AB,f-=>170@!/D,! ,& !''!*$)/GGAJ{#A& H ()kAGGAJ{#Hr2      c          	      v    USS u  pVU R                  XV5      (       d  [        SU S35      e[        U UUUUUS9$ )a  Returns the graph that results from contracting the specified edge.

Edge contraction identifies the two endpoints of the edge as a single node
incident to any edge that was incident to the original two nodes. A graph
that results from edge contraction is called a *minor* of the original
graph.

Parameters
----------
G : NetworkX graph
   The graph whose edge will be contracted.

edge : tuple
   Must be a pair of nodes in `G`.

self_loops : Boolean
   If this is True, any edges (including `edge`) joining the
   endpoints of `edge` in `G` become self-loops on the new node in the
   returned graph.

copy : Boolean (default True)
    If this is True, a the contraction will be performed on a copy of `G`,
    otherwise the contraction will happen in place.

store_contraction_as : str or None, default="contraction"
    Name of the node/edge attribute where information about the contraction
    should be stored. By default information about the contracted node and
    any contracted edges is stored in a ``"contraction"`` attribute on the
    resulting node and edge. If `None`, information about the contracted
    nodes/edges and their data are not stored.

Returns
-------
Networkx graph
   A new graph object of the same type as `G` (leaving `G` unmodified)
   with endpoints of `edge` identified in a single node. The right node
   of `edge` will be merged into the left one, so only the left one will
   appear in the returned graph.

Raises
------
ValueError
   If `edge` is not an edge in `G`.

Examples
--------
Attempting to contract two nonadjacent nodes yields an error:

>>> G = nx.cycle_graph(4)
>>> nx.contracted_edge(G, (1, 3))
Traceback (most recent call last):
  ...
ValueError: Edge (1, 3) does not exist in graph G; cannot contract it

Contracting two adjacent nodes in the cycle graph on *n* nodes yields the
cycle graph on *n - 1* nodes:

>>> C5 = nx.cycle_graph(5)
>>> C4 = nx.cycle_graph(4)
>>> M = nx.contracted_edge(C5, (0, 1), self_loops=False)
>>> nx.is_isomorphic(M, C4)
True

See also
--------
contracted_nodes
quotient_graph

NrW   zEdge z. does not exist in graph G; cannot contract it)rx   rq   ro   )rv   
ValueErrorr   )r*   edgerx   rq   ro   rD   rE   s          r   r
   r
   E  sU    V 8DA::a5&TUVV			1 r2   )NNNr   FN)TT)__doc__	itertoolsr   r   r   r   networkxr   r   networkx.exceptionr   networkx.utilsr	   __all__from_iterablerc   r   _dispatchabler   r!   r   r   r
   r>   r2   r   <module>r      s    9 @ @   0 , 
		K2\ XT: t ;tnNb J?$ $(PANPPf $  J?$ $(RANRRr2   