
    \Mh.                     J   d Z ddlmZ ddlZddlmZ ddlmZ ddlm	Z	 ddgZ
 G d	 d
e          Zd Z e	ed          Zej        d             Zej        d             Zej        d             Z ej        d          dd            Zeej        d                         ZdS )zHFunctions for measuring the quality of a partition (into
communities).

    )combinationsN)NetworkXError)is_partition)argmap
modularitypartition_qualityc                   "     e Zd ZdZ fdZ xZS )NotAPartitionz0Raised if a given collection is not a partition.c                 X    | d| }t                                          |           d S )Nz' is not a valid partition of the graph )super__init__)selfG
collectionmsg	__class__s       e/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/networkx/algorithms/community/quality.pyr   zNotAPartition.__init__   s4    GGAGG    )__name__
__module____qualname____doc__r   __classcell__)r   s   @r   r
   r
      s>        ::        r   r
   c                 R    t          | |          r| |fS t          j        d          )a  Decorator to check that a valid partition is input to a function

    Raises :exc:`networkx.NetworkXError` if the partition is not valid.

    This decorator should be used on functions whose first two arguments
    are a graph and a partition of the nodes of that graph (in that
    order)::

        >>> @require_partition
        ... def foo(G, partition):
        ...     print("partition is valid!")
        ...
        >>> G = nx.complete_graph(5)
        >>> partition = [{0, 1}, {2, 3}, {4}]
        >>> foo(G, partition)
        partition is valid!
        >>> partition = [{0}, {2, 3}, {4}]
        >>> foo(G, partition)
        Traceback (most recent call last):
          ...
        networkx.exception.NetworkXError: `partition` is not a valid partition of the nodes of G
        >>> partition = [{0, 1}, {1, 2, 3}, {4}]
        >>> foo(G, partition)
        Traceback (most recent call last):
          ...
        networkx.exception.NetworkXError: `partition` is not a valid partition of the nodes of G

    z6`partition` is not a valid partition of the nodes of G)r   nxr   r   	partitions     r   _require_partitionr      s2    : Ay!! )|

S
T
TTr   )r      c                 :     t           fd|D                       S )aR  Returns the number of intra-community edges for a partition of `G`.

    Parameters
    ----------
    G : NetworkX graph.

    partition : iterable of sets of nodes
        This must be a partition of the nodes of `G`.

    The "intra-community edges" are those edges joining a pair of nodes
    in the same block of the partition.

    c              3   f   K   | ]+}                     |                                          V  ,d S N)subgraphsize).0blockr   s     r   	<genexpr>z(intra_community_edges.<locals>.<genexpr>L   s;      ??Eqzz%  %%''??????r   )sumr   s   ` r   intra_community_edgesr)   =   s(     ????Y??????r   c                     |                                  rt          j        nt          j        }t          j        | ||                                          S )a  Returns the number of inter-community edges for a partition of `G`.
    according to the given
    partition of the nodes of `G`.

    Parameters
    ----------
    G : NetworkX graph.

    partition : iterable of sets of nodes
        This must be a partition of the nodes of `G`.

    The *inter-community edges* are those edges joining a pair of nodes
    in different blocks of the partition.

    Implementation note: this function creates an intermediate graph
    that may require the same amount of memory as that of `G`.

    )create_using)is_directedr   MultiDiGraph
MultiGraphquotient_graphr$   )r   r   MGs      r   inter_community_edgesr1   O   sB    8 MMOO	>BQ	;;;@@BBBr   c                 F    t          t          j        |           |          S )a  Returns the number of inter-community non-edges according to the
    given partition of the nodes of `G`.

    Parameters
    ----------
    G : NetworkX graph.

    partition : iterable of sets of nodes
        This must be a partition of the nodes of `G`.

    A *non-edge* is a pair of nodes (undirected if `G` is undirected)
    that are not adjacent in `G`. The *inter-community non-edges* are
    those non-edges on a pair of nodes in different blocks of the
    partition.

    Implementation note: this function creates two intermediate graphs,
    which may require up to twice the amount of memory as required to
    store `G`.

    )r1   r   
complementr   s     r   inter_community_non_edgesr4   o   s    < !q!1!19===r   weight)
edge_attrsr   c                    	
 t          |t                    st          |          }t           |          st           |                                           rpt                                                   
t                                                   t          
	                                          ddz  z  	nSt           
                                        x
t          
	                                          }|dz  d|dz  z  	 	
fd}t          t          ||                    S )a7  Returns the modularity of the given partition of the graph.

    Modularity is defined in [1]_ as

    .. math::
        Q = \frac{1}{2m} \sum_{ij} \left( A_{ij} - \gamma\frac{k_ik_j}{2m}\right)
            \delta(c_i,c_j)

    where $m$ is the number of edges (or sum of all edge weights as in [5]_),
    $A$ is the adjacency matrix of `G`, $k_i$ is the (weighted) degree of $i$,
    $\gamma$ is the resolution parameter, and $\delta(c_i, c_j)$ is 1 if $i$ and
    $j$ are in the same community else 0.

    According to [2]_ (and verified by some algebra) this can be reduced to

    .. math::
       Q = \sum_{c=1}^{n}
       \left[ \frac{L_c}{m} - \gamma\left( \frac{k_c}{2m} \right) ^2 \right]

    where the sum iterates over all communities $c$, $m$ is the number of edges,
    $L_c$ is the number of intra-community links for community $c$,
    $k_c$ is the sum of degrees of the nodes in community $c$,
    and $\gamma$ is the resolution parameter.

    The resolution parameter sets an arbitrary tradeoff between intra-group
    edges and inter-group edges. More complex grouping patterns can be
    discovered by analyzing the same network with multiple values of gamma
    and then combining the results [3]_. That said, it is very common to
    simply use gamma=1. More on the choice of gamma is in [4]_.

    The second formula is the one actually used in calculation of the modularity.
    For directed graphs the second formula replaces $k_c$ with $k^{in}_c k^{out}_c$.

    Parameters
    ----------
    G : NetworkX Graph

    communities : list or iterable of set of nodes
        These node sets must represent a partition of G's nodes.

    weight : string or None, optional (default="weight")
        The edge attribute that holds the numerical value used
        as a weight. If None or an edge does not have that attribute,
        then that edge has weight 1.

    resolution : float (default=1)
        If resolution is less than 1, modularity favors larger communities.
        Greater than 1 favors smaller communities.

    Returns
    -------
    Q : float
        The modularity of the partition.

    Raises
    ------
    NotAPartition
        If `communities` is not a partition of the nodes of `G`.

    Examples
    --------
    >>> G = nx.barbell_graph(3, 0)
    >>> nx.community.modularity(G, [{0, 1, 2}, {3, 4, 5}])
    0.35714285714285715
    >>> nx.community.modularity(G, nx.community.label_propagation_communities(G))
    0.35714285714285715

    References
    ----------
    .. [1] M. E. J. Newman "Networks: An Introduction", page 224.
       Oxford University Press, 2011.
    .. [2] Clauset, Aaron, Mark EJ Newman, and Cristopher Moore.
       "Finding community structure in very large networks."
       Phys. Rev. E 70.6 (2004). <https://arxiv.org/abs/cond-mat/0408187>
    .. [3] Reichardt and Bornholdt "Statistical Mechanics of Community Detection"
       Phys. Rev. E 74, 016110, 2006. https://doi.org/10.1103/PhysRevE.74.016110
    .. [4] M. E. J. Newman, "Equivalence between modularity optimization and
       maximum likelihood methods for community detection"
       Phys. Rev. E 94, 052315, 2016. https://doi.org/10.1103/PhysRevE.94.052315
    .. [5] Blondel, V.D. et al. "Fast unfolding of communities in large
       networks" J. Stat. Mech 10008, 1-12 (2008).
       https://doi.org/10.1088/1742-5468/2008/10/P10008
    )r5   r      c                    t          |           t          fd                    d          D                       }t          
fdD                       }rt          fdD                       n|}|z  |z  |z  	z  z
  S )Nc              3   ,   K   | ]\  }}}|v 
|V  d S r"    )r%   uvwtcomms       r   r'   z=modularity.<locals>.community_contribution.<locals>.<genexpr>   s.      XXAraSWii"iiiiXXr   r   )datadefaultc              3   (   K   | ]}|         V  d S r"   r;   )r%   r<   
out_degrees     r   r'   z=modularity.<locals>.community_contribution.<locals>.<genexpr>   s'      99qZ]999999r   c              3   (   K   | ]}|         V  d S r"   r;   )r%   r<   	in_degrees     r   r'   z=modularity.<locals>.community_contribution.<locals>.<genexpr>   s'      77QIaL777777r   )setr(   edges)	communityL_cout_degree_sumin_degree_sumr?   r   directedrE   mnormrC   
resolutionr5   s       @r   community_contributionz*modularity.<locals>.community_contribution   s    9~~XXXXQWWTW%J%JXXXXX9999D99999;CW7777$777777Qwn4}DtKKKr   )
isinstancelistr   r
   r,   dictrC   rE   r(   valuesdegreemap)r   communitiesr5   rO   deg_sumrP   rL   rE   rM   rN   rC   s   ` ``  @@@@@r   r   r      ss   j k4(( (;'';'' ,A{+++}}H 	!,,f,5566
F3344	
!!##$$1a4x!%ahhfh&=&=!>!>>
Yj''))**aK7A:~L L L L L L L L L L L L s);77888r   c                 N   i }t          |          D ]\  }}|D ]}|||<   |                                 sAt          d t          |d          D                       }|                                 r|dz  }nd}t          |           }||dz
  z  }|                                 s|dz  }d}	|}
|                                 D ]+}||d                  ||d                  k    r|	dz  }	&|
dz  }
,|	t          | j                  z  }|                                 rd}n|	|
z   |z  }||fS )aW  Returns the coverage and performance of a partition of G.

    The *coverage* of a partition is the ratio of the number of
    intra-community edges to the total number of edges in the graph.

    The *performance* of a partition is the number of
    intra-community edges plus inter-community non-edges divided by the total
    number of potential edges.

    This algorithm has complexity $O(C^2 + L)$ where C is the number of
    communities and L is the number of links.

    Parameters
    ----------
    G : NetworkX graph

    partition : sequence
        Partition of the nodes of `G`, represented as a sequence of
        sets of nodes (blocks). Each block of the partition represents a
        community.

    Returns
    -------
    (float, float)
        The (coverage, performance) tuple of the partition, as defined above.

    Raises
    ------
    NetworkXError
        If `partition` is not a valid partition of the nodes of `G`.

    Notes
    -----
    If `G` is a multigraph;
        - for coverage, the multiplicity of edges is counted
        - for performance, the result is -1 (total number of possible edges is not defined)

    References
    ----------
    .. [1] Santo Fortunato.
           "Community Detection in Graphs".
           *Physical Reports*, Volume 486, Issue 3--5 pp. 75--174
           <https://arxiv.org/abs/0906.0612>
    c              3   Z   K   | ]&\  }}t          |          t          |          z  V  'd S r"   )len)r%   p1p2s      r   r'   z$partition_quality.<locals>.<genexpr>:  sH       -
 -
"("bCGGc"gg-
 -
 -
 -
 -
 -
r   r8   r   r   g      )	enumerateis_multigraphr(   r   r,   r[   rG   )r   r   node_communityirH   nodepossible_inter_community_edgesntotal_pairsr)   r4   ecoverageperformances                 r   r   r     s   ` N!),, % %9 	% 	%D#$N4  	% ?? 	+), -
 -
,8A,F,F-
 -
 -
 *
 *
& ==?? 	0*a/*)*& 	AAq1u+K==??  > WWYY + +!A$>!A$#777!Q&!!%*%%$s17||3H X,/HHKW[  r   )r5   r   )r   	itertoolsr   networkxr   r   -networkx.algorithms.community.community_utilsr   networkx.utils.decoratorsr   __all__r
   r   require_partition_dispatchabler)   r1   r4   r   r   r;   r   r   <module>rp      s   
 # " " " " "     " " " " " " F F F F F F , , , , , ,,
-    M   U U UD F-v66  @ @ @" C C C> > > >@ X&&&n9 n9 n9 '&n9b W! W!  W! W! W!r   