1"""
2Spectral bipartivity measure.
3"""
4
5import networkx as nx
6
7__all__ = ["spectral_bipartivity"]
8
9
10@nx._dispatchable(edge_attrs="weight")
11def spectral_bipartivity(G, nodes=None, weight="weight"):
12 """Returns the spectral bipartivity.
13
14 Parameters
15 ----------
16 G : NetworkX graph
17
18 nodes : list or container optional(default is all nodes)
19 Nodes to return value of spectral bipartivity contribution.
20
21 weight : string or None optional (default = 'weight')
22 Edge data key to use for edge weights. If None, weights set to 1.
23
24 Returns
25 -------
26 sb : float or dict
27 A single number if the keyword nodes is not specified, or
28 a dictionary keyed by node with the spectral bipartivity contribution
29 of that node as the value.
30
31 Examples
32 --------
33 >>> from networkx.algorithms import bipartite
34 >>> G = nx.path_graph(4)
35 >>> bipartite.spectral_bipartivity(G)
36 1.0
37
38 Notes
39 -----
40 This implementation uses Numpy (dense) matrices which are not efficient
41 for storing large sparse graphs.
42
43 See Also
44 --------
45 color
46
47 References
48 ----------
49 .. [1] E. Estrada and J. A. Rodríguez-Velázquez, "Spectral measures of
50 bipartivity in complex networks", PhysRev E 72, 046105 (2005)
51 """
52 import scipy as sp
53
54 nodelist = list(G) # ordering of nodes in matrix
55 A = nx.to_numpy_array(G, nodelist, weight=weight)
56 expA = sp.linalg.expm(A)
57 expmA = sp.linalg.expm(-A)
58 coshA = 0.5 * (expA + expmA)
59 if nodes is None:
60 # return single number for entire graph
61 return float(coshA.diagonal().sum() / expA.diagonal().sum())
62 else:
63 # contribution for individual nodes
64 index = dict(zip(nodelist, range(len(nodelist))))
65 sb = {}
66 for n in nodes:
67 i = index[n]
68 sb[n] = coshA.item(i, i) / expA.item(i, i)
69 return sb