1 # Copyright 2017 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 """Operations for linear algebra.""" 16 17 from __future__ import absolute_import 18 from __future__ import division 19 from __future__ import print_function 20 21 from tensorflow.python.framework import ops 22 from tensorflow.python.ops import array_ops 23 from tensorflow.python.ops import gen_linalg_ops 24 from tensorflow.python.ops import linalg_ops 25 from tensorflow.python.ops import math_ops 26 from tensorflow.python.ops import special_math_ops 27 from tensorflow.python.util.tf_export import tf_export 28 29 # Linear algebra ops. 30 band_part = array_ops.matrix_band_part 31 cholesky = linalg_ops.cholesky 32 cholesky_solve = linalg_ops.cholesky_solve 33 det = linalg_ops.matrix_determinant 34 # pylint: disable=protected-access 35 slogdet = gen_linalg_ops._log_matrix_determinant 36 # pylint: disable=protected-access 37 diag = array_ops.matrix_diag 38 diag_part = array_ops.matrix_diag_part 39 eigh = linalg_ops.self_adjoint_eig 40 eigvalsh = linalg_ops.self_adjoint_eigvals 41 einsum = special_math_ops.einsum 42 expm = gen_linalg_ops._matrix_exponential 43 eye = linalg_ops.eye 44 inv = linalg_ops.matrix_inverse 45 logm = gen_linalg_ops._matrix_logarithm 46 lstsq = linalg_ops.matrix_solve_ls 47 norm = linalg_ops.norm 48 qr = linalg_ops.qr 49 set_diag = array_ops.matrix_set_diag 50 solve = linalg_ops.matrix_solve 51 svd = linalg_ops.svd 52 tensordot = math_ops.tensordot 53 trace = math_ops.trace 54 transpose = array_ops.matrix_transpose 55 triangular_solve = linalg_ops.matrix_triangular_solve 56 57 58 @tf_export('linalg.logdet') 59 def logdet(matrix, name=None): 60 """Computes log of the determinant of a hermitian positive definite matrix. 61 62 ```python 63 # Compute the determinant of a matrix while reducing the chance of over- or 64 underflow: 65 A = ... # shape 10 x 10 66 det = tf.exp(tf.logdet(A)) # scalar 67 ``` 68 69 Args: 70 matrix: A `Tensor`. Must be `float16`, `float32`, `float64`, `complex64`, 71 or `complex128` with shape `[..., M, M]`. 72 name: A name to give this `Op`. Defaults to `logdet`. 73 74 Returns: 75 The natural log of the determinant of `matrix`. 76 77 @compatibility(numpy) 78 Equivalent to numpy.linalg.slogdet, although no sign is returned since only 79 hermitian positive definite matrices are supported. 80 @end_compatibility 81 """ 82 # This uses the property that the log det(A) = 2*sum(log(real(diag(C)))) 83 # where C is the cholesky decomposition of A. 84 with ops.name_scope(name, 'logdet', [matrix]): 85 chol = gen_linalg_ops.cholesky(matrix) 86 return 2.0 * math_ops.reduce_sum( 87 math_ops.log(math_ops.real(array_ops.matrix_diag_part(chol))), 88 reduction_indices=[-1]) 89 90 91 @tf_export('linalg.adjoint') 92 def adjoint(matrix, name=None): 93 """Transposes the last two dimensions of and conjugates tensor `matrix`. 94 95 For example: 96 97 ```python 98 x = tf.constant([[1 + 1j, 2 + 2j, 3 + 3j], 99 [4 + 4j, 5 + 5j, 6 + 6j]]) 100 tf.linalg.adjoint(x) # [[1 - 1j, 4 - 4j], 101 # [2 - 2j, 5 - 5j], 102 # [3 - 3j, 6 - 6j]] 103 104 Args: 105 matrix: A `Tensor`. Must be `float16`, `float32`, `float64`, `complex64`, 106 or `complex128` with shape `[..., M, M]`. 107 name: A name to give this `Op` (optional). 108 109 Returns: 110 The adjoint (a.k.a. Hermitian transpose a.k.a. conjugate transpose) of 111 matrix. 112 """ 113 with ops.name_scope(name, 'adjoint', [matrix]): 114 matrix = ops.convert_to_tensor(matrix, name='matrix') 115 return array_ops.matrix_transpose(matrix, conjugate=True) 116