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

« back to all changes in this revision

Viewing changes to networkx/algorithms/pagerank.py

  • Committer: Bazaar Package Importer
  • Author(s): Cyril Brulebois
  • Date: 2009-11-23 15:44:34 UTC
  • mfrom: (1.2.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20091123154434-ellm2ut3a4edf9wh
Tags: 1.0~rc1~svn1492-1
* New upstream snapshot, past 1.0~rc1, as requested by Yaroslav
  Halchenko (Closes: #549996).
* Refresh patch accordingly:
   + debian/patches/10_doc_relocation.
* Get rid of extra LICENSE.txt file in /usr/share/doc.
* Use dh_compress -Xexamples/ to avoid compressing examples, thanks to
  Sandro Tosi (Closes: #539942).
* Bump Standards-Version from 3.8.0 to 3.8.3 (no changes needed).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
#    Copyright (C) 2004-2008 by 
 
3
#    Aric Hagberg <hagberg@lanl.gov>
 
4
#    Dan Schult <dschult@colgate.edu>
 
5
#    Pieter Swart <swart@lanl.gov>
 
6
#    All rights reserved.
 
7
#    BSD license.
 
8
#    NetworkX:http://networkx.lanl.gov/. 
 
9
__author__ = """Aric Hagberg (hagberg@lanl.gov)"""
 
10
 
 
11
import networkx
 
12
from networkx.exception import NetworkXError
 
13
__all__ = ['pagerank','pagerank_numpy','pagerank_scipy','google_matrix']
 
14
 
 
15
def pagerank(G,alpha=0.85,max_iter=100,tol=1.0e-8,nstart=None):
 
16
    """Return the PageRank of the nodes in the graph.
 
17
 
 
18
    PageRank computes the largest eigenvector of the stochastic
 
19
    adjacency matrix of G.  
 
20
    
 
21
 
 
22
    Parameters
 
23
    -----------
 
24
    G : graph
 
25
      A networkx graph 
 
26
 
 
27
    alpha : float, optional
 
28
      Parameter for PageRank, default=0.85
 
29
       
 
30
    max_iter : interger, optional
 
31
      Maximum number of iterations in power method.
 
32
 
 
33
    tol : float, optional
 
34
      Error tolerance used to check convergence in power method iteration.
 
35
 
 
36
    nstart : dictionary, optional
 
37
      Starting value of PageRank iteration for each node. 
 
38
 
 
39
    Returns
 
40
    -------
 
41
    nodes : dictionary
 
42
       Dictionary of nodes with value as PageRank 
 
43
 
 
44
 
 
45
    Examples
 
46
    --------
 
47
    >>> G=nx.DiGraph(nx.path_graph(4))
 
48
    >>> pr=nx.pagerank(G,alpha=0.9)
 
49
 
 
50
    Notes
 
51
    -----
 
52
    The eigenvector calculation is done by the power iteration method
 
53
    and has no guarantee of convergence.  The iteration will stop
 
54
    after max_iter iterations or an error tolerance of
 
55
    number_of_nodes(G)*tol has been reached.
 
56
 
 
57
    The PageRank algorithm was designed for directed graphs but this
 
58
    algorithm does not check if the input graph is directed and will
 
59
    execute on undirected graphs.
 
60
 
 
61
    For an overview see:
 
62
    A. Langville and C. Meyer, "A survey of eigenvector methods of web
 
63
    information retrieval."  http://citeseer.ist.psu.edu/713792.html
 
64
 
 
65
    """
 
66
    import networkx
 
67
    if type(G) == networkx.MultiGraph or type(G) == networkx.MultiDiGraph:
 
68
        raise Exception("pagerank() not defined for graphs with multiedges.")
 
69
 
 
70
    # create a copy in (right) stochastic form        
 
71
    W=networkx.stochastic_graph(G)        
 
72
 
 
73
    # choose fixed starting vector if not given
 
74
    if nstart is None:
 
75
        x=dict.fromkeys(W,1.0/W.number_of_nodes())
 
76
    else:
 
77
        x=nstart
 
78
        # normalize starting vector to 1                
 
79
        s=1.0/sum(x.values())
 
80
        for k in x: x[k]*=s
 
81
 
 
82
    nnodes=W.number_of_nodes()
 
83
    # "dangling" nodes, no links out from them
 
84
    out_degree=W.out_degree(with_labels=True)
 
85
#    dangle=[n for n in W if sum(W[n].values())==0.0]  
 
86
    dangle=[n for n in W if out_degree[n]==0.0]  
 
87
    # pagerank power iteration: make up to max_iter iterations        
 
88
    for i in range(max_iter):
 
89
        xlast=x
 
90
        x=dict.fromkeys(xlast.keys(),0)
 
91
        danglesum=alpha/nnodes*sum(xlast[n] for n in dangle)
 
92
        teleportsum=(1.0-alpha)/nnodes*sum(xlast.values())
 
93
        for n in x:
 
94
            # this matrix multiply looks odd because it is
 
95
            # doing a left multiply x^T=xlast^T*W
 
96
            for nbr in W[n]:
 
97
                x[nbr]+=alpha*xlast[n]*W[n][nbr]['weight']
 
98
            x[n]+=danglesum+teleportsum
 
99
        # normalize vector to 1                
 
100
        s=1.0/sum(x.values())
 
101
        for n in x: x[n]*=s
 
102
        # check convergence, l1 norm            
 
103
        err=sum([abs(x[n]-xlast[n]) for n in x])
 
104
        if err < tol:
 
105
            return x
 
106
 
 
107
    raise NetworkXError("pagerank: power iteration failed to converge in %d iterations."%(i+1))
 
108
 
 
109
 
 
110
 
 
111
def google_matrix(G,alpha=0.85,nodelist=None):
 
112
    import numpy
 
113
    import networkx
 
114
    M=networkx.to_numpy_matrix(G,nodelist=nodelist)
 
115
    (n,m)=M.shape # should be square
 
116
    # add constant to dangling nodes' row
 
117
    dangling=numpy.where(M.sum(axis=1)==0)
 
118
    for d in dangling[0]:
 
119
        M[d]=1.0/n
 
120
    # normalize        
 
121
    M=M/M.sum(axis=1)
 
122
    # add "teleportation"
 
123
    P=alpha*M+(1-alpha)*numpy.ones((n,n))/n
 
124
    return P
 
125
    
 
126
 
 
127
def pagerank_numpy(G,alpha=0.85,max_iter=100,tol=1.0e-6,nodelist=None):
 
128
    """Return a NumPy array of the PageRank of G.
 
129
    """
 
130
    import numpy
 
131
    import networkx
 
132
    M=networkx.google_matrix(G,alpha,nodelist)   
 
133
    (n,m)=M.shape # should be square
 
134
    x=numpy.ones((n))/n
 
135
    for i in range(max_iter):
 
136
        xlast=x
 
137
        x=numpy.dot(x,M)
 
138
        # check convergence, l1 norm            
 
139
        err=numpy.abs(x-xlast).sum()
 
140
        if err < n*tol:
 
141
            return numpy.asarray(x).flatten()
 
142
 
 
143
    raise NetworkXError("pagerank: power iteration failed to converge in %d iterations."%(i+1))
 
144
 
 
145
 
 
146
 
 
147
def pagerank_scipy(G,alpha=0.85,max_iter=100,tol=1.0e-6,nodelist=None):
 
148
    """Return a SciPy sparse array of the PageRank of G.
 
149
 
 
150
    """
 
151
    import scipy.sparse
 
152
    import networkx
 
153
    M=networkx.to_scipy_sparse_matrix(G,nodelist=nodelist)
 
154
    (n,m)=M.shape # should be square
 
155
    S=scipy.array(M.sum(axis=1)).flatten()
 
156
    index=scipy.where(S<>0)[0]
 
157
    for i in index:
 
158
        M[i,:]*=1.0/S[i]
 
159
    x=scipy.ones((n))/n  # initial guess
 
160
    dangle=scipy.array(scipy.where(M.sum(axis=1)==0,1.0/n,0)).flatten()
 
161
    for i in range(max_iter):
 
162
        xlast=x
 
163
        x=alpha*(x*M+scipy.dot(dangle,xlast))+(1-alpha)*xlast.sum()/n
 
164
        # check convergence, l1 norm            
 
165
        err=scipy.absolute(x-xlast).sum()
 
166
        if err < n*tol:
 
167
            return x
 
168
    raise NetworkXError("pagerank_scipy: power iteration failed to converge in %d iterations."%(i+1))
 
169