374 lines
11 KiB
Python
374 lines
11 KiB
Python
# -*- coding: utf-8 -*-
|
||
# Copyright (C) 2004-2019 by
|
||
# Aric Hagberg <hagberg@lanl.gov>
|
||
# Dan Schult <dschult@colgate.edu>
|
||
# Pieter Swart <swart@lanl.gov>
|
||
# All rights reserved.
|
||
# BSD license.
|
||
#
|
||
# Authors: Nanda H Krishna <nanda.harishankar@gmail.com>
|
||
"""Group centrality measures."""
|
||
from itertools import combinations
|
||
|
||
|
||
import networkx as nx
|
||
from networkx.utils.decorators import not_implemented_for
|
||
|
||
|
||
__all__ = ['group_betweenness_centrality',
|
||
'group_closeness_centrality',
|
||
'group_degree_centrality',
|
||
'group_in_degree_centrality',
|
||
'group_out_degree_centrality']
|
||
|
||
|
||
def group_betweenness_centrality(G, C, normalized=True, weight=None):
|
||
r"""Compute the group betweenness centrality for a group of nodes.
|
||
|
||
Group betweenness centrality of a group of nodes $C$ is the sum of the
|
||
fraction of all-pairs shortest paths that pass through any vertex in $C$
|
||
|
||
.. math::
|
||
|
||
c_B(C) =\sum_{s,t \in V-C; s<t} \frac{\sigma(s, t|C)}{\sigma(s, t)}
|
||
|
||
where $V$ is the set of nodes, $\sigma(s, t)$ is the number of
|
||
shortest $(s, t)$-paths, and $\sigma(s, t|C)$ is the number of
|
||
those paths passing through some node in group $C$. Note that
|
||
$(s, t)$ are not members of the group ($V-C$ is the set of nodes
|
||
in $V$ that are not in $C$).
|
||
|
||
Parameters
|
||
----------
|
||
G : graph
|
||
A NetworkX graph.
|
||
|
||
C : list or set
|
||
C is a group of nodes which belong to G, for which group betweenness
|
||
centrality is to be calculated.
|
||
|
||
normalized : bool, optional
|
||
If True, group betweenness is normalized by `2/((|V|-|C|)(|V|-|C|-1))`
|
||
for graphs and `1/((|V|-|C|)(|V|-|C|-1))` for directed graphs where `|V|`
|
||
is the number of nodes in G and `|C|` is the number of nodes in C.
|
||
|
||
weight : None or string, optional (default=None)
|
||
If None, all edge weights are considered equal.
|
||
Otherwise holds the name of the edge attribute used as weight.
|
||
|
||
Raises
|
||
------
|
||
NodeNotFound
|
||
If node(s) in C are not present in G.
|
||
|
||
Returns
|
||
-------
|
||
betweenness : float
|
||
Group betweenness centrality of the group C.
|
||
|
||
See Also
|
||
--------
|
||
betweenness_centrality
|
||
|
||
Notes
|
||
-----
|
||
The measure is described in [1]_.
|
||
The algorithm is an extension of the one proposed by Ulrik Brandes for
|
||
betweenness centrality of nodes. Group betweenness is also mentioned in
|
||
his paper [2]_ along with the algorithm. The importance of the measure is
|
||
discussed in [3]_.
|
||
|
||
The number of nodes in the group must be a maximum of n - 2 where `n`
|
||
is the total number of nodes in the graph.
|
||
|
||
For weighted graphs the edge weights must be greater than zero.
|
||
Zero edge weights can produce an infinite number of equal length
|
||
paths between pairs of nodes.
|
||
|
||
References
|
||
----------
|
||
.. [1] M G Everett and S P Borgatti:
|
||
The Centrality of Groups and Classes.
|
||
Journal of Mathematical Sociology. 23(3): 181-201. 1999.
|
||
http://www.analytictech.com/borgatti/group_centrality.htm
|
||
.. [2] Ulrik Brandes:
|
||
On Variants of Shortest-Path Betweenness
|
||
Centrality and their Generic Computation.
|
||
Social Networks 30(2):136-145, 2008.
|
||
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.72.9610&rep=rep1&type=pdf
|
||
.. [3] Sourav Medya et. al.:
|
||
Group Centrality Maximization via Network Design.
|
||
SIAM International Conference on Data Mining, SDM 2018, 126–134.
|
||
https://sites.cs.ucsb.edu/~arlei/pubs/sdm18.pdf
|
||
"""
|
||
betweenness = 0 # initialize betweenness to 0
|
||
V = set(G) # set of nodes in G
|
||
C = set(C) # set of nodes in C (group)
|
||
if len(C - V) != 0: # element(s) of C not in V
|
||
raise nx.NodeNotFound('The node(s) ' + str(list(C - V)) + ' are not '
|
||
'in the graph.')
|
||
V_C = V - C # set of nodes in V but not in C
|
||
# accumulation
|
||
for pair in combinations(V_C, 2): # (s, t) pairs of V_C
|
||
try:
|
||
paths = 0
|
||
paths_through_C = 0
|
||
for path in nx.all_shortest_paths(G, source=pair[0],
|
||
target=pair[1], weight=weight):
|
||
if set(path) & C:
|
||
paths_through_C += 1
|
||
paths += 1
|
||
betweenness += paths_through_C / paths
|
||
except nx.exception.NetworkXNoPath:
|
||
betweenness += 0
|
||
# rescaling
|
||
v, c = len(G), len(C)
|
||
if normalized:
|
||
scale = 1 / ((v - c) * (v - c - 1))
|
||
if not G.is_directed():
|
||
scale *= 2
|
||
else:
|
||
scale = None
|
||
if scale is not None:
|
||
betweenness *= scale
|
||
return betweenness
|
||
|
||
|
||
def group_closeness_centrality(G, S, weight=None):
|
||
r"""Compute the group closeness centrality for a group of nodes.
|
||
|
||
Group closeness centrality of a group of nodes $S$ is a measure
|
||
of how close the group is to the other nodes in the graph.
|
||
|
||
.. math::
|
||
|
||
c_{close}(S) = \frac{|V-S|}{\sum_{v \in V-S} d_{S, v}}
|
||
|
||
d_{S, v} = min_{u \in S} (d_{u, v})
|
||
|
||
where $V$ is the set of nodes, $d_{S, v}$ is the distance of
|
||
the group $S$ from $v$ defined as above. ($V-S$ is the set of nodes
|
||
in $V$ that are not in $S$).
|
||
|
||
Parameters
|
||
----------
|
||
G : graph
|
||
A NetworkX graph.
|
||
|
||
S : list or set
|
||
S is a group of nodes which belong to G, for which group closeness
|
||
centrality is to be calculated.
|
||
|
||
weight : None or string, optional (default=None)
|
||
If None, all edge weights are considered equal.
|
||
Otherwise holds the name of the edge attribute used as weight.
|
||
|
||
Raises
|
||
------
|
||
NodeNotFound
|
||
If node(s) in S are not present in G.
|
||
|
||
Returns
|
||
-------
|
||
closeness : float
|
||
Group closeness centrality of the group S.
|
||
|
||
See Also
|
||
--------
|
||
closeness_centrality
|
||
|
||
Notes
|
||
-----
|
||
The measure was introduced in [1]_.
|
||
The formula implemented here is described in [2]_.
|
||
|
||
Higher values of closeness indicate greater centrality.
|
||
|
||
It is assumed that 1 / 0 is 0 (required in the case of directed graphs,
|
||
or when a shortest path length is 0).
|
||
|
||
The number of nodes in the group must be a maximum of n - 1 where `n`
|
||
is the total number of nodes in the graph.
|
||
|
||
For directed graphs, the incoming distance is utilized here. To use the
|
||
outward distance, act on `G.reverse()`.
|
||
|
||
For weighted graphs the edge weights must be greater than zero.
|
||
Zero edge weights can produce an infinite number of equal length
|
||
paths between pairs of nodes.
|
||
|
||
References
|
||
----------
|
||
.. [1] M G Everett and S P Borgatti:
|
||
The Centrality of Groups and Classes.
|
||
Journal of Mathematical Sociology. 23(3): 181-201. 1999.
|
||
http://www.analytictech.com/borgatti/group_centrality.htm
|
||
.. [2] J. Zhao et. al.:
|
||
Measuring and Maximizing Group Closeness Centrality over
|
||
Disk Resident Graphs.
|
||
WWWConference Proceedings, 2014. 689-694.
|
||
http://wwwconference.org/proceedings/www2014/companion/p689.pdf
|
||
"""
|
||
if G.is_directed():
|
||
G = G.reverse() # reverse view
|
||
closeness = 0 # initialize to 0
|
||
V = set(G) # set of nodes in G
|
||
S = set(S) # set of nodes in group S
|
||
V_S = V - S # set of nodes in V but not S
|
||
shortest_path_lengths = nx.multi_source_dijkstra_path_length(G, S,
|
||
weight=weight)
|
||
# accumulation
|
||
for v in V_S:
|
||
try:
|
||
closeness += shortest_path_lengths[v]
|
||
except KeyError: # no path exists
|
||
closeness += 0
|
||
try:
|
||
closeness = len(V_S) / closeness
|
||
except ZeroDivisionError: # 1 / 0 assumed as 0
|
||
closeness = 0
|
||
return closeness
|
||
|
||
|
||
def group_degree_centrality(G, S):
|
||
"""Compute the group degree centrality for a group of nodes.
|
||
|
||
Group degree centrality of a group of nodes $S$ is the fraction
|
||
of non-group members connected to group members.
|
||
|
||
Parameters
|
||
----------
|
||
G : graph
|
||
A NetworkX graph.
|
||
|
||
S : list or set
|
||
S is a group of nodes which belong to G, for which group degree
|
||
centrality is to be calculated.
|
||
|
||
Raises
|
||
------
|
||
NetworkXError
|
||
If node(s) in S are not in G.
|
||
|
||
Returns
|
||
-------
|
||
centrality : float
|
||
Group degree centrality of the group S.
|
||
|
||
See Also
|
||
--------
|
||
degree_centrality
|
||
group_in_degree_centrality
|
||
group_out_degree_centrality
|
||
|
||
Notes
|
||
-----
|
||
The measure was introduced in [1]_.
|
||
|
||
The number of nodes in the group must be a maximum of n - 1 where `n`
|
||
is the total number of nodes in the graph.
|
||
|
||
References
|
||
----------
|
||
.. [1] M G Everett and S P Borgatti:
|
||
The Centrality of Groups and Classes.
|
||
Journal of Mathematical Sociology. 23(3): 181-201. 1999.
|
||
http://www.analytictech.com/borgatti/group_centrality.htm
|
||
"""
|
||
centrality = len(set().union(*list(set(G.neighbors(i))
|
||
for i in S)) - set(S))
|
||
centrality /= (len(G.nodes()) - len(S))
|
||
return centrality
|
||
|
||
|
||
@not_implemented_for('undirected')
|
||
def group_in_degree_centrality(G, S):
|
||
"""Compute the group in-degree centrality for a group of nodes.
|
||
|
||
Group in-degree centrality of a group of nodes $S$ is the fraction
|
||
of non-group members connected to group members by incoming edges.
|
||
|
||
Parameters
|
||
----------
|
||
G : graph
|
||
A NetworkX graph.
|
||
|
||
S : list or set
|
||
S is a group of nodes which belong to G, for which group in-degree
|
||
centrality is to be calculated.
|
||
|
||
Returns
|
||
-------
|
||
centrality : float
|
||
Group in-degree centrality of the group S.
|
||
|
||
Raises
|
||
------
|
||
NetworkXNotImplemented
|
||
If G is undirected.
|
||
|
||
NodeNotFound
|
||
If node(s) in S are not in G.
|
||
|
||
See Also
|
||
--------
|
||
degree_centrality
|
||
group_degree_centrality
|
||
group_out_degree_centrality
|
||
|
||
Notes
|
||
-----
|
||
The number of nodes in the group must be a maximum of n - 1 where `n`
|
||
is the total number of nodes in the graph.
|
||
|
||
`G.neighbors(i)` gives nodes with an outward edge from i, in a DiGraph,
|
||
so for group in-degree centrality, the reverse graph is used.
|
||
"""
|
||
return group_degree_centrality(G.reverse(), S)
|
||
|
||
|
||
@not_implemented_for('undirected')
|
||
def group_out_degree_centrality(G, S):
|
||
"""Compute the group out-degree centrality for a group of nodes.
|
||
|
||
Group out-degree centrality of a group of nodes $S$ is the fraction
|
||
of non-group members connected to group members by outgoing edges.
|
||
|
||
Parameters
|
||
----------
|
||
G : graph
|
||
A NetworkX graph.
|
||
|
||
S : list or set
|
||
S is a group of nodes which belong to G, for which group in-degree
|
||
centrality is to be calculated.
|
||
|
||
Returns
|
||
-------
|
||
centrality : float
|
||
Group out-degree centrality of the group S.
|
||
|
||
Raises
|
||
------
|
||
NetworkXNotImplemented
|
||
If G is undirected.
|
||
|
||
NodeNotFound
|
||
If node(s) in S are not in G.
|
||
|
||
See Also
|
||
--------
|
||
degree_centrality
|
||
group_degree_centrality
|
||
group_in_degree_centrality
|
||
|
||
Notes
|
||
-----
|
||
The number of nodes in the group must be a maximum of n - 1 where `n`
|
||
is the total number of nodes in the graph.
|
||
|
||
`G.neighbors(i)` gives nodes with an outward edge from i, in a DiGraph,
|
||
so for group out-degree centrality, the graph itself is used.
|
||
"""
|
||
return group_degree_centrality(G, S)
|