ó
    …~i§.  ã                   ó@  • S r SSKJr  SSKrSSKJr  SSKJr  SSKJ	r	  SS/r
 " S	 S
\5      rS r\	" \S5      r\R                  S 5       r\R                  S 5       r\R                  S 5       r\R                  " SS9SS j5       r\\R                  S 5       5       rg)zHFunctions for measuring the quality of a partition (into
communities).

é    )ÚcombinationsN)ÚNetworkXError)Úis_partition)ÚargmapÚ
modularityÚpartition_qualityc                   ó,   ^ • \ rS rSrSrU 4S jrSrU =r$ )ÚNotAPartitioné   z0Raised if a given collection is not a partition.c                 ó2   >• U SU 3n[         TU ]  U5        g )Nz' is not a valid partition of the graph )ÚsuperÚ__init__)ÚselfÚGÚ
collectionÚmsgÚ	__class__s       €Úb/home/mande/repo/quber/.venv/lib/python3.13/site-packages/networkx/algorithms/community/quality.pyr   ÚNotAPartition.__init__   s!   ø€ Ø�ÐCÀAÀ3ÐGˆÜ‰Ñ˜Õó    © )Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r   Ú__static_attributes__Ú__classcell__)r   s   @r   r
   r
      s   ø† Ù:÷ó r   r
   c                 óT   • [        X5      (       a  X4$ [        R                  " S5      e)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#      s)   € ô: �A×!Ñ!Øˆ|ÐÜ
×
Ò
ÐSÓ
TÐTr   )r   é   c                 ó.   ^ • [        U 4S jU 5       5      $ )a2  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   ób   >#   • U  H$  nTR                  U5      R                  5       v •  M&     g 7f©N)ÚsubgraphÚsize)Ú.0Úblockr   s     €r   Ú	<genexpr>Ú(intra_community_edges.<locals>.<genexpr>L   s&   øé € Ð?²Y¨Eˆq�z‰z˜%Ó ×%Ñ%×'Ð'²Yùs   ƒ,/)Úsumr!   s   ` r   Úintra_community_edgesr/   =   s   ø€ ô Ô?±YÓ?Ó?Ð?r   c                 ó²   • U R                  5       (       a  [        R                  O[        R                  n[        R                  " XUS9R                  5       $ )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_edgesr7   O   s9   € ð8 ŸM™MŸO™OŒ�Š´·±€BÜ×Ò˜Q¸Ñ;×@Ñ@ÓBÐBr   c                 óB   • [        [        R                  " U 5      U5      $ )aK  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`.

)r7   r    Ú
complementr!   s     r   Úinter_community_non_edgesr:   o   s   € ô< !¤§¢¨qÓ!1°9Ó=Ð=r   Úweight)Ú
edge_attrsc                 ó   ^ ^^^^^^	^
• [        U[        5      (       d  [        U5      n[        T U5      (       d  [        T U5      eT R	                  5       mT(       aR  [        T R                  TS95      m
[        T R                  TS95      m[        T
R                  5       5      mSTS-  -  m	O@[        T R                  TS95      =m
m[        T
R                  5       5      nUS-  mSUS-  -  m	U UUUU	U
UU4S jn[        [        XQ5      5      $ )a/  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
)r;   r$   é   c           	      óì   >^• [        U 5      m[        U4S jTR                  TTSS9 5       5      n[        U
4S jT 5       5      nT(       a  [        U4S jT 5       5      OUnUT-  TU-  U-  T	-  -
  $ )Nc              3   ó<   >#   • U  H  u  po2T;   d  M  Uv •  M     g 7fr'   r   )r*   ÚuÚvÚwtÚcomms       €r   r,   Ú=modularity.<locals>.community_contribution.<locals>.<genexpr>ø   s   øé € ÐXÒ%J™˜˜rÐSWÉi—"‘"Ò%Jùs   ƒ“	r$   )ÚdataÚdefaultc              3   ó.   >#   • U  H
  nTU   v •  M     g 7fr'   r   )r*   rA   Ú
out_degrees     €r   r,   rE   ú   s   øé € Ð9²D¨q˜Z¨ž]²Dùó   ƒc              3   ó.   >#   • U  H
  nTU   v •  M     g 7fr'   r   )r*   rA   Ú	in_degrees     €r   r,   rE   û   s   øé € Ð7²$¨Q˜I ažL²$ùrJ   )Úsetr.   Úedges)Ú	communityÚL_cÚout_degree_sumÚin_degree_sumrD   r   ÚdirectedrL   ÚmÚnormrI   Ú
resolutionr;   s       @€€€€€€€€r   Úcommunity_contributionÚ*modularity.<locals>.community_contributionö   sm   ù€ Ü�9‹~ˆÜÔX Q§W¡W¨T¸È WÑ%JÓXÓXˆäÔ9±DÓ9Ó9ˆÞ;CœÔ7±$Ó7Ô7Èˆà�Q‰w˜ nÑ4°}ÑDÀtÑKÑKÐKr   )Ú
isinstanceÚlistr   r
   r2   ÚdictrI   rL   r.   ÚvaluesÚdegreeÚmap)r   Úcommunitiesr;   rV   Údeg_sumrW   rS   rL   rT   rU   rI   s   ` ``  @@@@@r   r   r   �   sñ   ÿ€ ôj �k¤4×(Ñ(Ü˜;Ó'ˆÜ˜˜;×'Ñ'Ü˜A˜{Ó+Ð+à�}‰}‹€HÞÜ˜!Ÿ,™,¨f˜,Ð5Ó6ˆ
Ü˜Ÿ™¨F˜Ð3Ó4ˆ	Ü�
×!Ñ!Ó#Ó$ˆØ�1�a‘4‰x‰ä!% a§h¡h°f hÐ&=Ó!>Ð>ˆ
�YÜ�j×'Ñ'Ó)Ó*ˆØ�a‰KˆØ�7˜A‘:‰~ˆ÷Lô Lô ŒsÐ)Ó7Ó8Ð8r   c                 ó"  • 0 n[        U5       H  u  p4U H  nX2U'   M	     M     U R                  5       (       d7  [        S [        US5       5       5      nU R	                  5       (       a  US-  nOSn[        U 5      nXwS-
  -  nU R	                  5       (       d  US-  nSn	Un
U R                  5        H  nX+S      X+S      :X  a  U	S-  n	M  U
S-  n
M!     U	[        U R                  5      -  nU R                  5       (       a  SnXÍ4$ Xš-   U-  nXÍ4$ )aÏ  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   óT   #   • U  H  u  p[        U5      [        U5      -  v •  M      g 7fr'   )Úlen)r*   Úp1Úp2s      r   r,   Ú$partition_quality.<locals>.<genexpr>:  s#   é € ð -
Ú,F¡& "ŒC�‹G”c˜"“gÖÒ,Fùs   ‚&(r>   r   r$   g      ð¿)Ú	enumerateÚis_multigraphr.   r   r2   rc   rN   )r   r"   Únode_communityÚirO   ÚnodeÚpossible_inter_community_edgesÚnÚtotal_pairsr/   r:   ÚeÚcoverageÚperformances                 r   r   r     s8  € ð` €NÜ! )Ö,‰ˆÛˆDØ#$˜4Ó ó ñ -ð
 �?‰?×Ñä),ñ -
Ü,8¸ÀAÔ,Fó-
ó *
Ð&ð �=‰=�?‰?Ø*¨aÑ/Ð*øà)*Ð&ô 	ˆA‹€AØ˜1‘u‘+€KØ�=‰=�?‰?Ø˜ÑˆàÐØ >Ðð �W‰WŽYˆØ˜A™$Ñ >°A±$Ñ#7Ó7Ø! QÑ&Ò!à%¨Ñ*Ò%ñ	 ð %¤s¨1¯7©7£|Ñ3€Hà‡�×ÑØˆð Ð Ð ð -ÑHÈKÑWˆàÐ Ð r   )r;   r$   )r   Ú	itertoolsr   Únetworkxr    r   Ú-networkx.algorithms.community.community_utilsr   Únetworkx.utils.decoratorsr   Ú__all__r
   r#   Úrequire_partitionÚ_dispatchabler/   r7   r:   r   r   r   r   r   Ú<module>ry      sâ   ðñõ
 #ã Ý "Ý FÝ ,àÐ,Ð
-€ô�Mô òUñD Ð-¨vÓ6Ð ð ×Ññ@ó ð@ð" ×ÑñCó ðCð> ×Ññ>ó ð>ð@ ×Ò˜XÑ&ón9ó 'ðn9ðb Ø×ÑñW!ó ó ñW!r   