1# Copyright 2019 The TensorFlow Authors. All Rights Reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14# ============================================================================== 15"""Common utilities for registering LinearOperator methods.""" 16 17from __future__ import absolute_import 18from __future__ import division 19from __future__ import print_function 20 21 22# Note: only use this method in the commuting case. 23def combined_commuting_self_adjoint_hint(operator_a, operator_b): 24 """Get combined hint for self-adjoint-ness.""" 25 26 # The property is preserved under composition when the operators commute. 27 if operator_a.is_self_adjoint and operator_b.is_self_adjoint: 28 return True 29 30 # The property is not preserved when an operator with the property is composed 31 # with an operator without the property. 32 33 # pylint:disable=g-bool-id-comparison 34 if ((operator_a.is_self_adjoint is True and 35 operator_b.is_self_adjoint is False) or 36 (operator_a.is_self_adjoint is False and 37 operator_b.is_self_adjoint is True)): 38 return False 39 # pylint:enable=g-bool-id-comparison 40 41 # The property is not known when operators are not known to have the property 42 # or both operators don't have the property (the property for the complement 43 # class is not closed under composition). 44 return None 45 46 47def is_square(operator_a, operator_b): 48 """Return a hint to whether the composition is square.""" 49 if operator_a.is_square and operator_b.is_square: 50 return True 51 if operator_a.is_square is False and operator_b.is_square is False: # pylint:disable=g-bool-id-comparison 52 # Let A have shape [B, M, N], B have shape [B, N, L]. 53 m = operator_a.range_dimension 54 l = operator_b.domain_dimension 55 if m is not None and l is not None: 56 return m == l 57 58 if (operator_a.is_square != operator_b.is_square) and ( 59 operator_a.is_square is not None and operator_b.is_square is not None): 60 return False 61 62 return None 63 64 65# Note: Positive definiteness is only guaranteed to be preserved 66# when the operators commute and are symmetric. Only use this method in 67# commuting cases. 68def combined_commuting_positive_definite_hint(operator_a, operator_b): 69 """Get combined PD hint for compositions.""" 70 # pylint:disable=g-bool-id-comparison 71 if (operator_a.is_positive_definite is True and 72 operator_a.is_self_adjoint is True and 73 operator_b.is_positive_definite is True and 74 operator_b.is_self_adjoint is True): 75 return True 76 # pylint:enable=g-bool-id-comparison 77 78 return None 79 80 81def combined_non_singular_hint(operator_a, operator_b): 82 """Get combined hint for when .""" 83 # If either operator is not-invertible the composition isn't. 84 85 # pylint:disable=g-bool-id-comparison 86 if (operator_a.is_non_singular is False or 87 operator_b.is_non_singular is False): 88 return False 89 # pylint:enable=g-bool-id-comparison 90 91 return operator_a.is_non_singular and operator_b.is_non_singular 92