def so4_to_magic_su2s( mat: np.ndarray, *, rtol: float = 1e-5, atol: float = 1e-8, check_preconditions: bool = True ) -> Tuple[np.ndarray, np.ndarray]: """Finds 2x2 special-unitaries A, B where mat = Mag.H @ kron(A, B) @ Mag. Mag is the magic basis matrix: 1 0 0 i 0 i 1 0 0 i -1 0 (times sqrt(0.5) to normalize) 1 0 0 -i Args: mat: A real 4x4 orthogonal matrix. rtol: Per-matrix-entry relative tolerance on equality. atol: Per-matrix-entry absolute tolerance on equality. check_preconditions: When set, the code verifies that the given matrix is from SO(4). Defaults to set. Returns: A pair (A, B) of matrices in SU(2) such that Mag.H @ kron(A, B) @ Mag is approximately equal to the given matrix. Raises: ValueError: Bad matrix. """ if check_preconditions: if mat.shape != (4, 4) or not predicates.is_special_orthogonal(mat, atol=atol, rtol=rtol): raise ValueError('mat must be 4x4 special orthogonal.') ab = combinators.dot(MAGIC, mat, MAGIC_CONJ_T) _, a, b = kron_factor_4x4_to_2x2s(ab) return a, b
def so4_to_magic_su2s( mat: np.ndarray, tolerance: Tolerance = Tolerance.DEFAULT ) -> Tuple[np.ndarray, np.ndarray]: """Finds 2x2 special-unitaries A, B where mat = Mag.H @ kron(A, B) @ Mag. Mag is the magic basis matrix: 1 0 0 i 0 i 1 0 0 i -1 0 (times sqrt(0.5) to normalize) 1 0 0 -i Args: mat: A real 4x4 orthogonal matrix. tolerance: Per-matrix-entry tolerance on equality. Returns: A pair (A, B) of matrices in SU(2) such that Mag.H @ kron(A, B) @ Mag is approximately equal to the given matrix. Raises: ValueError: Bad matrix. """ if mat.shape != (4, 4) or not predicates.is_special_orthogonal( mat, tolerance): raise ValueError('mat must be 4x4 special orthogonal.') ab = combinators.dot(MAGIC, mat, MAGIC_CONJ_T) _, a, b = kron_factor_4x4_to_2x2s(ab, tolerance) return a, b
def test_is_special_orthogonal_tolerance(): tol = Tolerance(atol=0.5) # Pays attention to specified tolerance. assert predicates.is_special_orthogonal( np.array([[1, 0], [-0.5, 1]]), tol) assert not predicates.is_special_orthogonal( np.array([[1, 0], [-0.6, 1]]), tol) # Error isn't accumulated across entries, except for determinant factors. assert predicates.is_special_orthogonal( np.array([[1.2, 0, 0], [0, 1.2, 0], [0, 0, 1 / 1.2]]), tol) assert not predicates.is_special_orthogonal( np.array([[1.2, 0, 0], [0, 1.2, 0], [0, 0, 1.2]]), tol) assert not predicates.is_special_orthogonal( np.array([[1.2, 0, 0], [0, 1.3, 0], [0, 0, 1 / 1.2]]), tol)
def so4_to_magic_su2s( mat: np.ndarray, tolerance: Tolerance = Tolerance.DEFAULT ) -> Tuple[np.ndarray, np.ndarray]: """Finds 2x2 special-unitaries A, B where mat = Mag.H @ kron(A, B) @ Mag. Mag is the magic basis matrix: 1 0 0 i 0 i 1 0 0 i -1 0 (times sqrt(0.5) to normalize) 1 0 0 -i Args: mat: A real 4x4 orthogonal matrix. tolerance: Per-matrix-entry tolerance on equality. Returns: A pair (A, B) of matrices in SU(2) such that Mag.H @ kron(A, B) @ Mag is approximately equal to the given matrix. Raises: ValueError: Bad matrix. ArithmeticError: Failed to perform the decomposition to desired tolerance. """ if mat.shape != (4, 4) or not predicates.is_special_orthogonal(mat, tolerance): raise ValueError('mat must be 4x4 special orthogonal.') magic = np.array([[1, 0, 0, 1j], [0, 1j, 1, 0], [0, 1j, -1, 0], [1, 0, 0, -1j]]) * np.sqrt(0.5) ab = combinators.dot(magic, mat, np.conj(magic.T)) _, a, b = kron_factor_4x4_to_2x2s(ab, tolerance) # Check decomposition against desired tolerance. reconstructed = combinators.dot(np.conj(magic.T), combinators.kron(a, b), magic) if not tolerance.all_close(reconstructed, mat): raise ArithmeticError('Failed to decompose to desired tolerance.') return a, b
def so4_to_magic_su2s( mat: np.ndarray, tolerance: Tolerance = Tolerance.DEFAULT ) -> Tuple[np.ndarray, np.ndarray]: """Finds 2x2 special-unitaries A, B where mat = Mag.H @ kron(A, B) @ Mag. Mag is the magic basis matrix: 1 0 0 i 0 i 1 0 0 i -1 0 (times sqrt(0.5) to normalize) 1 0 0 -i Args: mat: A real 4x4 orthogonal matrix. tolerance: Per-matrix-entry tolerance on equality. Returns: A pair (A, B) of matrices in SU(2) such that Mag.H @ kron(A, B) @ Mag is approximately equal to the given matrix. Raises: ValueError: Bad matrix. ArithmeticError: Failed to perform the decomposition to desired tolerance. """ if mat.shape != (4, 4) or not predicates.is_special_orthogonal(mat, tolerance): raise ValueError('mat must be 4x4 special orthogonal.') magic = np.array([[1, 0, 0, 1j], [0, 1j, 1, 0], [0, 1j, -1, 0], [1, 0, 0, -1j]]) * np.sqrt(0.5) ab = combinators.dot(magic, mat, np.conj(magic.T)) _, a, b = kron_factor_4x4_to_2x2s(ab, tolerance) # Check decomposition against desired tolerance. reconstructed = combinators.dot(np.conj(magic.T), combinators.kron(a, b), magic) if not tolerance.all_close(reconstructed, mat): raise ArithmeticError('Failed to decompose to desired tolerance.') return a, b
np.linalg.inv(U) except np.linalg.LinAlgError: print("Not a valid unitary operation") # check if it is all real. This lets us use 2 CNOTS real = True for row in U: for element in row: if np.imag(element) != 0: real = False print("Nonreal matrix") # print("U\n") # print(U) print(is_special_orthogonal(U)) print("Determinant = ", np.around(np.linalg.det(U), 2)) mUm = magic_basis @ U @ magic_basis.conjugate().transpose() @ np.kron( I2, pauli_Z) @ CNOT1 @ CNOT2 @ CNOT1 tuple = kron_factor_4x4_to_2x2s(mUm) # print(tuple[1]) # print(tuple[2]) print() print(U) # print() # print(np.around(magic_basis.conjugate().transpose() @ U @ magic_basis, 2))
def test_bidiagonalize_unitary_with_special_orthogonals(mat): p, d, q = diagonalize.bidiagonalize_unitary_with_special_orthogonals(mat) assert predicates.is_special_orthogonal(p) assert predicates.is_special_orthogonal(q) assert np.allclose(p.dot(mat).dot(q), np.diag(d)) assert_bidiagonalized_by(mat, p, q)
def test_is_special_orthogonal(): assert predicates.is_special_orthogonal(np.empty((0, 0))) assert not predicates.is_special_orthogonal(np.empty((1, 0))) assert not predicates.is_special_orthogonal(np.empty((0, 1))) assert predicates.is_special_orthogonal(np.array([[1]])) assert not predicates.is_special_orthogonal(np.array([[-1]])) assert not predicates.is_special_orthogonal(np.array([[1j]])) assert not predicates.is_special_orthogonal(np.array([[5]])) assert not predicates.is_special_orthogonal(np.array([[3j]])) assert not predicates.is_special_orthogonal(np.array([[1, 0]])) assert not predicates.is_special_orthogonal(np.array([[1], [0]])) assert not predicates.is_special_orthogonal(np.array([[1, 0], [0, -2]])) assert not predicates.is_special_orthogonal(np.array([[1, 0], [0, -1]])) assert predicates.is_special_orthogonal(np.array([[-1, 0], [0, -1]])) assert not predicates.is_special_orthogonal(np.array([[1j, 0], [0, 1]])) assert not predicates.is_special_orthogonal(np.array([[1, 0], [1, 1]])) assert not predicates.is_special_orthogonal(np.array([[1, 1], [0, 1]])) assert not predicates.is_special_orthogonal(np.array([[1, 1], [1, 1]])) assert not predicates.is_special_orthogonal(np.array([[1, -1], [1, 1]])) assert predicates.is_special_orthogonal( np.array([[1, -1], [1, 1]]) * np.sqrt(0.5)) assert not predicates.is_special_orthogonal( np.array([[1, 1], [1, -1]]) * np.sqrt(0.5)) assert not predicates.is_special_orthogonal( np.array([[1, 1j], [1j, 1]]) * np.sqrt(0.5)) assert not predicates.is_special_orthogonal( np.array([[1, -1j], [1j, 1]]) * np.sqrt(0.5)) assert predicates.is_special_orthogonal( np.array([[1, 1e-11], [0, 1 + 1e-11]]))