comparison planemo/lib/python3.7/site-packages/networkx/algorithms/structuralholes.py @ 1:56ad4e20f292 draft

"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
author guerler
date Fri, 31 Jul 2020 00:32:28 -0400
parents
children
comparison
equal deleted inserted replaced
0:d30785e31577 1:56ad4e20f292
1 # -*- encoding: utf-8 -*-
2 #
3 # Copyright 2008-2019 NetworkX developers.
4 # Aric Hagberg <hagberg@lanl.gov>
5 # Dan Schult <dschult@colgate.edu>
6 # Pieter Swart <swart@lanl.gov>
7 # All rights reserved.
8 # BSD license.
9 """Functions for computing measures of structural holes."""
10
11 import networkx as nx
12
13 __all__ = ['constraint', 'local_constraint', 'effective_size']
14
15
16 def mutual_weight(G, u, v, weight=None):
17 """Returns the sum of the weights of the edge from `u` to `v` and
18 the edge from `v` to `u` in `G`.
19
20 `weight` is the edge data key that represents the edge weight. If
21 the specified key is `None` or is not in the edge data for an edge,
22 that edge is assumed to have weight 1.
23
24 Pre-conditions: `u` and `v` must both be in `G`.
25
26 """
27 try:
28 a_uv = G[u][v].get(weight, 1)
29 except KeyError:
30 a_uv = 0
31 try:
32 a_vu = G[v][u].get(weight, 1)
33 except KeyError:
34 a_vu = 0
35 return a_uv + a_vu
36
37
38 def normalized_mutual_weight(G, u, v, norm=sum, weight=None):
39 """Returns normalized mutual weight of the edges from `u` to `v`
40 with respect to the mutual weights of the neighbors of `u` in `G`.
41
42 `norm` specifies how the normalization factor is computed. It must
43 be a function that takes a single argument and returns a number.
44 The argument will be an iterable of mutual weights
45 of pairs ``(u, w)``, where ``w`` ranges over each (in- and
46 out-)neighbor of ``u``. Commons values for `normalization` are
47 ``sum`` and ``max``.
48
49 `weight` can be ``None`` or a string, if None, all edge weights
50 are considered equal. Otherwise holds the name of the edge
51 attribute used as weight.
52
53 """
54 scale = norm(mutual_weight(G, u, w, weight)
55 for w in set(nx.all_neighbors(G, u)))
56 return 0 if scale == 0 else mutual_weight(G, u, v, weight) / scale
57
58
59 def effective_size(G, nodes=None, weight=None):
60 r"""Returns the effective size of all nodes in the graph ``G``.
61
62 The *effective size* of a node's ego network is based on the concept
63 of redundancy. A person's ego network has redundancy to the extent
64 that her contacts are connected to each other as well. The
65 nonredundant part of a person's relationships it's the effective
66 size of her ego network [1]_. Formally, the effective size of a
67 node $u$, denoted $e(u)$, is defined by
68
69 .. math::
70
71 e(u) = \sum_{v \in N(u) \setminus \{u\}}
72 \left(1 - \sum_{w \in N(v)} p_{uw} m_{vw}\right)
73
74 where $N(u)$ is the set of neighbors of $u$ and $p_{uw}$ is the
75 normalized mutual weight of the (directed or undirected) edges
76 joining $u$ and $v$, for each vertex $u$ and $v$ [1]_. And $m_{vw}$
77 is the mutual weight of $v$ and $w$ divided by $v$ highest mutual
78 weight with any of its neighbors. The *mutual weight* of $u$ and $v$
79 is the sum of the weights of edges joining them (edge weights are
80 assumed to be one if the graph is unweighted).
81
82 For the case of unweighted and undirected graphs, Borgatti proposed
83 a simplified formula to compute effective size [2]_
84
85 .. math::
86
87 e(u) = n - \frac{2t}{n}
88
89 where `t` is the number of ties in the ego network (not including
90 ties to ego) and `n` is the number of nodes (excluding ego).
91
92 Parameters
93 ----------
94 G : NetworkX graph
95 The graph containing ``v``. Directed graphs are treated like
96 undirected graphs when computing neighbors of ``v``.
97
98 nodes : container, optional
99 Container of nodes in the graph ``G`` to compute the effective size.
100 If None, the effective size of every node is computed.
101
102 weight : None or string, optional
103 If None, all edge weights are considered equal.
104 Otherwise holds the name of the edge attribute used as weight.
105
106 Returns
107 -------
108 dict
109 Dictionary with nodes as keys and the constraint on the node as values.
110
111 Notes
112 -----
113 Burt also defined the related concept of *efficiency* of a node's ego
114 network, which is its effective size divided by the degree of that
115 node [1]_. So you can easily compute efficiency:
116
117 >>> G = nx.DiGraph()
118 >>> G.add_edges_from([(0, 1), (0, 2), (1, 0), (2, 1)])
119 >>> esize = nx.effective_size(G)
120 >>> efficiency = {n: v / G.degree(n) for n, v in esize.items()}
121
122 See also
123 --------
124 constraint
125
126 References
127 ----------
128 .. [1] Burt, Ronald S.
129 *Structural Holes: The Social Structure of Competition.*
130 Cambridge: Harvard University Press, 1995.
131
132 .. [2] Borgatti, S.
133 "Structural Holes: Unpacking Burt's Redundancy Measures"
134 CONNECTIONS 20(1):35-38.
135 http://www.analytictech.com/connections/v20(1)/holes.htm
136
137 """
138 def redundancy(G, u, v, weight=None):
139 nmw = normalized_mutual_weight
140 r = sum(nmw(G, u, w, weight=weight) * nmw(G, v, w, norm=max, weight=weight)
141 for w in set(nx.all_neighbors(G, u)))
142 return 1 - r
143 effective_size = {}
144 if nodes is None:
145 nodes = G
146 # Use Borgatti's simplified formula for unweighted and undirected graphs
147 if not G.is_directed() and weight is None:
148 for v in nodes:
149 # Effective size is not defined for isolated nodes
150 if len(G[v]) == 0:
151 effective_size[v] = float('nan')
152 continue
153 E = nx.ego_graph(G, v, center=False, undirected=True)
154 effective_size[v] = len(E) - (2 * E.size()) / len(E)
155 else:
156 for v in nodes:
157 # Effective size is not defined for isolated nodes
158 if len(G[v]) == 0:
159 effective_size[v] = float('nan')
160 continue
161 effective_size[v] = sum(redundancy(G, v, u, weight)
162 for u in set(nx.all_neighbors(G, v)))
163 return effective_size
164
165
166 def constraint(G, nodes=None, weight=None):
167 r"""Returns the constraint on all nodes in the graph ``G``.
168
169 The *constraint* is a measure of the extent to which a node *v* is
170 invested in those nodes that are themselves invested in the
171 neighbors of *v*. Formally, the *constraint on v*, denoted `c(v)`,
172 is defined by
173
174 .. math::
175
176 c(v) = \sum_{w \in N(v) \setminus \{v\}} \ell(v, w)
177
178 where `N(v)` is the subset of the neighbors of `v` that are either
179 predecessors or successors of `v` and `\ell(v, w)` is the local
180 constraint on `v` with respect to `w` [1]_. For the definition of local
181 constraint, see :func:`local_constraint`.
182
183 Parameters
184 ----------
185 G : NetworkX graph
186 The graph containing ``v``. This can be either directed or undirected.
187
188 nodes : container, optional
189 Container of nodes in the graph ``G`` to compute the constraint. If
190 None, the constraint of every node is computed.
191
192 weight : None or string, optional
193 If None, all edge weights are considered equal.
194 Otherwise holds the name of the edge attribute used as weight.
195
196 Returns
197 -------
198 dict
199 Dictionary with nodes as keys and the constraint on the node as values.
200
201 See also
202 --------
203 local_constraint
204
205 References
206 ----------
207 .. [1] Burt, Ronald S.
208 "Structural holes and good ideas".
209 American Journal of Sociology (110): 349–399.
210
211 """
212 if nodes is None:
213 nodes = G
214 constraint = {}
215 for v in nodes:
216 # Constraint is not defined for isolated nodes
217 if len(G[v]) == 0:
218 constraint[v] = float('nan')
219 continue
220 constraint[v] = sum(local_constraint(G, v, n, weight)
221 for n in set(nx.all_neighbors(G, v)))
222 return constraint
223
224
225 def local_constraint(G, u, v, weight=None):
226 r"""Returns the local constraint on the node ``u`` with respect to
227 the node ``v`` in the graph ``G``.
228
229 Formally, the *local constraint on u with respect to v*, denoted
230 $\ell(v)$, is defined by
231
232 .. math::
233
234 \ell(u, v) = \left(p_{uv} + \sum_{w \in N(v)} p_{uw} p{wv}\right)^2,
235
236 where $N(v)$ is the set of neighbors of $v$ and $p_{uv}$ is the
237 normalized mutual weight of the (directed or undirected) edges
238 joining $u$ and $v$, for each vertex $u$ and $v$ [1]_. The *mutual
239 weight* of $u$ and $v$ is the sum of the weights of edges joining
240 them (edge weights are assumed to be one if the graph is
241 unweighted).
242
243 Parameters
244 ----------
245 G : NetworkX graph
246 The graph containing ``u`` and ``v``. This can be either
247 directed or undirected.
248
249 u : node
250 A node in the graph ``G``.
251
252 v : node
253 A node in the graph ``G``.
254
255 weight : None or string, optional
256 If None, all edge weights are considered equal.
257 Otherwise holds the name of the edge attribute used as weight.
258
259 Returns
260 -------
261 float
262 The constraint of the node ``v`` in the graph ``G``.
263
264 See also
265 --------
266 constraint
267
268 References
269 ----------
270 .. [1] Burt, Ronald S.
271 "Structural holes and good ideas".
272 American Journal of Sociology (110): 349–399.
273
274 """
275 nmw = normalized_mutual_weight
276 direct = nmw(G, u, v, weight=weight)
277 indirect = sum(nmw(G, u, w, weight=weight) * nmw(G, w, v, weight=weight)
278 for w in set(nx.all_neighbors(G, u)))
279 return (direct + indirect) ** 2