Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/networkx/algorithms/assortativity/connectivity.py: 14%

37 statements  

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

1from collections import defaultdict 

2 

3import networkx as nx 

4 

5__all__ = ["average_degree_connectivity"] 

6 

7 

8@nx._dispatch(edge_attrs="weight") 

9def average_degree_connectivity( 

10 G, source="in+out", target="in+out", nodes=None, weight=None 

11): 

12 r"""Compute the average degree connectivity of graph. 

13 

14 The average degree connectivity is the average nearest neighbor degree of 

15 nodes with degree k. For weighted graphs, an analogous measure can 

16 be computed using the weighted average neighbors degree defined in 

17 [1]_, for a node `i`, as 

18 

19 .. math:: 

20 

21 k_{nn,i}^{w} = \frac{1}{s_i} \sum_{j \in N(i)} w_{ij} k_j 

22 

23 where `s_i` is the weighted degree of node `i`, 

24 `w_{ij}` is the weight of the edge that links `i` and `j`, 

25 and `N(i)` are the neighbors of node `i`. 

26 

27 Parameters 

28 ---------- 

29 G : NetworkX graph 

30 

31 source : "in"|"out"|"in+out" (default:"in+out") 

32 Directed graphs only. Use "in"- or "out"-degree for source node. 

33 

34 target : "in"|"out"|"in+out" (default:"in+out" 

35 Directed graphs only. Use "in"- or "out"-degree for target node. 

36 

37 nodes : list or iterable (optional) 

38 Compute neighbor connectivity for these nodes. The default is all 

39 nodes. 

40 

41 weight : string or None, optional (default=None) 

42 The edge attribute that holds the numerical value used as a weight. 

43 If None, then each edge has weight 1. 

44 

45 Returns 

46 ------- 

47 d : dict 

48 A dictionary keyed by degree k with the value of average connectivity. 

49 

50 Raises 

51 ------ 

52 NetworkXError 

53 If either `source` or `target` are not one of 'in', 

54 'out', or 'in+out'. 

55 If either `source` or `target` is passed for an undirected graph. 

56 

57 Examples 

58 -------- 

59 >>> G = nx.path_graph(4) 

60 >>> G.edges[1, 2]["weight"] = 3 

61 >>> nx.average_degree_connectivity(G) 

62 {1: 2.0, 2: 1.5} 

63 >>> nx.average_degree_connectivity(G, weight="weight") 

64 {1: 2.0, 2: 1.75} 

65 

66 See Also 

67 -------- 

68 average_neighbor_degree 

69 

70 References 

71 ---------- 

72 .. [1] A. Barrat, M. Barthélemy, R. Pastor-Satorras, and A. Vespignani, 

73 "The architecture of complex weighted networks". 

74 PNAS 101 (11): 3747–3752 (2004). 

75 """ 

76 # First, determine the type of neighbors and the type of degree to use. 

77 if G.is_directed(): 

78 if source not in ("in", "out", "in+out"): 

79 raise nx.NetworkXError('source must be one of "in", "out", or "in+out"') 

80 if target not in ("in", "out", "in+out"): 

81 raise nx.NetworkXError('target must be one of "in", "out", or "in+out"') 

82 direction = {"out": G.out_degree, "in": G.in_degree, "in+out": G.degree} 

83 neighbor_funcs = { 

84 "out": G.successors, 

85 "in": G.predecessors, 

86 "in+out": G.neighbors, 

87 } 

88 source_degree = direction[source] 

89 target_degree = direction[target] 

90 neighbors = neighbor_funcs[source] 

91 # `reverse` indicates whether to look at the in-edge when 

92 # computing the weight of an edge. 

93 reverse = source == "in" 

94 else: 

95 if source != "in+out" or target != "in+out": 

96 raise nx.NetworkXError( 

97 f"source and target arguments are only supported for directed graphs" 

98 ) 

99 source_degree = G.degree 

100 target_degree = G.degree 

101 neighbors = G.neighbors 

102 reverse = False 

103 dsum = defaultdict(int) 

104 dnorm = defaultdict(int) 

105 # Check if `source_nodes` is actually a single node in the graph. 

106 source_nodes = source_degree(nodes) 

107 if nodes in G: 

108 source_nodes = [(nodes, source_degree(nodes))] 

109 for n, k in source_nodes: 

110 nbrdeg = target_degree(neighbors(n)) 

111 if weight is None: 

112 s = sum(d for n, d in nbrdeg) 

113 else: # weight nbr degree by weight of (n,nbr) edge 

114 if reverse: 

115 s = sum(G[nbr][n].get(weight, 1) * d for nbr, d in nbrdeg) 

116 else: 

117 s = sum(G[n][nbr].get(weight, 1) * d for nbr, d in nbrdeg) 

118 dnorm[k] += source_degree(n, weight=weight) 

119 dsum[k] += s 

120 

121 # normalize 

122 return {k: avg if dnorm[k] == 0 else avg / dnorm[k] for k, avg in dsum.items()}