1"""
2Communicability.
3"""
4
5import networkx as nx
6from networkx.utils import not_implemented_for
7
8__all__ = ["communicability", "communicability_exp"]
9
10
11@not_implemented_for("directed")
12@not_implemented_for("multigraph")
13@nx._dispatchable
14def communicability(G):
15 r"""Returns communicability between all pairs of nodes in G.
16
17 The communicability between pairs of nodes in G is the sum of
18 walks of different lengths starting at node u and ending at node v.
19
20 Parameters
21 ----------
22 G: graph
23
24 Returns
25 -------
26 comm: dictionary of dictionaries
27 Dictionary of dictionaries keyed by nodes with communicability
28 as the value.
29
30 Raises
31 ------
32 NetworkXError
33 If the graph is not undirected and simple.
34
35 See Also
36 --------
37 communicability_exp:
38 Communicability between all pairs of nodes in G using spectral
39 decomposition.
40 communicability_betweenness_centrality:
41 Communicability betweenness centrality for each node in G.
42
43 Notes
44 -----
45 This algorithm uses a spectral decomposition of the adjacency matrix.
46 Let G=(V,E) be a simple undirected graph. Using the connection between
47 the powers of the adjacency matrix and the number of walks in the graph,
48 the communicability between nodes `u` and `v` based on the graph spectrum
49 is [1]_
50
51 .. math::
52 C(u,v)=\sum_{j=1}^{n}\phi_{j}(u)\phi_{j}(v)e^{\lambda_{j}},
53
54 where `\phi_{j}(u)` is the `u\rm{th}` element of the `j\rm{th}` orthonormal
55 eigenvector of the adjacency matrix associated with the eigenvalue
56 `\lambda_{j}`.
57
58 References
59 ----------
60 .. [1] Ernesto Estrada, Naomichi Hatano,
61 "Communicability in complex networks",
62 Phys. Rev. E 77, 036111 (2008).
63 https://arxiv.org/abs/0707.0756
64
65 Examples
66 --------
67 >>> G = nx.Graph([(0, 1), (1, 2), (1, 5), (5, 4), (2, 4), (2, 3), (4, 3), (3, 6)])
68 >>> c = nx.communicability(G)
69 """
70 import numpy as np
71
72 nodelist = list(G) # ordering of nodes in matrix
73 A = nx.to_numpy_array(G, nodelist)
74 # convert to 0-1 matrix
75 A[A != 0.0] = 1
76 w, vec = np.linalg.eigh(A)
77 expw = np.exp(w)
78 mapping = dict(zip(nodelist, range(len(nodelist))))
79 c = {}
80 # computing communicabilities
81 for u in G:
82 c[u] = {}
83 for v in G:
84 s = 0
85 p = mapping[u]
86 q = mapping[v]
87 for j in range(len(nodelist)):
88 s += vec[:, j][p] * vec[:, j][q] * expw[j]
89 c[u][v] = float(s)
90 return c
91
92
93@not_implemented_for("directed")
94@not_implemented_for("multigraph")
95@nx._dispatchable
96def communicability_exp(G):
97 r"""Returns communicability between all pairs of nodes in G.
98
99 Communicability between pair of node (u,v) of node in G is the sum of
100 walks of different lengths starting at node u and ending at node v.
101
102 Parameters
103 ----------
104 G: graph
105
106 Returns
107 -------
108 comm: dictionary of dictionaries
109 Dictionary of dictionaries keyed by nodes with communicability
110 as the value.
111
112 Raises
113 ------
114 NetworkXError
115 If the graph is not undirected and simple.
116
117 See Also
118 --------
119 communicability:
120 Communicability between pairs of nodes in G.
121 communicability_betweenness_centrality:
122 Communicability betweenness centrality for each node in G.
123
124 Notes
125 -----
126 This algorithm uses matrix exponentiation of the adjacency matrix.
127
128 Let G=(V,E) be a simple undirected graph. Using the connection between
129 the powers of the adjacency matrix and the number of walks in the graph,
130 the communicability between nodes u and v is [1]_,
131
132 .. math::
133 C(u,v) = (e^A)_{uv},
134
135 where `A` is the adjacency matrix of G.
136
137 References
138 ----------
139 .. [1] Ernesto Estrada, Naomichi Hatano,
140 "Communicability in complex networks",
141 Phys. Rev. E 77, 036111 (2008).
142 https://arxiv.org/abs/0707.0756
143
144 Examples
145 --------
146 >>> G = nx.Graph([(0, 1), (1, 2), (1, 5), (5, 4), (2, 4), (2, 3), (4, 3), (3, 6)])
147 >>> c = nx.communicability_exp(G)
148 """
149 import scipy as sp
150
151 nodelist = list(G) # ordering of nodes in matrix
152 A = nx.to_numpy_array(G, nodelist)
153 # convert to 0-1 matrix
154 A[A != 0.0] = 1
155 # communicability matrix
156 expA = sp.linalg.expm(A)
157 mapping = dict(zip(nodelist, range(len(nodelist))))
158 c = {}
159 for u in G:
160 c[u] = {}
161 for v in G:
162 c[u][v] = float(expA[mapping[u], mapping[v]])
163 return c