def linop_scale(w, op): # We assume w > 0. (This assumption only relates to the is_* attributes.) with ops.name_scope("linop_scale", values=[w]): # TODO(b/35301104): LinearOperatorComposition doesn't combine operators, so # special case combinations here. Once it does, this function can be # replaced by: # return linop_composition_lib.LinearOperatorComposition([ # scaled_identity(w), op]) def scaled_identity(w): return linop_identity_lib.LinearOperatorScaledIdentity( num_rows=op.range_dimension_tensor(), multiplier=w, is_non_singular=op.is_non_singular, is_self_adjoint=op.is_self_adjoint, is_positive_definite=op.is_positive_definite) if isinstance(op, linop_identity_lib.LinearOperatorIdentity): return scaled_identity(w) if isinstance(op, linop_identity_lib.LinearOperatorScaledIdentity): return scaled_identity(w * op.multiplier) if isinstance(op, linop_diag_lib.LinearOperatorDiag): return linop_diag_lib.LinearOperatorDiag( diag=w[..., array_ops.newaxis] * op.diag_part(), is_non_singular=op.is_non_singular, is_self_adjoint=op.is_self_adjoint, is_positive_definite=op.is_positive_definite) if isinstance(op, linop_tril_lib.LinearOperatorLowerTriangular): return linop_tril_lib.LinearOperatorLowerTriangular( tril=w[..., array_ops.newaxis, array_ops.newaxis] * op.to_dense(), is_non_singular=op.is_non_singular, is_self_adjoint=op.is_self_adjoint, is_positive_definite=op.is_positive_definite) raise NotImplementedError("Unsupported Linop type ({})".format( type(op).__name__))
def _solve_linear_operator_diag_tril(linop_diag, linop_triangular): return linear_operator_lower_triangular.LinearOperatorLowerTriangular( tril=linop_triangular.to_dense() / linop_diag.diag[..., None], 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_tril_diag(linop_triangular, linop_diag): return linear_operator_lower_triangular.LinearOperatorLowerTriangular( tril=linop_triangular.to_dense() * linop_diag.diag, is_non_singular=_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=_combined_self_adjoint_hint(linop_diag, linop_triangular), is_positive_definite=None, is_square=True)
def _add(self, op1, op2, operator_name, hints): if _type(op1) in _EFFICIENT_ADD_TO_TENSOR: op_add_to_tensor, op_other = op1, op2 else: op_add_to_tensor, op_other = op2, op1 return linear_operator_lower_triangular.LinearOperatorLowerTriangular( tril=op_add_to_tensor.add_to_tensor(op_other.to_dense()), is_non_singular=hints.is_non_singular, is_self_adjoint=hints.is_self_adjoint, is_positive_definite=hints.is_positive_definite, name=operator_name)
def _cholesky_linear_operator(linop): return linear_operator_lower_triangular.LinearOperatorLowerTriangular( linalg_ops.cholesky(linop.to_dense()), is_non_singular=True, is_self_adjoint=False, is_square=True)