(
    graph: nx.Graph,
    r: Optional[np.ndarray] = None,
    lambda_: float = 0.5,
    alpha: float = 0.5,
)
return divranks
Rank nodes in a network using the DivRank algorithm that attempts to
    balance between node centrality and diversity.

    Args:
        graph
        r: The "personalization vector"; by default, ``r = ones(1, n)/n``
        lambda_: Float in [0.0, 1.0]
        alpha: Float in [0.0, 1.0] that controls the strength of self-links.

    Returns:
        Mapping of node to score ordered by descending divrank score

    References:
        Mei, Q., Guo, J., & Radev, D. (2010, July). Divrank: the interplay of
        prestige and diversity in information networks. In Proceedings of the
        16th ACM SIGKDD international conference on Knowledge discovery and data
        mining (pp. 1009-1018). ACM.
        http://clair.si.umich.edu/~radev/papers/SIGKDD2010.pdf
Rank nodes in a network using the DivRank algorithm that attempts to
    balance between node centrality and diversity.
Rank nodes in a network using the DivRank algorithm that attempts to balance between node centrality and diversity .
def rank_nodes_by_divrank(
    graph: nx.Graph,
    r: Optional[np.ndarray] = None,
    lambda_: float = 0.5,
    alpha: float = 0.5,
) -> Dict[str, float]:
    """
    Rank nodes in a network using the DivRank algorithm that attempts to
    balance between node centrality and diversity.

    Args:
        graph
        r: The "personalization vector"; by default, ``r = ones(1, n)/n``
        lambda_: Float in [0.0, 1.0]
        alpha: Float in [0.0, 1.0] that controls the strength of self-links.

    Returns:
        Mapping of node to score ordered by descending divrank score

    References:
        Mei, Q., Guo, J., & Radev, D. (2010, July). Divrank: the interplay of
        prestige and diversity in information networks. In Proceedings of the
        16th ACM SIGKDD international conference on Knowledge discovery and data
        mining (pp. 1009-1018). ACM.
        http://clair.si.umich.edu/~radev/papers/SIGKDD2010.pdf
    """
    # check function arguments
    if len(graph) == 0:
        LOGGER.warning("`graph` is empty")
        return {}

    # specify the order of nodes to use in creating the matrix
    # and then later recovering the values from the order index
    nodes_list = [node for node in graph]
    # create adjacency matrix, i.e.
    # n x n matrix where entry W_ij is the weight of the edge from V_i to V_j
    W = nx.to_numpy_matrix(graph, nodelist=nodes_list, weight="weight").A
    n = W.shape[1]
    # create flat prior personalization vector if none given
    if r is None:
        r = np.array([n * [1 / float(n)]])
    # Specify some constants
    max_iter = 1000
    diff = 1e10
    tol = 1e-3
    pr = np.array([n * [1 / float(n)]])
    # Get p0(v -> u), i.e. transition probability prior to reinforcement
    tmp = np.reshape(np.sum(W, axis=1), (n, 1))
    idx_nan = np.flatnonzero(tmp == 0)
    W0 = W / np.tile(tmp, (1, n))
    W0[idx_nan, :] = 0
    del W

    # DivRank algorithm
    i = 0
    while i < max_iter and diff > tol:
        W1 = alpha * W0 * np.tile(pr, (n, 1))
        W1 = W1 - np.diag(W1[:, 0]) + (1 - alpha) * np.diag(pr[0, :])
        tmp1 = np.reshape(np.sum(W1, axis=1), (n, 1))
        P = W1 / np.tile(tmp1, (1, n))
        P = ((1 - lambda_) * P) + (lambda_ * np.tile(r, (n, 1)))
        pr_new = np.dot(pr, P)
        i += 1
        diff = np.sum(np.abs(pr_new - pr)) / np.sum(pr)
        pr = pr_new

    # sort nodes by divrank score
    results = sorted(
        ((i, score) for i, score in enumerate(pr.flatten().tolist())),
        key=itemgetter(1),
        reverse=True,
    )

    # replace node number by node value
    divranks = {nodes_list[result[0]]: result[1] for result in results}

    return divranks
def rank_nodes_by_divrank ( graph : nx . Graph , r : Optional [ np . ndarray ] = None , lambda_ : float = 0.5 , alpha : float = 0.5 , ) -> Dict [ str , float ] : # check function arguments if len ( graph ) == 0 : LOGGER . warning ( "`graph` is empty" ) return { } # specify the order of nodes to use in creating the matrix # and then later recovering the values from the order index nodes_list = [ node for node in graph ] # create adjacency matrix, i.e. # n x n matrix where entry W_ij is the weight of the edge from V_i to V_j W = nx . to_numpy_matrix ( graph , nodelist = nodes_list , weight = "weight" ) . A n = W . shape [ 1 ] # create flat prior personalization vector if none given if r is None : r = np . array ( [ n * [ 1 / float ( n ) ] ] ) # Specify some constants max_iter = 1000 diff = 1e10 tol = 1e-3 pr = np . array ( [ n * [ 1 / float ( n ) ] ] ) # Get p0(v -> u), i.e. transition probability prior to reinforcement tmp = np . reshape ( np . sum ( W , axis = 1 ) , ( n , 1 ) ) idx_nan = np . flatnonzero ( tmp == 0 ) W0 = W / np . tile ( tmp , ( 1 , n ) ) W0 [ idx_nan , : ] = 0 del W # DivRank algorithm i = 0 while i < max_iter and diff > tol : W1 = alpha * W0 * np . tile ( pr , ( n , 1 ) ) W1 = W1 - np . diag ( W1 [ : , 0 ] ) + ( 1 - alpha ) * np . diag ( pr [ 0 , : ] ) tmp1 = np . reshape ( np . sum ( W1 , axis = 1 ) , ( n , 1 ) ) P = W1 / np . tile ( tmp1 , ( 1 , n ) ) P = ( ( 1 - lambda_ ) * P ) + ( lambda_ * np . tile ( r , ( n , 1 ) ) ) pr_new = np . dot ( pr , P ) i += 1 diff = np . sum ( np . abs ( pr_new - pr ) ) / np . sum ( pr ) pr = pr_new # sort nodes by divrank score results = sorted ( ( ( i , score ) for i , score in enumerate ( pr . flatten ( ) . tolist ( ) ) ) , key = itemgetter ( 1 ) , reverse = True , ) # replace node number by node value divranks = { nodes_list [ result [ 0 ] ] : result [ 1 ] for result in results } return divranks