K i7dZddlmZddlmZmZddlZddlm Z m Z gdZ dZ dZ ee Dcic]\}}|e |d z c}}Zd Ze d ej"dd Zej"d Ze d ej"ddZe d ej"dZe d ej"dZycc}}w)z*Functions for analyzing triads of a graph.) defaultdict) combinations permutationsN)not_implemented_forpy_random_state)triadic_censusis_triad all_triadstriads_by_type triad_type)@rrrrrrr rrrrr r r rrr rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr)003012102021D021U021C111D111U030T030C201120D120U120C210300r c`||df||df||df||df||df||dff}tfd|DS)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 rrrr c3:K|]\}}}||vs|ywN).0uvxGs `/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/networkx/algorithms/triads.py z_tricode..~s!4WQ1!qt)q4s)sum)r6r4r3wcomboss` r7_tricoder<usL!Qi!QQ1I1ay1a*q!Rj QF 44 44 undirectedc 8 !t|j| |"t|t k7r tdt|t z }t Dcic]\}}|| }}}|r2|j z }|j fdt |D|Dcic]>}||j|j|j|jz@}}|Dcic]>}||j|j|j|jz@c}|r~Dcic]>}||j|j|j|jz @c}!t !fd|D}|dz} t fd|D} | dz} tjtd} D]^} || }| }|rdx}x}x}}|D]}|||| kr||}||z|| hz }|D]O}||||ks || ||cxkr ||ks#n&| ||vs.t|| ||}| t|xxdz cc<Q||vr| dxxt|z dz z cc<n| d xxt|z dz z cc<|s| vs!|}t|| z zz }t||z z z }|}t|| z zz }t||z z z }|s3| d xx dzzz z cc<| dxx dzzz z cc<adz zdz zd z}||dz z|dz zd z}||z }|t| j!z | d <| Scc}}wcc}wcc}wcc}w) amDetermines 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 Gc32K|]\}}||zfywr0r1)r2inNs r7r8z!triadic_census..s?1!QU?sc3@K|]}|D] }|vsd ywr Nr1)r2rBnbrnodesetsgl_nbrss r7r8z!triadic_census..(VHQKVS3gCU!V!V rc3@K|]}|D] }|vsd ywrEr1)r2rBrFdbl_nbrsrGs r7r8z!triadic_census..rIrJrr rrrr)set nbunch_iterlen ValueError enumeratenodesupdatepredkeyssuccr9dictfromkeys TRIAD_NAMESr<TRICODE_TO_NAMEvalues)"r6nodelistNnotrArBm not_nodesetnbrssglsgl_edges_outsidedbldbl_edges_outsidecensusr4vnbrs dbl_vnbrs sgl_unbrs_bdy sgl_unbrs_out dbl_unbrs_bdy dbl_unbrs_outr3unbrs neighborsr:code sgl_unbrs dbl_unbrstotal_trianglestriangles_without_nodeset total_censusrCrLrGrHs" @@@@r7rrsP!--)*GH W =NOO AA s7| D$G,-$!QA-A- gg'  ? +(>?? => >qAqvvay~~!&&).."22 2 >D >@AB1166!9>>#affQinn&666BH DOPqAqvvay~~'!&&)..*:::PV[VV1HV[VV1H]]; *F %VQQK LM MM MM MMM BAtqt|GE1a&0I 7Q4!A$;1Q4!A$#51#5!47:J#Aq!Q/D?401Q61 7 I~u S^!3a!77 u S^!3a!77 ($QK Y%@!AA Y%6%@!AA $QK Y%@!AA Y%6%@!AA 5 B8  5M.--STBT2TU UM 5M.--STBT2TU UMK%VRAE{a!e,2O!%!2dQh!?A E"%>>L 3v}}#77F5M MK . ?BQs* N2AN ;ANANcttjrKjdk(r8tjr#t fdj Dsyy)atReturns 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 rc3FK|]}||fjvywr0)edges)r2rBr6s r7r8zis_triad..2s >q1v*>s!TF) isinstancenxGraphorder is_directedanyrR)r6s`r7r r sE.!RXX 779>bnnQ/>AGGI>> r=T) returns_graphc#Kt|jd}|D]#}|j|j%yw)aA 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)] rN)rrRsubgraphcopy)r6tripletstriplets r7r r 7sA4AGGIq)H)jj!&&(()sAAct|}tt}|D]!}t|}||j |#|S)aReturns 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 ` 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 rlistr append)r6all_tri tri_by_typetriadnames r7r r VsLnmGd#K(% D  '( r=ct|stjdt|j }|dk(ry|dk(ry|dk(r[|j \}}t |t |k(ry|d|dk(ry|d|dk(ry |d|dk(s |d|dk(ry y|d k(rt |j d D]\}}}t |t |k(r |d|vry y t |jt |t |k(sY|d|d|dh|d|d|dhcxk(rt |jk(ryyyy|dk(rt |j dD]\}}}}t |t |k(s t |t |k(ry|dh|dhcxk(r't |jt |k(ry|dh|dhcxk(r't |jt |k(ry|d|dk(syy|dk(ry|dk(ryy)aReturns 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)rrr rrrr r!r"rr$r#r&r%rr'r(r)r*rr+rr,N) r rxNetworkXAlgorithmErrorrOrvrMrsymmetric_differencerR intersection)r6 num_edgese1e2e3e4s r7r r sNf A;''(LMMAGGIIA~ a aB r7c"g  Ube^ Ube^ Ube^r!u1~ . a&qwwy!4 JBB2w#b'!a5B;!R--c"g6#b'AqE2a5"Q%(RUBqE2a5,ASS^S!T  a*1779a8 "NBB2w#b'!r7c"g% qE7r!ugFR)=)=c"g)FF!GqE7r!ugFR)=)=c"g)FF!Ga5BqE>! " a a r=r0)__doc__ collectionsr itertoolsrrnetworkxrxnetworkx.utilsrr__all__TRICODESrYrQrZr< _dispatchablerr r r r )rArns00r7rs& 1#0? A J *