def test_diag_solve(self): operator1 = linalg_lib.LinearOperatorDiag([2., 3.], is_non_singular=True) operator2 = linalg_lib.LinearOperatorDiag([1., 2.], is_non_singular=True) operator3 = linalg_lib.LinearOperatorScaledIdentity( num_rows=2, multiplier=3., is_non_singular=True) operator_solve = operator1.solve(operator2) self.assertTrue( isinstance(operator_solve, linalg_lib.LinearOperatorDiag)) self.assertAllClose([0.5, 2 / 3.], self.evaluate(operator_solve.diag)) operator_solve = operator2.solve(operator1) self.assertTrue( isinstance(operator_solve, linalg_lib.LinearOperatorDiag)) self.assertAllClose([2., 3 / 2.], self.evaluate(operator_solve.diag)) operator_solve = operator1.solve(operator3) self.assertTrue( isinstance(operator_solve, linalg_lib.LinearOperatorDiag)) self.assertAllClose([3 / 2., 1.], self.evaluate(operator_solve.diag)) operator_solve = operator3.solve(operator1) self.assertTrue( isinstance(operator_solve, linalg_lib.LinearOperatorDiag)) self.assertAllClose([2 / 3., 1.], self.evaluate(operator_solve.diag))
def test_diag_matmul(self): operator1 = linalg_lib.LinearOperatorDiag([2., 3.]) operator2 = linalg_lib.LinearOperatorDiag([1., 2.]) operator3 = linalg_lib.LinearOperatorScaledIdentity( num_rows=2, multiplier=3.) operator_matmul = operator1.matmul(operator2) self.assertTrue(isinstance( operator_matmul, linalg_lib.LinearOperatorDiag)) self.assertAllClose([2., 6.], self.evaluate(operator_matmul.diag)) operator_matmul = operator2.matmul(operator1) self.assertTrue(isinstance( operator_matmul, linalg_lib.LinearOperatorDiag)) self.assertAllClose([2., 6.], self.evaluate(operator_matmul.diag)) operator_matmul = operator1.matmul(operator3) self.assertTrue(isinstance( operator_matmul, linalg_lib.LinearOperatorDiag)) self.assertAllClose([6., 9.], self.evaluate(operator_matmul.diag)) operator_matmul = operator3.matmul(operator1) self.assertTrue(isinstance( operator_matmul, linalg_lib.LinearOperatorDiag)) self.assertAllClose([6., 9.], self.evaluate(operator_matmul.diag))
def test_triangular_diag_matmul(self): operator1 = linalg_lib.LinearOperatorLowerTriangular([[1., 0., 0.], [2., 1., 0.], [2., 3., 3.]]) operator2 = linalg_lib.LinearOperatorDiag([2., 2., 3.]) operator_matmul = operator1.matmul(operator2) self.assertTrue( isinstance(operator_matmul, linalg_lib.LinearOperatorLowerTriangular)) self.assertAllClose( math_ops.matmul(operator1.to_dense(), operator2.to_dense()), self.evaluate(operator_matmul.to_dense())) operator_matmul = operator2.matmul(operator1) self.assertTrue( isinstance(operator_matmul, linalg_lib.LinearOperatorLowerTriangular)) self.assertAllClose( math_ops.matmul(operator2.to_dense(), operator1.to_dense()), self.evaluate(operator_matmul.to_dense()))
def testDiag(self): with self.cached_session(): shift = np.array([-1, 0, 1], dtype=np.float32) diag = np.array([[1, 2, 3], [2, 5, 6]], dtype=np.float32) scale = linalg.LinearOperatorDiag(diag, is_non_singular=True) affine = AffineLinearOperator(shift=shift, scale=scale, validate_args=True) x = np.array([[1, 0, -1], [2, 3, 4]], dtype=np.float32) y = diag * x + shift ildj = -np.sum(np.log(np.abs(diag)), axis=-1) self.assertEqual(affine.name, "affine_linear_operator") self.assertAllClose(y, affine.forward(x).eval()) self.assertAllClose(x, affine.inverse(y).eval()) self.assertAllClose( ildj, affine.inverse_log_det_jacobian(y, event_ndims=1).eval()) self.assertAllClose( -affine.inverse_log_det_jacobian(y, event_ndims=1).eval(), affine.forward_log_det_jacobian(x, event_ndims=1).eval())
def make_diag_scale(loc=None, scale_diag=None, scale_identity_multiplier=None, shape_hint=None, validate_args=False, assert_positive=False, name=None): """Creates a LinOp representing a diagonal matrix. Args: loc: Floating-point `Tensor`. This is used for inferring shape in the case where only `scale_identity_multiplier` is set. scale_diag: Floating-point `Tensor` representing the diagonal matrix. `scale_diag` has shape [N1, N2, ... k], which represents a k x k diagonal matrix. When `None` no diagonal term is added to the LinOp. scale_identity_multiplier: floating point rank 0 `Tensor` representing a scaling done to the identity matrix. When `scale_identity_multiplier = scale_diag = scale_tril = None` then `scale += IdentityMatrix`. Otherwise no scaled-identity-matrix is added to `scale`. shape_hint: scalar integer `Tensor` representing a hint at the dimension of the identity matrix when only `scale_identity_multiplier` is set. validate_args: Python `bool` indicating whether arguments should be checked for correctness. assert_positive: Python `bool` indicating whether LinOp should be checked for being positive definite. name: Python `str` name given to ops managed by this object. Returns: `LinearOperator` representing a lower triangular matrix. Raises: ValueError: If only `scale_identity_multiplier` is set and `loc` and `shape_hint` are both None. """ def _maybe_attach_assertion(x): if not validate_args: return x if assert_positive: return control_flow_ops.with_dependencies([ check_ops.assert_positive( x, message="diagonal part must be positive"), ], x) return control_flow_ops.with_dependencies([ check_ops.assert_none_equal( x, array_ops.zeros([], x.dtype), message="diagonal part must be non-zero") ], x) with ops.name_scope(name, "make_diag_scale", values=[loc, scale_diag, scale_identity_multiplier]): loc = _convert_to_tensor(loc, name="loc") scale_diag = _convert_to_tensor(scale_diag, name="scale_diag") scale_identity_multiplier = _convert_to_tensor( scale_identity_multiplier, name="scale_identity_multiplier") if scale_diag is not None: if scale_identity_multiplier is not None: scale_diag += scale_identity_multiplier[..., array_ops.newaxis] return linalg.LinearOperatorDiag( diag=_maybe_attach_assertion(scale_diag), is_non_singular=True, is_self_adjoint=True, is_positive_definite=assert_positive) if loc is None and shape_hint is None: raise ValueError("Cannot infer `event_shape` unless `loc` or " "`shape_hint` is specified.") if shape_hint is None: shape_hint = loc.shape[-1] if scale_identity_multiplier is None: return linalg.LinearOperatorIdentity( num_rows=shape_hint, dtype=loc.dtype.base_dtype, is_self_adjoint=True, is_positive_definite=True, assert_proper_shapes=validate_args) return linalg.LinearOperatorScaledIdentity( num_rows=shape_hint, multiplier=_maybe_attach_assertion(scale_identity_multiplier), is_non_singular=True, is_self_adjoint=True, is_positive_definite=assert_positive, assert_proper_shapes=validate_args)