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
« 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
5from ..utils import not_implemented_for
7__all__ = ["reciprocity", "overall_reciprocity"]
10@not_implemented_for("undirected", "multigraph")
11@nx._dispatch
12def reciprocity(G, nodes=None):
13 r"""Compute the reciprocity in a directed graph.
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}|$.
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.
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.
31 Returns
32 -------
33 out : dictionary
34 Reciprocity keyed by node label.
36 Notes
37 -----
38 The reciprocity is not defined for isolated nodes.
39 In such cases this function will return None.
41 """
42 # If `nodes` is not specified, calculate the reciprocity of the graph.
43 if nodes is None:
44 return overall_reciprocity(G)
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
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))
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)
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)
78@not_implemented_for("undirected", "multigraph")
79@nx._dispatch
80def overall_reciprocity(G):
81 """Compute the reciprocity for the whole graph.
83 See the doc of reciprocity for the definition.
85 Parameters
86 ----------
87 G : graph
88 A networkx graph
90 """
91 n_all_edge = G.number_of_edges()
92 n_overlap_edge = (n_all_edge - G.to_undirected().number_of_edges()) * 2
94 if n_all_edge == 0:
95 raise NetworkXError("Not defined for empty graphs")
97 return n_overlap_edge / n_all_edge