def eigen_decomp(X, real_part=False, right=True, sparse_comp=False): """ FUNCTION: Computes the eigen-decomposition of X. INPUTS: X = square matrix real_part = suppress complex part of evals,evecs sparse_comp = sparse matrix computation right = True, right-multiplying transition/generator matrix i.e. dot(rho) = rho O NOTE: Eigenvectors are organized column-wise! Sparse format typically not faster for eigen-decomposition. # TODO check that numpy/scipy is compiled against openblas as this will parallelize eigen_decomp automagically. """ if sparse_comp: import scipy.sparse.linalg as LA import scipy.sparse as sp X = sp.csr_matrix(X) if right: # right eigenvectors if is_symmetric(X): evals, EVECS = LA.eigsh(X) else: evals, EVECS = LA.eigs(X) else: # left eigenvectors if is_symmetric(X): evals, EVECS = LA.eigsh(X.T) else: evals, EVECS = LA.eigs(X.T) else: import numpy.linalg as LA if right: # right eigenvectors if is_symmetric(X): evals, EVECS = LA.eigh(X) else: evals, EVECS = LA.eig(X) else: # left eigenvectors if is_symmetric(X): evals, EVECS = LA.eigh(X.T) else: evals, EVECS = LA.eig(X.T) # eigenspectrum ordering from low-frequency (low abs e-vals) to high-frequency (high abs e-vals) ix = np.argsort(np.abs(evals)) EVECS = EVECS[:, ix] evals = evals[ix] evals[np.abs(evals) < config.min_val] = 0.0 if real_part: evals = np.real(evals) EVECS = np.real(EVECS) return evals, EVECS
def fit_transform(self, X, L): if L.shape[0] != L.shape[1] or L.shape[0] != X.shape[1]: raise ValueError("Laplacian matrix is of wrong shape") XtX = X.T.dot(X) n = XtX.shape[0] lambda_n = splinalg.eigh(XtX, k=1, which='LM')[0][0] eta_n = splinalg.eigh( L, k=1, which='LM')[0][0] #Largest eigenvalues of XtX and L, respectively newmat = (1 - self.beta) * (sparse.eye(n) - XtX / lambda_n) + (self.beta) * (L / eta_n) newd, newv = splinalg.eigh(newmat, k=self.n_components, which='SM') self.U = X.dot(newv) self.Qt = newv.T return self.U
def weighted_current(h, nk=400, fun=None): """Calculate the Ground state current""" if fun is None: delta = 0.01 def fun(e): return (-np.tanh(e / delta) + 1.0) / 2.0 jgs = np.zeros(h.intra.shape[0]) # current array hkgen = h.get_hk_gen() # generator fj = current_operator(h) # current operator ks = np.linspace(0.0, 1.0, nk, endpoint=False) # k-points for k in ks: # loop hk = hkgen(k) # Hamiltonian (es, ws) = lg.eigh(hk) # diagonalize ws = ws.transpose() # transpose jk = fj(k) # get the generator for (e, w) in zip(es, ws): # loop weight = fun(e) # weight print(weight) d = np.conjugate(w) * ket_Aw(jk, w) # current density jgs += d.real * weight # add contribution # jgs += (np.abs(w)**2*weight).real # add contribution jgs /= nk # normalize print("Total current", np.sum(jgs)) np.savetxt("CURRENT1D.OUT", np.matrix([range(len(jgs)), jgs]).T)
def current1d(h,nk=100,e=0.0,delta=0.01): """Calcualte the spatial profile of the current""" if h.dimensionality != 1: raise # only 1 dimensional hkgen = h.get_hk_gen() # get generator of the hamiltonian ks = np.linspace(0,1.,nk) # generate k points for k in ks: # loop over kpoints hk = hkgen(k) # get k-hamiltonian phik = np.exp(1j*2.*np.pi*k) # complex phase jk = 1j*(h.inter*phik - h.inter.H*np.conjugate(phik)) # current evasl,evecs = lg.eigh(hk) # eigenvectors and eigenvalues
def current1d(h, nk=100, e=0.0, delta=0.01): """Calcualte the spatial profile of the current""" if h.dimensionality != 1: raise # only 1 dimensional hkgen = h.get_hk_gen() # get generator of the hamiltonian ks = np.linspace(0, 1., nk) # generate k points for k in ks: # loop over kpoints hk = hkgen(k) # get k-hamiltonian phik = np.exp(1j * 2. * np.pi * k) # complex phase jk = 1j * (h.inter * phik - h.inter.H * np.conjugate(phik)) # current evasl, evecs = lg.eigh(hk) # eigenvectors and eigenvalues
def sqrtm_rotated(M): """Square root for Hermitian matrix in the diagonal basis, and rotation matrix""" import scipy.linalg as lg (evals,evecs) = lg.eigh(M) # eigenvals and eigenvecs if np.min(evals)<-0.001: raise # if it is not positive defined evecs = np.matrix(evecs).H # change of basis m2 = np.matrix([[0.0 for i in evals] for j in evals]) # create matrix for i in range(len(evals)): m2[i,i] = np.sqrt(np.abs(evals[i])) # square root # m2 = evecs.H * m2 * evecs # change of basis return (m2,evecs) # return matrix
def sqrtm_rotated(M): """Square root for Hermitian matrix in the diagonal basis, and rotation matrix""" import scipy.linalg as lg (evals, evecs) = lg.eigh(M) # eigenvals and eigenvecs if np.min(evals) < -0.001: raise # if it is not positive defined evecs = np.matrix(evecs).H # change of basis m2 = np.matrix([[0.0 for i in evals] for j in evals]) # create matrix for i in range(len(evals)): m2[i, i] = np.sqrt(np.abs(evals[i])) # square root # m2 = evecs.H * m2 * evecs # change of basis return (m2, evecs) # return matrix
def compute_largest_eigenvector(self, matrix): ''' compute the largest eigenvector for the matrix the matrix should be sparse return scipy.array ''' from scipy import linalg # SA is an important parameter for computing the smallest eigen value and the respective eigen vector # eigsh is special for symmetric matrix eig_index = (matrix.shape[0] - 2, matrix.shape[0] - 1) eigValue, eigMatrix = linalg.eigh(a=matrix, overwrite_a=True, eigvals=eig_index) return eigMatrix[:, 1]
def to_structure(matrix, alpha=1): """Compute best matching 3D genome structure from underlying input matrix using ShRec3D-derived method from Lesne et al., 2014. Link: https://www.ncbi.nlm.nih.gov/pubmed/25240436 The method performs two steps: first compute distance matrix by treating contact data as an adjacency graph (of weights equal to a power law function of the data), then embed the resulting distance matrix into 3D space. The alpha parameter influences the weighting of contacts: if alpha < 1 long-range interactions are prioritized; if alpha >> 1 short-range interactions have more weight wahen computing the distance matrix. """ connected = largest_connected_component(matrix) distances = to_distance(connected, alpha) n, m = connected.shape bary = np.sum(np.triu(distances, 1)) / (n**2) # barycenters d = np.array(np.sum(distances**2, 0) / n - bary) # distances to origin gram = np.array([(d[i] + d[j] - distances[i][j]**2) / 2 for i, j in itertools.product(range(n), range(m)) ]).reshape(n, m) normalized = gram / np.linalg.norm(gram, "fro") try: symmetric = np.array((normalized + normalized.T) / 2, dtype=np.longfloat) # just in case except AttributeError: symmetric = np.array((normalized + normalized.T) / 2) from scipy import linalg eigen_values, eigen_vectors = linalg.eigh(symmetric) if not (eigen_values >= 0).all(): warnings.warn("Negative eigen values were found.") idx = eigen_values.argsort()[-3:][::-1] values = eigen_values[idx] vectors = eigen_vectors[:, idx] coordinates = vectors * np.sqrt(values) return coordinates
def to_structure(matrix, alpha=1): """Compute best matching 3D genome structure from underlying input matrix using ShRec3D-derived method from Lesne et al., 2014. The method performs two steps: first compute distance matrix by treating contact data as an adjacency graph (of weights equal to a power law function of the data), then embed the resulting distance matrix into 3D space. The alpha parameter influences the weighting of contacts: if alpha < 1 long-range interactions are prioritized; if alpha >> 1 short-range interactions have more weight wahen computing the distance matrix. """ connected = largest_connected_component(matrix) distances = to_distance(connected, alpha) n, m = connected.shape bary = np.sum(np.triu(distances, 1)) / (n**2) # barycenters d = np.array(np.sum(distances**2, 0) / n - bary) # distances to origin gram = np.array([(d[i] + d[j] - distances[i][j]**2) / 2 for i, j in itertools.product(range(n), range(m))]).reshape(n, m) normalized = gram / np.linalg.norm(gram, 'fro') try: symmetric = np.array((normalized + normalized.T) / 2, dtype=np.longfloat) # just in case except AttributeError: symmetric = np.array((normalized + normalized.T) / 2) from scipy import linalg eigen_values, eigen_vectors = linalg.eigh(symmetric) if not (eigen_values >= 0).all(): warnings.warn("I couldn't import mpmath for arbitrary precision calculations." "Computed eigen values may be negative which will impact" "resulting structure.") idx = eigen_values.argsort()[-3:][::-1] values = eigen_values[idx] vectors = eigen_vectors[:, idx] coordinates = vectors * np.sqrt(values) return coordinates
def weighted_current(h,nk=400,fun=None): """Calculate the Ground state current""" if fun is None: delta = 0.01 def fun(e): return (-np.tanh(e/delta) + 1.0)/2.0 jgs = np.zeros(h.intra.shape[0]) # current array hkgen = h.get_hk_gen() # generator fj = current_operator(h) # current operator ks = np.linspace(0.0,1.0,nk,endpoint=False) # k-points for k in ks: # loop hk = hkgen(k) # Hamiltonian (es,ws) = lg.eigh(hk) # diagonalize ws = ws.transpose() # transpose jk = fj(k) # get the generator for (e,w) in zip(es,ws): # loop weight = fun(e) # weight print(weight) d = np.conjugate(w)*ket_Aw(jk,w) # current density jgs += d.real*weight # add contribution # jgs += (np.abs(w)**2*weight).real # add contribution jgs /= nk # normalize print("Total current",np.sum(jgs)) np.savetxt("CURRENT1D.OUT",np.matrix([range(len(jgs)),jgs]).T)
# print(np.min(vals),np.max(vals)) # plt.hist(vals, histtype='step') # vals, vecs = linalg.eig(adj_I_rw.toarray()) # vals = vals.astype(np.float64) # print(np.min(vals),np.max(vals)) # plt.hist(vals, histtype='step') # plt.show() try: vals, vecs, vec_inv = np.load(dataset+'_vals.npy'), \ np.load(dataset+'_vecs.npy'), \ np.load(dataset + '_vec_inv.npy') print('load vals, vecs, vec_inv from files') except: vals, vecs = linalg.eigh(adj_I_sym.toarray()) vecs = d_I_inv_sqrt.dot(vecs) vec_inv = np.linalg.inv(vecs) # vals = vals.astype(np.float64) # vec_inv = vec_inv.astype(np.float64) np.save(dataset+'_vals.npy', vals) np.save(dataset+'_vecs.npy', vecs) np.save(dataset+'_vec_inv.npy', vec_inv) #unsmoothed ax = plt.subplot(321) plt.title('unsmoothed') # ax.set_yscale("log") # plt.axis([-0.1, 1.6, 0.1, 1e7]) transformed = vec_inv*features