summaryrefslogtreecommitdiff
path: root/lib/python2.7/site-packages/setoolsgui/networkx/algorithms/centrality/flow_matrix.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python2.7/site-packages/setoolsgui/networkx/algorithms/centrality/flow_matrix.py')
-rw-r--r--lib/python2.7/site-packages/setoolsgui/networkx/algorithms/centrality/flow_matrix.py139
1 files changed, 139 insertions, 0 deletions
diff --git a/lib/python2.7/site-packages/setoolsgui/networkx/algorithms/centrality/flow_matrix.py b/lib/python2.7/site-packages/setoolsgui/networkx/algorithms/centrality/flow_matrix.py
new file mode 100644
index 0000000..d886182
--- /dev/null
+++ b/lib/python2.7/site-packages/setoolsgui/networkx/algorithms/centrality/flow_matrix.py
@@ -0,0 +1,139 @@
+# Helpers for current-flow betweenness and current-flow closness
+# Lazy computations for inverse Laplacian and flow-matrix rows.
+import networkx as nx
+
+def flow_matrix_row(G, weight='weight', dtype=float, solver='lu'):
+ # Generate a row of the current-flow matrix
+ import numpy as np
+ from scipy import sparse
+ from scipy.sparse import linalg
+ solvername={"full" :FullInverseLaplacian,
+ "lu": SuperLUInverseLaplacian,
+ "cg": CGInverseLaplacian}
+ n = G.number_of_nodes()
+ L = laplacian_sparse_matrix(G, nodelist=range(n), weight=weight,
+ dtype=dtype, format='csc')
+ C = solvername[solver](L, dtype=dtype) # initialize solver
+ w = C.w # w is the Laplacian matrix width
+ # row-by-row flow matrix
+ for u,v,d in G.edges_iter(data=True):
+ B = np.zeros(w, dtype=dtype)
+ c = d.get(weight,1.0)
+ B[u%w] = c
+ B[v%w] = -c
+ # get only the rows needed in the inverse laplacian
+ # and multiply to get the flow matrix row
+ row = np.dot(B, C.get_rows(u,v))
+ yield row,(u,v)
+
+
+# Class to compute the inverse laplacian only for specified rows
+# Allows computation of the current-flow matrix without storing entire
+# inverse laplacian matrix
+class InverseLaplacian(object):
+ def __init__(self, L, width=None, dtype=None):
+ global np
+ import numpy as np
+ (n,n) = L.shape
+ self.dtype = dtype
+ self.n = n
+ if width is None:
+ self.w = self.width(L)
+ else:
+ self.w = width
+ self.C = np.zeros((self.w,n), dtype=dtype)
+ self.L1 = L[1:,1:]
+ self.init_solver(L)
+
+ def init_solver(self,L):
+ pass
+
+ def solve(self,r):
+ raise("Implement solver")
+
+ def solve_inverse(self,r):
+ raise("Implement solver")
+
+
+ def get_rows(self, r1, r2):
+ for r in range(r1, r2+1):
+ self.C[r%self.w, 1:] = self.solve_inverse(r)
+ return self.C
+
+ def get_row(self, r):
+ self.C[r%self.w, 1:] = self.solve_inverse(r)
+ return self.C[r%self.w]
+
+
+ def width(self,L):
+ m=0
+ for i,row in enumerate(L):
+ w=0
+ x,y = np.nonzero(row)
+ if len(y) > 0:
+ v = y-i
+ w=v.max()-v.min()+1
+ m = max(w,m)
+ return m
+
+class FullInverseLaplacian(InverseLaplacian):
+ def init_solver(self,L):
+ self.IL = np.zeros(L.shape, dtype=self.dtype)
+ self.IL[1:,1:] = np.linalg.inv(self.L1.todense())
+
+ def solve(self,rhs):
+ s = np.zeros(rhs.shape, dtype=self.dtype)
+ s = np.dot(self.IL,rhs)
+ return s
+
+ def solve_inverse(self,r):
+ return self.IL[r,1:]
+
+
+class SuperLUInverseLaplacian(InverseLaplacian):
+ def init_solver(self,L):
+ from scipy.sparse import linalg
+ self.lusolve = linalg.factorized(self.L1.tocsc())
+
+ def solve_inverse(self,r):
+ rhs = np.zeros(self.n, dtype=self.dtype)
+ rhs[r]=1
+ return self.lusolve(rhs[1:])
+
+ def solve(self,rhs):
+ s = np.zeros(rhs.shape, dtype=self.dtype)
+ s[1:]=self.lusolve(rhs[1:])
+ return s
+
+
+
+class CGInverseLaplacian(InverseLaplacian):
+ def init_solver(self,L):
+ global linalg
+ from scipy.sparse import linalg
+ ilu= linalg.spilu(self.L1.tocsc())
+ n=self.n-1
+ self.M = linalg.LinearOperator(shape=(n,n), matvec=ilu.solve)
+
+ def solve(self,rhs):
+ s = np.zeros(rhs.shape, dtype=self.dtype)
+ s[1:]=linalg.cg(self.L1, rhs[1:], M=self.M)[0]
+ return s
+
+ def solve_inverse(self,r):
+ rhs = np.zeros(self.n, self.dtype)
+ rhs[r] = 1
+ return linalg.cg(self.L1, rhs[1:], M=self.M)[0]
+
+
+# graph laplacian, sparse version, will move to linalg/laplacianmatrix.py
+def laplacian_sparse_matrix(G, nodelist=None, weight='weight', dtype=None,
+ format='csr'):
+ import numpy as np
+ import scipy.sparse
+ A = nx.to_scipy_sparse_matrix(G, nodelist=nodelist, weight=weight,
+ dtype=dtype, format=format)
+ (n,n) = A.shape
+ data = np.asarray(A.sum(axis=1).T)
+ D = scipy.sparse.spdiags(data,0,n,n, format=format)
+ return D - A