diff --git a/qualtran/bloqs/basic_gates/su2_rotation.py b/qualtran/bloqs/basic_gates/su2_rotation.py index 02757875e7..5878f8d228 100644 --- a/qualtran/bloqs/basic_gates/su2_rotation.py +++ b/qualtran/bloqs/basic_gates/su2_rotation.py @@ -78,6 +78,24 @@ def rotation_matrix(self) -> NDArray[np.complex_]: ] ) + @staticmethod + def from_matrix(mat: NDArray[np.complex_]) -> 'SU2RotationGate': + theta = np.arctan2(np.abs(mat[1, 0]), np.abs(mat[0, 0])) + if np.isclose(np.cos(theta), 0): + alpha = 0 + phi = np.angle(mat[0, 1] / np.sin(theta)) + lambd = np.angle(mat[1, 0] / np.sin(theta)) + else: + alpha = np.angle(-mat[1, 1] / np.cos(theta)) + if np.isclose(np.sin(theta), 0): + phi = np.angle(mat[0, 0] / np.cos(theta) * np.exp(-1j * alpha)) + lambd = 0 + else: + phi = np.angle(mat[0, 1] / np.sin(theta) * np.exp(-1j * alpha)) + lambd = np.angle(mat[1, 0] / np.sin(theta) * np.exp(-1j * alpha)) + + return SU2RotationGate(theta, phi, lambd, alpha) + def add_my_tensors( self, tn: 'qtn.TensorNetwork', diff --git a/qualtran/bloqs/basic_gates/su2_rotation_test.py b/qualtran/bloqs/basic_gates/su2_rotation_test.py index 8e5520d77c..53869396f4 100644 --- a/qualtran/bloqs/basic_gates/su2_rotation_test.py +++ b/qualtran/bloqs/basic_gates/su2_rotation_test.py @@ -14,7 +14,9 @@ import cirq import numpy as np -from . import Hadamard, TGate +from qualtran import Bloq +from qualtran.bloqs.basic_gates import Hadamard, TGate, XGate, YGate, ZGate + from .su2_rotation import _hadamard, _su2_rotation_gate, _t_gate, SU2RotationGate @@ -47,3 +49,21 @@ def test_su2_rotation_gates(bloq_autotester): def test_su2_rotation_gate_example_unitaries_match(): np.testing.assert_allclose(_t_gate().tensor_contract(), TGate().tensor_contract()) np.testing.assert_allclose(_hadamard().tensor_contract(), Hadamard().tensor_contract()) + + +def test_from_matrix_on_random_unitaries(): + random_state = np.random.RandomState(42) + + for _ in range(20): + mat = cirq.testing.random_unitary(2, random_state=random_state) + np.testing.assert_allclose(SU2RotationGate.from_matrix(mat).rotation_matrix, mat) + + +def test_from_matrix_on_standard_gates(): + gates: list[Bloq] = [TGate(), XGate(), YGate(), ZGate(), Hadamard()] + + for gate in gates: + mat = gate.tensor_contract() + np.testing.assert_allclose( + SU2RotationGate.from_matrix(mat).rotation_matrix, mat, atol=1e-15 + )