
    Oh4Q                     6    d Z ddlmZ ddlmZ  G d de      Zy)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)
GraphErrorc                   n   e Zd ZdZd9dZd Zd9dZd:dZd Zd Z	d	 Z
d
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Z d  Z!d! Z"d" Z#d# Z$d$ Z%d% Z&d& Z'd' Z(d( Z)d;d)Z*d* Z+d+ Z,d;d,Z-d- Z.d. Z/d<d/Z0d=d0Z1d<d1Z2d9d2Z3d9d3Z4d9d4Z5d9d5Z6d6 Z7d7 Z8d<d8Z9y)>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).
    Nc                    d| _         i i c| _        | _        i i c| _        | _        |c|D ]]  }t        |      dk(  r|\  }}| j                  ||       )t        |      dk(  r|\  }}}| j                  |||       Qt        d|       yy)z 
        Initialization
        r   N      zCannot create edge from )	next_edgenodesedgeshidden_edgeshidden_nodeslenadd_edger   )selfr   itemheadtaildatas         `/mnt/c/Users/Administrator/Desktop/help_/test_env/lib/python3.12/site-packages/altgraph/Graph.py__init__zGraph.__init__)   s    
 !#R
DJ/12,4, Mt9>!%JD$MM$-Y!^'+$D$MM$d3$T%KLLM     c                 H    d| j                         | j                         fz  S )Nz<Graph: %d nodes, %d edges>)number_of_nodesnumber_of_edgesr   s    r   __repr__zGraph.__repr__=   s,    ,  "  "0
 
 	
r   c                 d    || j                   v ry|| j                  vrg g |f| j                  |<   yy)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)r   r   )r   node	node_datas      r   add_nodezGraph.add_nodeC   s;     4$$$tzz! "B	2DJJt "r   c                 t   | j                   }|r"| j                  |       | j                  |       	 | j                  |   d   j                  |       | j                  |   d   j                  |       |||f| j                  |<   | xj                   dz  c_         y# t        $ r t        d|d|      w xY w)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
        r      zInvalid nodes z -> N)r
   r!   r   appendKeyErrorr   r   )r   head_idtail_id	edge_datacreate_nodesedges         r   r   zGraph.add_edgeY   s     ~~ MM'"MM'"	LJJw"))$/JJw"))$/
 $Wi8

4!  	L'JKK	Ls   AB B7c                    	 | j                   |   x\  }}}| j                  |<   | j                  |   d   j                  |       | j                  |   d   j                  |       | j                   |= y# t        $ r t        d|z        w xY w)zd
        Hides an edge from the graph. The edge may be unhidden at some later
        time.
        r   r#   Invalid edge %sN)r   r   r   remover%   r   )r   r*   r&   r'   r(   s        r   	hide_edgezGraph.hide_edge|   s    
	7DHJJtDTT'GWi$*;*;D*AJJw"))$/JJw"))$/

4  	7.566	7s   A1A4 4Bc                     	 | j                  |      }| j                  |   |f| j                  |<   |D ]  }| j                  |        | j                  |= y# t        $ r t        d|z        w xY w)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   r   r.   r%   r   r   r   r1   r*   s       r   	hide_nodezGraph.hide_node   sz    
	7t,I'+zz$'7&CDd#! %t$%

4  	7.566	7s   AA A/c                     	 | j                   |   \  | j                  |<   }|D ]  }| j                  |        | j                   |= y# t        $ r t	        d|z        w xY w)z
        Restores a previously hidden node back into the graph and restores
        all of its incoming and outgoing edges.
        r0   N)r   r   restore_edger%   r   r2   s       r   restore_nodezGraph.restore_node   sp    
	7*.*;*;D*A'DJJti! (!!$'(!!$' 	7.566	7s   AA Ac                 $   	 | j                   |   \  }}}| j                  |   d   j                  |       | j                  |   d   j                  |       |||f| j                  |<   | j                   |= y# t        $ r t        d|z        w xY w)zH
        Restores a previously hidden edge back into the graph.
        r   r#   r,   N)r   r   r$   r   r%   r   )r   r*   r&   r'   r   s        r   r5   zGraph.restore_edge   s    	7%)%6%6t%<"GWdJJw"))$/JJw"))$/&5DJJt!!$' 	7.566	7s   A4A7 7Bc                     t        | j                  j                               D ]  }	 | j                  |        y# t        $ r Y #w xY w)z,
        Restores all hidden edges.
        N)listr   keysr5   r   r   r*   s     r   restore_all_edgeszGraph.restore_all_edges   sN     **//12 	D!!$'	  s   <	AAc                 v    t        | j                  j                               D ]  }| j                  |        y)z,
        Restores all hidden nodes.
        N)r9   r   r:   r6   r   r   s     r   restore_all_nodeszGraph.restore_all_nodes   s5     **//12 	$Dd#	$r   c                     || j                   v S )z5
        Test whether a node is in the graph
        r   r>   s     r   __contains__zGraph.__contains__   s     tzz!!r   c                 r    	 | j                   |   \  }}}||fS # t        $ r d\  }}t        d|z        w xY w)N
        Returns the edge that connects the head_id and tail_id nodes
        )NNr,   )r   r%   r   r   r*   r   r   r   s        r   
edge_by_idzGraph.edge_by_id   sS    	7#zz$/D$
 d|	  	7#JD$.566	7s    6c                 `    | j                  |      D ]  }| j                  |      |k(  s|c S  y)rD   N	out_edgesr   )r   r   r   r*   s       r   edge_by_nodezGraph.edge_by_node   s6     NN4( 	Dyy$&	 r   c                 ,    t        | j                        S )z-
        Returns the number of nodes
        )r   r   r   s    r   r   zGraph.number_of_nodes        4::r   c                 ,    t        | j                        S )z-
        Returns the number of edges
        )r   r   r   s    r   r   zGraph.number_of_edges   rL   r   c                 ,    t        | j                        S )z6
        Iterates over all nodes in the graph
        )iterr   r   s    r   __iter__zGraph.__iter__   s     DJJr   c                 H    t        | j                  j                               S )zS
        Return a list of the node ids for all visible nodes in the graph.
        )r9   r   r:   r   s    r   	node_listzGraph.node_list        DJJOO%&&r   c                 H    t        | j                  j                               S )zI
        Returns an iterator for all visible nodes in the graph.
        )r9   r   r:   r   s    r   	edge_listzGraph.edge_list   rS   r   c                 ,    t        | j                        S )z4
        Returns the number of hidden edges
        )r   r   r   s    r   number_of_hidden_edgeszGraph.number_of_hidden_edges        4$$%%r   c                 ,    t        | j                        S )z4
        Returns the number of hidden nodes
        )r   r   r   s    r   number_of_hidden_nodeszGraph.number_of_hidden_nodes  rX   r   c                 H    t        | j                  j                               S )z8
        Returns the list with the hidden nodes
        )r9   r   r:   r   s    r   hidden_node_listzGraph.hidden_node_list       D%%**,--r   c                 H    t        | j                  j                               S )z6
        Returns a list with the hidden edges
        )r9   r   r:   r   s    r   hidden_edge_listzGraph.hidden_edge_list  r]   r   c                 4    | j                   |   \  }}}||||fS )zQ
        return node, node data, outgoing edges, incoming edges for node
        rA   )r   r   incomingoutgoingr   s        r   describe_nodezGraph.describe_node  s(     $(::d#3 (DT8X--r   c                 4    | j                   |   \  }}}||||fS )z=
        return edge, edge data, head, tail for edge
        r   rE   s        r   describe_edgezGraph.describe_edge  s(      ::d+dDT4%%r   c                 &    | j                   |   d   S )z9
        Returns the data associated with a node
        r   rA   r>   s     r   r    zGraph.node_data!       zz$""r   c                 &    | j                   |   d   S )z:
        Returns the data associated with an edge
        r   re   r;   s     r   r(   zGraph.edge_data'  rh   r   c                 J    | j                   |   dd |fz   | j                   |<   y)z;
        Replace the edge data for a specific edge
        r   r   Nre   )r   r*   r(   s      r   update_edge_datazGraph.update_edge_data-  s)      ::d+Aa0I<?

4r   c                 &    | j                   |   d   S )z;
        Returns the node of the head of the edge.
        r   re   r;   s     r   r   z
Graph.head3  rh   r   c                 &    | j                   |   d   S )z7
        Returns node of the tail of the edge.
        r#   re   r;   s     r   r   z
Graph.tail9  rh   r   c                 h    | j                  |      D cg c]  }| j                  |       c}S c c}w )z;
        List of nodes connected by outgoing edges
        rH   r   r   ns      r   out_nbrszGraph.out_nbrs?  )     '+nnT&:;		!;;;   /c                 h    | j                  |      D cg c]  }| j                  |       c}S c c}w )z;
        List of nodes connected by incoming edges
        )	inc_edgesr   ro   s      r   inc_nbrszGraph.inc_nbrsE  rr   rs   c                     t        t        j                  | j                  |      | j	                  |      z               S )zH
        List of nodes connected by incoming and outgoing edges
        )r9   dictfromkeysrv   rq   r>   s     r   all_nbrszGraph.all_nbrsK  s/     DMM$--"5d8K"KLMMr   c                 p    	 t        | j                  |   d         S # t        $ r t        d|z        w xY w)z6
        Returns a list of the outgoing edges
        r#   r0   r9   r   r%   r   r>   s     r   rI   zGraph.out_edgesQ  @    	7

4(+,, 	7.566	7    5c                 p    	 t        | j                  |   d         S # t        $ r t        d|z        w xY w)z6
        Returns a list of the incoming edges
        r   r0   r|   r>   s     r   ru   zGraph.inc_edgesZ  r}   r~   c                 Z    t        | j                  |      | j                  |      z         S )z?
        Returns a list of incoming and outging edges.
        )setru   rI   r>   s     r   r1   zGraph.all_edgesc  s&     4>>$'$..*>>??r   c                 6    t        | j                  |            S )z6
        Returns the number of outgoing edges
        )r   rI   r>   s     r   
out_degreezGraph.out_degreei       4>>$'((r   c                 6    t        | j                  |            S )z6
        Returns the number of incoming edges
        )r   ru   r>   s     r   
inc_degreezGraph.inc_degreeo  r   r   c                 H    | j                  |      | j                  |      z   S )z,
        The total degree of a node
        )r   r   r>   s     r   
all_degreezGraph.all_degreeu  s!     t$tt'<<<r   c                 P   g }t               }i }|r%| j                  }| j                  }| j                  }n$| j                  }| j
                  }| j                  }| j                         D ]#  } ||      }	|	r|	||<   |j                  |       % |re|j                         }
|j                  |
        ||
      D ]6  } ||      }||v s||xx   dz  cc<   ||   dk(  s&|j                  |       8 |ret        |      t        | j                               k(  rd}||fS d}||fS )z
        Topological sort.

        Returns a list of nodes where the successors (based on outgoing and
        incoming edges selected by the forward parameter) of any given node
        appear in the sequence after that node.
        r#   r   TF)r   rI   r   r   ru   r   r   rR   r$   popleftr   )r   forward	topo_listqueueindeg	get_edges
get_degreeget_nextr   degree	curr_noder*   r'   valids                 r   
_topo_sortzGraph._topo_sort{  s4    	 IJyyHIJyyHNN$ 	#D%F$dT"	# IY'!), ."4.e#'Na'NW~*W-.  y>S!122E
 y!! Ey!!r   c                 &    | j                  d      S )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.
        Tr   r   r   s    r   forw_topo_sortzGraph.forw_topo_sort  s     t,,r   c                 &    | j                  d      S )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.
        Fr   r   r   s    r   back_topo_sortzGraph.back_topo_sort  s     u--r   c                 6   |r| j                   }| j                  }n| j                  }| j                  }t	               } ||      }|D ]  }|j                  |        |D ]6  } ||      D ])  }|r|j                  ||       |j                  ||       + 8 |S )z
        Private method creates a subgraph in a bfs order.

        The forward parameter specifies whether it is a forward or backward
        traversal.
        )forw_bfsrq   back_bfsrv   r   r!   r   )	r   start_idr   get_bfsget_nbrsgbfs_listr   nbr_ids	            r   _bfs_subgraphzGraph._bfs_subgraph  s     mmG}}HmmG}}HG8$ 	DJJt	  	-D"4. -JJtV,JJvt,	-	- r   c                 (    | j                  |d      S )z
        Creates and returns a subgraph consisting of the breadth first
        reachable nodes based on their outgoing edges.
        Tr   r   r   r   s     r   forw_bfs_subgraphzGraph.forw_bfs_subgraph  s    
 !!(D!99r   c                 (    | j                  |d      S )z
        Creates and returns a subgraph consisting of the breadth first
        reachable nodes based on the incoming edges.
        Fr   r   r   s     r   back_bfs_subgraphzGraph.back_bfs_subgraph  s    
 !!(E!::r   c              #   Z  K   |ht        |g      }}|r| j                  }| j                  }n| j                  }| j                  }|rc|j                         }| ||k(  ryt         ||            D ]1  }	 ||	      }
|
|vs|j                  |
       |j                  |
       3 |rbyyw)z
        Collecting nodes in some depth first traversal.

        The forward parameter specifies whether it is a forward or backward
        traversal.
        N)	r   rI   r   ru   r   popsortedaddr$   )r   startendr   visitedstackr   r   r   r*   r   s              r   iterdfszGraph.iterdfs  s       %.IyyHIyyH		IOCy34 '~w&KK%LL&	' s   A?B+&B+)B+c              #     K   |ht        |g      }}|r| j                  }| j                  }n| j                  }| j                  }| j
                  }	|ro|j                         }
 |	|
      }||	 ||      s'| |
|k(  ry ||
      D ]1  } ||      }||vs|j                  |       |j                  |       3 |rnyyw)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)	r   rI   r   ru   r   r    r   r   r$   )r   r   r   r   	conditionr   r   r   r   get_datar   	curr_datar*   r   s                 r   iterdatazGraph.iterdata  s       %.IyyHIyyH>>		I +I$(91EC!), '~w&KK%LL&	' s   BC&CCc              #   `  K   t        |dfg      |h}}|r| j                  }| j                  }n| j                  }| j                  }|rd|j                         \  }}	||	f ||k(  ry ||      D ]6  }
 ||
      }||vs|j                  |       |j                  ||	dz   f       8 |rcyyw)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.
        r   r#   N)r   rI   r   ru   r   r   r   r$   )r   r   r   r   r   r   r   r   r   	curr_stepr*   r   s               r   _iterbfszGraph._iterbfs"  s      
|,ugw IyyHIyyH#(==? Iyi((C!), 8~w&KK%LL$	A!67	8 s   A=B. +B.,B.c                 \    | j                  ||d      D cg c]  \  }}|	 c}}S c c}}w )z
        Returns a list of nodes in some forward BFS order.

        Starting from the start node the breadth first search proceeds along
        outgoing edges.
        Tr   r   )r   r   r   r   steps        r   r   zGraph.forw_bfs=  s+     (,}}UC}'NOtOOO   (c                 \    | j                  ||d      D cg c]  \  }}|	 c}}S c c}}w )z
        Returns a list of nodes in some backward BFS order.

        Starting from the start node the breadth first search proceeds along
        incoming edges.
        Fr   r   )r   r   r   r   _s        r   r   zGraph.back_bfsF  s+     %)MM%eM$LMqMMMr   c                 <    t        | j                  ||d            S )z
        Returns a list of nodes in some forward DFS order.

        Starting with the start node the depth first search proceeds along
        outgoing edges.
        Tr   r9   r   r   r   r   s      r   forw_dfszGraph.forw_dfsO  s     DLLTL:;;r   c                 <    t        | j                  ||d            S )z
        Returns a list of nodes in some backward DFS order.

        Starting from the start node the depth first search proceeds along
        incoming edges.
        Fr   r   r   s      r   back_dfszGraph.back_dfsX  s     DLLUL;<<r   c                     | j                         }|D ],  }| j                  |      }t        |      t        |      k7  s, y y)zq
        Returns :py:data:`True` if the graph's every node can be reached from
        every other node.
        FT)rR   r   r   )r   rR   r   r   s       r   	connectedzGraph.connecteda  sE    
 NN$	 	D}}T*H8}I.	 r   c                 @   d}t        | j                  |            }||v r|j                  |       |D ]B  }t        | j                  |            }||v r|j                  |       |t        ||z        z  }D t        |      }|rt	        |      ||dz
  z  z  }|S d}|S )a  
        Computes and returns the local clustering coefficient of node.

        The local cluster coefficient is proportion of the actual number of
        edges between neighbours of node and the maximum number of edges
        between those neighbours.

        See "Local Clustering Coefficient" on
        <http://en.wikipedia.org/wiki/Clustering_coefficient>
        for a formal definition.
        r   r#   g        )r   rq   r-   r   float)r   r   numnbr_setnbrsec_setnbr_num
clust_coefs           r   r   zGraph.clust_coefm  s     dmmD)*7?NN4  	*C$--,-Gg~s#3w())C		* g,sw'A+'>?J  Jr   c                 z    |rt        | j                  ||d            S t        | j                  ||d            S )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)r   r   r   F)r9   r   )r   r   r   r   s       r   get_hopszGraph.get_hops  s;    6 EsDIJJEsEJKKr   )N)r#   T)T)NT)NTN):__name__
__module____qualname____doc__r   r   r!   r   r.   r3   r6   r5   r<   r?   rB   rF   rJ   r   r   rP   rR   rU   rW   rZ   r\   r_   rc   rf   r    r(   rk   r   r   rq   rv   rz   rI   ru   r1   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r   r   r   r      s   &M(
3,!F7777$"
 ''&&...&##@##<<N77@))=-"^-.8:;'6'B86PN<=
>Lr   r   N)r   collectionsr   altgraphr   objectr   r   r   r   <module>r      s"     U
LF U
Lr   