ó ŸÃÒYc @ sUdZddlmZddlZddlZdddddd d d gZd „Zdd d„Z ddd d„Z dddd d„Z dddddddd d„Z e Z ddddd d„Zddddd d„Zdddddd d„Zd„Zd„Zdddd d„Zd d„Zd d„Zdd„Zd„ZdS(s‰ ****** 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. iÿÿÿÿ(tdivisionNtcircular_layouttkamada_kawai_layoutt random_layouttrescale_layoutt shell_layoutt spring_layouttspectral_layouttfruchterman_reingold_layoutcC sžddl}t|tjƒs@tjƒ}|j|ƒ|}n|dkr^|j|ƒ}n|j|ƒ}t|ƒ|kr”d}t |ƒ‚n||fS(Niÿÿÿÿs;length of center coordinates must match dimension of layout( tnumpyt isinstancetnxtGraphtadd_nodes_fromtNonetzerostasarraytlent ValueError(tGtcentertdimtnpt empty_graphtmsg((sm/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/drawing/layout.pyt_process_params*s     icC swddl}t|||ƒ\}}t|ƒ|f}|jj|ƒ|}|j|jƒ}tt||ƒƒ}|S(s¾Position 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. Returns ------- pos : dict A dictionary of positions keyed by node Examples -------- >>> G = nx.lollipop_graph(4, 3) >>> pos = nx.random_layout(G) iÿÿÿÿN(R RRtrandomtastypetfloat32tdicttzip(RRRRtshapetpos((sm/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/drawing/layout.pyR?s icC s.ddl}t|||ƒ\}}td|dƒ}t|ƒdkrRi}nØt|ƒdkr€i|tjj|ƒ6}nª|jddt|ƒdƒd d|j}|j |j ƒ}|j |j |ƒ|j |ƒ|jt|ƒ|fƒgƒ}t|d|ƒ|}tt||ƒƒ}|S(sÿPosition 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. Returns ------- pos : dict A dictionary of positions keyed by node Examples -------- >>> G = nx.path_graph(4) >>> pos = nx.circular_layout(G) Notes ----- This algorithm currently only works in two dimensions and does not try to minimize edge crossings. iÿÿÿÿNiiitscale(R RtmaxRR tutilstarbitrary_elementtlinspacetpiRRt column_stacktcostsinRRRR(RR!RRRtpaddimsR ttheta((sm/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/drawing/layout.pyRhs$  .!c C slddl}t|||ƒ\}}t|ƒdkr:iSt|ƒdkrci|tjj|ƒ6S|dkrt|ƒg}nt|dƒdkr d}nd}i}x¹|D]±}|jddt|ƒdƒd d|j } | j |j ƒ} |j |j | ƒ|j| ƒgƒ} t| d||t|ƒƒ|} |jt|| ƒƒ|d7}q³W|S( s: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. 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. Returns ------- pos : dict A dictionary of positions keyed by node Examples -------- >>> G = nx.path_graph(4) >>> shells = [[0], [1, 2, 3]] >>> pos = nx.shell_layout(G, shells) Notes ----- This algorithm currently only works in two dimensions and does not try to minimize edge crossings. iÿÿÿÿNiiggð?iR!(R RRR R#R$RtlistR%R&RRR'R(R)RtupdateR( RtnlistR!RRRtradiustnpostnodesR+R ((sm/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/drawing/layout.pyR¢s(%    .'$i2tweightc C s»ddl} t|||ƒ\}}|dk rztt|tt|ƒƒƒƒ} | jg|D]} | | ^q^ƒ}n|dk r)td„|j ƒDƒƒ} | dkr·d} nt|ƒ|f} | j j | ƒ| |}xIt |ƒD]2\}}||krð| j||ƒ||>> G = nx.path_graph(4) >>> pos = nx.spring_layout(G) # The same using longer but equivalent function name >>> pos = nx.fruchterman_reingold_layout(G) iÿÿÿÿNcs s"|]}|D] }|Vq qdS(N((t.0tpos_tuptcoord((sm/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/drawing/layout.pys ,siiiôR2tdtypetfR!(R RRRRtrangeRRR"tvaluesRt enumerateR R#R$R1Rtto_scipy_sparse_matrixRtsqrtt_sparse_fruchterman_reingoldtto_numpy_matrixt_fruchterman_reingoldR(RtkR tfixedt iterationsR2R!RRRtnfixedtvtdom_sizeRtpos_arrtitntAtnnodest_((sm/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/drawing/layout.pyRèsL:  !)    !  cC s»yddl}Wn#tk r5d}t|ƒ‚nXy|j\}} Wn&tk rqd}tj|ƒ‚nX|j|ƒ}|dkrº|j|jj||fƒd|j ƒ}n|j |j ƒ}|dkrî|j d|ƒ}nt t |j dƒt|j dƒt |j dƒt|j dƒƒd} | t|dƒ} |j|jd|jd|jdfd|j ƒ} x-t|ƒD]} |dd…|jdd…f||jdd…dd…f} |jj| d dƒ}|j|d dd |ƒ|jd | |||d |||ƒ}|jj|d dƒ}|j|d kd|ƒ}|jd|| |ƒ}|dk rŸd||ikisij,i->ijg(R t ImportErrorRtAttributeErrorR t NetworkXErrorRRRR6RR<R"tTtmintfloatRR8tnewaxistlinalgtnormtclipteinsumtwhere(RIR@R RARBRRRRJRKtttdttdeltat iterationtdistancet displacementtlengtht delta_pos((sm/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/drawing/layout.pyR?WsD   - O6B !   c C sêyddl}Wn#tk r5d}t|ƒ‚nXy|j\}} Wn&tk rqd} tj| ƒ‚nXyddlm} m} Wn#tk r±d} t| ƒ‚nXy|j ƒ}Wn| |ƒj ƒ}nX|dkr|j |j j ||fƒd|j ƒ}n|j|j ƒ}|dkr>g}n|dkr`|jd|ƒ}nd} | t|d ƒ}|j||fƒ}xTt|ƒD]F}|d 9}xÚt|jd ƒD]Å}||krØqÀn|||j}|j|d jd d ƒƒ}|j|d kd |ƒ}|j |j|ƒjƒƒ}|dd…|fc||||d |||jd d ƒ7_sparse_fruchterman_reingold() scipy numpy: http://scipy.org/ R6gð?gš™™™™™¹?iiiRLg{®Gáz„?(R RNRROR RPt scipy.sparseRbRcttolilRRRR6RR<RSRR8RQtsumRYt getrowviewttoarray(RIR@R RARBRRtmRJRKRRbRcRZR[R_R]RGR\R^tAiR`((sm/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/drawing/layout.pyR=˜sZ    -     2cC s™yddl}Wn#tk r5d}t|ƒ‚nXt|||ƒ\}}t|ƒ} |dkr„ttj|d|ƒƒ}nd|j| | fƒ} xwt |ƒD]i\} } | |krÈqªn|| } x>t |ƒD]0\}}|| krýqßn| || | |>> G = nx.path_graph(4) >>> pos = nx.kamada_kawai_layout(G) iÿÿÿÿNs4Kamada-Kawai layout requires numpy: http://scipy.orgR2g€„.ARR!(R RNRRRRR tshortest_path_lengthtonesR:Rtarrayt_kamada_kawai_solveRR(RtdistR R2R!RRRRtnNodestdist_mtxtrowtnrtrdisttcoltncRHRF((sm/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/drawing/layout.pyRâs0.       &c C s·ddl}yddlm}Wn#tk rEd}t|ƒ‚nXd}|d||j|jdƒd||f}|t|jƒddd |d tƒ}|j j d|fƒS( Niÿÿÿÿ(tminimizes4Kamada-Kawai layout requires scipy: http://scipy.orggü©ñÒMbP?iitmethodsL-BFGS-Btargstjac( R tscipy.optimizeRwRNteyeRt_kamada_kawai_costfntraveltTruetxtreshape( RqRFRRRwRtmeanwttcostargst optresult((sm/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/drawing/layout.pyRn/s  " cC s^|jd}|j||fƒ}|dd…|jdd…f||jdd…dd…f}|jj|ddƒ}|jd|d||j|ƒdƒ} ||d} d| |j|ƒijkigü©ñÒMbP?gð?gà?is ij,ij,ijk->iks ij,ij,ijk->jk( RRRTRURVRXR|t diag_indicesRfR~(tpos_vecRtinvdistt meanweightRRpRFR\tnodesept directiontoffsettcosttgradtsumpos((sm/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/drawing/layout.pyR}Es  B cC s¶ddl}t|||ƒ\}}t|ƒdkr¿t|ƒdkrZ|jgƒ}nRt|ƒdkr|j|gƒ}n+|j|j|ƒ|j|ƒdgƒ}tt||ƒƒSykt|ƒdkrÝt‚ntj |d|d d ƒ}|j ƒr||j |ƒ}nt ||ƒ}Wn]t tfk r‰tj|d|ƒ}|j ƒrw||j |ƒ}nt||ƒ}nXt||ƒ|}tt||ƒƒ}|S( sÔPosition nodes using the eigenvectors of the graph Laplacian. 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. Returns ------- pos : dict A dictionary of positions keyed by node Examples -------- >>> G = nx.path_graph(4) >>> pos = nx.spectral_layout(G) 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). iÿÿÿÿNiiig@iôR2R6td(R RRRmRRRRR R;t is_directedt transposet_sparse_spectralRNR>t _spectralR(RR2R!RRRR RI((sm/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/drawing/layout.pyR_s0( +   c C s yddl}Wn#tk r5d}t|ƒ‚nXy|j\}}Wn&tk rqd}tj|ƒ‚nX|j|ƒ}|j|d|jƒ}||j |ddƒ}||}|j j |ƒ\} } |j | ƒd|d!} |j | dd…| fƒS(Niÿÿÿÿs4spectral_layout() requires numpy: http://scipy.org/ s-spectral() takes an adjacency matrix as inputR6RLi(R RNRROR RPRtidentityR6RfRUteigtargsorttreal( RIRRRRJRKtItDtLt eigenvaluest eigenvectorstindex((sm/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/drawing/layout.pyR“©s"   cC sSy0ddl}ddlm}ddlm}Wn#tk rUd}t|ƒ‚nXy|j\}}Wn&tk r‘d}tj |ƒ‚nX|j |j ddƒj ƒ}||d||ƒ} | |} |d} t d | dt|j|ƒƒƒ} || | d d d | ƒ\} }|j| ƒd| !}|j|dd…|fƒS( Niÿÿÿÿ(Rb(teigshs=_sparse_spectral() requires scipy & numpy: http://scipy.org/ s4sparse_spectral() takes an adjacency matrix as inputRLiiitwhichtSMtncv(R RdRbtscipy.sparse.linalg.eigenRžRNRROR RPRRfRQR"tintR<R–R—(RIRRRbRžRRJRKtdataR™RšR@R¡R›RœR((sm/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/drawing/layout.pyR’Äs(     &!cC sÒd}xxt|jdƒD]c}|dd…|fc|dd…|fjƒ8t|jdƒD]&}|dd…|fc||9sR    ):F e @ I H  J   '