PageRenderTime 52ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/qiskit/quantum_info/operators/predicates.py

https://github.com/Qiskit/qiskit-terra
Python | 169 lines | 129 code | 6 blank | 34 comment | 0 complexity | 64100892e50640d658a55a05fb7af723 MD5 | raw file
  1. # This code is part of Qiskit.
  2. #
  3. # (C) Copyright IBM 2017, 2019.
  4. #
  5. # This code is licensed under the Apache License, Version 2.0. You may
  6. # obtain a copy of this license in the LICENSE.txt file in the root directory
  7. # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
  8. #
  9. # Any modifications or derivative works of this code must retain this
  10. # copyright notice, and modified files need to carry a notice indicating
  11. # that they have been altered from the originals.
  12. # pylint: disable=len-as-condition,unsubscriptable-object
  13. """
  14. Predicates for operators.
  15. """
  16. import numpy as np
  17. ATOL_DEFAULT = 1e-8
  18. RTOL_DEFAULT = 1e-5
  19. def matrix_equal(mat1,
  20. mat2,
  21. ignore_phase=False,
  22. rtol=RTOL_DEFAULT,
  23. atol=ATOL_DEFAULT):
  24. """Test if two arrays are equal.
  25. The final comparison is implemented using Numpy.allclose. See its
  26. documentation for additional information on tolerance parameters.
  27. If ignore_phase is True both matrices will be multiplied by
  28. exp(-1j * theta) where `theta` is the first nphase for a
  29. first non-zero matrix element `|a| * exp(1j * theta)`.
  30. Args:
  31. mat1 (matrix_like): a matrix
  32. mat2 (matrix_like): a matrix
  33. ignore_phase (bool): ignore complex-phase differences between
  34. matrices [Default: False]
  35. rtol (double): the relative tolerance parameter [Default {}].
  36. atol (double): the absolute tolerance parameter [Default {}].
  37. Returns:
  38. bool: True if the matrices are equal or False otherwise.
  39. """.format(RTOL_DEFAULT, ATOL_DEFAULT)
  40. if atol is None:
  41. atol = ATOL_DEFAULT
  42. if rtol is None:
  43. rtol = RTOL_DEFAULT
  44. mat1 = np.array(mat1)
  45. mat2 = np.array(mat2)
  46. if mat1.shape != mat2.shape:
  47. return False
  48. if ignore_phase:
  49. # Get phase of first non-zero entry of mat1 and mat2
  50. # and multiply all entries by the conjugate
  51. phases1 = np.angle(mat1[abs(mat1) > atol].ravel(order='F'))
  52. if len(phases1) > 0:
  53. mat1 = np.exp(-1j * phases1[0]) * mat1
  54. phases2 = np.angle(mat2[abs(mat2) > atol].ravel(order='F'))
  55. if len(phases2) > 0:
  56. mat2 = np.exp(-1j * phases2[0]) * mat2
  57. return np.allclose(mat1, mat2, rtol=rtol, atol=atol)
  58. def is_square_matrix(mat):
  59. """Test if an array is a square matrix."""
  60. mat = np.array(mat)
  61. if mat.ndim != 2:
  62. return False
  63. shape = mat.shape
  64. return shape[0] == shape[1]
  65. def is_diagonal_matrix(mat, rtol=RTOL_DEFAULT, atol=ATOL_DEFAULT):
  66. """Test if an array is a diagonal matrix"""
  67. if atol is None:
  68. atol = ATOL_DEFAULT
  69. if rtol is None:
  70. rtol = RTOL_DEFAULT
  71. mat = np.array(mat)
  72. if mat.ndim != 2:
  73. return False
  74. return np.allclose(mat, np.diag(np.diagonal(mat)), rtol=rtol, atol=atol)
  75. def is_symmetric_matrix(op, rtol=RTOL_DEFAULT, atol=ATOL_DEFAULT):
  76. """Test if an array is a symmetric matrix"""
  77. if atol is None:
  78. atol = ATOL_DEFAULT
  79. if rtol is None:
  80. rtol = RTOL_DEFAULT
  81. mat = np.array(op)
  82. if mat.ndim != 2:
  83. return False
  84. return np.allclose(mat, mat.T, rtol=rtol, atol=atol)
  85. def is_hermitian_matrix(mat, rtol=RTOL_DEFAULT, atol=ATOL_DEFAULT):
  86. """Test if an array is a Hermitian matrix"""
  87. if atol is None:
  88. atol = ATOL_DEFAULT
  89. if rtol is None:
  90. rtol = RTOL_DEFAULT
  91. mat = np.array(mat)
  92. if mat.ndim != 2:
  93. return False
  94. return np.allclose(mat, np.conj(mat.T), rtol=rtol, atol=atol)
  95. def is_positive_semidefinite_matrix(mat, rtol=RTOL_DEFAULT, atol=ATOL_DEFAULT):
  96. """Test if a matrix is positive semidefinite"""
  97. if atol is None:
  98. atol = ATOL_DEFAULT
  99. if rtol is None:
  100. rtol = RTOL_DEFAULT
  101. if not is_hermitian_matrix(mat, rtol=rtol, atol=atol):
  102. return False
  103. # Check eigenvalues are all positive
  104. vals = np.linalg.eigvalsh(mat)
  105. for v in vals:
  106. if v < -atol:
  107. return False
  108. return True
  109. def is_identity_matrix(mat,
  110. ignore_phase=False,
  111. rtol=RTOL_DEFAULT,
  112. atol=ATOL_DEFAULT):
  113. """Test if an array is an identity matrix."""
  114. if atol is None:
  115. atol = ATOL_DEFAULT
  116. if rtol is None:
  117. rtol = RTOL_DEFAULT
  118. mat = np.array(mat)
  119. if mat.ndim != 2:
  120. return False
  121. if ignore_phase:
  122. # If the matrix is equal to an identity up to a phase, we can
  123. # remove the phase by multiplying each entry by the complex
  124. # conjugate of the phase of the [0, 0] entry.
  125. theta = np.angle(mat[0, 0])
  126. mat = np.exp(-1j * theta) * mat
  127. # Check if square identity
  128. iden = np.eye(len(mat))
  129. return np.allclose(mat, iden, rtol=rtol, atol=atol)
  130. def is_unitary_matrix(mat, rtol=RTOL_DEFAULT, atol=ATOL_DEFAULT):
  131. """Test if an array is a unitary matrix."""
  132. mat = np.array(mat)
  133. # Compute A^dagger.A and see if it is identity matrix
  134. mat = np.conj(mat.T).dot(mat)
  135. return is_identity_matrix(mat, ignore_phase=False, rtol=rtol, atol=atol)
  136. def is_isometry(mat, rtol=RTOL_DEFAULT, atol=ATOL_DEFAULT):
  137. """Test if an array is an isometry."""
  138. mat = np.array(mat)
  139. # Compute A^dagger.A and see if it is identity matrix
  140. iden = np.eye(mat.shape[1])
  141. mat = np.conj(mat.T).dot(mat)
  142. return np.allclose(mat, iden, rtol=rtol, atol=atol)