def approximate(x, psi_x, thresholds: list, max_ranks: list): """Approximate psi_x using HOSVD and HOCUR, respectively. Parameters ---------- x: array snapshot matrix psi_x: array transformed data matrix thresholds: list of floats tresholds for HOSVD max_ranks: list of ints maximum ranks for HOCUR Returns ------- ranks_hosvd: list of lists of ints ranks of the approximations computed with HOSVD errors_hosvd: list of floats relative errors of the approximations computed with HOSVD ranks_hocur: list of lists of ints ranks of the approximations computed with HOCUR errors_hocur: list of floats relative errors of the approximations computed with HOCUR """ # define returns ranks_hosvd = [] errors_hosvd = [] ranks_hocur = [] errors_hocur = [] start_time = utl.progress('Approximation in TT format', 0) # reshape psi_x into tensor psi_x_full = psi_x.reshape([number_of_boxes, number_of_boxes, 1, 1, 1, psi_x.shape[1]]) # approximate psi_x using HOSVD for i in range(len(thresholds)): psi_approx = TT(psi_x_full, threshold=thresholds[i]) ranks_hosvd.append(psi_approx.ranks) errors_hosvd.append(np.linalg.norm(psi_x_full - psi_approx.full()) / np.linalg.norm(psi_x_full)) utl.progress('Approximation in TT format', 100 * (i + 1) / 6, cpu_time=_time.time() - start_time) # approximate psi_x using HOCUR for i in range(len(max_ranks)): psi_approx = tdt.hocur(x, basis_list, max_ranks[i], repeats=3, multiplier=100, progress=False) ranks_hocur.append(psi_approx.ranks) errors_hocur.append(np.linalg.norm(psi_x - psi_approx.transpose(cores=2).matricize()) / np.linalg.norm(psi_x)) utl.progress('Approximation in TT format', 100 * (i + 4) / 6, cpu_time=_time.time() - start_time) return ranks_hosvd, errors_hosvd, ranks_hocur, errors_hocur
def test_hocur(self): """test higher-order CUR decomposition""" tdt_1 = tdt.basis_decomposition(self.data, self.phi_1).transpose(cores=[self.d]).matricize() tdt_2 = tdt.hocur(self.data, self.phi_1, 5, repeats=10, progress=False).transpose(cores=[self.d]).matricize() self.assertLess(np.sum(np.abs(tdt_1-tdt_2)), self.tol)
def amuset_hocur(data_matrix, x_indices, y_indices, basis_list, max_rank=1000, multiplier=2, progress=False): """ AMUSEt (AMUSE on tensors) using HOCUR. Apply tEDMD to a given data matrix by using AMUSEt with HOCUR. This procedure is a tensor-based version of AMUSE using the tensor-train format. For more details, see [1]_. Parameters ---------- data_matrix : np.ndarray snapshot matrix x_indices : np.ndarray or list[np.ndarray] index sets for snapshot matrix x y_indices : np.ndarray or list[np.ndarray] index sets for snapshot matrix y basis_list : list[list[function]] list of basis functions in every mode max_rank : int, optional maximum ranks for HOSVD as well as HOCUR, default is 1000 multiplier : int multiplier for HOCUR progress : boolean, optional whether to show progress bar, default is False Returns ------- eigenvalues : np.ndarray or list[np.ndarray] tEDMD eigenvalues eigentensors : TT or list[TT] tEDMD eigentensors in TT format References ---------- ..[1] F. Nüske, P. Gelß, S. Klus, C. Clementi. "Tensor-based EDMD for the Koopman analysis of high-dimensional systems", arXiv:1908.04741, 2019 """ # define quantities eigenvalues = [] eigentensors = [] # construct transformed data tensor in TT format using HOCUR psi = tdt.hocur(data_matrix, basis_list, max_rank, repeats=1, multiplier=multiplier, progress=progress) # left-orthonormalization psi = psi.ortho_left(progress=progress) # extract last core last_core = psi.cores[-1] # convert x_indices and y_indices to lists if not isinstance(x_indices, list): x_indices = [x_indices] y_indices = [y_indices] # loop over all index sets for i in range(len(x_indices)): # compute reduced matrix matrix, u, s, v = _reduced_matrix(last_core, x_indices[i], y_indices[i]) # solve reduced eigenvalue problem eigenvalues_reduced, eigenvectors_reduced = np.linalg.eig(matrix) idx = (np.abs(eigenvalues_reduced - 1)).argsort() eigenvalues_reduced = np.real(eigenvalues_reduced[idx]) eigenvectors_reduced = np.real(eigenvectors_reduced[:, idx]) # construct eigentensors eigentensors_tmp = psi eigentensors_tmp.cores[-1] = u.dot(np.diag(np.reciprocal(s))).dot(eigenvectors_reduced)[:, :, None, None] # append results eigenvalues.append(eigenvalues_reduced) eigentensors.append(eigentensors_tmp) # only return lists if more than one set of x-indices/y-indices was given if len(x_indices) == 1: eigenvalues = eigenvalues[0] eigentensors = eigentensors[0] return eigenvalues, eigentensors