
    \Mh7                        d Z ddlmZ ddlmZmZ ddlZddlm	Z	m
Z
 g dZdZdZd	  ee          D             Zd
 Z e	d          ej        dd                        Zej        d             Z e	d           ej        d          d                         Z e	d          ej        d                         Z e	d          ej        d                         ZdS )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300c                 6    i | ]\  }}|t           |d z
           S )r   )TRIAD_NAMES).0icodes      Z/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/networkx/algorithms/triads.py
<dictcomp>r3   r   s'    OOO41k$(+OOO    c                 n     ||df||df||df||df||df||dff}t           fd|D                       S )zReturns 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   8   K   | ]\  }}}||         v |V  d S N )r/   uvxGs       r2   	<genexpr>z_tricode.<locals>.<genexpr>~   s1      44WQ1!qt))q))))44r4   )sum)r=   r;   r:   wcomboss   `    r2   _tricoderB   u   s^     !Qi!QQ1I1ay1a*q!RjQF4444444444r4   
undirectedc           	          t                               |                    |/t          |          t                    k    rt          d          t                     t                    z
  }d t	                    D             }|r8 j        z
  }|                    fdt	          |          D                         fd D             } fd D             |rP fd|D             t          fd|D                       }|d	z  }t          fd
|D                       }|d	z  }	t          	                    t          d          }
D ]}||         }|         }|rdx}x}x}}|D ]Y}||         ||         k    r||         }||z  ||hz
  }|D ]m}||         ||         k     s,||         ||         cxk     r||         k     r:n 6|||         vr-t           |||          }|
t          |         xx         dz  cc<   n||v r$|
dxx         t          |          z
  d	z
  z  cc<   n#|
dxx         t          |          z
  d	z
  z  cc<   |rt|vrp|         }|t          ||z
  z            z  }|t          ||z
  z
            z  }|         }|t          ||z
  z            z  }|t          ||z
  z
            z  }[|r2|
dxx         |||d	z  z   z
  z  cc<   |
dxx         |	||d	z  z   z
  z  cc<   dz
  z  d	z
  z  dz  }||dz
  z  |d	z
  z  dz  }||z
  }|t          |
                                          z
  |
d<   |
S )am  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

    Nz3nodelist includes duplicate nodes or nodes not in Gc                     i | ]\  }}||	S r9   r9   )r/   r0   ns      r2   r3   z"triadic_census.<locals>.<dictcomp>   s    ---$!QA---r4   c              3   ,   K   | ]\  }}||z   fV  d S r8   r9   )r/   r0   rF   Ns      r2   r>   z!triadic_census.<locals>.<genexpr>   s/      ??1!QU??????r4   c                     i | ]B}|j         |                                         j        |                                         z  CS r9   predkeyssuccr/   rF   r=   s     r2   r3   z"triadic_census.<locals>.<dictcomp>   s@    >>>qAqvay~~!&).."2"22>>>r4   c                     i | ]B}|j         |                                         j        |                                         z  CS r9   rJ   rN   s     r2   r3   z"triadic_census.<locals>.<dictcomp>   s@    BBB116!9>>##afQinn&6&66BBBr4   c                     i | ]B}|j         |                                         j        |                                         z  CS r9   rJ   rN   s     r2   r3   z"triadic_census.<locals>.<dictcomp>   s@    PPPqAqvay~~''!&)..*:*::PPPr4   c              3   :   K   | ]}|         D ]
}|vd V  dS r   Nr9   )r/   rF   nbrnodesetsgl_nbrss      r2   r>   z!triadic_census.<locals>.<genexpr>   >      VVHQKVVS3gCUCU!CUCUCUCUCUVVr4   r   c              3   :   K   | ]}|         D ]
}|vd V  dS rR   r9   )r/   rF   rS   dbl_nbrsrT   s      r2   r>   z!triadic_census.<locals>.<genexpr>   rV   r4   r   r   r   r   r   r   )setnbunch_iterlen
ValueError	enumeratenodesupdater?   dictfromkeysr.   rB   TRICODE_TO_NAMEvalues) r=   nodelistNnotmnot_nodesetnbrssglsgl_edges_outsidedbldbl_edges_outsidecensusr;   vnbrs	dbl_vnbrssgl_unbrs_bdysgl_unbrs_outdbl_unbrs_bdydbl_unbrs_outr:   unbrs	neighborsr@   r1   	sgl_unbrs	dbl_unbrstotal_trianglestriangles_without_nodesettotal_censusrH   rX   rT   rU   s    `                           @@@@r2   r   r      sQ   P !--))**GHW = =NOOOAAs7||D 	.-)G,,---A @g'	????	+(>(>??????
 ?>>>A>>>DBBBBBBBH %PPPPKPPPVVVVV[VVVVV1HVVVVV[VVVVV1H ]];**F %V %VQQK	 	NLMMMMMMMM 	B 	BAtqt||GE1a&0I 7 7Q4!A$;;1Q4!A$#5#5#5#51#5#5#5#5#5!47:J:J#Aq!Q//D?40111Q6111 I~~uS^^!3a!77uS^^!3a!77
  B(($QK	Y%@!A!AAY%6%@!A!AA$QK	Y%@!A!AAY%6%@!A!AA 	V5MMM.--STBT2TUUMMM5MMM.--STBT2TUUMMM AE{a!e,2O!%!2dQh!?A E"%>>L 3v}}#7#77F5MMr4   c                      t           t          j                  r[                                 dk    rCt          j                   r/t           fd                                 D                       sdS dS )at  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   H   K   | ]}||f                                 v V  d S r8   )edgesrN   s     r2   r>   zis_triad.<locals>.<genexpr>2  s4      >>q1v*>>>>>>r4   TF)
isinstancenxGraphorderis_directedanyr^   )r=   s   `r2   r	   r	     so    . !RX 7799>>bnQ//>>>>>AGGII>>>>> t5r4   T)returns_graphc              #      K   t          |                                 d          }|D ]+}|                     |                                          V  ,dS )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   r^   subgraphcopy)r=   tripletstriplets      r2   r
   r
   7  s_      4 AGGIIq))H ) )jj!!&&(((((() )r4   c                     t          |           }t          t                    }|D ],}t          |          }||                             |           -|S )a  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)r=   all_tritri_by_typetriadnames        r2   r   r   V  s[    n mmGd##K ( (%  D  ''''r4   c                 :   t          |           st          j        d          t          |                                           }|dk    rdS |dk    rdS |dk    r|                                 \  }}t          |          t          |          k    rdS |d         |d         k    rdS |d         |d         k    rd	S |d         |d         k    s|d         |d         k    rd
S dS |dk    rt          |                                 d          D ]\  }}}t          |          t          |          k    r|d         |v r dS  dS t          |                              t          |                    t          |          k    r_|d         |d         |d         h|d         |d         |d         hcxk    r%t          |                                           k    rn n dS  dS dS |dk    r t          |                                 d          D ]\  }}}}t          |          t          |          k    rt          |          t          |          k    r dS |d         h|d         hcxk    r3t          |          	                    t          |                    k    rn n dS |d         h|d         hcxk    r3t          |          	                    t          |                    k    rn n dS |d         |d         k    r dS dS |dk    rdS |dk    rdS dS )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	   r   NetworkXAlgorithmErrorr[   r}   rY   r   symmetric_differencer^   intersection)r=   	num_edgese1e2e3e4s         r2   r   r     s4   f A;; N'(LMMMAGGIIIA~~u	au	aBr77c"gg5Ube^^6Ube^^6Ube^^r!u1~~6  .~	a&qwwyy!44 
	 
	JBB2ww#b''!!a5B;;!66vvR--c"gg66#b''AAqE2a5"Q%(RUBqE2a5,ASSSSS^^SSSSS!66vv	 B
	 
	 
a*17799a88 
	" 
	"NBB2ww#b''!!r77c"gg%% 55qE7r!ugFFFFR)=)=c"gg)F)FFFFFF!66qE7r!ugFFFFR)=)=c"gg)F)FFFFFF!66a5BqE>>!66
	" 
	" 
au	au 
r4   r8   )__doc__collectionsr   	itertoolsr   r   networkxr   networkx.utilsr   r   __all__TRICODESr.   r]   rb   rB   _dispatchabler   r	   r
   r   r   r9   r4   r2   <module>r      s  
 1 0 # # # # # # 0 0 0 0 0 0 0 0     ? ? ? ? ? ? ? ?  AJ* PO99X;N;NOOO	5 	5 	5 \""S S S  #"Sl   : \""%%%) ) &% #"): \"": :  #":z \""] ]  #"] ] ]r4   