def test_defining_operator_using_real_convolution_kernel(self): with self.cached_session(): convolution_kernel = [1., 2., 1.] spectrum = math_ops.fft( math_ops.cast(convolution_kernel, dtypes.complex64)) # spectrum is shape [3] ==> operator is shape [3, 3] # spectrum is Hermitian ==> operator is real. operator = linalg.LinearOperatorCirculant(spectrum) # Allow for complex output so we can make sure it has zero imag part. self.assertEqual(operator.dtype, dtypes.complex64) matrix = operator.to_dense().eval() np.testing.assert_allclose(0, np.imag(matrix), atol=1e-6)
def test_real_hermitian_spectrum_gives_real_symmetric_operator(self): with self.cached_session() as sess: # This is a real and hermitian spectrum. spectrum = [[1., 2., 2.], [3., 4., 4.], [3., 4., 4.]] operator = linalg.LinearOperatorCirculant(spectrum) matrix_tensor = operator.to_dense() self.assertEqual(matrix_tensor.dtype, dtypes.complex64) matrix_t = array_ops.matrix_transpose(matrix_tensor) imag_matrix = math_ops.imag(matrix_tensor) matrix, matrix_transpose, imag_matrix = sess.run( [matrix_tensor, matrix_t, imag_matrix]) np.testing.assert_allclose(0, imag_matrix, atol=1e-6) self.assertAllClose(matrix, matrix_transpose, atol=0)
def test_hermitian_spectrum_gives_operator_with_zero_imag_part(self): with self.cached_session(): # Make spectrum the FFT of a real convolution kernel h. This ensures that # spectrum is Hermitian. h = linear_operator_test_util.random_normal(shape=(3, 4)) spectrum = fft_ops.fft(math_ops.cast(h, dtypes.complex64)) operator = linalg.LinearOperatorCirculant( spectrum, input_output_dtype=dtypes.complex64) matrix = operator.to_dense() imag_matrix = math_ops.imag(matrix) eps = np.finfo(np.float32).eps np.testing.assert_allclose(0, self.evaluate(imag_matrix), rtol=0, atol=eps * 3 * 4)
def _operator_and_matrix(self, build_info, dtype, use_placeholder, ensure_self_adjoint_and_pd=False): shape = build_info.shape # For this test class, we are creating Hermitian spectrums. # We also want the spectrum to have eigenvalues bounded away from zero. # # pre_spectrum is bounded away from zero. pre_spectrum = linear_operator_test_util.random_uniform( shape=self._shape_to_spectrum_shape(shape), dtype=dtype, minval=1., maxval=2.) pre_spectrum = math_ops.cast(math_ops.abs(pre_spectrum), dtype=dtype) pre_spectrum_c = _to_complex(pre_spectrum) # Real{IFFT[pre_spectrum]} # = IFFT[EvenPartOf[pre_spectrum]] # is the IFFT of something that is also bounded away from zero. # Therefore, FFT[pre_h] would be a well-conditioned spectrum. pre_h = fft_ops.ifft(pre_spectrum_c) # A spectrum is Hermitian iff it is the DFT of a real convolution kernel. # So we will make spectrum = FFT[h], for real valued h. h = math_ops.real(pre_h) h_c = _to_complex(h) spectrum = fft_ops.fft(h_c) lin_op_spectrum = spectrum if use_placeholder: lin_op_spectrum = array_ops.placeholder_with_default(spectrum, shape=None) operator = linalg.LinearOperatorCirculant( lin_op_spectrum, input_output_dtype=dtype, is_positive_definite=True if ensure_self_adjoint_and_pd else None, is_self_adjoint=True if ensure_self_adjoint_and_pd else None, ) mat = self._spectrum_to_circulant_1d(spectrum, shape, dtype=dtype) return operator, mat
def _operator_and_matrix(self, build_info, dtype, use_placeholder): shape = build_info.shape # Will be well conditioned enough to get accurate solves. spectrum = linear_operator_test_util.random_sign_uniform( shape=self._shape_to_spectrum_shape(shape), dtype=dtypes.complex64, minval=1., maxval=2.) lin_op_spectrum = spectrum if use_placeholder: lin_op_spectrum = array_ops.placeholder_with_default(spectrum, shape=None) operator = linalg.LinearOperatorCirculant(lin_op_spectrum, input_output_dtype=dtype) mat = self._spectrum_to_circulant_1d(spectrum, shape, dtype=dtype) return operator, mat
def operator_and_matrix(self, shape_info, dtype, use_placeholder, ensure_self_adjoint_and_pd=False): del ensure_self_adjoint_and_pd shape = shape_info.shape # Will be well conditioned enough to get accurate solves. spectrum = linear_operator_test_util.random_sign_uniform( shape=self._shape_to_spectrum_shape(shape), dtype=dtype, minval=1., maxval=2.) lin_op_spectrum = spectrum if use_placeholder: lin_op_spectrum = array_ops.placeholder_with_default(spectrum, shape=None) operator = linalg.LinearOperatorCirculant(lin_op_spectrum, input_output_dtype=dtype) self.assertEqual( operator.parameters, { "input_output_dtype": dtype, "is_non_singular": None, "is_positive_definite": None, "is_self_adjoint": None, "is_square": True, "name": "LinearOperatorCirculant", "spectrum": lin_op_spectrum, }) mat = self._spectrum_to_circulant_1d(spectrum, shape, dtype=dtype) return operator, mat
def test_real_spectrum_auto_sets_is_self_adjoint_to_true(self): spectrum = [1., 2.] operator = linalg.LinearOperatorCirculant(spectrum) self.assertTrue(operator.is_self_adjoint)
def test_real_spectrum_and_not_self_adjoint_hint_raises(self): spectrum = [1., 2.] with self.assertRaisesRegexp(ValueError, "real.*always.*self-adjoint"): linalg.LinearOperatorCirculant(spectrum, is_self_adjoint=False)
def test_assert_positive_definite_does_not_fail_when_pos_def(self): spectrum = math_ops.cast([6., 4, 2j + 2], dtypes.complex64) operator = linalg.LinearOperatorCirculant(spectrum) with self.cached_session(): operator.assert_positive_definite().run() # Should not fail
def test_assert_positive_definite_fails_for_non_positive_definite(self): spectrum = math_ops.cast([6., 4, 2j], dtypes.complex64) operator = linalg.LinearOperatorCirculant(spectrum) with self.cached_session(): with self.assertRaisesOpError("Not positive definite"): operator.assert_positive_definite().run()
def test_assert_non_singular_does_not_fail_for_non_singular_operator(self): spectrum = math_ops.cast([-3j, 4, 2j + 2], dtypes.complex64) operator = linalg.LinearOperatorCirculant(spectrum) with self.cached_session(): operator.assert_non_singular().run() # Should not fail
def test_assert_non_singular_fails_for_singular_operator(self): spectrum = math_ops.cast([0, 4, 2j + 2], dtypes.complex64) operator = linalg.LinearOperatorCirculant(spectrum) with self.cached_session(): with self.assertRaisesOpError("Singular operator"): operator.assert_non_singular().run()
def test_tape_safe(self): spectrum = variables_module.Variable( math_ops.cast([1. + 0j, 1. + 1j], dtypes.complex64)) operator = linalg.LinearOperatorCirculant(spectrum, is_self_adjoint=False) self.check_tape_safe(operator)