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
« prev ^ index » next coverage.py v7.3.2, created at 2023-10-20 07:00 +0000
1from collections import defaultdict
3import networkx as nx
5__all__ = ["average_degree_connectivity"]
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.
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
19 .. math::
21 k_{nn,i}^{w} = \frac{1}{s_i} \sum_{j \in N(i)} w_{ij} k_j
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`.
27 Parameters
28 ----------
29 G : NetworkX graph
31 source : "in"|"out"|"in+out" (default:"in+out")
32 Directed graphs only. Use "in"- or "out"-degree for source node.
34 target : "in"|"out"|"in+out" (default:"in+out"
35 Directed graphs only. Use "in"- or "out"-degree for target node.
37 nodes : list or iterable (optional)
38 Compute neighbor connectivity for these nodes. The default is all
39 nodes.
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.
45 Returns
46 -------
47 d : dict
48 A dictionary keyed by degree k with the value of average connectivity.
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.
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}
66 See Also
67 --------
68 average_neighbor_degree
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
121 # normalize
122 return {k: avg if dnorm[k] == 0 else avg / dnorm[k] for k, avg in dsum.items()}