Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/networkx/algorithms/reciprocity.py: 32%

34 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-10-20 07:00 +0000

1"""Algorithms to calculate reciprocity in a directed graph.""" 

2import networkx as nx 

3from networkx import NetworkXError 

4 

5from ..utils import not_implemented_for 

6 

7__all__ = ["reciprocity", "overall_reciprocity"] 

8 

9 

10@not_implemented_for("undirected", "multigraph") 

11@nx._dispatch 

12def reciprocity(G, nodes=None): 

13 r"""Compute the reciprocity in a directed graph. 

14 

15 The reciprocity of a directed graph is defined as the ratio 

16 of the number of edges pointing in both directions to the total 

17 number of edges in the graph. 

18 Formally, $r = |{(u,v) \in G|(v,u) \in G}| / |{(u,v) \in G}|$. 

19 

20 The reciprocity of a single node u is defined similarly, 

21 it is the ratio of the number of edges in both directions to 

22 the total number of edges attached to node u. 

23 

24 Parameters 

25 ---------- 

26 G : graph 

27 A networkx directed graph 

28 nodes : container of nodes, optional (default=whole graph) 

29 Compute reciprocity for nodes in this container. 

30 

31 Returns 

32 ------- 

33 out : dictionary 

34 Reciprocity keyed by node label. 

35 

36 Notes 

37 ----- 

38 The reciprocity is not defined for isolated nodes. 

39 In such cases this function will return None. 

40 

41 """ 

42 # If `nodes` is not specified, calculate the reciprocity of the graph. 

43 if nodes is None: 

44 return overall_reciprocity(G) 

45 

46 # If `nodes` represents a single node in the graph, return only its 

47 # reciprocity. 

48 if nodes in G: 

49 reciprocity = next(_reciprocity_iter(G, nodes))[1] 

50 if reciprocity is None: 

51 raise NetworkXError("Not defined for isolated nodes.") 

52 else: 

53 return reciprocity 

54 

55 # Otherwise, `nodes` represents an iterable of nodes, so return a 

56 # dictionary mapping node to its reciprocity. 

57 return dict(_reciprocity_iter(G, nodes)) 

58 

59 

60def _reciprocity_iter(G, nodes): 

61 """Return an iterator of (node, reciprocity).""" 

62 n = G.nbunch_iter(nodes) 

63 for node in n: 

64 pred = set(G.predecessors(node)) 

65 succ = set(G.successors(node)) 

66 overlap = pred & succ 

67 n_total = len(pred) + len(succ) 

68 

69 # Reciprocity is not defined for isolated nodes. 

70 # Return None. 

71 if n_total == 0: 

72 yield (node, None) 

73 else: 

74 reciprocity = 2 * len(overlap) / n_total 

75 yield (node, reciprocity) 

76 

77 

78@not_implemented_for("undirected", "multigraph") 

79@nx._dispatch 

80def overall_reciprocity(G): 

81 """Compute the reciprocity for the whole graph. 

82 

83 See the doc of reciprocity for the definition. 

84 

85 Parameters 

86 ---------- 

87 G : graph 

88 A networkx graph 

89 

90 """ 

91 n_all_edge = G.number_of_edges() 

92 n_overlap_edge = (n_all_edge - G.to_undirected().number_of_edges()) * 2 

93 

94 if n_all_edge == 0: 

95 raise NetworkXError("Not defined for empty graphs") 

96 

97 return n_overlap_edge / n_all_edge