code: 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
      try:
          # networkx < 3.0
          W = nx.to_numpy_matrix(
              graph, nodelist=nodes_list, weight="weight"
          ).A
      except AttributeError:
          # networkx >= 3.0
          W = nx.adjacency_matrix(
              graph, nodelist=nodes_list, weight="weight"
          ).toarray()
      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
  
file_path: textacy/src/textacy/representations/network.py
imports: from __future__ import annotations
  import collections
  import itertools
  import logging
  from operator import itemgetter
  from typing import Any, Collection, Literal, Optional, Sequence, Union
  import networkx
  import numpy
  from cytoolz import itertoolz
  from ..None import errors, similarity
label_desc: Use image node_id 5 for calling a global function with example usage: rank_nodes_by_divrank(graph, r, lambda_, alpha) and returns: divranks, dict