percolation.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. """Percolation centrality measures."""
  2. import networkx as nx
  3. from networkx.algorithms.centrality.betweenness import (
  4. _single_source_dijkstra_path_basic as dijkstra,
  5. )
  6. from networkx.algorithms.centrality.betweenness import (
  7. _single_source_shortest_path_basic as shortest_path,
  8. )
  9. __all__ = ["percolation_centrality"]
  10. @nx._dispatchable(node_attrs="attribute", edge_attrs="weight")
  11. def percolation_centrality(G, attribute="percolation", states=None, weight=None):
  12. r"""Compute the percolation centrality for nodes.
  13. Percolation centrality of a node $v$, at a given time, is defined
  14. as the proportion of ‘percolated paths’ that go through that node.
  15. This measure quantifies relative impact of nodes based on their
  16. topological connectivity, as well as their percolation states.
  17. Percolation states of nodes are used to depict network percolation
  18. scenarios (such as during infection transmission in a social network
  19. of individuals, spreading of computer viruses on computer networks, or
  20. transmission of disease over a network of towns) over time. In this
  21. measure usually the percolation state is expressed as a decimal
  22. between 0.0 and 1.0.
  23. When all nodes are in the same percolated state this measure is
  24. equivalent to betweenness centrality.
  25. Parameters
  26. ----------
  27. G : graph
  28. A NetworkX graph.
  29. attribute : None or string, optional (default='percolation')
  30. Name of the node attribute to use for percolation state, used
  31. if `states` is None. If a node does not set the attribute the
  32. state of that node will be set to the default value of 1.
  33. If all nodes do not have the attribute all nodes will be set to
  34. 1 and the centrality measure will be equivalent to betweenness centrality.
  35. states : None or dict, optional (default=None)
  36. Specify percolation states for the nodes, nodes as keys states
  37. as values.
  38. weight : None or string, optional (default=None)
  39. If None, all edge weights are considered equal.
  40. Otherwise holds the name of the edge attribute used as weight.
  41. The weight of an edge is treated as the length or distance between the two sides.
  42. Returns
  43. -------
  44. nodes : dictionary
  45. Dictionary of nodes with percolation centrality as the value.
  46. See Also
  47. --------
  48. betweenness_centrality
  49. Notes
  50. -----
  51. The algorithm is from Mahendra Piraveenan, Mikhail Prokopenko, and
  52. Liaquat Hossain [1]_
  53. Pair dependencies are calculated and accumulated using [2]_
  54. For weighted graphs the edge weights must be greater than zero.
  55. Zero edge weights can produce an infinite number of equal length
  56. paths between pairs of nodes.
  57. References
  58. ----------
  59. .. [1] Mahendra Piraveenan, Mikhail Prokopenko, Liaquat Hossain
  60. Percolation Centrality: Quantifying Graph-Theoretic Impact of Nodes
  61. during Percolation in Networks
  62. http://journals.plos.org/plosone/article?id=10.1371/journal.pone.0053095
  63. .. [2] Ulrik Brandes:
  64. A Faster Algorithm for Betweenness Centrality.
  65. Journal of Mathematical Sociology 25(2):163-177, 2001.
  66. https://doi.org/10.1080/0022250X.2001.9990249
  67. """
  68. percolation = dict.fromkeys(G, 0.0) # b[v]=0 for v in G
  69. nodes = G
  70. if states is None:
  71. states = nx.get_node_attributes(nodes, attribute, default=1)
  72. # sum of all percolation states
  73. p_sigma_x_t = 0.0
  74. for v in states.values():
  75. p_sigma_x_t += v
  76. for s in nodes:
  77. # single source shortest paths
  78. if weight is None: # use BFS
  79. S, P, sigma, _ = shortest_path(G, s)
  80. else: # use Dijkstra's algorithm
  81. S, P, sigma, _ = dijkstra(G, s, weight)
  82. # accumulation
  83. percolation = _accumulate_percolation(
  84. percolation, S, P, sigma, s, states, p_sigma_x_t
  85. )
  86. n = len(G)
  87. for v in percolation:
  88. percolation[v] *= 1 / (n - 2)
  89. return percolation
  90. def _accumulate_percolation(percolation, S, P, sigma, s, states, p_sigma_x_t):
  91. delta = dict.fromkeys(S, 0)
  92. while S:
  93. w = S.pop()
  94. coeff = (1 + delta[w]) / sigma[w]
  95. for v in P[w]:
  96. delta[v] += sigma[v] * coeff
  97. if w != s:
  98. # percolation weight
  99. pw_s_w = states[s] / (p_sigma_x_t - states[w])
  100. percolation[w] += delta[w] * pw_s_w
  101. return percolation