def test_bug_9793(self, dtype, rand, eps): if _IS_32BIT and dtype == np.complex_ and rand: pytest.xfail("bug in external fortran code") A = np.array( [[-1, -1, -1, 0, 0, 0], [0, 0, 0, 1, 1, 1], [1, 0, 0, 1, 0, 0], [0, 1, 0, 0, 1, 0], [0, 0, 1, 0, 0, 1]], dtype=dtype, order="C") B = A.copy() interp_decomp(A.T, eps, rand=rand) assert_array_equal(A, B)
def test_bug_9793(self): dtypes = [np.float_, np.complex_] rands = [True, False] epss = [1, 0.1] for dtype, eps, rand in itertools.product(dtypes, epss, rands): A = np.array( [[-1, -1, -1, 0, 0, 0], [0, 0, 0, 1, 1, 1], [1, 0, 0, 1, 0, 0], [0, 1, 0, 0, 1, 0], [0, 0, 1, 0, 0, 1]], dtype=dtype, order="C") B = A.copy() interp_decomp(A.T, eps, rand=rand) assert_array_equal(A, B)
def test_id_to_svd(self, A, eps, rank): k = rank idx, proj = pymatrixid.interp_decomp(A, k, rand=False) U, S, V = pymatrixid.id_to_svd(A[:, idx[:k]], idx, proj) B = U * S @ V.T.conj() assert_allclose(A, B, rtol=eps, atol=1e-08)
def test_real_id_fixed_rank(self, A, L, eps, rank, rand, lin_op): if _IS_32BIT and A.dtype == np.complex_ and rand: pytest.xfail("bug in external fortran code") k = rank A_or_L = A if not lin_op else L idx, proj = pymatrixid.interp_decomp(A_or_L, k, rand=rand) B = pymatrixid.reconstruct_matrix_from_id(A[:, idx[:k]], idx, proj) assert_allclose(A, B, rtol=eps, atol=1e-08)
def extract_independent_columns_ID(A, rank): if rank == 'randomized_rank': rank = compute_rank(A) elif rank == 'exact_rank': rank = exact_rank(A, eps=10**-5) col_idxs, _ = ID.interp_decomp(A, eps_or_k=rank, rand=True) return col_idxs[:rank]
def test_full_rank(self): eps = 1.0e-12 # fixed precision A = np.random.rand(16, 8) k, idx, proj = pymatrixid.interp_decomp(A, eps) assert_equal(k, A.shape[1]) P = pymatrixid.reconstruct_interp_matrix(idx, proj) B = pymatrixid.reconstruct_skel_matrix(A, k, idx) assert_allclose(A, B @ P) # fixed rank idx, proj = pymatrixid.interp_decomp(A, k) P = pymatrixid.reconstruct_interp_matrix(idx, proj) B = pymatrixid.reconstruct_skel_matrix(A, k, idx) assert_allclose(A, B @ P)
def test_full_rank(self): eps = 1.0e-12 # fixed precision A = np.random.rand(16, 8) k, idx, proj = pymatrixid.interp_decomp(A, eps) assert_(k == A.shape[1]) P = pymatrixid.reconstruct_interp_matrix(idx, proj) B = pymatrixid.reconstruct_skel_matrix(A, k, idx) assert_allclose(A, B.dot(P)) # fixed rank idx, proj = pymatrixid.interp_decomp(A, k) P = pymatrixid.reconstruct_interp_matrix(idx, proj) B = pymatrixid.reconstruct_skel_matrix(A, k, idx) assert_allclose(A, B.dot(P))
def test_real_id_skel_and_interp_matrices(self, A, L, eps, rank, rand, lin_op): k = rank A_or_L = A if not lin_op else L idx, proj = pymatrixid.interp_decomp(A_or_L, k, rand=rand) P = pymatrixid.reconstruct_interp_matrix(idx, proj) B = pymatrixid.reconstruct_skel_matrix(A, k, idx) assert_allclose(B, A[:, idx[:k]], rtol=eps, atol=1e-08) assert_allclose(B @ P, A, rtol=eps, atol=1e-08)
def randsvd(A, eps_or_k): """ Interpolative decomposition computed using randomized SVD approach. It is a wrapper for scipy.linalg.interpolative Parameters: ---------- eps_or_k : float or int Relative error (if `eps_or_k < 1`) or rank (if `eps_or_k >= 1`) of approximation. Returns: -------- u : {(m, k) } array Unitary matrices. The actual shape depends on the value of ``full_matrices``. Only returned when ``compute_uv`` is True. s : (k,) array The singular values for every matrix, sorted in descending order. v : {(n, k) } array Unitary matrices. The actual shape depends on the value of ``full_matrices``. Only returned when ``compute_uv`` is True. Notes: ------ See scipy.linalg.interpolative function interp_decomp, id_to_svd """ from scipy.linalg.interpolative import interp_decomp, id_to_svd if eps_or_k < 1: k, idx, proj = interp_decomp(A, eps_or_k) B = A[:,idx[:k]] else: idx, proj= interp_decomp(A, eps_or_k) k = eps_or_k B = A[:,idx[:k]] u, s, vh = id_to_svd(B, idx, proj) return u, s, vh
def ID(A, k): """ A_{m,n}=A[:,J] P :return P: k by n """ idx, proj = sli.interp_decomp(A, k) J = idx[:k] kp = np.eye(k) if len(proj): kp = np.hstack((kp, proj)) P = kp[:, np.argsort(idx)] return J, P
def __row_extraction(self): A = self.A Q = self.Q m, n = A.shape m, k = Q.shape idx, proj = sli.interp_decomp(Q, k, rand=False) Qj = sli.reconstruct_skel_matrix(Q, k, idx) X = sli.reconstruct_interp_matrix(idx, proj) Qj = Qj.T X = X.T V, R = linalg.qr(X) Ajj = A[np.ix_(idx, idx)] Z = np.dot(R, np.dot(Ajj, R)) w, W = linalg.eig(Z) U = np.dot(V, W) return w, U
def __row_extraction(self): A = self.A Q = self.Q m, n = A.shape m, k = Q.shape idx, proj = sli.interp_decomp(Q, k, rand=False) Qj = sli.reconstruct_skel_matrix(Q, k, idx) X = sli.reconstruct_interp_matrix(idx, proj) Qj = Qj.T X = X.T Aj = A[idx, :] W, R = linalg.qr(Aj.T) Z = np.dot(X, R.T) U, sigma, Vt = linalg.svd(Z) V = np.dot(W, Vt.T) Vt = V.T return U, sigma, Vt
def check_id(self, dtype): # Test ID routines on a Hilbert matrix. # set parameters n = 300 eps = 1e-12 # construct Hilbert matrix A = hilbert(n).astype(dtype) if np.issubdtype(dtype, np.complexfloating): A = A * (1 + 1j) L = aslinearoperator(A) # find rank S = np.linalg.svd(A, compute_uv=False) try: rank = np.nonzero(S < eps)[0][0] except: rank = n # print input summary _debug_print("Hilbert matrix dimension: %8i" % n) _debug_print("Working precision: %8.2e" % eps) _debug_print("Rank to working precision: %8i" % rank) # set print format fmt = "%8.2e (s) / %5s" # test real ID routines _debug_print("-----------------------------------------") _debug_print("Real ID routines") _debug_print("-----------------------------------------") # fixed precision _debug_print("Calling iddp_id / idzp_id ...", ) t0 = time.clock() k, idx, proj = pymatrixid.interp_decomp(A, eps, rand=False) t = time.clock() - t0 B = pymatrixid.reconstruct_matrix_from_id(A[:, idx[:k]], idx, proj) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) _debug_print("Calling iddp_aid / idzp_aid ...", ) t0 = time.clock() k, idx, proj = pymatrixid.interp_decomp(A, eps) t = time.clock() - t0 B = pymatrixid.reconstruct_matrix_from_id(A[:, idx[:k]], idx, proj) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) _debug_print("Calling iddp_rid / idzp_rid ...", ) t0 = time.clock() k, idx, proj = pymatrixid.interp_decomp(L, eps) t = time.clock() - t0 B = pymatrixid.reconstruct_matrix_from_id(A[:, idx[:k]], idx, proj) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) # fixed rank k = rank _debug_print("Calling iddr_id / idzr_id ...", ) t0 = time.clock() idx, proj = pymatrixid.interp_decomp(A, k, rand=False) t = time.clock() - t0 B = pymatrixid.reconstruct_matrix_from_id(A[:, idx[:k]], idx, proj) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) _debug_print("Calling iddr_aid / idzr_aid ...", ) t0 = time.clock() idx, proj = pymatrixid.interp_decomp(A, k) t = time.clock() - t0 B = pymatrixid.reconstruct_matrix_from_id(A[:, idx[:k]], idx, proj) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) _debug_print("Calling iddr_rid / idzr_rid ...", ) t0 = time.clock() idx, proj = pymatrixid.interp_decomp(L, k) t = time.clock() - t0 B = pymatrixid.reconstruct_matrix_from_id(A[:, idx[:k]], idx, proj) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) # check skeleton and interpolation matrices idx, proj = pymatrixid.interp_decomp(A, k, rand=False) P = pymatrixid.reconstruct_interp_matrix(idx, proj) B = pymatrixid.reconstruct_skel_matrix(A, k, idx) assert_(np.allclose(B, A[:, idx[:k]], eps)) assert_(np.allclose(B.dot(P), A, eps)) # test SVD routines _debug_print("-----------------------------------------") _debug_print("SVD routines") _debug_print("-----------------------------------------") # fixed precision _debug_print("Calling iddp_svd / idzp_svd ...", ) t0 = time.clock() U, S, V = pymatrixid.svd(A, eps, rand=False) t = time.clock() - t0 B = np.dot(U, np.dot(np.diag(S), V.T.conj())) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) _debug_print("Calling iddp_asvd / idzp_asvd...", ) t0 = time.clock() U, S, V = pymatrixid.svd(A, eps) t = time.clock() - t0 B = np.dot(U, np.dot(np.diag(S), V.T.conj())) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) _debug_print("Calling iddp_rsvd / idzp_rsvd...", ) t0 = time.clock() U, S, V = pymatrixid.svd(L, eps) t = time.clock() - t0 B = np.dot(U, np.dot(np.diag(S), V.T.conj())) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) # fixed rank k = rank _debug_print("Calling iddr_svd / idzr_svd ...", ) t0 = time.clock() U, S, V = pymatrixid.svd(A, k, rand=False) t = time.clock() - t0 B = np.dot(U, np.dot(np.diag(S), V.T.conj())) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) _debug_print("Calling iddr_asvd / idzr_asvd ...", ) t0 = time.clock() U, S, V = pymatrixid.svd(A, k) t = time.clock() - t0 B = np.dot(U, np.dot(np.diag(S), V.T.conj())) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) _debug_print("Calling iddr_rsvd / idzr_rsvd ...", ) t0 = time.clock() U, S, V = pymatrixid.svd(L, k) t = time.clock() - t0 B = np.dot(U, np.dot(np.diag(S), V.T.conj())) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) # ID to SVD idx, proj = pymatrixid.interp_decomp(A, k, rand=False) Up, Sp, Vp = pymatrixid.id_to_svd(A[:, idx[:k]], idx, proj) B = U.dot(np.diag(S).dot(V.T.conj())) assert_(np.allclose(A, B, eps)) # Norm estimates s = svdvals(A) norm_2_est = pymatrixid.estimate_spectral_norm(A) assert_(np.allclose(norm_2_est, s[0], 1e-6)) B = A.copy() B[:, 0] *= 1.2 s = svdvals(A - B) norm_2_est = pymatrixid.estimate_spectral_norm_diff(A, B) assert_(np.allclose(norm_2_est, s[0], 1e-6)) # Rank estimates B = np.array([[1, 1, 0], [0, 0, 1], [0, 0, 1]], dtype=dtype) for M in [A, B]: ML = aslinearoperator(M) rank_tol = 1e-9 rank_np = np.linalg.matrix_rank(M, norm(M, 2) * rank_tol) rank_est = pymatrixid.estimate_rank(M, rank_tol) rank_est_2 = pymatrixid.estimate_rank(ML, rank_tol) assert_(rank_est >= rank_np) assert_(rank_est <= rank_np + 10) assert_(rank_est_2 >= rank_np - 4) assert_(rank_est_2 <= rank_np + 4)
def hoid(T, rank=None, eps=None, method='qr', compute_core=True): """ Parameters: ----------- T: (I_1,...,I_d) dtensor object of dtensor class. See scikit.dtensor rank: (r_1,...,r_d) int array, optional Ranks of the individual modes eps: float, optional Relative error of the representation method: {'qr','randsvd'} string, optional qr uses pivoted QR, 'interpolative' uses scipy.linalg.interpolative Uses 'qr' by default compute_core: bool, optional Compute core tensor by projection. True by default Returns: -------- T: object of Tucker class G - core, U - list of mode vectors, I - index list. Returned if compute_core = True ulst: list List of column vectors. Returned if compute_core = False """ modes = matricize(T) dim = T.ndim assert (rank is not None) or (eps is not None) if eps is not None: eps_or_k = eps / np.sqrt(dim) clst, indlst = [], [] for d, mode in zip(range(dim), modes): if rank is not None: eps_or_k = rank[d] if method == 'qr': p, _ = id_(mode, eps_or_k) elif method == 'rrqr': assert eps_or_k >= 1. _, _, p = srrqr(mode, eps_or_k) elif method == 'rid': assert eps_or_k >= 1. rpp = mode.shape[0] + 10 #Oversampling factor Omega = np.random.randn(rpp, mode.shape[0]) ind, _ = interp_decomp(np.dot(Omega, mode), eps_or_k, rand=False) p = ind[:eps_or_k] elif method == 'randsvd': assert eps_or_k >= 1. k = eps_or_k ind, _ = interp_decomp(mode, eps_or_k) p = ind[:k] else: raise NotImplementedError c = mode[:, p] clst.append(c) indlst.append(p) #Compute core tensor if compute_core: cinv = [pinv(c, 1.e-8) for c in clst] G = T.ttm(cinv) return Tucker(G=G, U=clst, I=indlst) else: return clst
def _remove_redundancy_id(A, rhs, rank=None, randomized=True): """Eliminates redundant equations from a system of equations. Eliminates redundant equations from system of equations defined by Ax = b and identifies infeasibilities. Parameters ---------- A : 2-D array An array representing the left-hand side of a system of equations rhs : 1-D array An array representing the right-hand side of a system of equations rank : int, optional The rank of A randomized: bool, optional True for randomized interpolative decomposition Returns ------- A : 2-D array An array representing the left-hand side of a system of equations rhs : 1-D array An array representing the right-hand side of a system of equations status: int An integer indicating the status of the system 0: No infeasibility identified 2: Trivially infeasible message : str A string descriptor of the exit status of the optimization. """ status = 0 message = "" inconsistent = ("There is a linear combination of rows of A_eq that " "results in zero, suggesting a redundant constraint. " "However the same linear combination of b_eq is " "nonzero, suggesting that the constraints conflict " "and the problem is infeasible.") A, rhs, status, message = _remove_zero_rows(A, rhs) if status != 0: return A, rhs, status, message m, n = A.shape k = rank if rank is None: k = np.linalg.matrix_rank(A) idx, proj = interp_decomp(A.T, k, rand=randomized) # first k entries in idx are indices of the independent rows # remaining entries are the indices of the m-k dependent rows # proj provides a linear combinations of rows of A2 that form the # remaining m-k (dependent) rows. The same linear combination of entries # in rhs2 must give the remaining m-k entries. If not, the system is # inconsistent, and the problem is infeasible. if not np.allclose(rhs[idx[:k]] @ proj, rhs[idx[k:]]): status = 2 message = inconsistent # sort indices because the other redundancy removal routines leave rows # in original order and tests were written with that in mind idx = sorted(idx[:k]) A2 = A[idx, :] rhs2 = rhs[idx] return A2, rhs2, status, message
def IDLeft(matrix, rank, random=True): idx, proj = sli.interp_decomp(matrix, rank, rand=random) Askel = sli.reconstruct_skel_matrix(matrix, rank, idx) return Askel
def test_badcall(self): A = hilbert(5).astype(np.float32) with assert_raises(ValueError): pymatrixid.interp_decomp(A, 1e-6, rand=False)
def check_id(self, dtype): # Test ID routines on a Hilbert matrix. # set parameters n = 300 eps = 1e-12 # construct Hilbert matrix A = hilbert(n).astype(dtype) if np.issubdtype(dtype, np.complexfloating): A = A * (1 + 1j) L = aslinearoperator(A) # find rank S = np.linalg.svd(A, compute_uv=False) try: rank = np.nonzero(S < eps)[0][0] except: rank = n # print input summary _debug_print("Hilbert matrix dimension: %8i" % n) _debug_print("Working precision: %8.2e" % eps) _debug_print("Rank to working precision: %8i" % rank) # set print format fmt = "%8.2e (s) / %5s" # test real ID routines _debug_print("-----------------------------------------") _debug_print("Real ID routines") _debug_print("-----------------------------------------") # fixed precision _debug_print("Calling iddp_id / idzp_id ...",) t0 = time.clock() k, idx, proj = pymatrixid.interp_decomp(A, eps, rand=False) t = time.clock() - t0 B = pymatrixid.reconstruct_matrix_from_id(A[:, idx[:k]], idx, proj) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) _debug_print("Calling iddp_aid / idzp_aid ...",) t0 = time.clock() k, idx, proj = pymatrixid.interp_decomp(A, eps) t = time.clock() - t0 B = pymatrixid.reconstruct_matrix_from_id(A[:, idx[:k]], idx, proj) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) _debug_print("Calling iddp_rid / idzp_rid ...",) t0 = time.clock() k, idx, proj = pymatrixid.interp_decomp(L, eps) t = time.clock() - t0 B = pymatrixid.reconstruct_matrix_from_id(A[:, idx[:k]], idx, proj) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) # fixed rank k = rank _debug_print("Calling iddr_id / idzr_id ...",) t0 = time.clock() idx, proj = pymatrixid.interp_decomp(A, k, rand=False) t = time.clock() - t0 B = pymatrixid.reconstruct_matrix_from_id(A[:, idx[:k]], idx, proj) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) _debug_print("Calling iddr_aid / idzr_aid ...",) t0 = time.clock() idx, proj = pymatrixid.interp_decomp(A, k) t = time.clock() - t0 B = pymatrixid.reconstruct_matrix_from_id(A[:, idx[:k]], idx, proj) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) _debug_print("Calling iddr_rid / idzr_rid ...",) t0 = time.clock() idx, proj = pymatrixid.interp_decomp(L, k) t = time.clock() - t0 B = pymatrixid.reconstruct_matrix_from_id(A[:, idx[:k]], idx, proj) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) # check skeleton and interpolation matrices idx, proj = pymatrixid.interp_decomp(A, k, rand=False) P = pymatrixid.reconstruct_interp_matrix(idx, proj) B = pymatrixid.reconstruct_skel_matrix(A, k, idx) assert_(np.allclose(B, A[:,idx[:k]], eps)) assert_(np.allclose(B.dot(P), A, eps)) # test SVD routines _debug_print("-----------------------------------------") _debug_print("SVD routines") _debug_print("-----------------------------------------") # fixed precision _debug_print("Calling iddp_svd / idzp_svd ...",) t0 = time.clock() U, S, V = pymatrixid.svd(A, eps, rand=False) t = time.clock() - t0 B = np.dot(U, np.dot(np.diag(S), V.T.conj())) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) _debug_print("Calling iddp_asvd / idzp_asvd...",) t0 = time.clock() U, S, V = pymatrixid.svd(A, eps) t = time.clock() - t0 B = np.dot(U, np.dot(np.diag(S), V.T.conj())) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) _debug_print("Calling iddp_rsvd / idzp_rsvd...",) t0 = time.clock() U, S, V = pymatrixid.svd(L, eps) t = time.clock() - t0 B = np.dot(U, np.dot(np.diag(S), V.T.conj())) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) # fixed rank k = rank _debug_print("Calling iddr_svd / idzr_svd ...",) t0 = time.clock() U, S, V = pymatrixid.svd(A, k, rand=False) t = time.clock() - t0 B = np.dot(U, np.dot(np.diag(S), V.T.conj())) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) _debug_print("Calling iddr_asvd / idzr_asvd ...",) t0 = time.clock() U, S, V = pymatrixid.svd(A, k) t = time.clock() - t0 B = np.dot(U, np.dot(np.diag(S), V.T.conj())) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) _debug_print("Calling iddr_rsvd / idzr_rsvd ...",) t0 = time.clock() U, S, V = pymatrixid.svd(L, k) t = time.clock() - t0 B = np.dot(U, np.dot(np.diag(S), V.T.conj())) _debug_print(fmt % (t, np.allclose(A, B, eps))) assert_(np.allclose(A, B, eps)) # ID to SVD idx, proj = pymatrixid.interp_decomp(A, k, rand=False) Up, Sp, Vp = pymatrixid.id_to_svd(A[:, idx[:k]], idx, proj) B = U.dot(np.diag(S).dot(V.T.conj())) assert_(np.allclose(A, B, eps)) # Norm estimates s = svdvals(A) norm_2_est = pymatrixid.estimate_spectral_norm(A) assert_(np.allclose(norm_2_est, s[0], 1e-6)) B = A.copy() B[:,0] *= 1.2 s = svdvals(A - B) norm_2_est = pymatrixid.estimate_spectral_norm_diff(A, B) assert_(np.allclose(norm_2_est, s[0], 1e-6)) # Rank estimates B = np.array([[1, 1, 0], [0, 0, 1], [0, 0, 1]], dtype=dtype) for M in [A, B]: ML = aslinearoperator(M) rank_np = np.linalg.matrix_rank(M, 1e-9) rank_est = pymatrixid.estimate_rank(M, 1e-9) rank_est_2 = pymatrixid.estimate_rank(ML, 1e-9) assert_(rank_est >= rank_np) assert_(rank_est <= rank_np + 10) assert_(rank_est_2 >= rank_np) assert_(rank_est_2 <= rank_np + 10)
def imd(collection: Collection, taglist: List[str]=['all'], region: str='xanes', range: list=[-inf,inf], eps: float=1e-4, kweight: int=2) -> Dataset: """Computes the interpolative matrix decomposition for a collection. Parameters ---------- collection Collection with the groups to compute the rank. taglist List with keys to filter groups based on their ``tags`` attributes in the Collection. The default is ['all']. region XAFS region to compute the rank. Accepted values are 'dxanes', 'xanes', or 'exafs'. The default is 'xanes'. range Domain range in absolute values. Energy units are expected for 'dxanes' or 'xanes', while wavenumber (k) units are expected for 'exafs'. The default is [-:data:`~numpy.inf`, :data:`~numpy.inf`]. eps Relative error of approximation. The default is 1e-4. kweight Exponent for weighting chi(k) by k^kweight. Only valid for ``region='exafs'``. The default is 2. Returns ------- : Dataset with the following arguments: - ``rank`` : matrix rank. - ``idx`` : column index array. - ``proj`` : interpolation coefficients. - ``groupnames`` : list with names of groups. - ``energy`` : array with energy values. Returned only if ``region='xanes`` or ``region=dxanes``. - ``k`` : array with wavenumber values. Returned only if ``region='exafs'``. - ``matrix`` : array with observed values for groups in ``range``. - ``id_pars`` : dictionary with parameters of calculation. Notes ----- The interpolative decomposition (ID) of a :math:`m` by :math:`n` matrix :math:`A` of rank :math:`k < min\{m,n\}` is a factorization of the following form, .. math:: A\Pi = [A\Pi_1 \quad A\Pi_2 ] = A \Pi_1 [I \quad T] where :math:`\Pi = [\Pi_1 \quad \Pi_2]` is a permutation matrix, with :math:`\Pi_1` being a :math:`k` by :math:`n` matrix. The latter can be equivalently written as :math:`A = BP`, where :math:`B` is known as the *skeleton matrix*, while :math:`P` is known as the *interpolation matrix*. Therefore, the original matrix can be factorized into an skeleton matrix that preserves the original matrix rank, while the rest of the original matrix can be reconstructed through the interpolation matrix. Computation of the interpolative decompsition method is performed with the :func:`~scipy.linalg.interpolative.interp_decomp` function of ``scipy``, which is based on the ID software package [2]_. Therefore, the *skeleton matrix* can be computed as follows:: B = A[:,idx[:rank]] while the *interpolation matrix* can be computed as follows:: P = numpy.hstack([numpy.eye(rank), proj])[:, np.argsort(idx)] References ---------- .. [2] P.G. Martinsson, V. Rokhlin, Y. Shkolnisky, M. Tygert. “ID: a software package for low-rank approximation of matrices via interpolative decompositions, version 0.2.” http://tygert.com/id_doc.4.pdf. Example ------- >>> from araucaria.testdata import get_testpath >>> from araucaria import Dataset >>> from araucaria.xas import pre_edge, autobk >>> from araucaria.linalg import imd >>> from araucaria.io import read_collection_hdf5 >>> from araucaria.utils import check_objattrs >>> fpath = get_testpath('Fe_database.h5') >>> collection = read_collection_hdf5(fpath) >>> collection.apply(pre_edge) >>> out = imd(collection, region='xanes') >>> attrs = ['groupnames', 'energy', 'matrix', 'rank', 'idx', 'proj', 'id_pars'] >>> check_objattrs(out, Dataset, attrs) [True, True, True, True, True, True, True] >>> print(out.idx) [0 1 3 2] """ xvals, matrix = get_mapped_data(collection, taglist=taglist, region=region, range=range, kweight=kweight) # condtion number rnk, idx, proj = interp_decomp(matrix, eps_or_k=eps) # storing parameters id_pars = {'region' : region, 'range' : range, 'eps' : eps,} # additional parameters if region == 'exafs': xvar = 'k' # x-variable rank_pars['kweight'] = kweight else: # xanes/dxanes clustering xvar = 'energy' # x-variable # storing cluster results content = {'groupnames' : collection.get_names(taglist=taglist), xvar : xvals, 'matrix' : matrix, 'rank' : rnk, 'idx' : idx, 'proj' : proj, 'id_pars' : id_pars,} out = Dataset(**content) return out
import numpy as np import scipy.linalg as la import matplotlib.pyplot as plt n = 100 A0 = np.random.randn(n, n) U0, sigma0, VT0 = la.svd(A0) print(la.norm((U0 * sigma0).dot(VT0) - A0)) sigma = np.exp(-np.arange(n)) A = (U0 * sigma).dot(VT0) print("A:{}".format(A.shape)) plt.semilogy(sigma) import scipy.linalg.interpolative as sli k = 20 idx, proj = sli.interp_decomp(A, k) print("idx:{}".format(idx.shape)) print("proj:{}".format(proj.shape)) sort_idx = np.argsort(idx) B = A[:, idx[:k]] P = np.hstack([np.eye(k), proj])[:, np.argsort(idx)] print("B:{}".format(B.shape)) print("P:{}".format(P.shape)) Aapprox = np.dot(B, P) print("norm:{}".format(la.norm(A - Aapprox, 2)))
def hoid(T, rank = None, eps = None, method = 'qr', compute_core = True): """ Parameters: ----------- T: (I_1,...,I_d) dtensor object of dtensor class. See scikit.dtensor rank: (r_1,...,r_d) int array, optional Ranks of the individual modes eps: float, optional Relative error of the representation method: {'qr','randsvd'} string, optional qr uses pivoted QR, 'interpolative' uses scipy.linalg.interpolative Uses 'qr' by default compute_core: bool, optional Compute core tensor by projection. True by default Returns: -------- T: object of Tucker class G - core, U - list of mode vectors, I - index list. Returned if compute_core = True ulst: list List of column vectors. Returned if compute_core = False """ modes = matricize(T) dim = T.ndim assert (rank is not None) or (eps is not None) if eps is not None: eps_or_k = eps/np.sqrt(dim) clst, indlst = [], [] for d, mode in zip(range(dim), modes): if rank is not None: eps_or_k = rank[d] if method == 'qr': p, _ = id_(mode, eps_or_k) elif method == 'rrqr': assert eps_or_k >= 1. _,_,p = srrqr(mode, eps_or_k) elif method == 'rid': assert eps_or_k >= 1. rpp = mode.shape[0] + 10 #Oversampling factor Omega = np.random.randn(rpp,mode.shape[0]) ind, _ = interp_decomp(np.dot(Omega,mode), eps_or_k, rand = False) p = ind[:eps_or_k] elif method == 'randsvd': assert eps_or_k >= 1. k = eps_or_k ind, _ = interp_decomp(mode, eps_or_k) p = ind[:k] else: raise NotImplementedError c = mode[:, p] clst.append(c) indlst.append(p) #Compute core tensor if compute_core: cinv = [pinv(c, 1.e-8) for c in clst] G = T.ttm(cinv) return Tucker(G = G, U = clst, I = indlst) else: return clst