def _trace(self): # The diagonal of the [[nested] block] circulant operator is the mean of # the spectrum. # Proof: For the [0,...,0] element, this follows from the IDFT formula. # Then the result follows since all diagonal elements are the same. # Therefore, the trace is the sum of the spectrum. # Get shape of diag along with the axis over which to reduce the spectrum. # We will reduce the spectrum over all block indices. if tensor_shape.TensorShape(self.spectrum.shape).is_fully_defined(): spec_rank = tensor_shape.TensorShape(self.spectrum.shape).ndims axis = np.arange(spec_rank - self.block_depth, spec_rank, dtype=np.int32) else: spec_rank = array_ops.rank(self.spectrum) axis = math_ops.range(spec_rank - self.block_depth, spec_rank) # Real diag part "re_d". # Suppose tensor_shape.TensorShape(spectrum.shape) = [B1,...,Bb, N1, N2] # tensor_shape.TensorShape(self.shape) = [B1,...,Bb, N, N], with N1 * N2 = N. # tensor_shape.TensorShape(re_d_value.shape) = [B1,...,Bb] re_d_value = math_ops.reduce_sum(math_ops.real(self.spectrum), axis=axis) if not np.issubdtype(self.dtype, np.complexfloating): return _ops.cast(re_d_value, self.dtype) # Imaginary part, "im_d". if self.is_self_adjoint: im_d_value = array_ops.zeros_like(re_d_value) else: im_d_value = math_ops.reduce_sum(math_ops.imag(self.spectrum), axis=axis) return _ops.cast(math_ops.complex(re_d_value, im_d_value), self.dtype)
def assert_zero_imag_part(x, message=None, name="assert_zero_imag_part"): """Returns `Op` that asserts Tensor `x` has no non-zero imaginary parts. Args: x: Numeric `Tensor`, real, integer, or complex. message: A string message to prepend to failure message. name: A name to give this `Op`. Returns: An `Op` that asserts `x` has no entries with modulus zero. """ with ops.name_scope(name, values=[x]): x = ops.convert_to_tensor(x, name="x") dtype = x.dtype if dtype.is_floating: return control_flow_ops.no_op() zero = ops.convert_to_tensor(0, dtype=dtypes.real_dtype(dtype)) return check_ops.assert_equal(zero, math_ops.imag(x), message=message)
def assert_hermitian_spectrum(self, name="assert_hermitian_spectrum"): """Returns an `Op` that asserts this operator has Hermitian spectrum. This operator corresponds to a real-valued matrix if and only if its spectrum is Hermitian. Args: name: A name to give this `Op`. Returns: An `Op` that asserts this operator has Hermitian spectrum. """ eps = np.finfo(dtypes.real_dtype(self.dtype)).eps with self._name_scope(name): # pylint: disable=not-callable # Assume linear accumulation of error. max_err = eps * self.domain_dimension_tensor() imag_convolution_kernel = math_ops.imag(self.convolution_kernel()) return check_ops.assert_less(math_ops.abs(imag_convolution_kernel), max_err, message="Spectrum was not Hermitian")
def _assert_self_adjoint(self): imag_multiplier = math_ops.imag(self.multiplier) return check_ops.assert_equal( array_ops.zeros_like(imag_multiplier), imag_multiplier, message="LinearOperator was not self-adjoint")