
    VhGD                        d Z ddlZg dZej                  j                  d      ej                  d               ZddZej                  j                  d       ej                  dd      dd	              Z	ej                  j                  d       ej                  dd      dd
              Z
ej                  j                  d       ej                  dd      dd              Zej                  j                  d       ej                  dd      dd              Zej                  j                  d      ej                  j                  d       ej                  dd      d                      Zej                  j                  d      ej                  j                  d      ej                  d                      Zy)u  
Find the k-cores of a graph.

The k-core is found by recursively pruning nodes with degrees less than k.

See the following references for details:

An O(m) Algorithm for Cores Decomposition of Networks
Vladimir Batagelj and Matjaz Zaversnik, 2003.
https://arxiv.org/abs/cs.DS/0310049

Generalized Cores
Vladimir Batagelj and Matjaz Zaversnik, 2002.
https://arxiv.org/pdf/cs/0202039

For directed graphs a more general notion is that of D-cores which
looks at (k, l) restrictions on (in, out) degree. The (k, k) D-core
is the k-core.

D-cores: Measuring Collaboration of Directed Graphs Based on Degeneracy
Christos Giatsidis, Dimitrios M. Thilikos, Michalis Vazirgiannis, ICDM 2011.
http://www.graphdegeneracy.org/dcores_ICDM_2011.pdf

Multi-scale structure and topological anomaly detection via a new network statistic: The onion decomposition
L. Hébert-Dufresne, J. A. Grochow, and A. Allard
Scientific Reports 6, 31708 (2016)
http://doi.org/10.1038/srep31708

    N)core_numberk_corek_shellk_crustk_coronak_trussonion_layers
multigraphc           
         t        j                  |       dkD  rd}t        j                  |      t        | j	                               }t        ||j                        }dg}d}t        |      D ].  \  }}||   |kD  s|j                  |g||   |z
  z         ||   }0 t        |      D ci c]  \  }}||
 }	}}|}
| D ci c]"  }|t        t        j                  | |            $ }}|D ]t  }||   D ]j  }|
|   |
|   kD  s||   j                  |       |	|   }||
|      }||	|<   ||	||   <   ||   ||   c||<   ||<   ||
|   xx   dz  cc<   |
|xx   dz  cc<   l v |
S c c}}w c c}w )a  Returns the core number for each node.

    A k-core is a maximal subgraph that contains nodes of degree k or more.

    The core number of a node is the largest value k of a k-core containing
    that node.

    Parameters
    ----------
    G : NetworkX graph
       An undirected or directed graph

    Returns
    -------
    core_number : dictionary
       A dictionary keyed by node to the core number.

    Raises
    ------
    NetworkXNotImplemented
        If `G` is a multigraph or contains self loops.

    Notes
    -----
    For directed graphs the node degree is defined to be the
    in-degree + out-degree.

    Examples
    --------
    >>> degrees = [0, 1, 2, 2, 2, 2, 3]
    >>> H = nx.havel_hakimi_graph(degrees)
    >>> nx.core_number(H)
    {0: 1, 1: 2, 2: 2, 3: 2, 4: 1, 5: 2, 6: 0}
    >>> G = nx.DiGraph()
    >>> G.add_edges_from([(1, 2), (2, 1), (2, 3), (2, 4), (3, 4), (4, 3)])
    >>> nx.core_number(G)
    {1: 2, 2: 2, 3: 2, 4: 2}

    References
    ----------
    .. [1] An O(m) Algorithm for Cores Decomposition of Networks
       Vladimir Batagelj and Matjaz Zaversnik, 2003.
       https://arxiv.org/abs/cs.DS/0310049
    r   lInput graph has self loops which is not permitted; Consider using G.remove_edges_from(nx.selfloop_edges(G)).key   )nxnumber_of_selfloopsNetworkXNotImplementeddictdegreesortedget	enumerateextendlistall_neighborsremove)Gmsgdegreesnodesbin_boundariescurr_degreeivposnode_poscorenbrsu	bin_starts                 H/home/dcms/DCMS/lib/python3.12/site-packages/networkx/algorithms/core.pyr   r   -   s   ^ 
a 1$H 	 '',,188:G7,ESNK%  %11:#!!1#k)A"BC!!*K% &/u%566336H6D567AtB$$Q*++7D7 
a 		AAwa Qq!qk*473	'-0y)*/4Sz5;K,i %*tAw'1,'Q1		
 K 7 8s   /E)'E/c                     t        |       t        j                               fdD        }| j                  |      j	                         S )a  Returns the subgraph induced by nodes passing filter `k_filter`.

    Parameters
    ----------
    G : NetworkX graph
       The graph or directed graph to process
    k_filter : filter function
       This function filters the nodes chosen. It takes three inputs:
       A node of G, the filter's cutoff, and the core dict of the graph.
       The function should return a Boolean value.
    k : int, optional
      The order of the core. If not specified use the max core number.
      This value is used as the cutoff for the filter.
    core : dict, optional
      Precomputed core numbers keyed by node for the graph `G`.
      If not specified, the core numbers will be computed from `G`.

    c              3   8   K   | ]  } |      s|  y wN ).0r#   r&   kk_filters     r*   	<genexpr>z!_core_subgraph.<locals>.<genexpr>   s     51At 4Q5s   )r   maxvaluessubgraphcopy)r   r1   r0   r&   r   s    ``` r*   _core_subgraphr7   }   sJ    & |1~y55E::e!!##    T)preserve_all_attrsreturns_graphc                 $    d }t        | |||      S )a
  Returns the k-core of G.

    A k-core is a maximal subgraph that contains nodes of degree `k` or more.

    Parameters
    ----------
    G : NetworkX graph
      A graph or directed graph
    k : int, optional
      The order of the core. If not specified return the main core.
    core_number : dictionary, optional
      Precomputed core numbers for the graph G.

    Returns
    -------
    G : NetworkX graph
      The k-core subgraph

    Raises
    ------
    NetworkXNotImplemented
      The k-core is not defined for multigraphs or graphs with self loops.

    Notes
    -----
    The main core is the core with `k` as the largest core_number.

    For directed graphs the node degree is defined to be the
    in-degree + out-degree.

    Graph, node, and edge attributes are copied to the subgraph.

    Examples
    --------
    >>> degrees = [0, 1, 2, 2, 2, 2, 3]
    >>> H = nx.havel_hakimi_graph(degrees)
    >>> H.degree
    DegreeView({0: 1, 1: 2, 2: 2, 3: 2, 4: 2, 5: 3, 6: 0})
    >>> nx.k_core(H).nodes
    NodeView((1, 2, 3, 5))

    See Also
    --------
    core_number

    References
    ----------
    .. [1] An O(m) Algorithm for Cores Decomposition of Networks
       Vladimir Batagelj and Matjaz Zaversnik,  2003.
       https://arxiv.org/abs/cs.DS/0310049
    c                     ||    |k\  S r-   r.   r#   r0   cs      r*   r1   zk_core.<locals>.k_filter       tqyr8   r7   r   r0   r   r1   s       r*   r   r      s    n !Xq+66r8   c                 $    d }t        | |||      S )a  Returns the k-shell of G.

    The k-shell is the subgraph induced by nodes with core number k.
    That is, nodes in the k-core that are not in the (k+1)-core.

    Parameters
    ----------
    G : NetworkX graph
      A graph or directed graph.
    k : int, optional
      The order of the shell. If not specified return the outer shell.
    core_number : dictionary, optional
      Precomputed core numbers for the graph G.


    Returns
    -------
    G : NetworkX graph
       The k-shell subgraph

    Raises
    ------
    NetworkXNotImplemented
        The k-shell is not implemented for multigraphs or graphs with self loops.

    Notes
    -----
    This is similar to k_corona but in that case only neighbors in the
    k-core are considered.

    For directed graphs the node degree is defined to be the
    in-degree + out-degree.

    Graph, node, and edge attributes are copied to the subgraph.

    Examples
    --------
    >>> degrees = [0, 1, 2, 2, 2, 2, 3]
    >>> H = nx.havel_hakimi_graph(degrees)
    >>> H.degree
    DegreeView({0: 1, 1: 2, 2: 2, 3: 2, 4: 2, 5: 3, 6: 0})
    >>> nx.k_shell(H, k=1).nodes
    NodeView((0, 4))

    See Also
    --------
    core_number
    k_corona


    References
    ----------
    .. [1] A model of Internet topology using k-shell decomposition
       Shai Carmi, Shlomo Havlin, Scott Kirkpatrick, Yuval Shavitt,
       and Eran Shir, PNAS  July 3, 2007   vol. 104  no. 27  11150-11154
       http://www.pnas.org/content/104/27/11150.full
    c                     ||    |k(  S r-   r.   r=   s      r*   r1   zk_shell.<locals>.k_filter  r?   r8   r@   rA   s       r*   r   r      s    z !Xq+66r8   c                     t        j                  |       t        j                               dz
  fdD        }| j	                  |      j                         S )a  Returns the k-crust of G.

    The k-crust is the graph G with the edges of the k-core removed
    and isolated nodes found after the removal of edges are also removed.

    Parameters
    ----------
    G : NetworkX graph
       A graph or directed graph.
    k : int, optional
      The order of the shell. If not specified return the main crust.
    core_number : dictionary, optional
      Precomputed core numbers for the graph G.

    Returns
    -------
    G : NetworkX graph
       The k-crust subgraph

    Raises
    ------
    NetworkXNotImplemented
        The k-crust is not implemented for multigraphs or graphs with self loops.

    Notes
    -----
    This definition of k-crust is different than the definition in [1]_.
    The k-crust in [1]_ is equivalent to the k+1 crust of this algorithm.

    For directed graphs the node degree is defined to be the
    in-degree + out-degree.

    Graph, node, and edge attributes are copied to the subgraph.

    Examples
    --------
    >>> degrees = [0, 1, 2, 2, 2, 2, 3]
    >>> H = nx.havel_hakimi_graph(degrees)
    >>> H.degree
    DegreeView({0: 1, 1: 2, 2: 2, 3: 2, 4: 2, 5: 3, 6: 0})
    >>> nx.k_crust(H, k=1).nodes
    NodeView((0, 4, 6))

    See Also
    --------
    core_number

    References
    ----------
    .. [1] A model of Internet topology using k-shell decomposition
       Shai Carmi, Shlomo Havlin, Scott Kirkpatrick, Yuval Shavitt,
       and Eran Shir, PNAS  July 3, 2007   vol. 104  no. 27  11150-11154
       http://www.pnas.org/content/104/27/11150.full
    r   c              3   4   K   | ]  }|   k  s|  y wr-   r.   )r/   r#   r   r0   s     r*   r2   zk_crust.<locals>.<genexpr>W  s     ;1{1~':Q;   )r   r   r3   r4   r5   r6   )r   r0   r   r   s    `` r*   r   r     sY    v nnQ'y""$%);;E::e!!##r8   c                 *      fd}t         |||      S )a3  Returns the k-corona of G.

    The k-corona is the subgraph of nodes in the k-core which have
    exactly k neighbors in the k-core.

    Parameters
    ----------
    G : NetworkX graph
       A graph or directed graph
    k : int
       The order of the corona.
    core_number : dictionary, optional
       Precomputed core numbers for the graph G.

    Returns
    -------
    G : NetworkX graph
       The k-corona subgraph

    Raises
    ------
    NetworkXNotImplemented
        The k-corona is not defined for multigraphs or graphs with self loops.

    Notes
    -----
    For directed graphs the node degree is defined to be the
    in-degree + out-degree.

    Graph, node, and edge attributes are copied to the subgraph.

    Examples
    --------
    >>> degrees = [0, 1, 2, 2, 2, 2, 3]
    >>> H = nx.havel_hakimi_graph(degrees)
    >>> H.degree
    DegreeView({0: 1, 1: 2, 2: 2, 3: 2, 4: 2, 5: 3, 6: 0})
    >>> nx.k_corona(H, k=2).nodes
    NodeView((1, 2, 3, 5))

    See Also
    --------
    core_number

    References
    ----------
    .. [1]  k -core (bootstrap) percolation on complex networks:
       Critical phenomena and nonlocal effects,
       A. V. Goltsev, S. N. Dorogovtsev, and J. F. F. Mendes,
       Phys. Rev. E 73, 056101 (2006)
       http://link.aps.org/doi/10.1103/PhysRevE.73.056101
    c                 R    |    k(  xr t        fd|    D              k(  S )Nc              3   4   K   | ]  }|   k\  sd   yw)r   Nr.   )r/   wr>   r0   s     r*   r2   z)k_corona.<locals>.func.<locals>.<genexpr>  s     %CA1a%CrF   )sum)r#   r0   r>   r   s    ``r*   funczk_corona.<locals>.func  s*    tqyCQ#%C1%C"CCCr8   r@   )r   r0   r   rL   s   `   r*   r   r   [  s    pD !T1k22r8   directedc           	      @   t        j                  |       dkD  rd}t        j                  |      | j                         }d}|dkD  rd}g }t	               }|D ]p  }t	        ||         }|j                  |       |D 	cg c]	  }	|	|vs|	 }
}	|
D ]6  }	t        |t	        ||	         z        |dz
  k  s$|j                  ||	f       8 r |j                  |       t        |      }|j                  t        t        j                  |                   |dkD  r|S c c}	w )a  Returns the k-truss of `G`.

    The k-truss is the maximal induced subgraph of `G` which contains at least
    three vertices where every edge is incident to at least `k-2` triangles.

    Parameters
    ----------
    G : NetworkX graph
      An undirected graph
    k : int
      The order of the truss

    Returns
    -------
    H : NetworkX graph
      The k-truss subgraph

    Raises
    ------
    NetworkXNotImplemented
      If `G` is a multigraph or directed graph or if it contains self loops.

    Notes
    -----
    A k-clique is a (k-2)-truss and a k-truss is a (k+1)-core.

    Graph, node, and edge attributes are copied to the subgraph.

    K-trusses were originally defined in [2] which states that the k-truss
    is the maximal induced subgraph where each edge belongs to at least
    `k-2` triangles. A more recent paper, [1], uses a slightly different
    definition requiring that each edge belong to at least `k` triangles.
    This implementation uses the original definition of `k-2` triangles.

    Examples
    --------
    >>> degrees = [0, 1, 2, 2, 2, 2, 3]
    >>> H = nx.havel_hakimi_graph(degrees)
    >>> H.degree
    DegreeView({0: 1, 1: 2, 2: 2, 3: 2, 4: 2, 5: 3, 6: 0})
    >>> nx.k_truss(H, k=2).nodes
    NodeView((0, 1, 2, 3, 4, 5))

    References
    ----------
    .. [1] Bounds and Algorithms for k-truss. Paul Burkhardt, Vance Faber,
       David G. Harris, 2018. https://arxiv.org/abs/1806.05523v2
    .. [2] Trusses: Cohesive Subgraphs for Social Network Analysis. Jonathan
       Cohen, 2005.
    r   r   r      )r   r   r   r6   setaddlenappendremove_edges_fromremove_nodes_fromr   isolates)r   r0   r   H	n_droppedto_dropseenr(   nbrs_ur#   new_nbrss              r*   r   r     s$   l 
a 1$H 	 '',,	AI
a-	u 	+A1YFHHQK#);aQd];H; +vAaD	)*a!e4NNAq6*+		+ 	
G$L		DQ01 a- H <s   =	DDc           
          t        j                  |       dkD  rd}t        j                  |      i }| D ci c]"  }|t        t        j                  | |            $ }}t        | j                               }d}d}t        t        j                  |             }t        |      dkD  r|D ]  }|||<   |j                  |        d}t        |      dkD  rt        ||j                        }	||	d      }
|
|kD  r|
}g }|	D ]  }||   |kD  r n|j                  |        |D ]A  }|||<   ||   D ]!  }||   j                  |       ||   dz
  ||<   # |j                  |       C |dz   }t        |      dkD  r|S c c}w )u  Returns the layer of each vertex in an onion decomposition of the graph.

    The onion decomposition refines the k-core decomposition by providing
    information on the internal organization of each k-shell. It is usually
    used alongside the `core numbers`.

    Parameters
    ----------
    G : NetworkX graph
        An undirected graph without self loops.

    Returns
    -------
    od_layers : dictionary
        A dictionary keyed by node to the onion layer. The layers are
        contiguous integers starting at 1.

    Raises
    ------
    NetworkXNotImplemented
        If `G` is a multigraph or directed graph or if it contains self loops.

    Examples
    --------
    >>> degrees = [0, 1, 2, 2, 2, 2, 3]
    >>> H = nx.havel_hakimi_graph(degrees)
    >>> H.degree
    DegreeView({0: 1, 1: 2, 2: 2, 3: 2, 4: 2, 5: 3, 6: 0})
    >>> nx.onion_layers(H)
    {6: 1, 0: 2, 4: 3, 1: 4, 2: 4, 3: 4, 5: 4}

    See Also
    --------
    core_number

    References
    ----------
    .. [1] Multi-scale structure and topological anomaly detection via a new
       network statistic: The onion decomposition
       L. Hébert-Dufresne, J. A. Grochow, and A. Allard
       Scientific Reports 6, 31708 (2016)
       http://doi.org/10.1038/srep31708
    .. [2] Percolation and the effective structure of complex networks
       A. Allard and L. Hébert-Dufresne
       Physical Review X 9, 011023 (2019)
       http://doi.org/10.1103/PhysRevX.9.011023
    r   zqInput graph contains self loops which is not permitted; Consider using G.remove_edges_from(nx.selfloop_edges(G)).r   rO   r   )r   r   r   r   r   r   r   rV   rR   popr   r   rS   r   )r   r   	od_layersr#   	neighborsr   current_corecurrent_layerisolated_nodesr   
min_degree
this_layerns                r*   r	   r	     s   f 
a 1$H 	 '',,I:;<QD))!Q/00<I<188:GLM"++a.)N
>Q 	A(IaLKKN	 
g,
wGKK0U1X&
$%L
 	!AqzL(a 	!
  	A(IaLq\ ,!##A&$QZ!^
, KKN	 &)+ g,
. K =s   'E;)NNr-   )__doc__networkxr   __all__utilsnot_implemented_for_dispatchabler   r7   r   r   r   r   r   r	   r.   r8   r*   <module>rm      s  >  l+K  ,K\$6 l+T>87 ? ,87v l+T>>7 ? ,>7B l+T>>$ ? ,>$B l+T>93 ? ,93x j)l+T>L ? , *L^ l+j)^  * ,^r8   