ó
    …~i™7  ã                   ó¾  • S r SSKJr  SSKJrJr  SSKrSSKJ	r	J
r
  / SQrSrSr\" \5       V Vs0 s H  u  pU \US	-
     _M     snn rS
 r\	" S5      \R"                  SS j5       5       r\R"                  S 5       r\	" S5      \R"                  " SS9S 5       5       r\	" S5      \R"                  S 5       5       r\	" S5      \R"                  S 5       5       rgs  snn f )z*Functions for analyzing triads of a graph.é    )Údefaultdict)ÚcombinationsÚpermutationsN)Únot_implemented_forÚpy_random_state)Útriadic_censusÚis_triadÚ
all_triadsÚtriads_by_typeÚ
triad_type)@é   é   r   é   r   é   é   é   r   r   é   é   r   r   r   é   r   r   r   r   r   é	   r   é   r   é
   r   é   r   r   é   é   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   é   )Ú003Ú012Ú102Ú021DÚ021UÚ021CÚ111DÚ111UÚ030TÚ030CÚ201Ú120DÚ120UÚ120CÚ210Ú300r   c                 óV   ^ • XS4X!S4XS4X1S4X#S4X2S44n[        U 4S jU 5       5      $ )záReturns the integer code of the given triad.

This is some fancy magic that comes from Batagelj and Mrvar's paper. It
treats each edge joining a pair of `v`, `u`, and `w` as a bit in
the binary representation of an integer.

r   r   r   r   r   é    c              3   óB   >#   • U  H  u  po2TU   ;   d  M  Uv •  M     g 7f©N© )Ú.0ÚuÚvÚxÚGs       €ÚW/home/mande/repo/quber/.venv/lib/python3.13/site-packages/networkx/algorithms/triads.pyÚ	<genexpr>Ú_tricode.<locals>.<genexpr>~   s   øé € Ð4¢‘W�Q˜1¨q°©t©)�q‰q¢ùs   ƒ–	)Úsum)r6   r4   r3   ÚwÚcomboss   `    r7   Ú_tricoder=   u   s@   ø€ ð �Qˆi˜! ˜ Q¨1 I°°a¨y¸1À¸*ÀqÈRÀjÐQ€FÜÔ4¡Ó4Ó4Ð4ó    Ú
undirectedc           	      ó¦  ^^ ^!^"• [        U R                  U5      5      m!Ub#  [        U5      [        T!5      :w  a  [        S5      e[        U 5      mT[        T!5      -
  n[	        T!5       VVs0 s H  u  p4XC_M	     nnnU(       a3  U R
                  T!-
  nUR                  U4S j[	        U5       5       5        U  Vs0 s H>  oDU R                  U   R                  5       U R                  U   R                  5       -  _M@     nnU  Vs0 s H>  oDU R                  U   R                  5       U R                  U   R                  5       -  _M@     snm U(       a‚  W Vs0 s H>  oDU R                  U   R                  5       U R                  U   R                  5       -  _M@     snm"[        U!U"4S jU 5       5      nUS-  n	[        U U!4S jU 5       5      n
U
S-  n[         Vs0 s H  oÌS_M     nnT! GH~  nX~   nT U   nU(       a  S=n=n=nnU GH%  nUU   X^   ::  a  M  UU   nUU-  UU1-
  nU HU  nUU   UU   :  d%  X^   UU   s=:  a  UU   :  d  M&  O  M*  XçU   ;  d  M4  [        XUU5      nU[        U   ==   S-  ss'   MW     UU;   a  US==   T[        U5      -
  S-
  -  ss'   OUS	==   T[        U5      -
  S-
  -  ss'   U(       d  MÃ  UT!;  d  MË  T"U   nW[        UUT!-
  -  5      -  nW[        UU-
  T!-
  5      -  nT U   nW[        UUT!-
  -  5      -  nW[        UU-
  T!-
  5      -  nGM(     U(       d  GMR  US	==   W	WWS-  -   -
  -  ss'   US==   WWWS-  -   -
  -  ss'   GM�     TTS-
  -  TS-
  -  S
-  nX"S-
  -  US-
  -  S
-  nUU-
  nU[        UR                  5       5      -
  US'   U$ s  snnf s  snf s  snf s  snf s  snf )a…  Determines the triadic census of a directed graph.

The triadic census is a count of how many of the 16 possible types of
triads are present in a directed graph. If a list of nodes is passed, then
only those triads are taken into account which have elements of nodelist in them.

Parameters
----------
G : digraph
   A NetworkX DiGraph
nodelist : list
    List of nodes for which you want to calculate triadic census

Returns
-------
census : dict
   Dictionary with triad type as keys and number of occurrences as values.

Examples
--------
>>> G = nx.DiGraph([(1, 2), (2, 3), (3, 1), (3, 4), (4, 1), (4, 2)])
>>> triadic_census = nx.triadic_census(G)
>>> for key, value in triadic_census.items():
...     print(f"{key}: {value}")
003: 0
012: 0
102: 0
021D: 0
021U: 0
021C: 0
111D: 0
111U: 0
030T: 2
030C: 2
201: 0
120D: 0
120U: 0
120C: 0
210: 0
300: 0

Notes
-----
This algorithm has complexity $O(m)$ where $m$ is the number of edges in
the graph.

For undirected graphs, the triadic census can be computed by first converting
the graph into a directed graph using the ``G.to_directed()`` method.
After this conversion, only the triad types 003, 102, 201 and 300 will be
present in the undirected scenario.

Raises
------
ValueError
    If `nodelist` contains duplicate nodes or nodes not in `G`.
    If you want to ignore this you can preprocess with `set(nodelist) & G.nodes`

See also
--------
triad_graph

References
----------
.. [1] Vladimir Batagelj and Andrej Mrvar, A subquadratic triad census
    algorithm for large sparse networks with small maximum degree,
    University of Ljubljana,
    http://vlado.fmf.uni-lj.si/pub/networks/doc/triads/triads.pdf

z3nodelist includes duplicate nodes or nodes not in Gc              3   ó4   >#   • U  H  u  pX!T-   4v •  M     g 7fr0   r1   )r2   ÚiÚnÚNs      €r7   r8   Ú!triadic_census.<locals>.<genexpr>Õ   s   øé € Ð?Ò(>¡ �!˜‘U•Ò(>ùs   ƒc              3   óP   >#   • U  H  nTU     H  o"T;  d  M
  S v •  M     M     g7f©r   Nr1   )r2   rC   ÚnbrÚnodesetÚsgl_nbrss      €€r7   r8   rE   à   ó$   øé € ÐVš[˜°H¸QµK¨SÈgÑCU—!‘!±K‘!š[ùó   ƒ&™&r   c              3   óP   >#   • U  H  nTU     H  o"T;  d  M
  S v •  M     M     g7frG   r1   )r2   rC   rH   Údbl_nbrsrI   s      €€r7   r8   rE   â   rK   rL   r   r   r   r   r   r   )ÚsetÚnbunch_iterÚlenÚ
ValueErrorÚ	enumerateÚnodesÚupdateÚpredÚkeysÚsuccr:   ÚTRIAD_NAMESr=   ÚTRICODE_TO_NAMEÚvalues)#r6   ÚnodelistÚNnotrB   rC   ÚmÚnot_nodesetÚnbrsÚsglÚsgl_edges_outsideÚdblÚdbl_edges_outsideÚnameÚcensusr4   ÚvnbrsÚ	dbl_vnbrsÚsgl_unbrs_bdyÚsgl_unbrs_outÚdbl_unbrs_bdyÚdbl_unbrs_outr3   ÚunbrsÚ	neighborsr;   ÚcodeÚ	sgl_unbrsÚ	dbl_unbrsÚtotal_trianglesÚtriangles_without_nodesetÚtotal_censusrD   rN   rI   rJ   s#                                  @@@@r7   r   r   �   sá  û€ ôP �!—-‘- Ó)Ó*€GØÑ¤ H£´°W³Ó =ÜÐNÓOÐOäˆA‹€AØŒs�7‹|Ñ€Dô $ GÔ,Ô-Ò,‘$�!ˆŠÑ,€AÑ-Þà—g‘g Ñ'ˆØ	�‰Ô?¬	°+Ô(>Ó?Ô?ñ
 =>Ó>ºA°qˆq�v‰v�a‰y�~‰~Ó !§&¡&¨¡)§.¡.Ó"2Ñ2Ò2¹A€DÐ>Ù@AÓBÂ¸1�1—6‘6˜!‘9—>‘>Ó# a§f¡f¨Q¡i§n¡nÓ&6Ñ6Ò6ÁÑB€HæÙDOÓPÂK¸q�q—v‘v˜a‘y—~‘~Ó'¨!¯&©&°©)¯.©.Ó*:Ñ:Ò:ÁKÑPˆäÕV™[ÓVÓVˆØ 1™HÐÜÕV™[ÓVÓVˆØ 1™HÐõ #.Ó.¢+˜$�AŠg¡+€FÐ.äˆØ‘ˆØ˜Q‘Kˆ	ÞàLMÐMˆMÐM˜MÐM¨M¸MÜˆAØ�‰t�q‘t‹|ÙØ˜‘GˆEØ ™¨1¨a¨&Ñ0ˆIã�Ø�Q‘4˜!˜A™$“; 1¡4¨!¨A©$Õ#5°°1±×#5Ñ#5¸!ÈÁ7Õ:JÜ# A¨!¨QÓ/�DØœ?¨4Ñ0Ó1°QÑ6Õ1ñ ð �I‹~Ø�u“ ¤S¨£^Ñ!3°aÑ!7Ñ7”à�u“ ¤S¨£^Ñ!3°aÑ!7Ñ7“÷
 ˆt˜ Õ(Ø$ Q™K�	Ø¤ Y°¸±Ñ%@Ó!AÑA�Ø¤ Y°Ñ%6¸Ñ%@Ó!AÑA�Ø$ Q™K�	Ø¤ Y°¸±Ñ%@Ó!AÑA�Ø¤ Y°Ñ%6¸Ñ%@Ó!AÑA“ñ5 ÷8 ‰4à�5‹MÐ.°-À-ÐSTÑBTÑ2TÑUÑU‹MØ�5‹MÐ.°-À-ÐSTÑBTÑ2TÑUÑUŽMñK ðR ˜A ™E‘{ a¨!¡eÑ,°Ñ2€OØ!%°©Ñ!2°d¸Q±hÑ!?ÀAÑ EÐØ"Ð%>Ñ>€LØ ¤3 v§}¡}£Ó#7Ñ7€Fˆ5�Mà€MùóK 	.ùò ?ùÚBùò Qùò /s!   Á,N9Â;AN?ÄAOÅAO	ÇOc                 óô   ^ • [        T [        R                  5      (       aX  T R                  5       S:X  aD  [        R                  " T 5      (       a)  [        U 4S jT R                  5        5       5      (       d  gg)a0  Returns True if the graph G is a triad, else False.

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

Returns
-------
istriad : boolean
   Whether G is a valid triad

Examples
--------
>>> G = nx.DiGraph([(1, 2), (2, 3), (3, 1)])
>>> nx.is_triad(G)
True
>>> G.add_edge(0, 1)
>>> nx.is_triad(G)
False
r   c              3   óL   >#   • U  H  oU4TR                  5       ;   v •  M     g 7fr0   )Úedges)r2   rC   r6   s     €r7   r8   Úis_triad.<locals>.<genexpr>2  s   øé € Ð>²I¨q˜1�v §¡£Ö*²Iùs   ƒ!$TF)Ú
isinstanceÚnxÚGraphÚorderÚis_directedÚanyrT   )r6   s   `r7   r	   r	     sN   ø€ ô. �!”R—X‘X×ÑØ�7‰7‹9˜‹>œbŸnšn¨Q×/Ñ/ÜÔ>°A·G±G´IÓ>×>Ñ>ØØr>   T)Úreturns_graphc              #   ó”   #   • [        U R                  5       S5      nU H$  nU R                  U5      R                  5       v •  M&     g7f)a»  A generator of all possible triads in G.

Parameters
----------
G : digraph
   A NetworkX DiGraph

Returns
-------
all_triads : generator of DiGraphs
   Generator of triads (order-3 DiGraphs)

Examples
--------
>>> G = nx.DiGraph([(1, 2), (2, 3), (3, 1), (3, 4), (4, 1), (4, 2)])
>>> for triad in nx.all_triads(G):
...     print(triad.edges)
[(1, 2), (2, 3), (3, 1)]
[(1, 2), (4, 1), (4, 2)]
[(3, 1), (3, 4), (4, 1)]
[(2, 3), (3, 4), (4, 2)]

r   N)r   rT   ÚsubgraphÚcopy)r6   ÚtripletsÚtriplets      r7   r
   r
   7  s;   é € ô4 ˜AŸG™G›I qÓ)€HÛˆØ�j‰j˜Ó!×&Ñ&Ó(Ô(ò ùs   ‚AAc                 óˆ   • [        U 5      n[        [        5      nU H!  n[        U5      nX$   R	                  U5        M#     U$ )aR  Returns a list of all triads for each triad type in a directed graph.
There are exactly 16 different types of triads possible. Suppose 1, 2, 3 are three
nodes, they will be classified as a particular triad type if their connections
are as follows:

- 003: 1, 2, 3
- 012: 1 -> 2, 3
- 102: 1 <-> 2, 3
- 021D: 1 <- 2 -> 3
- 021U: 1 -> 2 <- 3
- 021C: 1 -> 2 -> 3
- 111D: 1 <-> 2 <- 3
- 111U: 1 <-> 2 -> 3
- 030T: 1 -> 2 -> 3, 1 -> 3
- 030C: 1 <- 2 <- 3, 1 -> 3
- 201: 1 <-> 2 <-> 3
- 120D: 1 <- 2 -> 3, 1 <-> 3
- 120U: 1 -> 2 <- 3, 1 <-> 3
- 120C: 1 -> 2 -> 3, 1 <-> 3
- 210: 1 -> 2 <-> 3, 1 <-> 3
- 300: 1 <-> 2 <-> 3, 1 <-> 3

Refer to the :doc:`example gallery </auto_examples/graph/plot_triad_types>`
for visual examples of the triad types.

Parameters
----------
G : digraph
   A NetworkX DiGraph

Returns
-------
tri_by_type : dict
   Dictionary with triad types as keys and lists of triads as values.

Examples
--------
>>> G = nx.DiGraph([(1, 2), (1, 3), (2, 3), (3, 1), (5, 6), (5, 4), (6, 7)])
>>> dict = nx.triads_by_type(G)
>>> dict["120C"][0].edges()
OutEdgeView([(1, 2), (1, 3), (2, 3), (3, 1)])
>>> dict["012"][0].edges()
OutEdgeView([(1, 2)])

References
----------
.. [1] Snijders, T. (2012). "Transitivity and triads." University of
    Oxford.
    https://web.archive.org/web/20170830032057/http://www.stats.ox.ac.uk/~snijders/Trans_Triads_ha.pdf
)r
   r   Úlistr   Úappend)r6   Úall_triÚtri_by_typeÚtriadre   s        r7   r   r   V  sE   € ôn ˜‹m€GÜœdÓ#€KÛˆÜ˜%Ó ˆØÑ× Ñ  Ö'ñ ð Ðr>   c                 óÎ  • [        U 5      (       d  [        R                  " S5      e[        U R	                  5       5      nUS:X  a  gUS:X  a  gUS:X  a_  U R	                  5       u  p#[        U5      [        U5      :X  a  gUS   US   :X  a  gUS   US   :X  a  g	US   US   :X  d  US   US   :X  a  g
gUS:X  a¾  [        U R	                  5       S5       HŸ  u  p#n[        U5      [        U5      :X  a  US   U;   a    g  g[        U5      R                  [        U5      5      [        U5      :X  d  M]  US   US   US   1US   US   US   1s=:X  a  [        U R                  5       5      :X  a     g    g  g   gUS:X  aÛ  [        U R	                  5       S5       H¼  u  p#pE[        U5      [        U5      :X  d  M   [        U5      [        U5      :X  a    gUS   1US   1s=:X  a)  [        U5      R                  [        U5      5      :X  a     g  US   1US   1s=:X  a)  [        U5      R                  [        U5      5      :X  a     g  US   US   :X  d  M¼    g   gUS:X  a  gUS:X  a  gg)a\  Returns the sociological triad type for a triad.

Parameters
----------
G : digraph
   A NetworkX DiGraph with 3 nodes

Returns
-------
triad_type : str
   A string identifying the triad type

Examples
--------
>>> G = nx.DiGraph([(1, 2), (2, 3), (3, 1)])
>>> nx.triad_type(G)
'030C'
>>> G.add_edge(1, 3)
>>> nx.triad_type(G)
'120C'

Notes
-----
There can be 6 unique edges in a triad (order-3 DiGraph) (so 2^^6=64 unique
triads given 3 nodes). These 64 triads each display exactly 1 of 16
topologies of triads (topologies can be permuted). These topologies are
identified by the following notation:

{m}{a}{n}{type} (for example: 111D, 210, 102)

Here:

{m}     = number of mutual ties (takes 0, 1, 2, 3); a mutual tie is (0,1)
          AND (1,0)
{a}     = number of asymmetric ties (takes 0, 1, 2, 3); an asymmetric tie
          is (0,1) BUT NOT (1,0) or vice versa
{n}     = number of null ties (takes 0, 1, 2, 3); a null tie is NEITHER
          (0,1) NOR (1,0)
{type}  = a letter (takes U, D, C, T) corresponding to up, down, cyclical
          and transitive. This is only used for topologies that can have
          more than one form (eg: 021D and 021U).

References
----------
.. [1] Snijders, T. (2012). "Transitivity and triads." University of
    Oxford.
    https://web.archive.org/web/20170830032057/http://www.stats.ox.ac.uk/~snijders/Trans_Triads_ha.pdf
z"G is not a triad (order-3 DiGraph)r   r   r   r   r   r   r    r!   r"   r   r$   r#   r&   r%   r   r'   r(   r)   r*   r   r+   r   r,   N)
r	   rz   ÚNetworkXAlgorithmErrorrQ   rw   rO   r   Úsymmetric_differencerT   Úintersection)r6   Ú	num_edgesÚe1Úe2Úe3Úe4s         r7   r   r   •  s>  € ôf �A�;‰;Ü×'Ò'Ð(LÓMÐMÜ�A—G‘G“I“€IØ�Aƒ~ØØ	�a‹ØØ	�a‹Ø—‘“‰ˆÜˆr‹7”c˜"“gÓØØ�‰U�b˜‘e‹^ØØ�‰U�b˜‘e‹^ØØ�‰U�b˜‘e‹^˜r !™u¨¨1©›~Øð  .à	�a‹Ü& q§w¡w£y°!Ö4‰JˆB�BÜ�2‹wœ#˜b›'Ó!Ø�a‘5˜B“;Ù!áÜ�R“×-Ñ-¬c°"«gÓ6¼#¸b»'ÕAØ�q‘E˜2˜a™5 " Q¡%Ð(¨R°©U°B°q±E¸2¸a¹5Ð,AÕSÄSÈÏÉËÃ^ÔSÙ!ð Tó ò 5ð 
�a‹Ü*¨1¯7©7«9°aÖ8‰NˆB�BÜ�2‹wœ#˜b›'Õ!ä�r“7œc "›gÓ%Ù Ø�q‘E�7˜r !™u˜gÕF¬¨R«×)=Ñ)=¼cÀ"»gÓ)FÔFÙ!ð Gà�q‘E�7˜r !™u˜gÕF¬¨R«×)=Ñ)=¼cÀ"»gÓ)FÔFÙ!ð Gà�a‘5˜B˜q™E•>Ù!ò 9ð 
�a‹ØØ	�a‹Øð 
r>   r0   )Ú__doc__Úcollectionsr   Ú	itertoolsr   r   Únetworkxrz   Únetworkx.utilsr   r   Ú__all__ÚTRICODESrY   rS   rZ   r=   Ú_dispatchabler   r	   r
   r   r   )rB   ro   s   00r7   Ú<module>rœ      s(  ðñ
 1å #ß 0ã ß ?ò€ðA€ðJ€ñ* <EÀXÔ;NÔOÒ;N±°�1�k $¨¡(Ñ+Ò+Ñ;NÒO€ò	5ñ �\Ó"Ø×ÑóSó ó #ðSðl ×Ññó ðñ: �\Ó"Ø×Ò Ñ%ñ)ó &ó #ð)ñ: �\Ó"Ø×Ññ:ó ó #ð:ñz �\Ó"Ø×Ññ]ó ó #ñ]ùóK	 Ps   °C