percolation.py 4.0 KB

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