+
    �°³j‚%  ã                   ó¨   € R t ^ RIt^ RIHt ^ RIHt ^ RIHt R.t	]! R4      ]P                  ! RRR	7      RRR
^/R l4       4       tRRRRR/R lltR# )z?Community detection and quality functions for bipartite graphs.N)Úis_partition)ÚNotAPartition)Únot_implemented_forÚ
modularityÚdirectedÚbipartite_modularityÚweight)ÚnameÚ
edge_attrsÚ
resolutionc               ó¢  a aaaaaaa	a
€ \        V\        4      '       g   \        V4      p\        S V4      '       g   \        S V4      h\	        V4      o
\	        S 4      S
,
          o\        S P                  SR7      4      o\        V3R lS
 4       4      oS^ 8X  d   R# ^S^,          ,          o	V VVVV	V
VV3R lo\        V3R lV 4       4      # )a×  Returns Barber's bipartite modularity of the given partition.

Bipartite modularity [1]_ adapts Newman's modularity to bipartite
networks by replacing the configuration-model null model with one
that respects the bipartite structure: expected edges only occur
between the two node sets. For a bipartite graph with "red" nodes
(one set) and "blue" nodes (the other), it is defined as

.. math::

    Q_B = \frac{1}{m} \sum_{v=1}^{r} \sum_{w=1}^{c}
          \left( \tilde{A}_{vw} - \gamma\frac{k_v d_w}{m} \right)
          \delta(c_v, c_w)

where $m$ is the (weighted) number of edges, $\tilde{A}$ is the
bipartite adjacency matrix, $k_v$ is the (weighted) degree of red
node $v$, $d_w$ is the (weighted) degree of blue node $w$, $\gamma$
is the resolution parameter, and $\delta(c_v, c_w)$ is 1 if $v$ and
$w$ are in the same community, else 0.

Following Clauset, Newman and Moore [2]_, this can be rewritten as a
sum over communities:

.. math::

    Q_B = \sum_{c=1}^{n}
          \left[ \frac{L_c}{m} - \gamma\,\frac{k_c d_c}{m^2} \right]

where $L_c$ is the (weighted) number of intra-community edges for
community $c$, $k_c$ is the sum of degrees of the red nodes in $c$,
and $d_c$ is the sum of degrees of the blue nodes in $c$. This is
the form used in the implementation.

Note the structural analogy with the standard (unipartite) sum
formulation `L_c/m - gamma * (k_c / 2m)^2`: the null-model term is
a product of two degree sums, and in the undirected unipartite case
those two sums coincide so the product becomes a square. In the
bipartite case the sums differ (red vs. blue), so the null model
term remains a product of two distinct terms.

Communities in a bipartite modularity partition may contain nodes
from both bipartite sets; the bipartite structure enters only
through the null model.

Parameters
----------
G : NetworkX Graph
    An undirected bipartite graph.

communities : list or iterable of sets of nodes
    These node sets must represent a partition of `G`'s nodes.
    Communities may contain nodes from both bipartite sets.

nodes : container of nodes
    A container with all nodes in **one** bipartite node set (the
    "red" nodes). The other set is inferred as ``set(G) - set(nodes)``.
    This follows the convention used throughout the bipartite
    subpackage.

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

resolution : float (default=1)
    Resolution parameter $\gamma$. With the default ``resolution=1``,
    $Q_B$ reduces to Barber's original definition. Values smaller
    than 1 favor larger communities; values greater than 1 favor
    smaller communities. The resolution parameter is not part of
    Barber's original definition, but a standard extension
    consistent with :func:`networkx.community.modularity`.

Returns
-------
Q_B : float
    The bipartite modularity of the partition.

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

NetworkXNotImplemented
    If `G` is directed. Barber's formulation is for undirected
    bipartite graphs.

Examples
--------
Two disconnected :math:`K_{2,2}` components form a strong bipartite
community structure:

>>> G = nx.Graph([(0, 2), (1, 3)])
>>> red = {0, 1}
>>> nx.bipartite.modularity(G, [{0, 2}, {1, 3}], red)
0.5

Notes
-----
The functions in the bipartite package do not check that `nodes` is
actually one side of a bipartition of `G`. It is the caller's
responsibility to provide a valid bipartite graph and a valid
bipartite node set.

See Also
--------
modularity

References
----------
.. [1] Barber, M. J. (2007). "Modularity and community detection in
   bipartite networks." Physical Review E, 76(6), 066102.
   https://doi.org/10.1103/PhysRevE.76.066102
.. [2] Clauset, A., Newman, M. E. J., and Moore, C. (2004).
   "Finding community structure in very large networks."
   Physical Review E, 70(6), 066111.
©r   c              3   ó6   <"  € T F  pSV,          x € K  	  R # 5i©N© )Ú.0ÚvÚdegrees   & €Úh/home/luca/screen-checking/.venv/lib/python3.14/site-packages/networkx/algorithms/bipartite/community.pyÚ	<genexpr>Úmodularity.<locals>.<genexpr>�   s   øé € Ð#™s˜!ˆF�1�IŠI›sùó   ƒg        c           	      ó$  <a€ \        V 4      o\        V3R  lSP                  SS^R7       4       4      p\        V3R lSS
,           4       4      p\        V3R lSS,           4       4      pVS,          SV,          V,          S	,          ,
          # )c              3   ó>   <"  € T F  w  rq2S9   g   K  Vx € K  	  R # 5ir   r   )r   Ú_r   ÚwtÚcomms   &   €r   r   Ú=modularity.<locals>.community_contribution.<locals>.<genexpr>›   s   øé € ÐXÑ%J™˜˜rÐSWÉi—"’"Ó%Jùs   ƒ“
©ÚdataÚdefaultc              3   ó6   <"  € T F  pSV,          x € K  	  R # 5ir   r   ©r   Úur   s   & €r   r   r   �   s   øé € Ð0¡Z �&˜—)’)£Zùr   c              3   ó6   <"  € T F  pSV,          x € K  	  R # 5ir   r   r"   s   & €r   r   r   ž   s   øé € Ð1¡[ �&˜—)’)£[ùr   )ÚsetÚsumÚedges)Ú	communityÚL_cÚk_cÚd_cr   ÚGÚbluer   ÚmÚnormÚredr   r   s   &   @€€€€€€€€r   Úcommunity_contributionÚ*modularity.<locals>.community_contribution”   ss   ù€ Ü�9‹~ˆô ÔX Q§W¡W¨T¸È WÔ%JÓXÓXˆäÔ0 T¨C¦ZÓ0Ó0ˆÜÔ1 T¨D¦[Ó1Ó1ˆà�Q�w˜ cÕ)¨CÕ/°$Õ6Õ6Ð6ó    c              3   ó4   <"  € T F  pS! V4      x € K  	  R # 5ir   r   )r   Úcr1   s   & €r   r   r   ¢   s   øé € Ð>±+¨QÑ% a×(Ð(³+ùs   ƒ)Ú
isinstanceÚlistr   r   r%   Údictr   r&   )r,   ÚcommunitiesÚnodesr   r   r-   r1   r   r.   r/   r0   s   f&&dd@@@@@@r   r   r      s©   ÿø€ ôn �k¤4×(Ò(Ü˜;Ó'ˆÜ˜˜;×'Ò'Ü˜A˜{Ó+Ð+ä
ˆe‹*€CÜˆq‹6�C�<€Dä�!—(‘( &�(Ó)Ó*€Fô 	Ô#™sÓ#Ó#€AàˆA„vÙàˆq�!�t�8€D÷7ô 7ô Ô>±+Ó>Ó>Ð>r3   Úred_degree_attrÚ
red_degreeÚblue_degree_attrÚblue_degreec          	     óŒ  aaaa€ V P                   o\        VV3R lV 4       4      p\        VV3R lV 4       4      p	\        VV3R lS 4       4      p
\        VV3R lS 4       4      p\        V3R lV P                  W^R7       4       4      pWÇ,          W8V,          W©,          ,           ,          V^,          ,          ,
          # )a	  Change in bipartite modularity from merging two disjoint communities.

Computes ``Q_B(P') - Q_B(P)`` where P contains `community_a` and
`community_b` as separate communities and P' is obtained by replacing
them with their union ``community_a U community_b``.

For bipartite modularity ``Q_B = sum_c [L_c/m - gamma k_c d_c / m^2]``,
the merge delta has the closed form

    merge_delta = E(A, B) / m - gamma * (k_A d_B + k_B d_A) / m^2

where ``E(A, B)`` is the sum of edge weights between A and B,
``k_C`` is the sum of the "red" degrees of nodes in C, and ``d_C``
is the sum of the "blue" degrees of nodes in C.

**Attribute-based interface.** Rather than identifying each node
with a single bipartite side (which breaks once Louvain/Leiden has
aggregated communities into super-nodes that mix both colors), this
helper reads per-node ``red_degree_attr`` and ``blue_degree_attr``
attributes. On the original bipartite graph a red node has
``red_degree = G.degree(v)`` and ``blue_degree = 0`` (and vice
versa). On an aggregated graph each super-node carries the sums
of both attributes over its constituent nodes; both may be
nonzero. This is the same pattern used for directed modularity
(in-degree / out-degree tracked as separate attributes).

`community_a` and `community_b` must be disjoint and non-empty.
Self-loops are tolerated: on the original graph they are absent by
the bipartite convention, and on aggregated graphs they represent
intra-community edges which are not part of ``E(A, B)`` and are
correctly excluded by the ``v in community_b`` filter below.

Parameters
----------
G : NetworkX Graph
    A graph whose nodes carry the red/blue degree attributes. May
    be an original bipartite graph or an aggregated graph produced
    by a multilevel optimizer.
community_a, community_b : set
    Two disjoint communities to merge.
resolution : float
    Resolution parameter gamma.
weight : str or None
    Edge weight attribute.
red_degree_attr : str
    Keyword-only. Name of the node attribute holding the
    "red-side" contribution to the node's degree.
blue_degree_attr : str
    Keyword-only. Name of the node attribute holding the
    "blue-side" contribution to the node's degree.
m : float
    Keyword-only. Total (weighted) edge count, a graph-level
    invariant preserved across aggregation.
c              3   óV   <"  € T F  pSV,          P                  S^ 4      x € K   	  R# 5i©é    N©Úget©r   r   r:   r;   s   & €€r   r   Ú4_bipartite_modularity_merge_delta.<locals>.<genexpr>è   ó#   øé € ÐD¹°1ˆe�A�h�l‰l˜?¨A×.Ð.»ùó   ƒ&)c              3   óV   <"  € T F  pSV,          P                  S^ 4      x € K   	  R# 5irA   rC   ©r   r   r=   r:   s   & €€r   r   rF   é   ó$   øé € ÐE¹°Aˆe�A�h�l‰lÐ+¨Q×/Ð/»ùrH   c              3   óV   <"  € T F  pSV,          P                  S^ 4      x € K   	  R# 5irA   rC   rE   s   & €€r   r   rF   ê   rG   rH   c              3   óV   <"  € T F  pSV,          P                  S^ 4      x € K   	  R# 5irA   rC   rJ   s   & €€r   r   rF   ë   rK   rH   c              3   ó@   <"  € T F  w  rpVS9   g   K  Vx € K  	  R # 5ir   r   )r   r   r   r   Úcommunity_bs   &   €r   r   rF   ñ   s&   øé € ð áD‰HˆA�"Ø�Ñ÷ 	ŠÛDùs   ƒ”
r   )r:   r&   r'   )r,   Úcommunity_arO   r   r   r;   r=   r.   Úk_aÚd_aÚk_bÚd_bÚE_crossr:   s   &&f&&dd$     @r   Ú!_bipartite_modularity_merge_deltarV   ¥   s›   û€ ðD �G‰G€EÜ
ÕD¹ÓDÓ
D€CÜ
ÕE¹ÓEÓ
E€CÜ
ÕD¹ÓDÓ
D€CÜ
ÕE¹ÓEÓ
E€Cô ô àŸ™ À!˜ÔDóó €Gð �;˜¨S¥y°3µ9Õ'<Õ=ÀÀ1ÅÕDÕDÐDr3   r   )Ú__doc__ÚnetworkxÚnxÚ-networkx.algorithms.community.community_utilsr   Ú%networkx.algorithms.community.qualityr   Únetworkx.utils.decoratorsr   Ú__all__Ú_dispatchabler   rV   r   r3   r   Ú<module>r_      s}   ðÙ Eã Ý FÝ ?Ý 9àˆ.€ñ �ZÓ Ø×ÒÐ-¸(ÔCðU?°ð U?ÀQó U?ó Dó !ðU?ñpREð !ðREð #÷REr3   