def test_compute_modes(self): ws = np.identity(self.num_states) tol = 1e-6 weights_full = np.mat(np.random.random((self.num_states, self.num_states))) weights_full = np.triu(weights_full) + np.triu(weights_full, 1).H weights_full = weights_full*weights_full weights_diag = np.random.random(self.num_states) weights_list = [None, weights_diag, weights_full] vec_array = np.random.random((self.num_states, self.num_vecs)) for weights in weights_list: IP = VectorSpaceMatrices(weights=weights).compute_inner_product_mat correlation_mat_true = IP(vec_array, vec_array) eigen_vals_true, eigen_vecs_true = util.eigh(correlation_mat_true) build_coeff_mat_true = eigen_vecs_true * np.mat(np.diag( eigen_vals_true**-0.5)) modes_true = vec_array.dot(build_coeff_mat_true) modes, eigen_vals, eigen_vecs, correlation_mat = \ compute_POD_matrices_snaps_method(vec_array, self.mode_indices, inner_product_weights=weights, return_all=True) np.testing.assert_allclose(eigen_vals, eigen_vals_true, rtol=tol) np.testing.assert_allclose(eigen_vecs, eigen_vecs_true) np.testing.assert_allclose(correlation_mat, correlation_mat_true) np.testing.assert_allclose(modes, modes_true[:,self.mode_indices]) modes, eigen_vals, eigen_vecs = \ compute_POD_matrices_direct_method(vec_array, self.mode_indices, inner_product_weights=weights, return_all=True) np.testing.assert_allclose(eigen_vals, eigen_vals_true) np.testing.assert_allclose(np.abs(eigen_vecs), np.abs(eigen_vecs_true)) np.testing.assert_allclose(np.abs(modes), np.abs(modes_true[:,self.mode_indices]))
def test_compute_modes(self): ws = np.identity(self.num_states) tol = 1e-6 # Generate different inner product weights. Each weight matrix should # be positive definite semidefinite. weights_full = np.mat( np.random.random((self.num_states, self.num_states))) weights_full = 0.5 * (weights_full + weights_full.T) weights_full = weights_full + self.num_states * np.eye(self.num_states) weights_diag = np.random.random(self.num_states) weights_list = [None, weights_diag, weights_full] vec_array = np.random.random((self.num_states, self.num_vecs)) for weights in weights_list: IP = VectorSpaceMatrices(weights=weights).compute_inner_product_mat correlation_mat_true = IP(vec_array, vec_array) eigvals_true, eigvecs_true = util.eigh(correlation_mat_true) build_coeff_mat_true = eigvecs_true * np.mat( np.diag(eigvals_true**-0.5)) modes_true = vec_array.dot(build_coeff_mat_true) modes, eigvals, eigvecs, correlation_mat = \ compute_POD_matrices_snaps_method(vec_array, self.mode_indices, inner_product_weights=weights, return_all=True) np.testing.assert_allclose(eigvals, eigvals_true, rtol=tol) np.testing.assert_allclose(eigvecs, eigvecs_true) np.testing.assert_allclose(correlation_mat, correlation_mat_true) np.testing.assert_allclose(modes, modes_true[:, self.mode_indices]) modes, eigvals, eigvecs = \ compute_POD_matrices_direct_method( vec_array, self.mode_indices, inner_product_weights=weights, return_all=True) np.testing.assert_allclose(eigvals, eigvals_true) np.testing.assert_allclose(np.abs(eigvecs), np.abs(eigvecs_true)) np.testing.assert_allclose( np.abs(modes), np.abs(modes_true[:, self.mode_indices]))
def test_compute_modes(self): ws = np.identity(self.num_states) tol = 1e-6 weights_full = np.mat( np.random.random((self.num_states, self.num_states))) weights_full = np.triu(weights_full) + np.triu(weights_full, 1).H weights_full = weights_full * weights_full weights_diag = np.random.random(self.num_states) weights_list = [None, weights_diag, weights_full] vec_array = np.random.random((self.num_states, self.num_vecs)) for weights in weights_list: IP = VectorSpaceMatrices(weights=weights).compute_inner_product_mat correlation_mat_true = IP(vec_array, vec_array) eigen_vals_true, eigen_vecs_true = util.eigh(correlation_mat_true) build_coeff_mat_true = eigen_vecs_true * np.mat( np.diag(eigen_vals_true**-0.5)) modes_true = vec_array.dot(build_coeff_mat_true) modes, eigen_vals, eigen_vecs, correlation_mat = \ compute_POD_matrices_snaps_method(vec_array, self.mode_indices, inner_product_weights=weights, return_all=True) np.testing.assert_allclose(eigen_vals, eigen_vals_true, rtol=tol) np.testing.assert_allclose(eigen_vecs, eigen_vecs_true) np.testing.assert_allclose(correlation_mat, correlation_mat_true) np.testing.assert_allclose(modes, modes_true[:, self.mode_indices]) modes, eigen_vals, eigen_vecs = \ compute_POD_matrices_direct_method(vec_array, self.mode_indices, inner_product_weights=weights, return_all=True) np.testing.assert_allclose(eigen_vals, eigen_vals_true) np.testing.assert_allclose(np.abs(eigen_vecs), np.abs(eigen_vecs_true)) np.testing.assert_allclose( np.abs(modes), np.abs(modes_true[:, self.mode_indices]))
def test_eigh(self): # Set tolerance for test of eigval/eigvec properties. Value necessary # for test to pass depends on array size, as well as atol and rtol # values test_atol = 1e-12 # Generate random array num_rows = 100 # Test arrays that are and are not positive definite for is_pos_def in [True, False]: # Test both real and complex data for is_complex in [True, False]: # Generate random array with values between 0 and 1 array = np.random.random((num_rows, num_rows)) if is_complex: array = array + 1j * np.random.random((num_rows, num_rows)) # Make array conjugate-symmetric. Note that if the array is # large, for some reason an in-place operation causes the # operation to fail (not sure why...). Values are still between # 0 and 1. array = 0.5 * (array + array.conj().T) # If necessary, make the array positive definite by first making # it symmetric (adding the transpose), and then making it # diagonally dominant (each element is less than 1, so add N * I # to make the diagonal dominant). Here an in-place change seems # to be ok. if is_pos_def: array = array + num_rows * np.eye(num_rows) # Make sure array is positive definite, otherwise # force test to quit. if np.linalg.eig(array)[0].min() < 0.: raise ValueError( 'Failed to generate positive definite array ' 'for test.') # Compute full set of eigenvalues to help choose tolerance # levels that guarantee truncation (otherwise tests won't # actually check those features). eigvals_full = np.linalg.eig(array)[0] atol_list = [np.median(abs(eigvals_full)), None] rtol_list = [ np.median(abs(eigvals_full)) / abs(np.max(eigvals_full)), None ] # Loop through different tolerance values for atol in atol_list: for rtol in rtol_list: # For each case, test that returned values are in fact # eigenvalues and eigenvectors of the given array. # Since each pair that is returned (not truncated due to # tolerances) should have this property, we can test # this even if tolerances are passed in. Compare to the # zero array because then we only have to check the # absolute magnitue of each term, rather than consider # relative errors with respect to nonzero terms. eigvals, eigvecs = util.eigh( array, rtol=rtol, atol=atol, is_positive_definite=is_pos_def) np.testing.assert_allclose( array.dot(eigvecs) - eigvecs.dot(np.diag(eigvals)), np.zeros(eigvecs.shape), atol=test_atol) # If either tolerance is nonzero, make sure that # something is actually truncated, otherwise force test # to quit. To do this, make sure the eigvec array is # not square. if rtol and eigvals.size == eigvals_full.size: raise ValueError( 'Failed to choose relative tolerance that ' 'forces truncation.') if atol and eigvals.size == eigvals_full.size: raise ValueError( 'Failed to choose absolute tolerance that ' 'forces truncation.') # If the positive definite flag is passed in, make sure # the returned eigenvalues are all positive if is_pos_def: self.assertTrue(eigvals.min() > 0) # If a relative tolerance is passed in, make sure the # relative tolerance is satisfied. if rtol is not None: self.assertTrue( abs(eigvals).min() / abs(eigvals).max() > rtol) # If an absolute tolerance is passed in, make sure the # absolute tolerance is satisfied. if atol is not None: self.assertTrue(abs(eigvals).min() > atol)
def _helper_compute_DMD_from_data(self, vec_array, inner_product, adv_vec_array=None, max_num_eigvals=None): # Generate adv_vec_array for the case of a sequential dataset if adv_vec_array is None: adv_vec_array = vec_array[:, 1:] vec_array = vec_array[:, :-1] # Create lists of vecs, advanced vecs for inner product function vecs = [vec_array[:, i] for i in range(vec_array.shape[1])] adv_vecs = [adv_vec_array[:, i] for i in range(adv_vec_array.shape[1])] # Compute SVD of data vectors correlation_mat = inner_product(vecs, vecs) correlation_mat_eigvals, correlation_mat_eigvecs = util.eigh( correlation_mat) U = vec_array.dot(np.array(correlation_mat_eigvecs)).dot( np.diag(correlation_mat_eigvals**-0.5)) U_list = [U[:, i] for i in range(U.shape[1])] # Truncate SVD if necessary if max_num_eigvals is not None and (max_num_eigvals < correlation_mat_eigvals.size): correlation_mat_eigvals = correlation_mat_eigvals[:max_num_eigvals] correlation_mat_eigvecs = correlation_mat_eigvecs[:, : max_num_eigvals] U = U[:, :max_num_eigvals] U_list = U_list[:max_num_eigvals] # Compute eigendecomposition of low order linear operator A_tilde = inner_product(U_list, adv_vecs).dot( np.array(correlation_mat_eigvecs)).dot( np.diag(correlation_mat_eigvals**-0.5)) eigvals, R_low_order_eigvecs, L_low_order_eigvecs =\ util.eig_biorthog(A_tilde, scale_choice='left') R_low_order_eigvecs = np.mat(R_low_order_eigvecs) L_low_order_eigvecs = np.mat(L_low_order_eigvecs) # Compute build coefficients build_coeffs_proj = (correlation_mat_eigvecs.dot( np.diag(correlation_mat_eigvals**-0.5)).dot(R_low_order_eigvecs)) build_coeffs_exact = (correlation_mat_eigvecs.dot( np.diag( correlation_mat_eigvals**-0.5)).dot(R_low_order_eigvecs).dot( np.diag(eigvals**-1.))) # Compute modes modes_proj = vec_array.dot(build_coeffs_proj) modes_exact = adv_vec_array.dot(build_coeffs_exact) adj_modes = U.dot(L_low_order_eigvecs) adj_modes_list = [ np.array(adj_modes[:, i]) for i in range(adj_modes.shape[1]) ] # Compute spectrum spectral_coeffs = np.abs( np.array(inner_product(adj_modes_list, vecs[0:1])).squeeze()) return (modes_exact, modes_proj, spectral_coeffs, eigvals, R_low_order_eigvecs, L_low_order_eigvecs, correlation_mat_eigvals, correlation_mat_eigvecs, adj_modes)
def test_eigh(self): # Set tolerance for test of eigval/eigvec properties. Value necessary # for test to pass depends on array size, as well as atol and rtol # values test_atol = 1e-12 # Generate random array num_rows = 100 # Test arrays that are and are not positive definite for is_pos_def in [True, False]: # Test both real and complex data for is_complex in [True, False]: # Generate random array with values between 0 and 1 array = np.random.random((num_rows, num_rows)) if is_complex: array = array + 1j * np.random.random((num_rows, num_rows)) # Make array conjugate-symmetric. Note that if the array is # large, for some reason an in-place operation causes the # operation to fail (not sure why...). Values are still between # 0 and 1. array = 0.5 * (array + array.conj().T) # If necessary, make the array positive definite by first making # it symmetric (adding the transpose), and then making it # diagonally dominant (each element is less than 1, so add N * I # to make the diagonal dominant). Here an in-place change seems # to be ok. if is_pos_def: array = array + num_rows * np.eye(num_rows) # Make sure array is positive definite, otherwise # force test to quit. if np.linalg.eig(array)[0].min() < 0.: raise ValueError( 'Failed to generate positive definite array ' 'for test.') # Compute full set of eigenvalues to help choose tolerance # levels that guarantee truncation (otherwise tests won't # actually check those features). eigvals_full = np.linalg.eig(array)[0] atol_list = [np.median(abs(eigvals_full)), None] rtol_list = [ np.median(abs(eigvals_full)) / abs(np.max(eigvals_full)), None] # Loop through different tolerance values for atol in atol_list: for rtol in rtol_list: # For each case, test that returned values are in fact # eigenvalues and eigenvectors of the given array. # Since each pair that is returned (not truncated due to # tolerances) should have this property, we can test # this even if tolerances are passed in. Compare to the # zero array because then we only have to check the # absolute magnitue of each term, rather than consider # relative errors with respect to nonzero terms. eigvals, eigvecs = util.eigh( array, rtol=rtol, atol=atol, is_positive_definite=is_pos_def) np.testing.assert_allclose( array.dot(eigvecs) - eigvecs.dot(np.diag(eigvals)), np.zeros(eigvecs.shape), atol=test_atol) # If either tolerance is nonzero, make sure that # something is actually truncated, otherwise force test # to quit. To do this, make sure the eigvec array is # not square. if rtol and eigvals.size == eigvals_full.size: raise ValueError( 'Failed to choose relative tolerance that ' 'forces truncation.') if atol and eigvals.size == eigvals_full.size: raise ValueError( 'Failed to choose absolute tolerance that ' 'forces truncation.') # If the positive definite flag is passed in, make sure # the returned eigenvalues are all positive if is_pos_def: self.assertTrue(eigvals.min() > 0) # If a relative tolerance is passed in, make sure the # relative tolerance is satisfied. if rtol is not None: self.assertTrue( abs(eigvals).min() / abs(eigvals).max() > rtol) # If an absolute tolerance is passed in, make sure the # absolute tolerance is satisfied. if atol is not None: self.assertTrue(abs(eigvals).min() > atol)