
    sh1              	       `    S SK r S SKrS/r\R                  " SS9SSSSSSSS.S j5       rS	 rg)
    Nbirankweight)
edge_attrsd   gư>)alphabetatop_personalizationbottom_personalizationmax_itertolr   c                   SSK n	SSKn
[        U5      n[        U 5      U-
  n[        U5      n[        U5      nUS:X  d  US:X  a  [        R
                  " S5      e[        U5      n[        U5      nUc  U(       a  SOSnUc  U(       a  SOSnUS:  d  US:  a  [        R
                  " S5      eUS:  d  US:  a  [        R
                  " S5      eU	R                  U Vs/ s H  oR                  US5      PM     sn[        S9nU	R                  U Vs/ s H  oR                  US5      PM     sn[        S9n[        R                  R                  XX[        S	9nUR                  S[        S
9nSUUS:H  '   U
R                  R                  SU	R                  U5      -  /S/4X4[        S9nUR                  S[        S
9nSUUS:H  '   U
R                  R                  SU	R                  U5      -  /S/4X4[        S9nUR!                  5       U-  UR!                  5       -  nUR"                  nU	R%                  U[        S9U-  nUUU-  -  SU-
  U-  -   n['        U5       GHQ  nUnUnUUU-  -  SU-
  U-  -   nUUU-  -  SU-
  U-  -   nU	R)                  UU-
  U	R+                  SU5      -  5      R                  5       nU[        U5      U-  :  a  Ms  U	R)                  UU-
  U	R+                  SU5      -  5      R                  5       nU[        U5      U-  :  a  M  US:X  aD  US:X  a>  UU	R,                  R/                  US5      -  nUU	R,                  R/                  US5      -  n[1        [3        [4        R6                  " X5      [9        [        [4        R6                  " UU5      5      5      5      s  $    [        R:                  " U5      es  snf s  snf )up  Compute the BiRank score for nodes in a bipartite network.

Given the bipartite sets $U$ and $P$, the BiRank algorithm seeks to satisfy
the following recursive relationships between the scores of nodes $j \in P$
and $i \in U$:

.. math::

    p_j = \alpha \sum_{i \in U} \frac{w_{ij}}{\sqrt{d_i}\sqrt{d_j}} u_i
    + (1 - \alpha) p_j^0

    u_i = \beta \sum_{j \in P} \frac{w_{ij}}{\sqrt{d_i}\sqrt{d_j}} p_j
    + (1 - \beta) u_i^0

where

* $p_j$ and $u_i$ are the BiRank scores of nodes $j \in P$ and $i \in U$.
* $w_{ij}$ is the weight of the edge between nodes $i \in U$ and $j \in P$
  (With a value of 0 if no edge exists).
* $d_i$ and $d_j$ are the weighted degrees of nodes $i \in U$ and $j \in P$,
  respectively.
* $p_j^0$ and $u_i^0$ are personalization values that can encode a priori
  weights for the nodes $j \in P$ and $i \in U$, respectively. Akin to the
  personalization vector used by PageRank.
* $\alpha$ and $\beta$ are damping hyperparameters applying to nodes in $P$
  and $U$ respectively. They can take values in the interval $[0, 1]$, and
  are analogous to those used by PageRank.

Below are two use cases for this algorithm.

1. Personalized Recommendation System
    Given a bipartite graph representing users and items, BiRank can be used
    as a collaborative filtering algorithm to recommend items to users.
    Previous ratings are encoded as edge weights, and the specific ratings
    of an individual user on a set of items is used as the personalization
    vector over items. See the example below for an implementation of this
    on a toy dataset provided in [1]_.

2. Popularity Prediction
    Given a bipartite graph representing user interactions with items, e.g.
    commits to a GitHub repository, BiRank can be used to predict the
    popularity of a given item. Edge weights should encode the strength of
    the interaction signal. This could be a raw count, or weighted by a time
    decay function like that specified in Eq. (15) of [1]_. The
    personalization vectors can be used to encode existing popularity
    signals, for example, the monthly download count of a repository's
    package.

Parameters
----------
G : graph
    A bipartite network

nodes : iterable of nodes
    Container with all nodes belonging to the first bipartite node set
    ('top'). The nodes in this set use the hyperparameter `alpha`, and the
    personalization dictionary `top_personalization`. The nodes in the second
    bipartite node set ('bottom') are automatically determined by taking the
    complement of 'top' with respect to the graph `G`.

alpha : float, optional (default=0.80 if top_personalization not empty, else 1)
    Damping factor for the 'top' nodes. Must be in the interval $[0, 1]$.
    Larger alpha and beta generally reduce the effect of the personalizations
    and increase the number of iterations before convergence. Choice of value
    is largely dependent on use case, and experimentation is recommended.

beta : float, optional (default=0.80 if bottom_personalization not empty, else 1)
    Damping factor for the 'bottom' nodes. Must be in the interval $[0, 1]$.
    Larger alpha and beta generally reduce the effect of the personalizations
    and increase the number of iterations before convergence. Choice of value
    is largely dependent on use case, and experimentation is recommended.

top_personalization : dict, optional (default=None)
    Dictionary keyed by nodes in 'top' to that node's personalization value.
    Unspecified nodes in 'top' will be assigned a personalization value of 0.
    Personalization values are used to encode a priori weights for a given node,
    and should be non-negative.

bottom_personalization : dict, optional (default=None)
    Dictionary keyed by nodes in 'bottom' to that node's personalization value.
    Unspecified nodes in 'bottom' will be assigned a personalization value of 0.
    Personalization values are used to encode a priori weights for a given node,
    and should be non-negative.

max_iter : int, optional (default=100)
    Maximum number of iterations in power method eigenvalue solver.

tol : float, optional (default=1.0e-6)
    Error tolerance used to check convergence in power method solver. The
    iteration will stop after a tolerance of both ``len(top) * tol`` and
    ``len(bottom) * tol`` is reached for nodes in 'top' and 'bottom'
    respectively.

weight : string or None, optional (default='weight')
    Edge data key to use as weight.

Returns
-------
birank : dictionary
    Dictionary keyed by node to that node's BiRank score.

Raises
------
NetworkXAlgorithmError
    If the parameters `alpha` or `beta` are not in the interval [0, 1],
    if either of the bipartite sets are empty, or if negative values are
    provided in the personalization dictionaries.

PowerIterationFailedConvergence
    If the algorithm fails to converge to the specified tolerance
    within the specified number of iterations of the power iteration
    method.

Examples
--------
Construct a bipartite graph with user-item ratings and use BiRank to
recommend items to a user (user 1). The example below uses the `rating`
edge attribute as the weight of the edges. The `top_personalization` vector
is used to encode the user's previous ratings on items.

Creation of graph, bipartite sets for the example.

>>> elist = [
...     ("u1", "p1", 5),
...     ("u2", "p1", 5),
...     ("u2", "p2", 4),
...     ("u3", "p1", 3),
...     ("u3", "p3", 2),
... ]
>>> G = nx.Graph()
>>> G.add_weighted_edges_from(elist, weight="rating")
>>> product_nodes = ("p1", "p2", "p3")
>>> user = "u1"

First, we create a personalization vector for the user based on on their
ratings of past items. In this case they have only rated one item (p1, with
a rating of 5) in the past.

>>> user_personalization = {
...     product: rating
...     for _, product, rating in G.edges(nbunch=user, data="rating")
... }
>>> user_personalization
{'p1': 5}

Calculate the BiRank score of all nodes in the graph, filter for the items
that the user has not rated yet, and sort the results by score.

>>> user_birank_results = nx.bipartite.birank(
...     G, product_nodes, top_personalization=user_personalization, weight="rating"
... )
>>> user_birank_results = filter(
...     lambda item: item[0][0] == "p" and user not in G.neighbors(item[0]),
...     user_birank_results.items(),
... )
>>> user_birank_results = sorted(
...     user_birank_results, key=lambda item: item[1], reverse=True
... )
>>> user_recommendations = {
...     product: round(score, 5) for product, score in user_birank_results
... }
>>> user_recommendations
{'p2': 1.44818, 'p3': 1.04811}

We find that user 1 should be recommended item p2 over item p3. This is due
to the fact that user 2 rated also rated p1 highly, while user 3 did not.
Thus user 2's tastes are inferred to be similar to user 1's, and carry more
weight in the recommendation.

See Also
--------
:func:`~networkx.algorithms.link_analysis.pagerank_alg.pagerank`
:func:`~networkx.algorithms.link_analysis.hits_alg.hits`
:func:`~networkx.algorithms.bipartite.centrality.betweenness_centrality`
:func:`~networkx.algorithms.bipartite.basic.sets`
:func:`~networkx.algorithms.bipartite.basic.is_bipartite`

Notes
-----
The `nodes` input parameter must contain all nodes in one bipartite
node set, but the dictionary returned contains all nodes from both
bipartite node sets. See :mod:`bipartite documentation
<networkx.algorithms.bipartite>` for further details on how
bipartite graphs are handled in NetworkX.

In the case a personalization dictionary is not provided for top (bottom)
`alpha` (`beta`) will default to 1. This is because a damping factor
without a non-zero entry in the personalization vector will lead to the
algorithm converging to the zero vector.

References
----------
.. [1] Xiangnan He, Ming Gao, Min-Yen Kan, and Dingxian Wang. 2017.
   BiRank: Towards Ranking on Bipartite Graphs. IEEE Trans. on Knowl.
   and Data Eng. 29, 1 (January 2017), 57–71.
   https://arxiv.org/pdf/1708.04396

r   NzRThe BiRank algorithm requires a bipartite graph with at least onenode in each set.g?   z$alpha must be in the interval [0, 1]z#beta must be in the interval [0, 1])dtype)r   r   )axisr   g      ?)shaper   )numpyscipysetlennxNetworkXAlgorithmError_clean_personalization_dictarraygetfloat	bipartitebiadjacency_matrixsumsparse	dia_arraysqrttocsrTonesrangeabsolutemaximumlinalgnormdictzip	itertoolschainmapPowerIterationFailedConvergence) Gnodesr   r   r	   r
   r   r   r   npsptopbottom	top_countbottom_countnp0u0W	p_degreesD_p	u_degreesD_uSS_Tpu_p_lastu_lasterr_uerr_ps                                    /Users/tiagomarins/Projetos/claudeai/copy_bank/venv/lib/python3.13/site-packages/networkx/algorithms/bipartite/link_analysis.pyr   r      s   f  e*CVc\FCIv;LA~*'' 
 	
 66IJ89OP }*|,s!qyEAI''(NOOax4!8''(MNN 
#>#Q**1a0#>e	LB	VDV--a3VDE	RB 	''3U'SA1E*I #Ii1n
))


	"
"	#aS)$  C
 1E*I #Ii1n
))


	"
"	#aS)*  C
 			a#))+%A
##C 		')3AA!d(b(A 8_S1WUb 00AENa$h"_, VaZ2::c6+BBCGGICFSL VaZ2::c6+BBCGGICFSL  A:$!)BIINN1a((ABIINN1a((A 	,c%A9N.OP
 	
/ 8 
,
,X
66q ?Ds   OOc                     U c  0 $ [        S U R                  5        5       5      (       a  [        R                  " S5      eU R	                  5        VVs0 s H  u  pUS:w  d  M  X_M     snn$ s  snnf )z}Filter out zero values from the personalization dictionary,
handle case where None is passed, ensure values are non-negative.c              3   *   #    U  H	  oS :  v   M     g7f)r   N ).0values     rI   	<genexpr>._clean_personalization_dict.<locals>.<genexpr>:  s     
;":19":s   z,Personalization values must be non-negative.r   )anyvaluesr   r   items)personalizationnoderN   s      rI   r   r   5  sj     	

;/"8"8":
;;;''(VWW+:+@+@+BQ+BKDeqjKDK+BQQQs   A.$A.)r,   networkxr   __all___dispatchabler   r   rL       rI   <module>rZ      sQ     * X&
 	i7 'i7X	RrY   