redundancy.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. """Node redundancy for bipartite graphs."""
  2. from itertools import combinations
  3. import networkx as nx
  4. from networkx import NetworkXError
  5. __all__ = ["node_redundancy"]
  6. @nx._dispatchable
  7. def node_redundancy(G, nodes=None):
  8. r"""Computes the node redundancy coefficients for the nodes in the bipartite
  9. graph `G`.
  10. The redundancy coefficient of a node `v` is the fraction of pairs of
  11. neighbors of `v` that are both linked to other nodes. In a one-mode
  12. projection these nodes would be linked together even if `v` were
  13. not there.
  14. More formally, for any vertex `v`, the *redundancy coefficient of `v`* is
  15. defined by
  16. .. math::
  17. rc(v) = \frac{|\{\{u, w\} \subseteq N(v),
  18. \: \exists v' \neq v,\: (v',u) \in E\:
  19. \mathrm{and}\: (v',w) \in E\}|}{ \frac{|N(v)|(|N(v)|-1)}{2}},
  20. where `N(v)` is the set of neighbors of `v` in `G` [1]_.
  21. Parameters
  22. ----------
  23. G : graph
  24. A bipartite graph
  25. nodes : list or iterable (optional)
  26. Compute redundancy for these nodes. The default is all nodes in G.
  27. Returns
  28. -------
  29. redundancy : dictionary
  30. A dictionary keyed by node with the node redundancy value.
  31. Examples
  32. --------
  33. Compute the redundancy coefficient of each node in a graph:
  34. >>> from networkx.algorithms import bipartite
  35. >>> G = nx.cycle_graph(4)
  36. >>> rc = bipartite.node_redundancy(G)
  37. >>> rc[0]
  38. 1.0
  39. Compute the average redundancy for the graph:
  40. >>> from networkx.algorithms import bipartite
  41. >>> G = nx.cycle_graph(4)
  42. >>> rc = bipartite.node_redundancy(G)
  43. >>> sum(rc.values()) / len(G)
  44. 1.0
  45. Compute the average redundancy for a set of nodes:
  46. >>> from networkx.algorithms import bipartite
  47. >>> G = nx.cycle_graph(4)
  48. >>> rc = bipartite.node_redundancy(G)
  49. >>> nodes = [0, 2]
  50. >>> sum(rc[n] for n in nodes) / len(nodes)
  51. 1.0
  52. Raises
  53. ------
  54. NetworkXError
  55. If any of the nodes in the graph (or in `nodes`, if specified) has
  56. (out-)degree less than two (which would result in division by zero,
  57. according to the definition of the redundancy coefficient).
  58. References
  59. ----------
  60. .. [1] Latapy, Matthieu, Clémence Magnien, and Nathalie Del Vecchio (2008).
  61. Basic notions for the analysis of large two-mode networks.
  62. Social Networks 30(1), 31--48.
  63. """
  64. if nodes is None:
  65. nodes = G
  66. if any(len(G[v]) < 2 for v in nodes):
  67. raise NetworkXError(
  68. "Cannot compute redundancy coefficient for a node"
  69. " that has fewer than two neighbors."
  70. )
  71. # TODO This can be trivially parallelized.
  72. return {v: _node_redundancy(G, v) for v in nodes}
  73. def _node_redundancy(G, v):
  74. """Returns the redundancy of the node `v` in the bipartite graph `G`.
  75. If `G` is a graph with `n` nodes, the redundancy of a node is the ratio
  76. of the "overlap" of `v` to the maximum possible overlap of `v`
  77. according to its degree. The overlap of `v` is the number of pairs of
  78. neighbors that have mutual neighbors themselves, other than `v`.
  79. `v` must have at least two neighbors in `G`.
  80. """
  81. n = len(G[v])
  82. overlap = sum(
  83. 1 for (u, w) in combinations(G[v], 2) if (set(G[u]) & set(G[w])) - {v}
  84. )
  85. return (2 * overlap) / (n * (n - 1))