K i*dZddlZddlmZgdZdZedd0dZd1d Z d2d Z d3d Z ed d4ddddZ e Z ed d5dZ ed d6dZdZ d7dZdZdZd8dZd9dZd9dZd1dZ d:d Z d;d!Zed" dd,Zd>d-Zd d ddd.d/Zy)?a ****** Layout ****** Node positioning algorithms for graph drawing. For `random_layout()` the possible resulting shape is a square of side [0, scale] (default: [0, 1]) Changing `center` shifts the layout by that amount. For the other layout routines, the extent is [center - scale, center + scale] (default: [-1, 1]). Warning: Most layout routines have only been tested in 2-dimensions. N)np_random_state)bipartite_layoutcircular_layoutforceatlas2_layoutkamada_kawai_layout random_layoutrescale_layoutrescale_layout_dict shell_layout spring_layoutspectral_layout planar_layoutfruchterman_reingold_layout spiral_layoutmultipartite_layout bfs_layout arf_layoutcddl}t|tjs'tj}|j ||}||j |}n|j |}t||k7r d}t|||fS)Nrz;length of center coordinates must match dimension of layout) numpy isinstancenxGraphadd_nodes_fromzerosasarraylen ValueError)Gcenterdimnp empty_graphmsgs ]/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/networkx/drawing/layout.py_process_paramsr%*sv a "hhj ""1%  ~#F# 6{cKo f9cddl}t|||\}}|jt|||z}|j |j }t t||}|tj||||S)aPosition nodes uniformly at random in the unit square. For every node, a position is generated by choosing each of dim coordinates uniformly at random on the interval [0.0, 1.0). NumPy (http://scipy.org) is required for this function. Parameters ---------- G : NetworkX graph or list of nodes A position will be assigned to every node in G. center : array-like or None Coordinate pair around which to center the layout. dim : int Dimension of layout. seed : int, RandomState instance or None optional (default=None) Set the random state for deterministic node layouts. If int, `seed` is the seed used by the random number generator, if numpy.random.RandomState instance, `seed` is the random number generator, if None, the random number generator is the RandomState instance used by numpy.random. store_pos_as : str, default None If non-None, the position of each node will be stored on the graph as an attribute with this string as its name, which can be accessed with ``G.nodes[...][store_pos_as]``. The function still returns the dictionary. Returns ------- pos : dict A dictionary of positions keyed by node Examples -------- >>> from pprint import pprint >>> G = nx.lollipop_graph(4, 3) >>> pos = nx.random_layout(G) >>> # suppress the returned dict and store on the graph directly >>> _ = nx.random_layout(G, seed=42, store_pos_as="pos") >>> pprint(nx.get_node_attributes(G, "pos")) {0: array([0.37454012, 0.9507143 ], dtype=float32), 1: array([0.7319939, 0.5986585], dtype=float32), 2: array([0.15601864, 0.15599452], dtype=float32), 3: array([0.05808361, 0.8661761 ], dtype=float32), 4: array([0.601115 , 0.7080726], dtype=float32), 5: array([0.02058449, 0.96990985], dtype=float32), 6: array([0.83244264, 0.21233912], dtype=float32)} rN) rr%randrastypefloat32dictziprset_node_attributes)rrr seed store_pos_asr!poss r$rr?srl63/IAv ))CFC 6 )C **RZZ C s1c{ C q#|4 Jr&c ddl}|dkr tdt|||\}}td|dz }t |dk(ri}nt |dk(r"t j j||i}n|jddt |dzdddz|jz}|j|j}|j|j||j||jt ||fg}t!|||z}t#t%||}|t j&||||S)aPosition nodes on a circle. Parameters ---------- G : NetworkX graph or list of nodes A position will be assigned to every node in G. scale : number (default: 1) Scale factor for positions. center : array-like or None Coordinate pair around which to center the layout. dim : int Dimension of layout. If dim>2, the remaining dimensions are set to zero in the returned positions. If dim<2, a ValueError is raised. store_pos_as : str, default None If non-None, the position of each node will be stored on the graph as an attribute with this string as its name, which can be accessed with ``G.nodes[...][store_pos_as]``. The function still returns the dictionary. Returns ------- pos : dict A dictionary of positions keyed by node Raises ------ ValueError If dim < 2 Examples -------- >>> from pprint import pprint >>> G = nx.path_graph(4) >>> pos = nx.circular_layout(G) >>> # suppress the returned dict and store on the graph directly >>> _ = nx.circular_layout(G, store_pos_as="pos") >>> pprint(nx.get_node_attributes(G, "pos")) {0: array([9.99999986e-01, 2.18556937e-08]), 1: array([-3.57647606e-08, 1.00000000e+00]), 2: array([-9.9999997e-01, -6.5567081e-08]), 3: array([ 1.98715071e-08, -9.99999956e-01])} Notes ----- This algorithm currently only works in two dimensions and does not try to minimize edge crossings. rNr(zcannot handle dimensions < 2r3scale)rrr%maxrrutilsarbitrary_elementlinspacepir+r, column_stackcossinrr r-r.r/) rr7rr r1r!paddimsr2thetas r$rrs.p Qw78863/IAv!cAgG 1v{ Q1xx))!,f5 Aq#a&1*-cr2Q6> RZZ(oo VVE]BFF5M288SVW4E+F G S.73q#; q#|4 Jr&cddl}|dk7r tdt|||\}}t|dk(riSt|dk(r!tj j ||iS| t|g}|t|z }t|ddk(rd} n|} ||jt|z }|} i} |D]} |jdd|jzt| d|j| z} | |j|j| |j| gz|z}| jt| || |z } | |z } |t j || || S) a$Position nodes in concentric circles. Parameters ---------- G : NetworkX graph or list of nodes A position will be assigned to every node in G. nlist : list of lists List of node lists for each shell. rotate : angle in radians (default=pi/len(nlist)) Angle by which to rotate the starting position of each shell relative to the starting position of the previous shell. To recreate behavior before v2.5 use rotate=0. scale : number (default: 1) Scale factor for positions. center : array-like or None Coordinate pair around which to center the layout. dim : int Dimension of layout, currently only dim=2 is supported. Other dimension values result in a ValueError. store_pos_as : str, default None If non-None, the position of each node will be stored on the graph as an attribute with this string as its name, which can be accessed with ``G.nodes[...][store_pos_as]``. The function still returns the dictionary. Returns ------- pos : dict A dictionary of positions keyed by node Raises ------ ValueError If dim != 2 Examples -------- >>> from pprint import pprint >>> G = nx.path_graph(4) >>> shells = [[0], [1, 2, 3]] >>> pos = nx.shell_layout(G, shells) >>> # suppress the returned dict and store on the graph directly >>> _ = nx.shell_layout(G, shells, store_pos_as="pos") >>> pprint(nx.get_node_attributes(G, "pos")) {0: array([0., 0.]), 1: array([-5.00000000e-01, -4.37113883e-08]), 2: array([ 0.24999996, -0.43301272]), 3: array([0.24999981, 0.43301281])} Notes ----- This algorithm currently only works in two dimensions and does not try to minimize edge crossings. rNr(can only handle 2 dimensionsr3F)endpointdtype)rrr%rrr9r:listr<r;r,r=r>r?updater.r/)rnlistrotater7rr r1r! radius_bumpradius first_thetanposnodesrAr2s r$r r su~ ax78863/IAv 1v{  1v{**1-v66 }a #e*$K 58} ~U#K D  KK1ruu9c%j5 K S  ru rvve}'EFFO CsO$+v   q$ 5 Kr&verticalcLddl}|dvr d}t|t||d\}}t|dk(riSd} || z} | dz | dz f} |.tj j |\} } t|}n0t|} t|| z } t| t| z}|jdt| }|j| t| }|jd| t| }|jd| t| }|j||g| z }|j||g| z }|j||g}t|||z}|d k(r |ddddd f}tt||}|t j ||||S) a` Position nodes in two straight lines. Parameters ---------- G : NetworkX graph or list of nodes A position will be assigned to every node in G. nodes : collection of nodes Nodes in one node set of the graph. This set will be placed on left or top. If `None` (the default), a node set is chosen arbitrarily if the graph if bipartite. align : string (default='vertical') The alignment of nodes. Vertical or horizontal. scale : number (default: 1) Scale factor for positions. center : array-like or None Coordinate pair around which to center the layout. aspect_ratio : number (default=4/3): The ratio of the width to the height of the layout. store_pos_as : str, default None If non-None, the position of each node will be stored on the graph as an attribute with this string as its name, which can be accessed with ``G.nodes[...][store_pos_as]``. The function still returns the dictionary. Returns ------- pos : dict A dictionary of positions keyed by node. Raises ------ NetworkXError If ``nodes=None`` and `G` is not bipartite. Examples -------- >>> G = nx.complete_bipartite_graph(3, 3) >>> pos = nx.bipartite_layout(G) The ordering of the layout (i.e. which nodes appear on the left/top) can be specified with the `nodes` parameter: >>> top, bottom = nx.bipartite.sets(G) >>> pos = nx.bipartite_layout(G, nodes=bottom) # "bottom" set appears on the left `store_pos_as` can be used to store the node positions for the computed layout directly on the nodes: >>> _ = nx.bipartite_layout(G, nodes=bottom, store_pos_as="pos") >>> from pprint import pprint >>> pprint(nx.get_node_attributes(G, "pos")) {0: array([ 1. , -0.75]), 1: array([1., 0.]), 2: array([1. , 0.75]), 3: array([-1. , -0.75]), 4: array([-1., 0.]), 5: array([-1. , 0.75])} The ``bipartite_layout`` function can be used with non-bipartite graphs by explicitly specifying how the layout should be partitioned with `nodes`: >>> G = nx.complete_graph(5) # Non-bipartite >>> pos = nx.bipartite_layout(G, nodes={0, 1, 2}) Notes ----- This algorithm currently only works in two dimensions and does not try to minimize edge crossings. rNrP horizontal,align must be either vertical or horizontal.r(rr r3r6rSr5)rrr%rr bipartitesetsrGsetrepeatr;r= concatenater r-r.r/)rrOalignr7r aspect_ratior1r!r#heightwidthoffsettopbottomleft_xsright_xsleft_ysright_ystop_pos bottom_posr2s r$rrBsl ..<o&a8IAv 1v{ F 6 !Eai! $F }ll''* VQ%jQ#S DL(ii3s8$GyyF ,Hkk!VSX.G{{1fc&k2Hoow01F:G(H!56?J ..':. /C E *V 3C !TrT'l s5# C q#|4 Jr& weightauto?)methodgravityc  "ddl}| dvr td| dk(rt|dkrdnd} t||| \}}|h| td |D]}||vstd t |Dcic]\}}|| }}}|j |Dcgc] }||vs||c}}|xt d |jD}|dk(rd }| jt|| |z|z}t |D]!\}}||vs |j ||||<#nd}d }t|dk(riSt|d k(rJtjj|j|i}| tj||| |St|dk\s| dk(rTtj||d }|%|#|j\}}||j!|z }t#||||||| | | | }nPtj$||}|%|#|j\}}||j!|z }t'||||||| | }||t)|||z}t+t-||}| tj||| |Scc}}wcc}w)aPosition nodes using Fruchterman-Reingold force-directed algorithm. The algorithm simulates a force-directed representation of the network treating edges as springs holding nodes close, while treating nodes as repelling objects, sometimes called an anti-gravity force. Simulation continues until the positions are close to an equilibrium. There are some hard-coded values: minimal distance between nodes (0.01) and "temperature" of 0.1 to ensure nodes don't fly away. During the simulation, `k` helps determine the distance between nodes, though `scale` and `center` determine the size and place after rescaling occurs at the end of the simulation. Fixing some nodes doesn't allow them to move in the simulation. It also turns off the rescaling feature at the simulation's end. In addition, setting `scale` to `None` turns off rescaling. Parameters ---------- G : NetworkX graph or list of nodes A position will be assigned to every node in G. k : float (default=None) Optimal distance between nodes. If None the distance is set to 1/sqrt(n) where n is the number of nodes. Increase this value to move nodes farther apart. pos : dict or None optional (default=None) Initial positions for nodes as a dictionary with node as keys and values as a coordinate list or tuple. If None, then use random initial positions. fixed : list or None optional (default=None) Nodes to keep fixed at initial position. Nodes not in ``G.nodes`` are ignored. ValueError raised if `fixed` specified and `pos` not. iterations : int optional (default=50) Maximum number of iterations taken threshold: float optional (default = 1e-4) Threshold for relative error in node position changes. The iteration stops if the error is below this threshold. weight : string or None optional (default='weight') The edge attribute that holds the numerical value used for the edge weight. Larger means a stronger attractive force. If None, then all edge weights are 1. scale : number or None (default: 1) Scale factor for positions. Not used unless `fixed is None`. If scale is None, no rescaling is performed. center : array-like or None Coordinate pair around which to center the layout. Not used unless `fixed is None`. dim : int Dimension of layout. seed : int, RandomState instance or None optional (default=None) Used only for the initial positions in the algorithm. Set the random state for deterministic node layouts. If int, `seed` is the seed used by the random number generator, if numpy.random.RandomState instance, `seed` is the random number generator, if None, the random number generator is the RandomState instance used by numpy.random. store_pos_as : str, default None If non-None, the position of each node will be stored on the graph as an attribute with this string as its name, which can be accessed with ``G.nodes[...][store_pos_as]``. The function still returns the dictionary. method : str optional (default='auto') The method to compute the layout. If 'force', the force-directed Fruchterman-Reingold algorithm [1]_ is used. If 'energy', the energy-based optimization algorithm [2]_ is used with absolute values of edge weights and gravitational forces acting on each connected component. If 'auto', we use 'force' if ``len(G) < 500`` and 'energy' otherwise. gravity: float optional (default=1.0) Used only for the method='energy'. The positive coefficient of gravitational forces per connected component. Returns ------- pos : dict A dictionary of positions keyed by node Examples -------- >>> from pprint import pprint >>> G = nx.path_graph(4) >>> pos = nx.spring_layout(G) >>> # suppress the returned dict and store on the graph directly >>> _ = nx.spring_layout(G, seed=123, store_pos_as="pos") >>> pprint(nx.get_node_attributes(G, "pos")) {0: array([-0.61520994, -1. ]), 1: array([-0.21840965, -0.35501755]), 2: array([0.21841264, 0.35502078]), 3: array([0.61520696, 0.99999677])} # The same using longer but equivalent function name >>> pos = nx.fruchterman_reingold_layout(G) References ---------- .. [1] Fruchterman, Thomas MJ, and Edward M. Reingold. "Graph drawing by force-directed placement." Software: Practice and experience 21, no. 11 (1991): 1129-1164. http://dx.doi.org/10.1002/spe.4380211102 .. [2] Hamaguchi, Hiroki, Naoki Marumo, and Akiko Takeda. "Initial Placement for Fruchterman--Reingold Force Model With Coordinate Newton Direction." arXiv preprint arXiv:2412.20317 (2024). https://arxiv.org/abs/2412.20317 rN)rjforceenergyz1the method must be either auto, force, or energy.rjrorpz'nodes are fixed without positions givenc3.K|] }|D]}|ywN).0pos_tupcoords r$ z spring_layout..^sNgNUuNuNsr3frirFrir6)rrrr% enumeraterr8valuesr*rr9r:rOr/to_scipy_sparse_arrayshapesqrt_sparse_fruchterman_reingoldto_numpy_array_fruchterman_reingoldr r-r.)rkr2fixed iterations thresholdrir7rr r0r1rlrmr!nodeinfixeddom_sizepos_arrnAnnodes_s r$r r sN 00LMM FSLh63/IAv  ;FG G LD3 !JKK L*316ga$'66 UMTdfnF4LMN NCJJLNN q=H))CFC(83f<aL 0DAqCxZZA/  0 1v{  1v{xx))!'')4f=  #  " "1c< 8  1v}(*  $ $QvS A 9*IFA2776?*A* q'5*idFG    a / 9*IFA2776?*A# q'5*id  }*S.7 s1c{ C q#|4 Jg7Ms. J J J cddl} |j\} } |.|j |j | ||j}n|j|j}||jd| z }tt|jdt|jdz t|jdt|jdz dz} | |dzz }|j|jd|jd|jdf|j}t|D]}|dd|jddf||jddddfz }|j j#|d}|j%|d d| |j'd |||z|d zz ||z|z z }|j j#|d}|j)|d kd|}|j'd || |z }|d||<||z }| |z} |j j#|| z |ks|S|S#t$r} d} tj| | d} ~ wwxYw)Nr9fruchterman_reingold() takes an adjacency matrix as inputrFrkr3皙?r5axis{Gz?)outz ijk,ij->ikr(zij,i->ijrD)rrAttributeErrorr NetworkXErrorrr*rFr+rr8Tminrrangenewaxislinalgnormclipeinsumwhere)rrr2rrrr r0r!rrerrr#tdtdelta iterationdistance displacementlength delta_poss r$rrsU -GG   {jj63/qwwj?jj! y GGC&L ! CaMCaM )3suuQx=3suuQx=+HICOA j1n B HHciilCIIaL#))A,?qwwH OE:& Arzz1$%BJJ1,<(==99>>%b>1 $(3yy %!a%(A+"5H q8H"H  26&4-f5IIj,F C  "Ie  y R IINN9 % .) ;  J/. Jc -Is#,-sI I.I))I.c ddl} ddl} |j\} } |.| j |j| ||j}n|j|j}|g}|| jd| z }|dk(rt|| ||||||| S |j}tt|j dt#|j dz t|j dt#|j dz dz}||dzz }| j%|| f}t'|D]E}|dz}t'|jdD]}||vr|||z j }| j|dzj)d }| j+|d kd |}|j-|j/}|dd|fxx|||z|dzz ||z|z z zj)d z cc<| j|dzj)d }| j+|d kd|}||z|z j }||z }||z}| j0j3|| z |ksE|S|S#t$r}d}t j ||d}~wwxYw#t$r-| jj|j}Yikr'?r3)reshaperrrrrmaximumrrlogaddatrrravel)xr2gradcostlrr distance2rAdcentersdelta0r batchsizebincountr rrmrlabels n_componentsrr!s r$_cost_FRz._energy_fruchterman_reingold.._cost_FRBsii &xx &q&), 4AA M6*A!RZZ*+c"**a2B.CCEuu}15I 9e4Iwwy)H1Q("BBIIlBFQTI=M4MuUUD1I BFF2 >*a!e4 4D AqD266"&&"233 3D 4"((L#./  '63'8ArzzM22S8 &.(( # x"))..a.2PTU2U'U VVVU TZZ\!!r&)maxitergtolL-BFGS-BT)rljacoptions)rrrtocsrrr csr_arrayabsrcsgraphconnected_componentsroptimizeminimizerrr)rrrr2rrrr rmrrrrrrrr!s``` ` `` @@@@@r$rr)s !|8::# GGI q A QSSA A99,,AA!eATL&{{6"HI"">%i8G ;;  #))+jdG  a W # II   "#sC22$DDc ddl}t|||\}}t|} | dk(riS| tt j ||}d|j | | fz} t|D]2\} } | |vr || } t|D]\}}|| vr | || | |<4|U|dk\rt||}nB|dk(rt||}n/tt||jddt|}|j|Dcgc]}|| c}}t| ||}t|| |z}tt||}|t j||||Scc}w) arPosition nodes using Kamada-Kawai path-length cost-function. Parameters ---------- G : NetworkX graph or list of nodes A position will be assigned to every node in G. dist : dict (default=None) A two-level dictionary of optimal distances between nodes, indexed by source and destination node. If None, the distance is computed using shortest_path_length(). pos : dict or None optional (default=None) Initial positions for nodes as a dictionary with node as keys and values as a coordinate list or tuple. If None, then use circular_layout() for dim >= 2 and a linear layout for dim == 1. weight : string or None optional (default='weight') The edge attribute that holds the numerical value used for the edge weight. If None, then all edge weights are 1. scale : number (default: 1) Scale factor for positions. center : array-like or None Coordinate pair around which to center the layout. dim : int Dimension of layout. store_pos_as : str, default None If non-None, the position of each node will be stored on the graph as an attribute with this string as its name, which can be accessed with ``G.nodes[...][store_pos_as]``. The function still returns the dictionary. Returns ------- pos : dict A dictionary of positions keyed by node Examples -------- >>> from pprint import pprint >>> G = nx.path_graph(4) >>> pos = nx.kamada_kawai_layout(G) >>> # suppress the returned dict and store on the graph directly >>> _ = nx.kamada_kawai_layout(G, store_pos_as="pos") >>> pprint(nx.get_node_attributes(G, "pos")) {0: array([0.99996577, 0.99366857]), 1: array([0.32913544, 0.33543827]), 2: array([-0.33544334, -0.32910684]), 3: array([-0.99365787, -1. ])} rNr{g.Ar')r r(r3r6)rr%rr-rshortest_path_lengthonesr|rrr.r;array_kamada_kawai_solver r/)rdistr2rir7rr r1r!nNodesdist_mtxrownrrdistcolncrrs r$rrgs}~63/IAv VF {  |B++Af=>RWWff-..HQ<+R T> R | +GC!&rHSM#  + + { !8s+C AX!!-Cs1bkk!QA789Chh*1A*+G h 5C E *V 3C s1c{ C q#|4 J+s E%c ddl}ddl}d}|d||j|jddzzz ||f}|jj t |jd|d}|jjd|fS)NrMbP?r3rT)rlargsrr5) rreyerrr_kamada_kawai_costfnrrr)rrr r!rmeanwtcostargs optresults r$rrs  FABFF8>>!+<$=$DDEvsSH $$    %I ;;  Cy ))r&c ||jd}|j||f}|dd|jddf||jddddfz }|jj |d}|j d|d||j |dzzz } ||zdz } d| |j|<d|j| d zz} |j d || | |j d || | z } |j|d} | d|z|j| d zzz } | || zz } | | jfS) Nrr5rz ijk,ij->ijkr3rrkrr(z ij,ij,ijk->ikz ij,ij,ijk->jk) rrrrrrr diag_indicesrr)pos_vecr!invdist meanweightr rrrnodesep directionr_rrsumposs r$rrsH ]]1 Foovsm,G Arzz1$ % Aq0@(A AEiinnUn,G -Wrvvf~PT?T5T0UVI w  $F&'F2??6 "#  " "D 99_gvy ABII&)E D VVG!V $FC* rvvfai0 00DJ D $**, r&cBddl}t|||\}}t|dkrt|dk(r|jg}nUt|dk(r|j|g}n4|j|j ||j|dzg}t t ||S t|dkrttj||d}|jr||j|z}t||}t#|| |z}t t ||}|tj$||||S#ttf$rEtj|| }|jr||jz }t!||}YwxYw) aPosition nodes using the eigenvectors of the graph Laplacian. Using the unnormalized Laplacian, the layout shows possible clusters of nodes which are an approximation of the ratio cut. If dim is the number of dimensions then the positions are the entries of the dim eigenvectors corresponding to the ascending eigenvalues starting from the second one. Parameters ---------- G : NetworkX graph or list of nodes A position will be assigned to every node in G. weight : string or None optional (default='weight') The edge attribute that holds the numerical value used for the edge weight. If None, then all edge weights are 1. scale : number (default: 1) Scale factor for positions. center : array-like or None Coordinate pair around which to center the layout. dim : int Dimension of layout. store_pos_as : str, default None If non-None, the position of each node will be stored on the graph as an attribute with this string as its name, which can be accessed with ``G.nodes[...][store_pos_as]``. The function still returns the dictionary. Returns ------- pos : dict A dictionary of positions keyed by node Examples -------- >>> from pprint import pprint >>> G = nx.path_graph(4) >>> pos = nx.spectral_layout(G) >>> # suppress the returned dict and store on the graph directly >>> _ = nx.spectral_layout(G, store_pos_as="pos") >>> pprint(nx.get_node_attributes(G, "pos")) {0: array([-1. , 0.76536686]), 1: array([-0.41421356, -0.76536686]), 2: array([ 0.41421356, -0.76536686]), 3: array([1. , 0.76536686])} Notes ----- Directed graphs will be considered as undirected graphs when positioning the nodes. For larger graphs (>500 nodes) this will use the SciPy sparse eigenvalue solver (ARPACK). rNr(r3@rqdrzr{r6)rr%rrrr-r.rrr~ is_directed transpose_sparse_spectral ImportErrorrr _spectralr r/) rrir7rr r1r!r2rs r$r r smv63/IAv 1v{ q6Q;((2,C Vq[((F8$C((BHHSM288F+;c+ABCCC3K   q6C<   $ $QvS A ==?BLLO#Aq#& E *V 3C s1c{ C q#|4 J  $   a / ==? HA3  s.AE AFFcddl} |j\}}|j ||j |j|dz}||z }|jj|\} } |j| d|dz} |j| dd| fS#t$r}d}tj||d}~wwxYw)Nrz-spectral() takes an adjacency matrix as inputrr3r) rrrrridentityrFrreigargsortreal) rr r!rrrr#DL eigenvalues eigenvectorsindexs r$rr]s-GG  F!'' *RVVAAV->>A AA " a 0K JJ{ #Aa 0E 77<5) ** -=s#,-sB B>!B99B>c*ddl}ddl} |j\}}|j j|j j|jdd||}||z } |dz} td| zdzt|j|} |j jj| | d| \} } |j| d| }|j!| dd|fS#t$r}d}t j ||d}~wwxYw)Nrz4sparse_spectral() takes an adjacency matrix as inputr3rr(SM)whichncv)rrrrrrrrspdiagsrr8intrreigshrr)rr r!rrrrr#rr rrr r r s r$rrrs-GG  BII--aeeemQOPA AA aA a!eaiRWWV_- .C " 0 0 6 6q!4S 6 QK JJ{ #Aa (E 77<5) ** -Ds#,-sC,, D5D  DcFddl}|dk7r tdt|||\}}t|dk(riSt |t j r|}n/t j|\}}|st jdt j|}t|} |j| D cgc]} ||  c} }|j|j}t|||z}tt!| |}|t j"||||Scc} w)aTPosition nodes without edge intersections. Parameters ---------- G : NetworkX graph or list of nodes A position will be assigned to every node in G. If G is of type nx.PlanarEmbedding, the positions are selected accordingly. scale : number (default: 1) Scale factor for positions. center : array-like or None Coordinate pair around which to center the layout. dim : int Dimension of layout. store_pos_as : str, default None If non-None, the position of each node will be stored on the graph as an attribute with this string as its name, which can be accessed with ``G.nodes[...][store_pos_as]``. The function still returns the dictionary. Returns ------- pos : dict A dictionary of positions keyed by node Raises ------ NetworkXException If G is not planar Examples -------- >>> from pprint import pprint >>> G = nx.path_graph(4) >>> pos = nx.planar_layout(G) >>> # suppress the returned dict and store on the graph directly >>> _ = nx.planar_layout(G, store_pos_as="pos") >>> pprint(nx.get_node_attributes(G, "pos")) {0: array([-0.77777778, -0.33333333]), 1: array([ 1. , -0.33333333]), 2: array([0.11111111, 0.55555556]), 3: array([-0.33333333, 0.11111111])} rNr(rCzG is not planar.r6)rrr%rrrPlanarEmbeddingcheck_planarityNetworkXExceptioncombinatorial_embedding_to_posrGvstackr+float64r r-r.r/) rr7rr r1r! embedding is_planarr2 node_listrs r$rrs\ ax78863/IAv 1v{ !R''( !11!4 9&&'9: : + +I 6CYI ))Y/SV/ 0C **RZZ C E *V 3C s9c" #C q#|4 J 0s0 DFc Rddl}|dk7r tdt|||\}}t|dk(riSt|dk(r>> from pprint import pprint >>> G = nx.path_graph(4) >>> pos = nx.spiral_layout(G) >>> nx.draw(G, pos=pos) >>> # suppress the returned dict and store on the graph directly >>> _ = nx.spiral_layout(G, store_pos_as="pos") >>> pprint(nx.get_node_attributes(G, "pos")) {0: array([-0.64153279, -0.68555087]), 1: array([-0.03307913, -0.46344795]), 2: array([0.34927952, 0.14899882]), 3: array([0.32533239, 1. ])} Notes ----- This algorithm currently only works in two dimensions. rNr(rCr3rrr6)rrr%rrr9r:r/rappendr>r?arangefloatrrr r-r.)rr7rr resolution equidistantr1r!r2chordsteprArrrangles r$rrsL ax78863/IAv 1v{  1v{xx))!,f5  #  " "1c< 8 C $,''s1v ?Au A UQY E JJu )266%=1+<= > ? yyQuy-T!ll4"((BFF5M266%=+I"JJK #e 4v =C s1c{ C q#|4 Jr&cPddl}|dvr d}t|t||d\}}t|dk(riS t|t d|j Dk7rt jd tt|j} d} g} t| } t!| j D]\} }t|}|j#| |}|j%d|t& }| d z dz |d z dz f}|j)||g|z }| |} n|j+| |g} | j-|t/| | |z} |d k(r | dddddf} tt1| | } |t j2|| || S#t$rht j||}t|t|k7rt jd |t jj|}YwxYw#t$r|} YwxYw)aPosition nodes in layers of straight lines. Parameters ---------- G : NetworkX graph or list of nodes A position will be assigned to every node in G. subset_key : string or dict (default='subset') If a string, the key of node data in G that holds the node subset. If a dict, keyed by layer number to the nodes in that layer/subset. align : string (default='vertical') The alignment of nodes. Vertical or horizontal. scale : number (default: 1) Scale factor for positions. center : array-like or None Coordinate pair around which to center the layout. store_pos_as : str, default None If non-None, the position of each node will be stored on the graph as an attribute with this string as its name, which can be accessed with ``G.nodes[...][store_pos_as]``. The function still returns the dictionary. Returns ------- pos : dict A dictionary of positions keyed by node. Examples -------- >>> G = nx.complete_multipartite_graph(28, 16, 10) >>> pos = nx.multipartite_layout(G) >>> # suppress the returned dict and store on the graph directly >>> G = nx.complete_multipartite_graph(28, 16, 10) >>> _ = nx.multipartite_layout(G, store_pos_as="pos") or use a dict to provide the layers of the layout >>> G = nx.Graph([(0, 1), (1, 2), (1, 3), (3, 4)]) >>> layers = {"a": [0], "b": [1], "c": [2, 3], "d": [4]} >>> pos = nx.multipartite_layout(G, subset_key=layers) Notes ----- This algorithm currently only works in two dimensions and does not try to minimize edge crossings. Network does not need to be a complete multipartite graph. As long as nodes have subset_key data, they will be placed in the corresponding layers. rNrRrTr(rUc32K|]}t|ywrsrrurOs r$rxz&multipartite_layout..sEUEz4all nodes must be in one subset of `subset_key` dictz'all nodes need a subset_key attribute: rr3r6rSr5)rrr%rrr}rrrget_node_attributesr9groupsr-sorteditems TypeErrorr|rYr r!r=rZextendr r.r/)r subset_keyr[r7rr1r!r#node_to_subsetlayersr2rOr^rlayerr]xsysr_ layer_poss r$rrEs/p ..<o&a8IAv 1v{  5 q6SE1B1B1DEE E""F  FfZ--/01 C E KEfmmo. 5U YYq& ! YYq&Y .19/FQJ!#34OORH-6 ;C..#y!12C U  E *V 3C !TrT'l s5# C q#|4 JK 5//:> ~ #a& (""9*F XX__^4 5 s%AF";"H"A-HH H%$H%r0)r0r1cddl} ddl} |dkr d} t| tj||} || }n0|j D]} | |vs| | j || <t|}|dk(r|S| j||f| j|z }t|D cic]\}} | | c} }|jD]"\}}||k7s fd||fD\}}||||f<$| jt|j}|| j|z}|dz}d}||kDr|dd| j f|| j z }| j"j%|dd | j f}| j'5| j)d |d | j f|z||z |zz }ddd| j+d}|||zz }| j"j%|dj-}||kDrn |dz }||kDrt/t1|j |}|tj2||||Scc} }w#1swYxYw) a Arf layout for networkx The attractive and repulsive forces (arf) layout [1] improves the spring layout in three ways. First, it prevents congestion of highly connected nodes due to strong forcing between nodes. Second, it utilizes the layout space more effectively by preventing large gaps that spring layout tends to create. Lastly, the arf layout represents symmetries in the layout better than the default spring layout. Parameters ---------- G : nx.Graph or nx.DiGraph Networkx graph. pos : dict Initial position of the nodes. If set to None a random layout will be used. scaling : float Scales the radius of the circular layout space. a : float Strength of springs between connected nodes. Should be larger than 1. The greater a, the clearer the separation of unconnected sub clusters. etol : float Gradient sum of spring forces must be larger than `etol` before successful termination. dt : float Time step for force differential equation simulations. max_iter : int Max iterations before termination of the algorithm. seed : int, RandomState instance or None optional (default=None) Set the random state for deterministic node layouts. If int, `seed` is the seed used by the random number generator, if numpy.random.RandomState instance, `seed` is the random number generator, if None, the random number generator is the RandomState instance used by numpy.random. store_pos_as : str, default None If non-None, the position of each node will be stored on the graph as an attribute with this string as its name, which can be accessed with ``G.nodes[...][store_pos_as]``. The function still returns the dictionary. Returns ------- pos : dict A dictionary of positions keyed by node. Examples -------- >>> G = nx.grid_graph((5, 5)) >>> pos = nx.arf_layout(G) >>> # suppress the returned dict and store on the graph directly >>> G = nx.grid_graph((5, 5)) >>> _ = nx.arf_layout(G, store_pos_as="pos") References ---------- .. [1] "Self-Organization Applied to Dynamic Network Layout", M. Geipel, International Journal of Modern Physics C, 2007, Vol 18, No 10, pp. 1537-1549. https://doi.org/10.1142/S0129183107011558 https://arxiv.org/abs/0704.1748 rNr3z'The parameter a should be larger than 1)r0c3(K|] }| ywrsrt)rur node_orders r$rxzarf_layout..s6! 1 6sr5r.ignore)warningsrrrrrOcopyrrrr|edgesrrGr}rrrrcatch_warnings simplefilternansumrr-r.r/)rr2scalingaetolrmax_iterr0r1r=r!r#pos_tmprNKrryidxjdxprhoerrorn_iterdiffrchanger;s @r$rrs}RAv7oqt,G {GGI 1D3#DM..0D  1 AAAv  A"&&)#A)216ga$'6J 1 661v6HCAc3hK 4 %&A BGGAJ C 1HE F $,BJJ!BJJ-/ IINN4bN )#rzz/ : $ $ & @  ! !( +sBJJ'$.q4?F @6* Vb[ vB/335 H  !  $," s1779a !C q#|4 JK7* @ @s- I&/I,,I5r1) edge_attrs mutates_inputdr)rFjitter_tolerance scaling_ratiormdistributed_actionstrong_gravity node_mass node_sizeri dissuade_hubslinlogr0r r1c  ddl}t|dk(riS|Atj||| }|j t |j }nt|t|k(r1|j |Dcgc]}||jc}}n|j t |j }|jd}|jd}|j}|| jt||||z zz}t|D] \}}||vs ||j||<"|jt|}|jt|}d}| i} nd}|i}t|D]A\}}|j||j|dz||<| j|d||<Ct|}|j||f}|j||f}|j||f}tj || }d }d} d}!d}"d}#t#|D]}$|dddf|dz }%|j$j'|%d }&| rQ|j)d|&z |&z }|j+|d|j-d ||}|j-d |%|}n|j-d |%| }|r ||dddfz}|dddf|dz}'|r|&|dddf |dz z }&|&d z}(|j+|'d|j+|(d|'|(z |z})|j-d |%|)}||j/|dz }*|r| |dddfz|*z}nf|j1dd5|*|j$j'|*d dddfz }+ddd|j3+d}+| |dddfz|+z}||z|z},|"||j$j'||,z d zj5z }"|#d|z|j$j'||,zd zj5z }#|||"|#| |!|\} }!|rt|j$j'|,d }-||-z}.d| zd|j7| |.zzz })|j9|)|-zd|j;|-j<z|-z })n:||j$j'|,d z}.| d|j7| |.zzz })|,|)dddfz}/||/z }t?|/j5dksntAtC||}|tjD||||Scc}w#1swYxYw)an Position nodes using the ForceAtlas2 force-directed layout algorithm. This function applies the ForceAtlas2 layout algorithm [1]_ to a NetworkX graph, positioning the nodes in a way that visually represents the structure of the graph. The algorithm uses physical simulation to minimize the energy of the system, resulting in a more readable layout. Parameters ---------- G : nx.Graph A NetworkX graph to be laid out. pos : dict or None, optional Initial positions of the nodes. If None, random initial positions are used. max_iter : int (default: 100) Number of iterations for the layout optimization. jitter_tolerance : float (default: 1.0) Controls the tolerance for adjusting the speed of layout generation. scaling_ratio : float (default: 2.0) Determines the scaling of attraction and repulsion forces. gravity : float (default: 1.0) Determines the amount of attraction on nodes to the center. Prevents islands (i.e. weakly connected or disconnected parts of the graph) from drifting away. distributed_action : bool (default: False) Distributes the attraction force evenly among nodes. strong_gravity : bool (default: False) Applies a strong gravitational pull towards the center. node_mass : dict or None, optional Maps nodes to their masses, influencing the attraction to other nodes. node_size : dict or None, optional Maps nodes to their sizes, preventing crowding by creating a halo effect. weight : string or None, optional (default: None) The edge attribute that holds the numerical value used for the edge weight. If None, then all edge weights are 1. dissuade_hubs : bool (default: False) Prevents the clustering of hub nodes. linlog : bool (default: False) Uses logarithmic attraction instead of linear. seed : int, RandomState instance or None optional (default=None) Used only for the initial positions in the algorithm. Set the random state for deterministic node layouts. If int, `seed` is the seed used by the random number generator, if numpy.random.RandomState instance, `seed` is the random number generator, if None, the random number generator is the RandomState instance used by numpy.random. dim : int (default: 2) Sets the dimensions for the layout. Ignored if `pos` is provided. store_pos_as : str, default None If non-None, the position of each node will be stored on the graph as an attribute with this string as its name, which can be accessed with ``G.nodes[...][store_pos_as]``. The function still returns the dictionary. Examples -------- >>> import networkx as nx >>> G = nx.florentine_families_graph() >>> pos = nx.forceatlas2_layout(G) >>> nx.draw(G, pos=pos) >>> # suppress the returned dict and store on the graph directly >>> pos = nx.forceatlas2_layout(G, store_pos_as="pos") >>> _ = nx.forceatlas2_layout(G, store_pos_as="pos") References ---------- .. [1] Jacomy, M., Venturini, T., Heymann, S., & Bastian, M. (2014). ForceAtlas2, a continuous graph layout algorithm for handy network visualization designed for the Gephi software. PloS one, 9(6), e98679. https://doi.org/10.1371/journal.pone.0098679 rN)r r0rFTr3r{cddl}d|j|z}|j|}d} d} t| ||z|dzz } |t|| z} ||z dkDr|| kDr|dz}t| |} |dk(r |j} n | |z|z|z } || |zkDr || kDr|dz}n |d kr|d z}d}|t| |z ||zz}||fS) aComputes the scaling factor for the force in the ForceAtlas2 layout algorithm. This helper function adjusts the speed and efficiency of the layout generation based on the current state of the system, such as the number of nodes, current swing, and traction forces. Parameters ---------- n : int Number of nodes in the graph. swing : float The current swing, representing the oscillation of the nodes. traction : float The current traction force, representing the attraction between nodes. speed : float The current speed of the layout generation. speed_efficiency : float The efficiency of the current speed, influencing how fast the layout converges. jitter_tolerance : float The tolerance for jitter, affecting how much speed adjustment is allowed. Returns ------- tuple A tuple containing the updated speed and speed efficiency. Notes ----- This function is a part of the ForceAtlas2 layout algorithm and is used to dynamically adjust the layout parameters to achieve an optimal and stable visualization. rNg?rhr(rrgffffff?g?)rrrr8inf)rswingtractionspeedspeed_efficiencyrWr! opt_jitter min_jitter max_jittermin_speed_efficiencyotherjitter target_speedmax_rises r$estimate_factorz+forceatlas2_layout..estimate_factorsD BGGAJ& WWZ(  #J X 51 <=!C E$:: 8 c !"66 C' !12F A:66L!$44x?%GL 6H$ $"66 C' T\  # L50(U2BCC&&&r&r5z ij, ij -> ijz ijk, ij -> ikr(r<)divideinvalid)nanrrg$@r)#rrrrrrGr}r>r8rsizer*r|rgetdegreerrrrr fill_diagonalrmeanerrstate nan_to_numrrminimumrrrr-r.r/)0rr2rFrWrXrmrYrZr[r\rir]r^r0r r1r!rrpos_initmax_posmin_posrKmassrs adjust_sizesr gravities attraction repulsionrrorerfrcrdrrQrtmpd2factor pos_centeredunit_vecrHdfswingingfactored_updates0 r$rr>sv 1v{  {qc5((4 -. SSV ((;CINN,;<88D./,,A,&,,A,&llDIIc!fc2g6GHH"1 0ICs{"4y~~/  0 88CF D 88CF DL   q\+ TMM$(:;S MM$*S + AA!S"I1c(#J!S"I !F+A>'@ E EH 8_Gq$w'$-/99>>$R>0 &&X..9J   Z +>:qAJ?D*EJ))OT1==J  $q$w- 'J1d7md4j(  agd3 3H q[ a  Q(m+IIotV< q!99  44=0<?IHh? Y'"))..B.*OPQSWPW*XX Y}}X1}5H 44=08;Ii')3 $&(8rBBGGIIS4Z"))..61A."KKPPRR"1      #  R0BbyH5[A0@(A$ABFZZ TBGGBHH4E-EFKFbiinnV"n==Ha"''%(*:";;U<(VV cddl}||jdz}|j|j}|dkDr|||z z}|S)aReturns scaled position array to (-scale, scale) in all axes. The function acts on NumPy arrays which hold position information. Each position is one row of the array. The dimension of the space equals the number of columns. Each coordinate in one column. To rescale, the mean (center) is subtracted from each axis separately. Then all values are scaled so that the largest magnitude value from all axes equals `scale` (thus, the aspect ratio is preserved). The resulting NumPy Array is returned (order of rows unchanged). Parameters ---------- pos : numpy array positions to be scaled. Each row is a position. scale : number (default: 1) The size of the resulting extent in all directions. attribute : str, default None If non-None, the position of each node will be stored on the graph as an attribute named `attribute` which can be accessed with `G.nodes[...][attribute]`. The function still returns the dictionary. Returns ------- pos : numpy array scaled positions. Each row is a position. See Also -------- rescale_layout_dict rNr)rrwrr8)r2r7r!lims r$r r YsMD3888 C &&+// C Qw us{ Jr&cddl}|siS|jt|j}t ||}t t ||S)aReturn a dictionary of scaled positions keyed by node Parameters ---------- pos : A dictionary of positions keyed by node scale : number (default: 1) The size of the resulting extent in all directions. Returns ------- pos : A dictionary of positions keyed by node Examples -------- >>> import numpy as np >>> pos = {0: np.array((0, 0)), 1: np.array((1, 1)), 2: np.array((0.5, 0.5))} >>> nx.rescale_layout_dict(pos) {0: array([-1., -1.]), 1: array([1., 1.]), 2: array([0., 0.])} >>> pos = {0: np.array((0, 0)), 1: np.array((-1, 1)), 2: np.array((-0.5, 0.5))} >>> nx.rescale_layout_dict(pos, scale=2) {0: array([ 2., -2.]), 1: array([-2., 2.]), 2: array([0., 0.])} See Also -------- rescale_layout rNr6)rrrGr}r r-r.)r2r7r!pos_vs r$r r sE:  HHT#**,' (E 5 .E C  r&)r[r7rr1cJt||d\}}tttj||}t |t d|jDk7rtjdt|||||}|tj||||S)aPosition nodes according to breadth-first search algorithm. Parameters ---------- G : NetworkX graph A position will be assigned to every node in G. start : node in `G` Starting node for bfs center : array-like or None Coordinate pair around which to center the layout. store_pos_as : str, default None If non-None, the position of each node will be stored on the graph as an attribute with this string as its name, which can be accessed with ``G.nodes[...][store_pos_as]``. The function still returns the dictionary. Returns ------- pos : dict A dictionary of positions keyed by node. Examples -------- >>> from pprint import pprint >>> G = nx.path_graph(4) >>> pos = nx.bfs_layout(G, 0) >>> # suppress the returned dict and store on the graph directly >>> _ = nx.bfs_layout(G, 0, store_pos_as="pos") >>> pprint(nx.get_node_attributes(G, "pos")) {0: array([-1., 0.]), 1: array([-0.33333333, 0. ]), 2: array([0.33333333, 0. ]), 3: array([1., 0.])} Notes ----- This algorithm currently only works in two dimensions and does not try to minimize edge crossings. r(c32K|]}t|ywrsr)r*s r$rxzbfs_layout..s=ESZ=r+zwbfs_layout didn't include all nodes. Perhaps use input graph: G.subgraph(nx.node_connected_component(G, start)))r2r[r7r) r%r-r|r bfs_layersrrr}rrr/)rstartr[r7rr1r4r2s r$rrsZ 61-IAv)BMM!U34 5F 1v=V]]_=== H   fEv C q#|4 Jr&)Nr(NN)r3Nr(N)NNr3Nr(N)NrPr3NgUUUUUU?N) NNN2-C6?rir3Nr(NN)NNNrrr(N) NNNrrr(Nrprk)NNrir3Nr(N)rir3Nr(N)r()r3Nr(gffffff?FN)subsetrPr3NN)Nr3g?gư>rrars)r3)__doc__networkxrnetworkx.utilsr__all__r%rrr rr rrrrrrrr rrrrrr _dispatchablerr r rrtr&r$rsN$* (*>>BRlKOi\   ~B     H  HHV,PT::z    UUp;@    cL*, 2^B+*+6FV  l`RVm`   E EEPXnb5IJ V     #VKVr*Z#!L#-AdQU@r&