Repository: networkx/networkx

Issue:
Add 'weight' keyword option to eigenvector and Katz centrality
Both the eigenvector_centrality() and katz_centrality() functions use edge weights if 'weight' is an attribute of the edge but don't describe that in the documentation. 
Also other NetworkX functions  allow the user to specify the attribute keyword when calling the function with weight= including the option for weight=None.
These should be the same.



Discussion:

Resolving patch:
diff --git a/networkx/algorithms/centrality/eigenvector.py b/networkx/algorithms/centrality/eigenvector.py
--- a/networkx/algorithms/centrality/eigenvector.py
+++ b/networkx/algorithms/centrality/eigenvector.py
@@ -1,29 +1,30 @@
 """
 Eigenvector centrality.
 """
-#    Copyright (C) 2004-2011 by 
+#    Copyright (C) 2004-2013 by
 #    Aric Hagberg <hagberg@lanl.gov>
 #    Dan Schult <dschult@colgate.edu>
 #    Pieter Swart <swart@lanl.gov>
 #    All rights reserved.
 #    BSD license.
 import networkx as nx
-__author__ = "\n".join(['Aric Hagberg (hagberg@lanl.gov)',
+__author__ = "\n".join(['Aric Hagberg (aric.hagberg@gmail.com)',
                         'Pieter Swart (swart@lanl.gov)',
                         'Sasha Gutfraind (ag362@cornell.edu)'])
 __all__ = ['eigenvector_centrality',
            'eigenvector_centrality_numpy']
 
-def eigenvector_centrality(G,max_iter=100,tol=1.0e-6,nstart=None):
+def eigenvector_centrality(G, max_iter=100, tol=1.0e-6, nstart=None,
+                           weight='weight'):
     """Compute the eigenvector centrality for the graph G.
 
-    Uses the power method to find the eigenvector for the 
+    Uses the power method to find the eigenvector for the
     largest eigenvalue of the adjacency matrix of G.
 
     Parameters
     ----------
     G : graph
-      A networkx graph 
+      A networkx graph
 
     max_iter : interger, optional
       Maximum number of iterations in power method.
@@ -32,7 +33,11 @@ def eigenvector_centrality(G,max_iter=100,tol=1.0e-6,nstart=None):
       Error tolerance used to check convergence in power method iteration.
 
     nstart : dictionary, optional
-      Starting value of eigenvector iteration for each node. 
+      Starting value of eigenvector iteration for each node.
+
+    weight : None or string, optional
+      If None, all edge weights are considered equal.
+      Otherwise holds the name of the edge attribute used as weight.
 
     Returns
     -------
@@ -41,8 +46,8 @@ def eigenvector_centrality(G,max_iter=100,tol=1.0e-6,nstart=None):
 
     Examples
     --------
-    >>> G=nx.path_graph(4)
-    >>> centrality=nx.eigenvector_centrality(G)
+    >>> G = nx.path_graph(4)
+    >>> centrality = nx.eigenvector_centrality(G)
     >>> print(['%s %0.2f'%(node,centrality[node]) for node in centrality])
     ['0 0.37', '1 0.60', '2 0.60', '3 0.37']
 
@@ -67,49 +72,56 @@ def eigenvector_centrality(G,max_iter=100,tol=1.0e-6,nstart=None):
     if type(G) == nx.MultiGraph or type(G) == nx.MultiDiGraph:
         raise nx.NetworkXException("Not defined for multigraphs.")
 
-    if len(G)==0:
+    if len(G) == 0:
         raise nx.NetworkXException("Empty graph.")
 
     if nstart is None:
-        # choose starting vector with entries of 1/len(G) 
-        x=dict([(n,1.0/len(G)) for n in G])
+        # choose starting vector with entries of 1/len(G)
+        x = dict([(n,1.0/len(G)) for n in G])
     else:
-        x=nstart
+        x = nstart
     # normalize starting vector
-    s=1.0/sum(x.values())
-    for k in x: x[k]*=s
-    nnodes=G.number_of_nodes()
-    # make up to max_iter iterations        
+    s = 1.0/sum(x.values())
+    for k in x: 
+        x[k] *= s
+    nnodes = G.number_of_nodes()
+    # make up to max_iter iterations
     for i in range(max_iter):
-        xlast=x
-        x=dict.fromkeys(xlast, 0)
+        xlast = x
+        x = dict.fromkeys(xlast, 0)
         # do the multiplication y=Ax
         for n in x:
             for nbr in G[n]:
-                x[n]+=xlast[nbr]*G[n][nbr].get('weight',1)
+                x[n] += xlast[nbr]*G[n][nbr].get(weight, 1)
         # normalize vector
         try:
-            s=1.0/sqrt(sum(v**2 for v in x.values()))
+            s = 1.0/sqrt(sum(v**2 for v in x.values()))
         # this should never be zero?
         except ZeroDivisionError:
-            s=1.0
-        for n in x: x[n]*=s
-        # check convergence            
-        err=sum([abs(x[n]-xlast[n]) for n in x])
+            s = 1.0
+        for n in x:
+            x[n] *= s
+        # check convergence
+        err = sum([abs(x[n]-xlast[n]) for n in x])
         if err < nnodes*tol:
             return x
 
-    raise nx.NetworkXError("""eigenvector_centrality(): 
+    raise nx.NetworkXError("""eigenvector_centrality():
 power iteration failed to converge in %d iterations."%(i+1))""")
 
 
-def eigenvector_centrality_numpy(G):
+def eigenvector_centrality_numpy(G, weight='weight'):
     """Compute the eigenvector centrality for the graph G.
 
     Parameters
     ----------
     G : graph
-      A networkx graph 
+      A networkx graph
+
+    weight : None or string, optional
+      If None, all edge weights are considered equal.
+      Otherwise holds the name of the edge attribute used as weight.
+
 
     Returns
     -------
@@ -118,8 +130,8 @@ def eigenvector_centrality_numpy(G):
 
     Examples
     --------
-    >>> G=nx.path_graph(4)
-    >>> centrality=nx.eigenvector_centrality_numpy(G)
+    >>> G = nx.path_graph(4)
+    >>> centrality = nx.eigenvector_centrality_numpy(G)
     >>> print(['%s %0.2f'%(node,centrality[node]) for node in centrality])
     ['0 0.37', '1 0.60', '2 0.60', '3 0.37']
 
@@ -145,17 +157,17 @@ def eigenvector_centrality_numpy(G):
     if type(G) == nx.MultiGraph or type(G) == nx.MultiDiGraph:
         raise nx.NetworkXException('Not defined for multigraphs.')
 
-    if len(G)==0:
+    if len(G) == 0:
         raise nx.NetworkXException('Empty graph.')
 
-    A=nx.adj_matrix(G,nodelist=G.nodes())
-    eigenvalues,eigenvectors=np.linalg.eig(A)
+    A = nx.adj_matrix(G, nodelist=G.nodes(), weight='weight')
+    eigenvalues,eigenvectors = np.linalg.eig(A)
     # eigenvalue indices in reverse sorted order
-    ind=eigenvalues.argsort()[::-1]
+    ind = eigenvalues.argsort()[::-1]
     # eigenvector of largest eigenvalue at ind[0], normalized
-    largest=np.array(eigenvectors[:,ind[0]]).flatten().real
-    norm=np.sign(largest.sum())*np.linalg.norm(largest)
-    centrality=dict(zip(G,map(float,largest/norm)))
+    largest = np.array(eigenvectors[:,ind[0]]).flatten().real
+    norm = np.sign(largest.sum())*np.linalg.norm(largest)
+    centrality = dict(zip(G,map(float,largest/norm)))
     return centrality
 
 
diff --git a/networkx/algorithms/centrality/katz.py b/networkx/algorithms/centrality/katz.py
--- a/networkx/algorithms/centrality/katz.py
+++ b/networkx/algorithms/centrality/katz.py
@@ -8,8 +8,8 @@
 #    All rights reserved.
 #    BSD license.
 import networkx as nx
-from networkx.utils import *
-__author__ = "\n".join(['Aric Hagberg (hagberg@lanl.gov)',
+from networkx.utils import not_implemented_for
+__author__ = "\n".join(['Aric Hagberg (aric.hagberg@gmail.com)',
                         'Pieter Swart (swart@lanl.gov)',
                         'Sasha Gutfraind (ag362@cornell.edu)',
                         'Vincent Gauthier (vgauthier@luxbulb.org)'])
@@ -19,7 +19,8 @@
 
 @not_implemented_for('multigraph')
 def katz_centrality(G, alpha=0.1, beta=1.0,
-                    max_iter=1000, tol=1.0e-6, nstart=None, normalized=True):
+                    max_iter=1000, tol=1.0e-6, nstart=None, normalized=True,
+                    weight = 'weight'):
     r"""Compute the Katz centrality for the nodes of the graph G.
 
 
@@ -76,6 +77,10 @@ def katz_centrality(G, alpha=0.1, beta=1.0,
     normalized : bool, optional (default=True)
       If True normalize the resulting values.
 
+    weight : None or string, optional
+      If None, all edge weights are considered equal.
+      Otherwise holds the name of the edge attribute used as weight.
+
     Returns
     -------
     nodes : dictionary
@@ -121,16 +126,16 @@ def katz_centrality(G, alpha=0.1, beta=1.0,
     """
     from math import sqrt
 
-    if len(G)==0:
+    if len(G) == 0:
         return {}
 
-    nnodes=G.number_of_nodes()
+    nnodes = G.number_of_nodes()
 
     if nstart is None:
         # choose starting vector with entries of 0
-        x=dict([(n,0) for n in G])
+        x = dict([(n,0) for n in G])
     else:
-        x=nstart
+        x = nstart
 
     try:
         b = dict.fromkeys(G,float(beta))
@@ -142,35 +147,36 @@ def katz_centrality(G, alpha=0.1, beta=1.0,
 
     # make up to max_iter iterations
     for i in range(max_iter):
-        xlast=x
-        x=dict.fromkeys(xlast, 0)
+        xlast = x
+        x = dict.fromkeys(xlast, 0)
         # do the multiplication y = Alpha * Ax - Beta
         for n in x:
             for nbr in G[n]:
-                x[n] += xlast[nbr] * G[n][nbr].get('weight',1)
+                x[n] += xlast[nbr] * G[n][nbr].get(weight,1)
             x[n] = alpha*x[n] + b[n]
 
         # check convergence
-        err=sum([abs(x[n]-xlast[n]) for n in x])
+        err = sum([abs(x[n]-xlast[n]) for n in x])
         if err < nnodes*tol:
             if normalized:
                 # normalize vector
                 try:
-                    s=1.0/sqrt(sum(v**2 for v in x.values()))
+                    s = 1.0/sqrt(sum(v**2 for v in x.values()))
                 # this should never be zero?
                 except ZeroDivisionError:
-                    s=1.0
+                    s = 1.0
             else:
                 s = 1
             for n in x:
-                x[n]*=s
+                x[n] *= s
             return x
 
     raise nx.NetworkXError('Power iteration failed to converge in ',
                            '%d iterations."%(i+1))')
 
 @not_implemented_for('multigraph')
-def katz_centrality_numpy(G, alpha=0.1, beta=1.0, normalized=True):
+def katz_centrality_numpy(G, alpha=0.1, beta=1.0, normalized=True,
+                          weight = 'weight'):
     r"""Compute the Katz centrality for the graph G.
 
 
@@ -217,6 +223,10 @@ def katz_centrality_numpy(G, alpha=0.1, beta=1.0, normalized=True):
     normalized : bool
       If True normalize the resulting values.
 
+    weight : None or string, optional
+      If None, all edge weights are considered equal.
+      Otherwise holds the name of the edge attribute used as weight.
+
     Returns
     -------
     nodes : dictionary
@@ -260,14 +270,14 @@ def katz_centrality_numpy(G, alpha=0.1, beta=1.0, normalized=True):
         import numpy as np
     except ImportError:
         raise ImportError('Requires NumPy: http://scipy.org/')
-    if len(G)==0:
+    if len(G) == 0:
         return {}
     try:
         nodelist = beta.keys()
         if set(nodelist) != set(G):
             raise nx.NetworkXError('beta dictionary '
                                    'must have a value for every node')
-        b = np.array(list(beta.values()),dtype=float)
+        b = np.array(list(beta.values()), dtype=float)
     except AttributeError:
         nodelist = G.nodes()
         try:
@@ -275,14 +285,14 @@ def katz_centrality_numpy(G, alpha=0.1, beta=1.0, normalized=True):
         except (TypeError,ValueError):
             raise nx.NetworkXError('beta must be a number')
 
-    A=nx.adj_matrix(G, nodelist=nodelist)
+    A = nx.adj_matrix(G, nodelist=nodelist, weight=weight)
     n = np.array(A).shape[0]
     centrality = np.linalg.solve( np.eye(n,n) - (alpha * A) , b)
     if normalized:
         norm = np.sign(sum(centrality)) * np.linalg.norm(centrality)
     else:
         norm = 1.0
-    centrality=dict(zip(nodelist, map(float,centrality/norm)))
+    centrality = dict(zip(nodelist, map(float,centrality/norm)))
     return centrality
 
 


Test patch:
diff --git a/networkx/algorithms/centrality/tests/test_eigenvector_centrality.py b/networkx/algorithms/centrality/tests/test_eigenvector_centrality.py
--- a/networkx/algorithms/centrality/tests/test_eigenvector_centrality.py
+++ b/networkx/algorithms/centrality/tests/test_eigenvector_centrality.py
@@ -13,7 +13,7 @@ def setupClass(cls):
             import numpy as np
         except ImportError:
             raise SkipTest('NumPy not available.')
-        
+
     def test_K5(self):
         """Eigenvector centrality: K5"""
         G=networkx.complete_graph(5)
@@ -22,7 +22,7 @@ def test_K5(self):
         b_answer=dict.fromkeys(G,v)
         for n in sorted(G):
             assert_almost_equal(b[n],b_answer[n])
-        nstart = dict([(n,1) for n in G]) 
+        nstart = dict([(n,1) for n in G])
         b=networkx.eigenvector_centrality(G,nstart=nstart)
         for n in sorted(G):
             assert_almost_equal(b[n],b_answer[n])
@@ -42,6 +42,16 @@ def test_P3(self):
             assert_almost_equal(b[n],b_answer[n],places=4)
 
 
+    def test_P3_unweighted(self):
+        """Eigenvector centrality: P3"""
+        G=networkx.path_graph(3)
+        b_answer={0: 0.5, 1: 0.7071, 2: 0.5}
+        b=networkx.eigenvector_centrality_numpy(G, weight=None)
+        for n in sorted(G):
+            assert_almost_equal(b[n],b_answer[n],places=4)
+
+
+
     @raises(networkx.NetworkXError)
     def test_maxiter(self):
         G=networkx.path_graph(3)
@@ -58,7 +68,7 @@ def setupClass(cls):
             raise SkipTest('NumPy not available.')
 
     def setUp(self):
-    
+
         G=networkx.DiGraph()
 
         edges=[(1,2),(1,3),(2,4),(3,2),(3,5),(4,2),(4,5),(4,6),\
@@ -67,7 +77,7 @@ def setUp(self):
 
         G.add_edges_from(edges,weight=2.0)
         self.G=G
-        self.G.evc=[0.25368793,  0.19576478,  0.32817092,  0.40430835,  
+        self.G.evc=[0.25368793,  0.19576478,  0.32817092,  0.40430835,
                     0.48199885, 0.15724483,  0.51346196,  0.32475403]
 
         H=networkx.DiGraph()
@@ -78,7 +88,7 @@ def setUp(self):
 
         G.add_edges_from(edges)
         self.H=G
-        self.H.evc=[0.25368793,  0.19576478,  0.32817092,  0.40430835,  
+        self.H.evc=[0.25368793,  0.19576478,  0.32817092,  0.40430835,
                     0.48199885, 0.15724483,  0.51346196,  0.32475403]
 
 
diff --git a/networkx/algorithms/centrality/tests/test_katz_centrality.py b/networkx/algorithms/centrality/tests/test_katz_centrality.py
--- a/networkx/algorithms/centrality/tests/test_katz_centrality.py
+++ b/networkx/algorithms/centrality/tests/test_katz_centrality.py
@@ -194,6 +194,32 @@ def test_bad_beta_numbe(self):
         e = networkx.katz_centrality_numpy(G, 0.1,beta='foo')
 
 
+    def test_K5_unweighted(self):
+        """Katz centrality: K5"""
+        G = networkx.complete_graph(5)
+        alpha = 0.1
+        b = networkx.katz_centrality(G, alpha, weight=None)
+        v = math.sqrt(1 / 5.0)
+        b_answer = dict.fromkeys(G, v)
+        for n in sorted(G):
+            assert_almost_equal(b[n], b_answer[n])
+        nstart = dict([(n, 1) for n in G])
+        b = networkx.eigenvector_centrality_numpy(G)
+        for n in sorted(G):
+            assert_almost_equal(b[n], b_answer[n], places=3)
+
+    def test_P3_unweighted(self):
+        """Katz centrality: P3"""
+        alpha = 0.1
+        G = networkx.path_graph(3)
+        b_answer = {0: 0.5598852584152165, 1: 0.6107839182711449,
+                    2: 0.5598852584152162}
+        b = networkx.katz_centrality_numpy(G, alpha, weight=None)
+        for n in sorted(G):
+            assert_almost_equal(b[n], b_answer[n], places=4)
+
+
+
 class TestKatzCentralityDirected(object):
     def setUp(self):
         G = networkx.DiGraph()