~ubuntu-branches/ubuntu/utopic/python-networkx/utopic

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#-*- coding: utf-8 -*-
#    Copyright (C) 2011 by 
#    Jordi Torrents <jtorrents@milnou.net>
#    Aric Hagberg <hagberg@lanl.gov>
#    All rights reserved.
#    BSD license.
import networkx as nx
__author__ = """\n""".join(['Jordi Torrents <jtorrents@milnou.net>',
                            'Aric Hagberg (hagberg@lanl.gov)'])
__all__ = ["average_neighbor_degree"]


def _average_nbr_deg(G, source_degree, target_degree, nodes=None, weight=None):
    # average degree of neighbors
    avg = {}
    for n,deg in source_degree(nodes,weight=weight).items():
        # normalize but not by zero degree
        if deg == 0:
            deg = 1
        nbrdeg = target_degree(G[n])
        if weight is None:
            avg[n] = sum(nbrdeg.values())/float(deg)
        else:
            avg[n] = sum((G[n][nbr].get(weight,1)*d 
                          for nbr,d in nbrdeg.items()))/float(deg)
    return avg

def average_neighbor_degree(G, source='out', target='out',
                            nodes=None, weight=None):
    r"""Returns the average degree of the neighborhood of each node.

    The average degree of a node `i` is

    .. math::

        k_{nn,i} = \frac{1}{|N(i)|} \sum_{j \in N(i)} k_j

    where `N(i)` are the neighbors of node `i` and `k_j` is
    the degree of node `j` which belongs to `N(i)`. For weighted 
    graphs, an analogous measure can be defined [1]_,

    .. math::

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

    where `s_i` is the weighted degree of node `i`, `w_{ij}`
    is the weight of the edge that links `i` and `j` and
    `N(i)` are the neighbors of node `i`.


    Parameters
    ----------
    G : NetworkX graph

    source : string ("in"|"out")
       Directed graphs only.
       Use "in"- or "out"-degree for source node.  

    target : string ("in"|"out")
       Directed graphs only.
       Use "in"- or "out"-degree for target node.

    nodes : list or iterable, optional 
        Compute neighbor degree for specified nodes.  The default is
        all nodes in the graph.


    weight : string or None, optional (default=None)
       The edge attribute that holds the numerical value used as a weight.
       If None, then each edge has weight 1.

    Returns
    -------
    d: dict
       A dictionary keyed by node with average neighbors degree value.

    Examples
    --------
    >>> G=nx.path_graph(4)
    >>> G.edge[0][1]['weight'] = 5
    >>> G.edge[2][3]['weight'] = 3

    >>> nx.average_neighbor_degree(G)
    {0: 2.0, 1: 1.5, 2: 1.5, 3: 2.0}
    >>> nx.average_neighbor_degree(G, weight='weight')
    {0: 2.0, 1: 1.1666666666666667, 2: 1.25, 3: 2.0}

    >>> G=nx.DiGraph()
    >>> G.add_path([0,1,2,3])
    >>> nx.average_neighbor_degree(G, source='in', target='in')
    {0: 1.0, 1: 1.0, 2: 1.0, 3: 0.0}

    >>> nx.average_neighbor_degree(G, source='out', target='out')
    {0: 1.0, 1: 1.0, 2: 0.0, 3: 0.0}
 
    Notes
    -----
    For directed graphs you can also specify in-degree or out-degree 
    by passing keyword arguments.

    See Also
    --------
    average_degree_connectivity 
    
    References
    ----------    
    .. [1] A. Barrat, M. Barthélemy, R. Pastor-Satorras, and A. Vespignani, 
       "The architecture of complex weighted networks". 
       PNAS 101 (11): 3747–3752 (2004).
    """
    source_degree = G.degree
    target_degree = G.degree
    if G.is_directed():
        direction = {'out':G.out_degree,
                     'in':G.in_degree}
        source_degree = direction[source]
        target_degree = direction[target]
    return _average_nbr_deg(G, source_degree, target_degree, 
                            nodes=nodes, weight=weight)

# obsolete
# def average_neighbor_in_degree(G, nodes=None, weight=None):
#     if not G.is_directed():
#         raise nx.NetworkXError("Not defined for undirected graphs.")
#     return _average_nbr_deg(G, G.in_degree, G.in_degree, nodes, weight)
# average_neighbor_in_degree.__doc__=average_neighbor_degree.__doc__

# def average_neighbor_out_degree(G, nodes=None, weight=None):
#     if not G.is_directed():
#         raise nx.NetworkXError("Not defined for undirected graphs.")
#     return _average_nbr_deg(G, G.out_degree, G.out_degree, nodes, weight)
# average_neighbor_out_degree.__doc__=average_neighbor_degree.__doc__