def operator_and_matrix(
      self, build_info, dtype, use_placeholder,
      ensure_self_adjoint_and_pd=False):
    del ensure_self_adjoint_and_pd
    shape = list(build_info.shape)

    # Create 2 matrices/operators, A1, A2, which becomes A = A1 A2.
    # Use inner dimension of 2.
    k = 2
    batch_shape = shape[:-2]
    shape_1 = batch_shape + [shape[-2], k]
    shape_2 = batch_shape + [k, shape[-1]]

    matrices = [
        linear_operator_test_util.random_normal(
            shape_1, dtype=dtype), linear_operator_test_util.random_normal(
                shape_2, dtype=dtype)
    ]

    lin_op_matrices = matrices

    if use_placeholder:
      lin_op_matrices = [
          array_ops.placeholder_with_default(
              matrix, shape=None) for matrix in matrices]

    operator = linalg.LinearOperatorComposition(
        [linalg.LinearOperatorFullMatrix(l) for l in lin_op_matrices])

    matmul_order_list = list(reversed(matrices))
    mat = matmul_order_list[0]
    for other_mat in matmul_order_list[1:]:
      mat = math_ops.matmul(other_mat, mat)

    return operator, mat
Ejemplo n.º 2
0
    def test_block_diag_matmul_type(self):
        matrices1 = []
        matrices2 = []
        for i in range(1, 5):
            matrices1.append(
                linalg.LinearOperatorFullMatrix(
                    linear_operator_test_util.random_normal(
                        [2, i], dtype=dtypes.float32)))

            matrices2.append(
                linalg.LinearOperatorFullMatrix(
                    linear_operator_test_util.random_normal(
                        [i, 3], dtype=dtypes.float32)))

        operator1 = block_diag.LinearOperatorBlockDiag(matrices1,
                                                       is_square=False)
        operator2 = block_diag.LinearOperatorBlockDiag(matrices2,
                                                       is_square=False)

        expected_matrix = math_ops.matmul(operator1.to_dense(),
                                          operator2.to_dense())
        actual_operator = operator1.matmul(operator2)

        self.assertIsInstance(actual_operator,
                              block_diag.LinearOperatorBlockDiag)
        actual_, expected_ = self.evaluate(
            [actual_operator.to_dense(), expected_matrix])
        self.assertAllClose(actual_, expected_)
  def test_block_diag_solve_raises(self):
    matrices1 = []
    for i in range(1, 5):
      matrices1.append(linalg.LinearOperatorFullMatrix(
          linear_operator_test_util.random_normal(
              [i, i], dtype=dtypes.float32)))
    operator1 = block_diag.LinearOperatorBlockDiag(matrices1)
    operator2 = linalg.LinearOperatorFullMatrix(
        linear_operator_test_util.random_normal(
            [15, 3], dtype=dtypes.float32))

    with self.assertRaisesRegex(ValueError, "Operators are incompatible"):
      operator1.solve(operator2)
Ejemplo n.º 4
0
    def _operator_and_mat_and_feed_dict(self, build_info, dtype,
                                        use_placeholder):
        sess = ops.get_default_session()
        shape = list(build_info.shape)

        # Test only the case of 2 matrices.
        # The Square test uses either 1 or 2, so we have tested the case of 1 matrix
        # sufficiently.
        num_operators = 2

        # Create 2 matrices/operators, A1, A2, which becomes A = A1 A2.
        # Use inner dimension of 2.
        k = 2
        batch_shape = shape[:-2]
        shape_1 = batch_shape + [shape[-2], k]
        shape_2 = batch_shape + [k, shape[-1]]

        matrices = [
            linear_operator_test_util.random_normal(shape_1, dtype=dtype),
            linear_operator_test_util.random_normal(shape_2, dtype=dtype)
        ]

        if use_placeholder:
            matrices_ph = [
                array_ops.placeholder(dtype=dtype)
                for _ in range(num_operators)
            ]
            # Evaluate here because (i) you cannot feed a tensor, and (ii)
            # values are random and we want the same value used for both mat and
            # feed_dict.
            matrices = sess.run(matrices)
            operator = linalg.LinearOperatorComposition([
                linalg.LinearOperatorFullMatrix(m_ph) for m_ph in matrices_ph
            ])
            feed_dict = {m_ph: m for (m_ph, m) in zip(matrices_ph, matrices)}
        else:
            operator = linalg.LinearOperatorComposition(
                [linalg.LinearOperatorFullMatrix(m) for m in matrices])
            feed_dict = None

        # Convert back to Tensor.  Needed if use_placeholder, since then we have
        # already evaluated each matrix to a numpy array.
        matmul_order_list = list(reversed(matrices))
        mat = ops.convert_to_tensor(matmul_order_list[0])
        for other_mat in matmul_order_list[1:]:
            mat = math_ops.matmul(other_mat, mat)

        return operator, mat, feed_dict
    def test_real_spectrum_gives_self_adjoint_operator(self):
        with self.cached_session():
            # This is a real and hermitian spectrum.
            spectrum = linear_operator_test_util.random_normal(
                shape=(2, 2, 3, 5), dtype=dtypes.float32)
            operator = linalg.LinearOperatorCirculant3D(spectrum)
            self.assertAllEqual((2, 2 * 3 * 5, 2 * 3 * 5), operator.shape)

            self.assertEqual(
                operator.parameters, {
                    "input_output_dtype": dtypes.complex64,
                    "is_non_singular": None,
                    "is_positive_definite": None,
                    "is_self_adjoint": None,
                    "is_square": True,
                    "name": "LinearOperatorCirculant3D",
                    "spectrum": spectrum,
                })

            matrix_tensor = operator.to_dense()
            self.assertEqual(matrix_tensor.dtype, dtypes.complex64)
            matrix_h = linalg.adjoint(matrix_tensor)

            matrix, matrix_h = self.evaluate([matrix_tensor, matrix_h])
            self.assertAllEqual((2, 2 * 3 * 5, 2 * 3 * 5), matrix.shape)
            self.assertAllClose(matrix, matrix_h)
Ejemplo n.º 6
0
    def test_block_diag_solve_type(self):
        matrices1 = []
        matrices2 = []
        for i in range(1, 5):
            matrices1.append(
                linalg.LinearOperatorFullMatrix(
                    linear_operator_test_util.random_tril_matrix(
                        [i, i],
                        dtype=dtypes.float32,
                        force_well_conditioned=True)))

            matrices2.append(
                linalg.LinearOperatorFullMatrix(
                    linear_operator_test_util.random_normal(
                        [i, 3], dtype=dtypes.float32)))

        operator1 = block_diag.LinearOperatorBlockDiag(matrices1)
        operator2 = block_diag.LinearOperatorBlockDiag(matrices2,
                                                       is_square=False)

        expected_matrix = linalg.solve(operator1.to_dense(),
                                       operator2.to_dense())
        actual_operator = operator1.solve(operator2)

        self.assertIsInstance(actual_operator,
                              block_diag.LinearOperatorBlockDiag)
        actual_, expected_ = self.evaluate(
            [actual_operator.to_dense(), expected_matrix])
        self.assertAllClose(actual_, expected_)
  def _operator_and_mat_and_feed_dict(self, shape, dtype, use_placeholder):
    sess = ops.get_default_session()
    shape = list(shape)

    # Test only the case of 2 matrices.
    # The Square test uses either 1 or 2, so we have tested the case of 1 matrix
    # sufficiently.
    num_operators = 2

    # Create 2 matrices/operators, A1, A2, which becomes A = A1 A2.
    # Use inner dimension of 2.
    k = 2
    batch_shape = shape[:-2]
    shape_1 = batch_shape + [shape[-2], k]
    shape_2 = batch_shape + [k, shape[-1]]

    matrices = [
        linear_operator_test_util.random_normal(
            shape_1, dtype=dtype), linear_operator_test_util.random_normal(
                shape_2, dtype=dtype)
    ]

    if use_placeholder:
      matrices_ph = [
          array_ops.placeholder(dtype=dtype) for _ in range(num_operators)
      ]
      # Evaluate here because (i) you cannot feed a tensor, and (ii)
      # values are random and we want the same value used for both mat and
      # feed_dict.
      matrices = sess.run(matrices)
      operator = linalg.LinearOperatorComposition(
          [linalg.LinearOperatorFullMatrix(m_ph) for m_ph in matrices_ph])
      feed_dict = {m_ph: m for (m_ph, m) in zip(matrices_ph, matrices)}
    else:
      operator = linalg.LinearOperatorComposition(
          [linalg.LinearOperatorFullMatrix(m) for m in matrices])
      feed_dict = None

    # Convert back to Tensor.  Needed if use_placeholder, since then we have
    # already evaluated each matrix to a numpy array.
    matmul_order_list = list(reversed(matrices))
    mat = ops.convert_to_tensor(matmul_order_list[0])
    for other_mat in matmul_order_list[1:]:
      mat = math_ops.matmul(other_mat, mat)

    return operator, mat, feed_dict
        def generate_well_conditioned(shape, dtype):
            m, n = shape[-2], shape[-1]
            min_dim = min(m, n)
            # Generate singular values that are close to 1.
            d = linear_operator_test_util.random_normal(shape[:-2] + [min_dim],
                                                        mean=1.,
                                                        stddev=0.1,
                                                        dtype=dtype)
            zeros = array_ops.zeros(shape=shape[:-2] + [m, n], dtype=dtype)
            d = linalg_lib.set_diag(zeros, d)
            u, _ = linalg_lib.qr(
                linear_operator_test_util.random_normal(shape[:-2] + [m, m],
                                                        dtype=dtype))

            v, _ = linalg_lib.qr(
                linear_operator_test_util.random_normal(shape[:-2] + [n, n],
                                                        dtype=dtype))
            return math_ops.matmul(u, math_ops.matmul(d, v))
Ejemplo n.º 9
0
    def test_slice_single_param_operator(self):
        matrix = linear_operator_test_util.random_normal(shape=[1, 4, 3, 2, 2],
                                                         dtype=dtypes.float32)
        operator = linalg.LinearOperatorFullMatrix(matrix, is_square=True)
        sliced = operator[..., array_ops.newaxis, 2:, array_ops.newaxis]

        self.assertAllEqual(
            list(
                array_ops.zeros([1, 4, 3])[..., array_ops.newaxis, 2:,
                                           array_ops.newaxis].shape),
            sliced.batch_shape_tensor())
    def test_real_spectrum_gives_self_adjoint_operator(self):
        with self.cached_session():
            # This is a real and hermitian spectrum.
            spectrum = linear_operator_test_util.random_normal(
                shape=(3, 3), dtype=dtypes.float32)
            operator = linalg.LinearOperatorCirculant2D(spectrum)

            matrix_tensor = operator.to_dense()
            self.assertEqual(matrix_tensor.dtype, dtypes.complex64)
            matrix_h = linalg.adjoint(matrix_tensor)
            matrix, matrix_h = self.evaluate([matrix_tensor, matrix_h])
            self.assertAllClose(matrix, matrix_h, atol=0)
  def _operator_and_matrix(self, build_info, dtype, use_placeholder):
    shape = list(build_info.shape)
    matrix = linear_operator_test_util.random_normal(shape, dtype=dtype)

    lin_op_matrix = matrix

    if use_placeholder:
      lin_op_matrix = array_ops.placeholder_with_default(matrix, shape=None)

    operator = linalg.LinearOperatorFullMatrix(lin_op_matrix, is_square=True)

    return operator, matrix
  def operator_and_matrix(
      self, shape_info, dtype, use_placeholder,
      ensure_self_adjoint_and_pd=False):

    expected_blocks = (
        shape_info.__dict__["blocks"] if "blocks" in shape_info.__dict__
        else [[list(shape_info.shape)]])

    matrices = []
    for i, row_shapes in enumerate(expected_blocks):
      row = []
      for j, block_shape in enumerate(row_shapes):
        if i == j:  # operator is on the diagonal
          row.append(
              linear_operator_test_util.random_positive_definite_matrix(
                  block_shape, dtype, force_well_conditioned=True))
        else:
          row.append(
              linear_operator_test_util.random_normal(block_shape, dtype=dtype))
      matrices.append(row)

    lin_op_matrices = matrices

    if use_placeholder:
      lin_op_matrices = [[
          array_ops.placeholder_with_default(
              matrix, shape=None) for matrix in row] for row in matrices]

    operator = block_lower_triangular.LinearOperatorBlockLowerTriangular(
        [[linalg.LinearOperatorFullMatrix(  # pylint:disable=g-complex-comprehension
            l,
            is_square=True,
            is_self_adjoint=True if ensure_self_adjoint_and_pd else None,
            is_positive_definite=True if ensure_self_adjoint_and_pd else None)
          for l in row] for row in lin_op_matrices])

    # Should be auto-set.
    self.assertTrue(operator.is_square)

    # Broadcast the shapes.
    expected_shape = list(shape_info.shape)
    broadcasted_matrices = linear_operator_util.broadcast_matrix_batch_dims(
        [op for row in matrices for op in row])  # pylint: disable=g-complex-comprehension
    matrices = [broadcasted_matrices[i * (i + 1) // 2:(i + 1) * (i + 2) // 2]
                for i in range(len(matrices))]

    block_lower_triangular_dense = _block_lower_triangular_dense(
        expected_shape, matrices)

    if not use_placeholder:
      block_lower_triangular_dense.set_shape(expected_shape)

    return operator, block_lower_triangular_dense
  def test_real_spectrum_gives_self_adjoint_operator(self):
    with self.cached_session():
      # This is a real and hermitian spectrum.
      spectrum = linear_operator_test_util.random_normal(
          shape=(3, 3), dtype=dtypes.float32)
      operator = linalg.LinearOperatorCirculant2D(spectrum)

      matrix_tensor = operator.to_dense()
      self.assertEqual(matrix_tensor.dtype, dtypes.complex64)
      matrix_h = linalg.adjoint(matrix_tensor)
      matrix, matrix_h = self.evaluate([matrix_tensor, matrix_h])
      self.assertAllClose(matrix, matrix_h, atol=0)
Ejemplo n.º 14
0
  def _operator_and_matrix(self, build_info, dtype, use_placeholder):
    shape = list(build_info.shape)
    matrix = linear_operator_test_util.random_normal(shape, dtype=dtype)

    lin_op_matrix = matrix

    if use_placeholder:
      lin_op_matrix = array_ops.placeholder_with_default(matrix, shape=None)

    operator = linalg.LinearOperatorFullMatrix(lin_op_matrix, is_square=True)

    return operator, matrix
 def test_hermitian_spectrum_gives_operator_with_zero_imag_part(self):
   with self.cached_session():
     # Make spectrum the FFT of a real convolution kernel h.  This ensures that
     # spectrum is Hermitian.
     h = linear_operator_test_util.random_normal(shape=(3, 4))
     spectrum = fft_ops.fft(math_ops.cast(h, dtypes.complex64))
     operator = linalg.LinearOperatorCirculant(
         spectrum, input_output_dtype=dtypes.complex64)
     matrix = operator.to_dense()
     imag_matrix = math_ops.imag(matrix)
     eps = np.finfo(np.float32).eps
     np.testing.assert_allclose(
         0, self.evaluate(imag_matrix), rtol=0, atol=eps * 3 * 4)
Ejemplo n.º 16
0
 def test_hermitian_spectrum_gives_operator_with_zero_imag_part(self):
   with self.cached_session():
     # Make spectrum the FFT of a real convolution kernel h.  This ensures that
     # spectrum is Hermitian.
     h = linear_operator_test_util.random_normal(shape=(3, 4))
     spectrum = fft_ops.fft(math_ops.cast(h, dtypes.complex64))
     operator = linalg.LinearOperatorCirculant(
         spectrum, input_output_dtype=dtypes.complex64)
     matrix = operator.to_dense()
     imag_matrix = math_ops.imag(matrix)
     eps = np.finfo(np.float32).eps
     np.testing.assert_allclose(
         0, self.evaluate(imag_matrix), rtol=0, atol=eps * 3 * 4)
  def test_real_spectrum_gives_self_adjoint_operator(self):
    with self.test_session() as sess:
      # This is a real and hermitian spectrum.
      spectrum = linear_operator_test_util.random_normal(
          shape=(3, 3), dtype=dtypes.float32)
      operator = linalg.LinearOperatorCirculant2D(spectrum)

      matrix_tensor = operator.to_dense()
      self.assertEqual(matrix_tensor.dtype,
                       linear_operator_circulant._DTYPE_COMPLEX)
      matrix_h = linalg.adjoint(matrix_tensor)
      matrix, matrix_h = sess.run([matrix_tensor, matrix_h])
      self.assertAllClose(matrix, matrix_h, atol=0)
    def test_real_spectrum_gives_self_adjoint_operator(self):
        with self.test_session() as sess:
            # This is a real and hermitian spectrum.
            spectrum = linear_operator_test_util.random_normal(
                shape=(3, 3), dtype=dtypes.float32)
            operator = linalg.LinearOperatorCirculant2D(spectrum)

            matrix_tensor = operator.to_dense()
            self.assertEqual(matrix_tensor.dtype,
                             linear_operator_circulant._DTYPE_COMPLEX)
            matrix_h = linalg.adjoint(matrix_tensor)
            matrix, matrix_h = sess.run([matrix_tensor, matrix_h])
            self.assertAllClose(matrix, matrix_h, atol=0)
Ejemplo n.º 19
0
    def operator_and_matrix(self, build_info, dtype, use_placeholder):
        sess = ops.get_default_session()
        shape = list(build_info.shape)

        # Test only the case of 2 matrices.
        # The Square test uses either 1 or 2, so we have tested the case of 1 matrix
        # sufficiently.
        num_operators = 2

        # Create 2 matrices/operators, A1, A2, which becomes A = A1 A2.
        # Use inner dimension of 2.
        k = 2
        batch_shape = shape[:-2]
        shape_1 = batch_shape + [shape[-2], k]
        shape_2 = batch_shape + [k, shape[-1]]

        matrices = [
            linear_operator_test_util.random_normal(shape_1, dtype=dtype),
            linear_operator_test_util.random_normal(shape_2, dtype=dtype)
        ]

        lin_op_matrices = matrices

        if use_placeholder:
            lin_op_matrices = [
                array_ops.placeholder_with_default(matrix, shape=None)
                for matrix in matrices
            ]

        operator = linalg.LinearOperatorComposition(
            [linalg.LinearOperatorFullMatrix(l) for l in lin_op_matrices])

        matmul_order_list = list(reversed(matrices))
        mat = matmul_order_list[0]
        for other_mat in matmul_order_list[1:]:
            mat = math_ops.matmul(other_mat, mat)

        return operator, mat
  def _operator_and_matrix(self, build_info, dtype, use_placeholder):
    sess = ops.get_default_session()
    shape = list(build_info.shape)

    # Test only the case of 2 matrices.
    # The Square test uses either 1 or 2, so we have tested the case of 1 matrix
    # sufficiently.
    num_operators = 2

    # Create 2 matrices/operators, A1, A2, which becomes A = A1 A2.
    # Use inner dimension of 2.
    k = 2
    batch_shape = shape[:-2]
    shape_1 = batch_shape + [shape[-2], k]
    shape_2 = batch_shape + [k, shape[-1]]

    matrices = [
        linear_operator_test_util.random_normal(
            shape_1, dtype=dtype), linear_operator_test_util.random_normal(
                shape_2, dtype=dtype)
    ]

    lin_op_matrices = matrices

    if use_placeholder:
      lin_op_matrices = [
          array_ops.placeholder_with_default(
              matrix, shape=None) for matrix in matrices]

    operator = linalg.LinearOperatorComposition(
        [linalg.LinearOperatorFullMatrix(l) for l in lin_op_matrices])

    matmul_order_list = list(reversed(matrices))
    mat = matmul_order_list[0]
    for other_mat in matmul_order_list[1:]:
      mat = math_ops.matmul(other_mat, mat)

    return operator, mat
Ejemplo n.º 21
0
    def test_real_spectrum_gives_self_adjoint_operator(self):
        with self.cached_session() as sess:
            # This is a real and hermitian spectrum.
            spectrum = linear_operator_test_util.random_normal(
                shape=(2, 2, 3, 5), dtype=dtypes.float32)
            operator = linalg.LinearOperatorCirculant3D(spectrum)
            self.assertAllEqual((2, 2 * 3 * 5, 2 * 3 * 5), operator.shape)

            matrix_tensor = operator.to_dense()
            self.assertEqual(matrix_tensor.dtype,
                             linear_operator_circulant._DTYPE_COMPLEX)
            matrix_h = linalg.adjoint(matrix_tensor)

            matrix, matrix_h = self.evaluate([matrix_tensor, matrix_h])
            self.assertAllEqual((2, 2 * 3 * 5, 2 * 3 * 5), matrix.shape)
            self.assertAllClose(matrix, matrix_h)
Ejemplo n.º 22
0
 def test_slice_nested_operator(self):
     linop = linalg.LinearOperatorKronecker([
         linalg.LinearOperatorBlockDiag([
             linalg.LinearOperatorDiag(array_ops.ones([1, 2, 2])),
             linalg.LinearOperatorDiag(array_ops.ones([3, 5, 2, 2]))
         ]),
         linalg.LinearOperatorFullMatrix(
             linear_operator_test_util.random_normal(
                 shape=[4, 1, 1, 1, 3, 3], dtype=dtypes.float32))
     ])
     self.assertAllEqual(linop[0, ...].batch_shape_tensor(), [3, 5, 2])
     self.assertAllEqual(
         linop[0, ..., array_ops.newaxis].batch_shape_tensor(),
         [3, 5, 2, 1])
     self.assertAllEqual(linop[..., array_ops.newaxis].batch_shape_tensor(),
                         [4, 3, 5, 2, 1])
  def test_real_spectrum_gives_self_adjoint_operator(self):
    with self.cached_session() as sess:
      # This is a real and hermitian spectrum.
      spectrum = linear_operator_test_util.random_normal(
          shape=(2, 2, 3, 5), dtype=dtypes.float32)
      operator = linalg.LinearOperatorCirculant3D(spectrum)
      self.assertAllEqual((2, 2 * 3 * 5, 2 * 3 * 5), operator.shape)

      matrix_tensor = operator.to_dense()
      self.assertEqual(matrix_tensor.dtype,
                       linear_operator_circulant._DTYPE_COMPLEX)
      matrix_h = linalg.adjoint(matrix_tensor)

      matrix, matrix_h = self.evaluate([matrix_tensor, matrix_h])
      self.assertAllEqual((2, 2 * 3 * 5, 2 * 3 * 5), matrix.shape)
      self.assertAllClose(matrix, matrix_h)
    def test_defining_operator_using_real_convolution_kernel(self):
        with self.cached_session():
            convolution_kernel = linear_operator_test_util.random_normal(
                shape=(2, 2, 3, 5), dtype=dtypes.float32)
            # Convolution kernel is real ==> spectrum is Hermitian.
            spectrum = fft_ops.fft3d(
                math_ops.cast(convolution_kernel, dtypes.complex64))

            # spectrum is Hermitian ==> operator is real.
            operator = linalg.LinearOperatorCirculant3D(spectrum)
            self.assertAllEqual((2, 2 * 3 * 5, 2 * 3 * 5), operator.shape)

            # Allow for complex output so we can make sure it has zero imag part.
            self.assertEqual(operator.dtype, dtypes.complex64)
            matrix = operator.to_dense().eval()
            self.assertAllEqual((2, 2 * 3 * 5, 2 * 3 * 5), matrix.shape)
            np.testing.assert_allclose(0, np.imag(matrix), atol=1e-6)
  def test_defining_operator_using_real_convolution_kernel(self):
    with self.cached_session():
      convolution_kernel = linear_operator_test_util.random_normal(
          shape=(2, 2, 3, 5), dtype=dtypes.float32)
      # Convolution kernel is real ==> spectrum is Hermitian.
      spectrum = fft_ops.fft3d(
          math_ops.cast(convolution_kernel, dtypes.complex64))

      # spectrum is Hermitian ==> operator is real.
      operator = linalg.LinearOperatorCirculant3D(spectrum)
      self.assertAllEqual((2, 2 * 3 * 5, 2 * 3 * 5), operator.shape)

      # Allow for complex output so we can make sure it has zero imag part.
      self.assertEqual(operator.dtype, dtypes.complex64)
      matrix = operator.to_dense().eval()
      self.assertAllEqual((2, 2 * 3 * 5, 2 * 3 * 5), matrix.shape)
      np.testing.assert_allclose(0, np.imag(matrix), atol=1e-6)
  def operator_and_matrix(self, build_info, dtype, use_placeholder):
    shape_before_adjoint = list(build_info.shape)
    # We need to swap the last two dimensions because we are taking the adjoint
    # of this operator
    shape_before_adjoint[-1], shape_before_adjoint[-2] = (
        shape_before_adjoint[-2], shape_before_adjoint[-1])
    matrix = linear_operator_test_util.random_normal(
        shape_before_adjoint, dtype=dtype)

    lin_op_matrix = matrix

    if use_placeholder:
      lin_op_matrix = array_ops.placeholder_with_default(matrix, shape=None)

    operator = LinearOperatorAdjoint(
        linalg.LinearOperatorFullMatrix(lin_op_matrix))

    return operator, linalg.adjoint(matrix)
  def operator_and_matrix(self, build_info, dtype, use_placeholder):
    shape_before_adjoint = list(build_info.shape)
    # We need to swap the last two dimensions because we are taking the adjoint
    # of this operator
    shape_before_adjoint[-1], shape_before_adjoint[-2] = (
        shape_before_adjoint[-2], shape_before_adjoint[-1])
    matrix = linear_operator_test_util.random_normal(
        shape_before_adjoint, dtype=dtype)

    lin_op_matrix = matrix

    if use_placeholder:
      lin_op_matrix = array_ops.placeholder_with_default(matrix, shape=None)

    operator = LinearOperatorAdjoint(
        linalg.LinearOperatorFullMatrix(lin_op_matrix))

    return operator, linalg.adjoint(matrix)
    def _operator_and_mat_and_feed_dict(self, shape, dtype, use_placeholder):
        matrix = linear_operator_test_util.random_normal(shape, dtype=dtype)
        if use_placeholder:
            matrix_ph = array_ops.placeholder(dtype=dtype)
            # Evaluate here because (i) you cannot feed a tensor, and (ii)
            # values are random and we want the same value used for both mat and
            # feed_dict.
            matrix = matrix.eval()
            operator = linalg.LinearOperatorFullMatrix(matrix_ph)
            feed_dict = {matrix_ph: matrix}
        else:
            operator = linalg.LinearOperatorFullMatrix(matrix)
            feed_dict = None

        # Convert back to Tensor.  Needed if use_placeholder, since then we have
        # already evaluated matrix to a numpy array.
        mat = ops.convert_to_tensor(matrix)

        return operator, mat, feed_dict
  def _operator_and_mat_and_feed_dict(self, shape, dtype, use_placeholder):
    matrix = linear_operator_test_util.random_normal(shape, dtype=dtype)
    if use_placeholder:
      matrix_ph = array_ops.placeholder(dtype=dtype)
      # Evaluate here because (i) you cannot feed a tensor, and (ii)
      # values are random and we want the same value used for both mat and
      # feed_dict.
      matrix = matrix.eval()
      operator = linalg.LinearOperatorFullMatrix(matrix_ph)
      feed_dict = {matrix_ph: matrix}
    else:
      operator = linalg.LinearOperatorFullMatrix(matrix)
      feed_dict = None

    # Convert back to Tensor.  Needed if use_placeholder, since then we have
    # already evaluated matrix to a numpy array.
    mat = ops.convert_to_tensor(matrix)

    return operator, mat, feed_dict
Ejemplo n.º 30
0
    def operator_and_matrix(self,
                            shape_info,
                            dtype,
                            use_placeholder,
                            ensure_self_adjoint_and_pd=False):
        del ensure_self_adjoint_and_pd
        shape = list(shape_info.shape)
        expected_blocks = (shape_info.__dict__["blocks"]
                           if "blocks" in shape_info.__dict__ else [shape])
        matrices = [
            linear_operator_test_util.random_normal(block_shape, dtype=dtype)
            for block_shape in expected_blocks
        ]

        lin_op_matrices = matrices

        if use_placeholder:
            lin_op_matrices = [
                array_ops.placeholder_with_default(matrix, shape=None)
                for matrix in matrices
            ]

        blocks = []
        for l in lin_op_matrices:
            blocks.append(
                linalg.LinearOperatorFullMatrix(l,
                                                is_square=False,
                                                is_self_adjoint=False,
                                                is_positive_definite=False))
        operator = block_diag.LinearOperatorBlockDiag(blocks)

        # Broadcast the shapes.
        expected_shape = list(shape_info.shape)

        matrices = linear_operator_util.broadcast_matrix_batch_dims(matrices)

        block_diag_dense = _block_diag_dense(expected_shape, matrices)

        if not use_placeholder:
            block_diag_dense.set_shape(expected_shape)

        return operator, block_diag_dense
Ejemplo n.º 31
0
  def test_real_spectrum_gives_self_adjoint_operator(self):

    if test.is_built_with_rocm():
      # ROCm does not yet support BLAS operations with complext types
      self.skipTest("ROCm does not support BLAS operations for complex types")

    with self.cached_session():
      # This is a real and hermitian spectrum.
      spectrum = linear_operator_test_util.random_normal(
          shape=(2, 2, 3, 5), dtype=dtypes.float32)
      operator = linalg.LinearOperatorCirculant3D(spectrum)
      self.assertAllEqual((2, 2 * 3 * 5, 2 * 3 * 5), operator.shape)

      matrix_tensor = operator.to_dense()
      self.assertEqual(matrix_tensor.dtype, dtypes.complex64)
      matrix_h = linalg.adjoint(matrix_tensor)

      matrix, matrix_h = self.evaluate([matrix_tensor, matrix_h])
      self.assertAllEqual((2, 2 * 3 * 5, 2 * 3 * 5), matrix.shape)
      self.assertAllClose(matrix, matrix_h)
Ejemplo n.º 32
0
    def operator_and_matrix(self,
                            shape_info,
                            dtype,
                            use_placeholder,
                            ensure_self_adjoint_and_pd=False):
        # Recall A = L + UDV^H
        shape = list(shape_info.shape)
        diag_shape = shape[:-1]
        k = shape[-2] // 2 + 1
        u_perturbation_shape = shape[:-1] + [k]
        diag_update_shape = shape[:-2] + [k]

        # base_operator L will be a symmetric positive definite diagonal linear
        # operator, with condition number as high as 1e4.
        base_diag = self._gen_positive_diag(dtype, diag_shape)
        lin_op_base_diag = base_diag

        # U
        u = linear_operator_test_util.random_normal_correlated_columns(
            u_perturbation_shape, dtype=dtype)
        lin_op_u = u

        # V
        v = linear_operator_test_util.random_normal_correlated_columns(
            u_perturbation_shape, dtype=dtype)
        lin_op_v = v

        # D
        if self._is_diag_update_positive or ensure_self_adjoint_and_pd:
            diag_update = self._gen_positive_diag(dtype, diag_update_shape)
        else:
            diag_update = linear_operator_test_util.random_normal(
                diag_update_shape, stddev=1e-4, dtype=dtype)
        lin_op_diag_update = diag_update

        if use_placeholder:
            lin_op_base_diag = array_ops.placeholder_with_default(base_diag,
                                                                  shape=None)
            lin_op_u = array_ops.placeholder_with_default(u, shape=None)
            lin_op_v = array_ops.placeholder_with_default(v, shape=None)
            lin_op_diag_update = array_ops.placeholder_with_default(
                diag_update, shape=None)

        base_operator = linalg.LinearOperatorDiag(lin_op_base_diag,
                                                  is_positive_definite=True,
                                                  is_self_adjoint=True)

        operator = linalg.LinearOperatorLowRankUpdate(
            base_operator,
            lin_op_u,
            v=lin_op_v if self._use_v else None,
            diag_update=lin_op_diag_update if self._use_diag_update else None,
            is_diag_update_positive=self._is_diag_update_positive)

        # The matrix representing L
        base_diag_mat = array_ops.matrix_diag(base_diag)

        # The matrix representing D
        diag_update_mat = array_ops.matrix_diag(diag_update)

        # Set up mat as some variant of A = L + UDV^H
        if self._use_v and self._use_diag_update:
            # In this case, we have L + UDV^H and it isn't symmetric.
            expect_use_cholesky = False
            matrix = base_diag_mat + math_ops.matmul(
                u, math_ops.matmul(diag_update_mat, v, adjoint_b=True))
        elif self._use_v:
            # In this case, we have L + UDV^H and it isn't symmetric.
            expect_use_cholesky = False
            matrix = base_diag_mat + math_ops.matmul(u, v, adjoint_b=True)
        elif self._use_diag_update:
            # In this case, we have L + UDU^H, which is PD if D > 0, since L > 0.
            expect_use_cholesky = self._is_diag_update_positive
            matrix = base_diag_mat + math_ops.matmul(
                u, math_ops.matmul(diag_update_mat, u, adjoint_b=True))
        else:
            # In this case, we have L + UU^H, which is PD since L > 0.
            expect_use_cholesky = True
            matrix = base_diag_mat + math_ops.matmul(u, u, adjoint_b=True)

        if expect_use_cholesky:
            self.assertTrue(operator._use_cholesky)
        else:
            self.assertFalse(operator._use_cholesky)

        return operator, matrix
  def _operator_and_mat_and_feed_dict(self, build_info, dtype, use_placeholder):
    # Recall A = L + UDV^H
    shape = list(build_info.shape)
    diag_shape = shape[:-1]
    k = shape[-2] // 2 + 1
    u_perturbation_shape = shape[:-1] + [k]
    diag_update_shape = shape[:-2] + [k]

    # base_operator L will be a symmetric positive definite diagonal linear
    # operator, with condition number as high as 1e4.
    base_diag = linear_operator_test_util.random_uniform(
        diag_shape, minval=1e-4, maxval=1., dtype=dtype)
    base_diag_ph = array_ops.placeholder(dtype=dtype)

    # U
    u = linear_operator_test_util.random_normal_correlated_columns(
        u_perturbation_shape, dtype=dtype)
    u_ph = array_ops.placeholder(dtype=dtype)

    # V
    v = linear_operator_test_util.random_normal_correlated_columns(
        u_perturbation_shape, dtype=dtype)
    v_ph = array_ops.placeholder(dtype=dtype)

    # D
    if self._is_diag_update_positive:
      diag_update = linear_operator_test_util.random_uniform(
          diag_update_shape, minval=1e-4, maxval=1., dtype=dtype)
    else:
      diag_update = linear_operator_test_util.random_normal(
          diag_update_shape, stddev=1e-4, dtype=dtype)
    diag_update_ph = array_ops.placeholder(dtype=dtype)

    if use_placeholder:
      # Evaluate here because (i) you cannot feed a tensor, and (ii)
      # values are random and we want the same value used for both mat and
      # feed_dict.
      base_diag = base_diag.eval()
      u = u.eval()
      v = v.eval()
      diag_update = diag_update.eval()

      # In all cases, set base_operator to be positive definite.
      base_operator = linalg.LinearOperatorDiag(
          base_diag_ph, is_positive_definite=True)

      operator = linalg.LinearOperatorLowRankUpdate(
          base_operator,
          u=u_ph,
          v=v_ph if self._use_v else None,
          diag_update=diag_update_ph if self._use_diag_update else None,
          is_diag_update_positive=self._is_diag_update_positive)
      feed_dict = {
          base_diag_ph: base_diag,
          u_ph: u,
          v_ph: v,
          diag_update_ph: diag_update}
    else:
      base_operator = linalg.LinearOperatorDiag(
          base_diag, is_positive_definite=True)
      operator = linalg.LinearOperatorLowRankUpdate(
          base_operator,
          u,
          v=v if self._use_v else None,
          diag_update=diag_update if self._use_diag_update else None,
          is_diag_update_positive=self._is_diag_update_positive)
      feed_dict = None

    # The matrix representing L
    base_diag_mat = array_ops.matrix_diag(base_diag)

    # The matrix representing D
    diag_update_mat = array_ops.matrix_diag(diag_update)

    # Set up mat as some variant of A = L + UDV^H
    if self._use_v and self._use_diag_update:
      # In this case, we have L + UDV^H and it isn't symmetric.
      expect_use_cholesky = False
      mat = base_diag_mat + math_ops.matmul(
          u, math_ops.matmul(diag_update_mat, v, adjoint_b=True))
    elif self._use_v:
      # In this case, we have L + UDV^H and it isn't symmetric.
      expect_use_cholesky = False
      mat = base_diag_mat + math_ops.matmul(u, v, adjoint_b=True)
    elif self._use_diag_update:
      # In this case, we have L + UDU^H, which is PD if D > 0, since L > 0.
      expect_use_cholesky = self._is_diag_update_positive
      mat = base_diag_mat + math_ops.matmul(
          u, math_ops.matmul(diag_update_mat, u, adjoint_b=True))
    else:
      # In this case, we have L + UU^H, which is PD since L > 0.
      expect_use_cholesky = True
      mat = base_diag_mat + math_ops.matmul(u, u, adjoint_b=True)

    if expect_use_cholesky:
      self.assertTrue(operator._use_cholesky)
    else:
      self.assertFalse(operator._use_cholesky)

    return operator, mat, feed_dict
  def _operator_and_mat_and_feed_dict(self, shape, dtype, use_placeholder):
    # Recall A = L + UDV^H
    shape = list(shape)
    diag_shape = shape[:-1]
    k = shape[-2] // 2 + 1
    u_perturbation_shape = shape[:-1] + [k]
    diag_update_shape = shape[:-2] + [k]

    # base_operator L will be a symmetric positive definite diagonal linear
    # operator, with condition number as high as 1e4.
    base_diag = linear_operator_test_util.random_uniform(
        diag_shape, minval=1e-4, maxval=1., dtype=dtype)
    base_diag_ph = array_ops.placeholder(dtype=dtype)

    # U
    u = linear_operator_test_util.random_normal_correlated_columns(
        u_perturbation_shape, dtype=dtype)
    u_ph = array_ops.placeholder(dtype=dtype)

    # V
    v = linear_operator_test_util.random_normal_correlated_columns(
        u_perturbation_shape, dtype=dtype)
    v_ph = array_ops.placeholder(dtype=dtype)

    # D
    if self._is_diag_update_positive:
      diag_update = linear_operator_test_util.random_uniform(
          diag_update_shape, minval=1e-4, maxval=1., dtype=dtype)
    else:
      diag_update = linear_operator_test_util.random_normal(
          diag_update_shape, stddev=1e-4, dtype=dtype)
    diag_update_ph = array_ops.placeholder(dtype=dtype)

    if use_placeholder:
      # Evaluate here because (i) you cannot feed a tensor, and (ii)
      # values are random and we want the same value used for both mat and
      # feed_dict.
      base_diag = base_diag.eval()
      u = u.eval()
      v = v.eval()
      diag_update = diag_update.eval()

      # In all cases, set base_operator to be positive definite.
      base_operator = linalg.LinearOperatorDiag(
          base_diag_ph, is_positive_definite=True)

      operator = linalg.LinearOperatorLowRankUpdate(
          base_operator,
          u=u_ph,
          v=v_ph if self._use_v else None,
          diag_update=diag_update_ph if self._use_diag_update else None,
          is_diag_update_positive=self._is_diag_update_positive)
      feed_dict = {
          base_diag_ph: base_diag,
          u_ph: u,
          v_ph: v,
          diag_update_ph: diag_update}
    else:
      base_operator = linalg.LinearOperatorDiag(
          base_diag, is_positive_definite=True)
      operator = linalg.LinearOperatorLowRankUpdate(
          base_operator,
          u,
          v=v if self._use_v else None,
          diag_update=diag_update if self._use_diag_update else None,
          is_diag_update_positive=self._is_diag_update_positive)
      feed_dict = None

    # The matrix representing L
    base_diag_mat = array_ops.matrix_diag(base_diag)

    # The matrix representing D
    diag_update_mat = array_ops.matrix_diag(diag_update)

    # Set up mat as some variant of A = L + UDV^H
    if self._use_v and self._use_diag_update:
      # In this case, we have L + UDV^H and it isn't symmetric.
      expect_use_cholesky = False
      mat = base_diag_mat + math_ops.matmul(
          u, math_ops.matmul(diag_update_mat, v, adjoint_b=True))
    elif self._use_v:
      # In this case, we have L + UDV^H and it isn't symmetric.
      expect_use_cholesky = False
      mat = base_diag_mat + math_ops.matmul(u, v, adjoint_b=True)
    elif self._use_diag_update:
      # In this case, we have L + UDU^H, which is PD if D > 0, since L > 0.
      expect_use_cholesky = self._is_diag_update_positive
      mat = base_diag_mat + math_ops.matmul(
          u, math_ops.matmul(diag_update_mat, u, adjoint_b=True))
    else:
      # In this case, we have L + UU^H, which is PD since L > 0.
      expect_use_cholesky = True
      mat = base_diag_mat + math_ops.matmul(u, u, adjoint_b=True)

    if expect_use_cholesky:
      self.assertTrue(operator._use_cholesky)
    else:
      self.assertFalse(operator._use_cholesky)

    return operator, mat, feed_dict
  def operator_and_matrix(self, shape_info, dtype, use_placeholder,
                          ensure_self_adjoint_and_pd=False):
    # Recall A = L + UDV^H
    shape = list(shape_info.shape)
    diag_shape = shape[:-1]
    k = shape[-2] // 2 + 1
    u_perturbation_shape = shape[:-1] + [k]
    diag_update_shape = shape[:-2] + [k]

    # base_operator L will be a symmetric positive definite diagonal linear
    # operator, with condition number as high as 1e4.
    base_diag = self._gen_positive_diag(dtype, diag_shape)
    lin_op_base_diag = base_diag

    # U
    u = linear_operator_test_util.random_normal_correlated_columns(
        u_perturbation_shape, dtype=dtype)
    lin_op_u = u

    # V
    v = linear_operator_test_util.random_normal_correlated_columns(
        u_perturbation_shape, dtype=dtype)
    lin_op_v = v

    # D
    if self._is_diag_update_positive or ensure_self_adjoint_and_pd:
      diag_update = self._gen_positive_diag(dtype, diag_update_shape)
    else:
      diag_update = linear_operator_test_util.random_normal(
          diag_update_shape, stddev=1e-4, dtype=dtype)
    lin_op_diag_update = diag_update

    if use_placeholder:
      lin_op_base_diag = array_ops.placeholder_with_default(
          base_diag, shape=None)
      lin_op_u = array_ops.placeholder_with_default(u, shape=None)
      lin_op_v = array_ops.placeholder_with_default(v, shape=None)
      lin_op_diag_update = array_ops.placeholder_with_default(
          diag_update, shape=None)

    base_operator = linalg.LinearOperatorDiag(
        lin_op_base_diag,
        is_positive_definite=True,
        is_self_adjoint=True)

    operator = linalg.LinearOperatorLowRankUpdate(
        base_operator,
        lin_op_u,
        v=lin_op_v if self._use_v else None,
        diag_update=lin_op_diag_update if self._use_diag_update else None,
        is_diag_update_positive=self._is_diag_update_positive)

    # The matrix representing L
    base_diag_mat = array_ops.matrix_diag(base_diag)

    # The matrix representing D
    diag_update_mat = array_ops.matrix_diag(diag_update)

    # Set up mat as some variant of A = L + UDV^H
    if self._use_v and self._use_diag_update:
      # In this case, we have L + UDV^H and it isn't symmetric.
      expect_use_cholesky = False
      matrix = base_diag_mat + math_ops.matmul(
          u, math_ops.matmul(diag_update_mat, v, adjoint_b=True))
    elif self._use_v:
      # In this case, we have L + UDV^H and it isn't symmetric.
      expect_use_cholesky = False
      matrix = base_diag_mat + math_ops.matmul(u, v, adjoint_b=True)
    elif self._use_diag_update:
      # In this case, we have L + UDU^H, which is PD if D > 0, since L > 0.
      expect_use_cholesky = self._is_diag_update_positive
      matrix = base_diag_mat + math_ops.matmul(
          u, math_ops.matmul(diag_update_mat, u, adjoint_b=True))
    else:
      # In this case, we have L + UU^H, which is PD since L > 0.
      expect_use_cholesky = True
      matrix = base_diag_mat + math_ops.matmul(u, u, adjoint_b=True)

    if expect_use_cholesky:
      self.assertTrue(operator._use_cholesky)
    else:
      self.assertFalse(operator._use_cholesky)

    return operator, matrix