;i4Q>dZddlmZddlmZGddeZdS)z altgraph.Graph - Base Graph class ================================= .. #--Version 2.1 #--Bob Ippolito October, 2004 #--Version 2.0 #--Istvan Albert June, 2004 #--Version 1.0 #--Nathan Denny, May 27, 1999 )deque) GraphErrorcpeZdZdZd;dZdZd;dZdd1Z0d?d2Z1d>d3Z2d;d4Z3d;d5Z4d;d6Z5d;d7Z6d8Z7d9Z8d>d:Z9dS)@Grapha The Graph class represents a directed graph with *N* nodes and *E* edges. Naming conventions: - the prefixes such as *out*, *inc* and *all* will refer to methods that operate on the outgoing, incoming or all edges of that node. For example: :py:meth:`inc_degree` will refer to the degree of the node computed over the incoming edges (the number of neighbours linking to the node). - the prefixes such as *forw* and *back* will refer to the orientation of the edges used in the method with respect to the node. For example: :py:meth:`forw_bfs` will start at the node then use the outgoing edges to traverse the graph (goes forward). NcDd|_iic|_|_iic|_|_|v|D]u}t |dkr|\}}|||1t |dkr|\}}}||||btd|dSdS)z Initialization rNzCannot create edge from ) next_edgenodesedges hidden_edges hidden_nodeslenadd_edger)selfr itemheadtaildatas BC:\PYTHON\MyICR_Workspace\venv\Lib\site-packages\altgraph/Graph.py__init__zGraph.__init__)s !#R DJ/12,4,   M Mt99>>!%JD$MM$----YY!^^'+$D$MM$d3333$*TT%KLLL   M McXd||fzS)Nz)number_of_nodesnumber_of_edgesrs r__repr__zGraph.__repr__=s2,  " "  " "0   rcL||jvrdS||jvrgg|f|j|<dSdS)z Adds a new node to the graph. Arbitrary data can be attached to the node via the node_data parameter. Adding the same node twice will be silently ignored. The node must be a hashable value. N)rr )rnode node_datas radd_nodezGraph.add_nodeCsE 4$ $ $ F tz ! ! "B 2DJt    " !rTc|j}|r*|||| |j|d||j|d|n##t$rt d|d|wxYw|||f|j|<|xjdz c_dS)a Adds a directed edge going from head_id to tail_id. Arbitrary data can be attached to the edge via edge_data. It may create the nodes if adding edges between nonexisting ones. :param head_id: head node :param tail_id: tail node :param edge_data: (optional) data attached to the edge :param create_nodes: (optional) creates the head_id or tail_id node in case they did not exist rr"zInvalid nodes z -> N)r r!r appendKeyErrorrr )rhead_idtail_id edge_data create_nodesedges rrzGraph.add_edgeYs~  # MM' " " " MM' " " "  L Jw  " ) )$ / / / Jw  " ) )$ / / / / L L L*''JKK K L$Wi8 4 !s A B B"c& |j|x\}}}|j|<|j|d||j|d||j|=dS#t$rt d|zwxYw)zd Hides an edge from the graph. The edge may be unhidden at some later time. rr"Invalid edge %sN)r r r remover%r)rr*r&r'r(s r hide_edgezGraph.hide_edge|s  7DHJtDT T 'GWi$*;D*A Jw  " ) )$ / / / Jw  " ) )$ / / / 4    7 7 7.566 6 7s A/A33Bc ||}|j||f|j|<|D]}|||j|=dS#t$rt d|zwxYw)z Hides a node from the graph. The incoming and outgoing edges of the node will also be hidden. The node may be unhidden at some later time. Invalid node %sN) all_edgesr rr.r%rrrr1r*s r hide_nodezGraph.hide_nodes  7t,,I'+z$'7&CD d #! % %t$$$$ 4    7 7 7.566 6 7s AAA/c |j|\|j|<}|D]}|||j|=dS#t$rt d|zwxYw)z Restores a previously hidden node back into the graph and restores all of its incoming and outgoing edges. r0N)rr restore_edger%rr2s r restore_nodezGraph.restore_nodes  7*.*;D*A 'DJt i! ( (!!$''''!$''' 7 7 7.566 6 7s :>Ac, |j|\}}}|j|d||j|d||||f|j|<|j|=dS#t$rt d|zwxYw)zH Restores a previously hidden edge back into the graph. rr"r,N)r r r$r r%r)rr*r&r'rs rr5zGraph.restore_edges 7%)%6t%< "GWd Jw  " ) )$ / / / Jw  " ) )$ / / /&5DJt !$''' 7 7 7.566 6 7s A2A66Bct|jD](} ||#t$rY%wxYwdS)z, Restores all hidden edges. N)listr keysr5rrr*s rrestore_all_edgeszGraph.restore_all_edgessp*//1122  D !!$''''      sA A  A ct|jD]}||dS)z, Restores all hidden nodes. N)r9rr:r6rrs rrestore_all_nodeszGraph.restore_all_nodessK*//1122 $ $D   d # # # # $ $rc||jvS)z5 Test whether a node is in the graph r r>s r __contains__zGraph.__contains__stz!!rcz |j|\}}}n%#t$rd\}}td|zwxYw||fS)N Returns the edge that connects the head_id and tail_id nodes )NNr,)r r%rrr*rrrs r edge_by_idzGraph.edge_by_ids` 7#z$/ D$ 7 7 7#JD$.566 6 7d|s"6cp||D]}|||kr|cS dS)rDN) out_edgesr)rrrr*s r edge_by_nodezGraph.edge_by_nodesGNN4((  Dyy$&& 'trc*t|jS)z- Returns the number of nodes )rr rs rrzGraph.number_of_nodes4:rc*t|jS)z- Returns the number of edges )rr rs rrzGraph.number_of_edgesrKrc*t|jS)z6 Iterates over all nodes in the graph )iterr rs r__iter__zGraph.__iter__sDJrcNt|jS)zS Return a list of the node ids for all visible nodes in the graph. )r9r r:rs r node_listzGraph.node_listDJOO%%&&&rcNt|jS)zI Returns an iterator for all visible nodes in the graph. )r9r r:rs r edge_listzGraph.edge_listrRrc*t|jS)z4 Returns the number of hidden edges )rr rs rnumber_of_hidden_edgeszGraph.number_of_hidden_edges4$%%%rc*t|jS)z4 Returns the number of hidden nodes )rrrs rnumber_of_hidden_nodeszGraph.number_of_hidden_nodesrWrcNt|jS)z8 Returns the list with the hidden nodes )r9rr:rs rhidden_node_listzGraph.hidden_node_list!D%**,,---rcNt|jS)z6 Returns a list with the hidden edges )r9r r:rs rhidden_edge_listzGraph.hidden_edge_list r\rc0|j|\}}}||||fS)zQ return node, node data, outgoing edges, incoming edges for node rA)rrincomingoutgoingrs r describe_nodezGraph.describe_nodes&$(:d#3 (DT8X--rc0|j|\}}}||||fS)z= return edge, edge data, head, tail for edge r rEs r describe_edgezGraph.describe_edges& :d+dDT4%%rc(|j|dS)z9 Returns the data associated with a node rrAr>s rr zGraph.node_data!z$""rc(|j|dS)z: Returns the data associated with an edge rrdr;s rr(zGraph.edge_data'rgrcH|j|dd|fz|j|<dS)z; Replace the edge data for a specific edge rrNrd)rr*r(s rupdate_edge_datazGraph.update_edge_data-s- :d+AaC0I<? 4rc(|j|dS)z; Returns the node of the head of the edge. rrdr;s rrz Graph.head3rgrc(|j|dS)z7 Returns node of the tail of the edge. r"rdr;s rrz Graph.tail9rgrcFfd|DS)z; List of nodes connected by outgoing edges c:g|]}|S)r.0nrs r z"Graph.out_nbrs..C#;;; ! ;;;r)rHr>s` rout_nbrszGraph.out_nbrs?+<;;;dnnT&:&:;;;;rcFfd|DS)z; List of nodes connected by incoming edges c:g|]}|Sro)rrps rrsz"Graph.inc_nbrs..Irtr) inc_edgesr>s` rinc_nbrszGraph.inc_nbrsErvrctt||||zS)zH List of nodes connected by incoming and outgoing edges )r9dictfromkeysrzrur>s rall_nbrszGraph.all_nbrsKs;DMM$--"5"5 d8K8K"KLLMMMrc t|j|dS#t$rtd|zwxYw)z6 Returns a list of the outgoing edges r"r0r9r r%rr>s rrHzGraph.out_edgesQP 7 4(+,, , 7 7 7.566 6 7"?c t|j|dS#t$rtd|zwxYw)z6 Returns a list of the incoming edges rr0rr>s rryzGraph.inc_edgesZrrcrt||||zS)z? Returns a list of incoming and outging edges. )setryrHr>s rr1zGraph.all_edgescs/4>>$''$..*>*>>???rcFt||S)z6 Returns the number of outgoing edges )rrHr>s r out_degreezGraph.out_degreei4>>$''(((rcFt||S)z6 Returns the number of incoming edges )rryr>s r inc_degreezGraph.inc_degreeorrcX||||zS)z, The total degree of a node )rrr>s r all_degreezGraph.all_degreeus't$$tt'<'<<>S!1!122 2 2EEEy!!rc.|dS)z Topological sort. Returns a list of nodes where the successors (based on outgoing edges) of any given node appear in the sequence after that node. Trrrs rforw_topo_sortzGraph.forw_topo_sortst,,,rc.|dS)z Reverse topological sort. Returns a list of nodes where the successors (based on incoming edges) of any given node appear in the sequence after that node. Frrrs rback_topo_sortzGraph.back_topo_sortsu---rc.|r|j}|j}n|j}|j}t }||}|D]}|||D]?}||D]1}|r||||||2@|S)z Private method creates a subgraph in a bfs order. The forward parameter specifies whether it is a forward or backward traversal. )forw_bfsruback_bfsrzrr!r) rstart_idrget_bfsget_nbrsgbfs_listrnbr_ids r _bfs_subgraphzGraph._bfs_subgraphs  %mG}HHmG}H GG78$$  D JJt     - -D"(4.. - --JJtV,,,,JJvt,,,,  - rc0||dS)z Creates and returns a subgraph consisting of the breadth first reachable nodes based on their outgoing edges. Trrrrs rforw_bfs_subgraphzGraph.forw_bfs_subgraphs !!(D!999rc0||dS)z Creates and returns a subgraph consisting of the breadth first reachable nodes based on the incoming edges. Frrrs rback_bfs_subgraphzGraph.back_bfs_subgraphs !!(E!:::rc#bK|ht|g}}|r|j}|j}n|j}|j}|rx|}|V||krdSt ||D];} || } | |vr*|| || <|vdSdS)z Collecting nodes in some depth first traversal. The forward parameter specifies whether it is a forward or backward traversal. N) rrHrryrpopsortedaddr$) rstartendrvisitedstackrrrr*rs riterdfsz Graph.iterdfss %..  !IyHHIyH ' IOOOCyy3344 ' 'x~~w&&KK%%%LL&&& ' ' ' ' 'rc#K|ht|g}}|r|j}|j}n|j}|j}|j} |r|} | | } | | || s1| V| |krdS|| D];} || } | |vr*|| || <|dSdS)z Perform a depth-first walk of the graph (as ``iterdfs``) and yield the item data of every node where condition matches. The condition callback is only called when node_data is not None. N) rrHrryrr rrr$)rrrr conditionrrrrget_datar curr_datar*rs riterdatazGraph.iterdatas %..  !IyHHIyH> ' I ++I$(91E1E(C! ),, ' 'x~~w&&KK%%%LL&&& ' ' ' ' 'rc#`Kt|dfg|h}}|r|j}|j}n|j}|j}|ru|\}} || fV||krdS||D]@} || } | |vr/|| || | dzfA|sdSdS)z The forward parameter specifies whether it is a forward or backward traversal. Returns a list of tuples where the first value is the hop value the second value is the node id. rr"N)rrHrryrrrr$) rrrrrrrrr curr_stepr*rs r_iterbfszGraph._iterbfs"s  |,,ugw  !IyHHIyH 8#(==?? Iyi( ( ( (C! ),, 8 8x~~w&&KK%%%LL$ A !6777 8 8 8 8 8rcFd|||dDS)z Returns a list of nodes in some forward BFS order. Starting from the start node the breadth first search proceeds along outgoing edges. cg|]\}}|Sroro)rqrsteps rrsz"Graph.forw_bfs..DsOOOtOOOrTrrrrrs rrzGraph.forw_bfs=s+POt}}UC}'N'NOOOOrcFd|||dDS)z Returns a list of nodes in some backward BFS order. Starting from the start node the breadth first search proceeds along incoming edges. cg|]\}}|Sroro)rqr_s rrsz"Graph.back_bfs..MsMMMqMMMrFrrrs rrzGraph.back_bfsFs+NMDMM%eM$L$LMMMMrcLt|||dS)z Returns a list of nodes in some forward DFS order. Starting with the start node the depth first search proceeds along outgoing edges. Trr9rrs rforw_dfszGraph.forw_dfsOs$DLLTL::;;;rcLt|||dS)z Returns a list of nodes in some backward DFS order. Starting from the start node the depth first search proceeds along incoming edges. Frrrs rback_dfszGraph.back_dfsXs$DLLUL;;<< for a formal definition. rr"g)rrur-rfloat)rrnumnbr_setnbrsec_setnbr_num clust_coefs rrzGraph.clust_coefmsdmmD))** 7?? NN4  * *C$--,,--Gg~~s### 3w()) )CCg,,  sw'A+'>?JJJrc|r%t|||dSt|||dS)a$ Computes the hop distance to all nodes centered around a node. First order neighbours are at hop 1, their neigbours are at hop 2 etc. Uses :py:meth:`forw_bfs` or :py:meth:`back_bfs` depending on the value of the forward parameter. If the distance between all neighbouring nodes is 1 the hop number corresponds to the shortest distance between the nodes. :param start: the starting node :param end: ending node (optional). When not specified will search the whole graph. :param forward: directionality parameter (optional). If C{True} (default) it uses L{forw_bfs} otherwise L{back_bfs}. :return: returns a list of tuples where each tuple contains the node and the hop. Typical usage:: >>> print (graph.get_hops(1, 8)) >>> [(1, 0), (2, 1), (3, 1), (4, 2), (5, 3), (7, 4), (8, 5)] # node 1 is at 0 hops # node 2 is at 1 hop # ... # node 8 is at 5 hops T)rrrF)r9r)rrrrs rget_hopszGraph.get_hopssM6  L EsD IIJJ J EsE JJKK Kr)N)r"T)T)NT)NTN):__name__ __module__ __qualname____doc__rrr!rr.r3r6r5r<r?rBrFrIrrrOrQrTrVrYr[r^rbrer r(rjrrrurzr~rHryr1rrrrrrrrrrrrrrrrrrrrorrrrs&MMMM(   3333,!!!!F 7 7 7 7 7 7 7 7 7 7 7 7$$$"""        ''' ''' &&& &&& ... ... ...&&&### ### @@@ ### ### <<< <<< NNN 777777@@@ ))) ))) === -"-"-"-"^---...8:::;;;''''6''''B88886PPPPNNNN<<<<====   >LLLLLLrrN)r collectionsraltgraphrobjectrrorrrs}  U LU LU LU LU LFU LU LU LU LU Lr