def _convert_to_su4(U): r"""Check unitarity of a 4x4 matrix and convert it to :math:`SU(4)` if the determinant is not 1. Args: U (array[complex]): A matrix, presumed to be :math:`4 \times 4` and unitary. Returns: array[complex]: A :math:`4 \times 4` matrix in :math:`SU(4)` that is equivalent to U up to a global phase. """ # Check unitarity if not math.allclose( math.dot(U, math.T(math.conj(U))), math.eye(4), atol=1e-7): raise ValueError("Operator must be unitary.") # Compute the determinant det = math.linalg.det(U) # Convert to SU(4) if it's not close to 1 if not math.allclose(det, 1.0): exp_angle = -1j * math.cast_like(math.angle(det), 1j) / 4 U = math.cast_like(U, det) * math.exp(exp_angle) return U
def _convert_to_su2(U): r"""Check unitarity of a matrix and convert it to :math:`SU(2)` if possible. Args: U (array[complex]): A matrix, presumed to be :math:`2 \times 2` and unitary. Returns: array[complex]: A :math:`2 \times 2` matrix in :math:`SU(2)` that is equivalent to U up to a global phase. """ # Check unitarity if not math.allclose( math.dot(U, math.T(math.conj(U))), math.eye(2), atol=1e-7): raise ValueError("Operator must be unitary.") # Compute the determinant det = U[0, 0] * U[1, 1] - U[0, 1] * U[1, 0] # Convert to SU(2) if it's not close to 1 if not math.allclose(det, [1.0]): exp_angle = -1j * math.cast_like(math.angle(det), 1j) / 2 U = math.cast_like(U, exp_angle) * math.exp(exp_angle) return U