def _solve_linear_operator(linop_a, linop_b): """Generic solve of two `LinearOperator`s.""" is_square = registrations_util.is_square(linop_a, linop_b) is_non_singular = None is_self_adjoint = None is_positive_definite = None if is_square: is_non_singular = registrations_util.combined_non_singular_hint( linop_a, linop_b) elif is_square is False: # pylint:disable=g-bool-id-comparison is_non_singular = False is_self_adjoint = False is_positive_definite = False return linear_operator_composition.LinearOperatorComposition( operators=[ linear_operator_inversion.LinearOperatorInversion(linop_a), linop_b ], is_non_singular=is_non_singular, is_self_adjoint=is_self_adjoint, is_positive_definite=is_positive_definite, is_square=is_square, )
def _matmul_linear_operator_circulant_circulant(linop_a, linop_b): return linear_operator_circulant.LinearOperatorCirculant( spectrum=linop_a.spectrum * linop_b.spectrum, is_non_singular=registrations_util.combined_non_singular_hint( linop_a, linop_b), is_self_adjoint=registrations_util.combined_commuting_self_adjoint_hint( linop_a, linop_b), is_positive_definite=( registrations_util.combined_commuting_positive_definite_hint( linop_a, linop_b)), is_square=True)
def _matmul_linear_operator_tril_diag(linop_triangular, linop_diag): return linear_operator_lower_triangular.LinearOperatorLowerTriangular( tril=linop_triangular.to_dense() * linop_diag.diag, is_non_singular=registrations_util.combined_non_singular_hint( linop_diag, linop_triangular), # This is safe to do since the Triangular matrix is only self-adjoint # when it is a diagonal matrix, and hence commutes. is_self_adjoint=registrations_util.combined_commuting_self_adjoint_hint( linop_diag, linop_triangular), is_positive_definite=None, is_square=True)
def _matmul_linear_operator_diag(linop_a, linop_b): return linear_operator_diag.LinearOperatorDiag( diag=linop_a.diag * linop_b.diag, is_non_singular=registrations_util.combined_non_singular_hint( linop_a, linop_b), is_self_adjoint=registrations_util.combined_commuting_self_adjoint_hint( linop_a, linop_b), is_positive_definite=( registrations_util.combined_commuting_positive_definite_hint( linop_a, linop_b)), is_square=True)
def _matmul_linear_operator_diag_scaled_identity_left( linop_scaled_identity, linop_diag): return linear_operator_diag.LinearOperatorDiag( diag=linop_diag.diag * linop_scaled_identity.multiplier, is_non_singular=registrations_util.combined_non_singular_hint( linop_diag, linop_scaled_identity), is_self_adjoint=registrations_util.combined_commuting_self_adjoint_hint( linop_diag, linop_scaled_identity), is_positive_definite=( registrations_util.combined_commuting_positive_definite_hint( linop_diag, linop_scaled_identity)), is_square=True)
def _matmul_linear_operator_scaled_identity(linop_a, linop_b): """Matmul of two ScaledIdentity `LinearOperators`.""" return linear_operator_identity.LinearOperatorScaledIdentity( num_rows=linop_a.domain_dimension_tensor(), multiplier=linop_a.multiplier * linop_b.multiplier, is_non_singular=registrations_util.combined_non_singular_hint( linop_a, linop_b), is_self_adjoint=registrations_util.combined_commuting_self_adjoint_hint( linop_a, linop_b), is_positive_definite=( registrations_util.combined_commuting_positive_definite_hint( linop_a, linop_b)), is_square=True)
def _matmul_linear_operator_block_diag_block_diag(linop_a, linop_b): return linear_operator_block_diag.LinearOperatorBlockDiag( operators=[ o1.matmul(o2) for o1, o2 in zip( linop_a.operators, linop_b.operators)], is_non_singular=registrations_util.combined_non_singular_hint( linop_a, linop_b), # In general, a product of self-adjoint positive-definite block diagonal # matrices is not self = self - adjoint. is_self_adjoint=None, # In general, a product of positive-definite block diagonal matrices is # not positive-definite. is_positive_definite=None, is_square=True)
def _matmul_linear_operator_circulant_circulant(linop_a, linop_b): if not isinstance(linop_a, linop_b.__class__): return _matmul_linear_operator(linop_a, linop_b) return linop_a.__class__( spectrum=linop_a.spectrum * linop_b.spectrum, is_non_singular=registrations_util.combined_non_singular_hint( linop_a, linop_b), is_self_adjoint=registrations_util.combined_commuting_self_adjoint_hint( linop_a, linop_b), is_positive_definite=( registrations_util.combined_commuting_positive_definite_hint( linop_a, linop_b)), is_square=True)