Skip to content

Commit 2cfdf1f

Browse files
maffoopavoljuhas
andauthored
Add convenience methods to create PhasedXZ gate from ZYZ decomposition (#6569)
Co-authored-by: Pavol Juhas <[email protected]>
1 parent 1a8caa4 commit 2cfdf1f

File tree

3 files changed

+42
-2
lines changed

3 files changed

+42
-2
lines changed

cirq-core/cirq/ops/phased_x_gate.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
@value.value_equality(manual_cls=True, approximate=True)
3030
class PhasedXPowGate(raw_types.Gate):
31-
r"""A gate equivalent to $Z^{p} X^t Z^{-p}$.
31+
r"""A gate equivalent to $Z^{-p} X^t Z^{p}$ (in time order).
3232
3333
The unitary matrix of `cirq.PhasedXPowGate(exponent=t, phase_exponent=p)` is:
3434
$$

cirq-core/cirq/ops/phased_x_z_gate.py

+17-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
@value.value_equality(approximate=True)
2929
class PhasedXZGate(raw_types.Gate):
30-
r"""A single qubit gate equivalent to the circuit $Z^z Z^{a} X^x Z^{-a}$.
30+
r"""A single qubit gate equivalent to the circuit $Z^{-a} X^x Z^{a} Z^z$ (in time order).
3131
3232
The unitary matrix of `cirq.PhasedXZGate(x_exponent=x, z_exponent=z, axis_phase_exponent=a)` is:
3333
$$
@@ -67,6 +67,22 @@ def __init__(
6767
self._z_exponent = z_exponent
6868
self._axis_phase_exponent = axis_phase_exponent
6969

70+
@classmethod
71+
def from_zyz_angles(cls, z0_rad: float, y_rad: float, z1_rad: float) -> 'cirq.PhasedXZGate':
72+
"""Create a PhasedXZGate from ZYZ angles.
73+
74+
The returned gate is equivalent to $Rz(z0_rad) Ry(y_rad) Rz(z1_rad)$ (in time order).
75+
"""
76+
return cls.from_zyz_exponents(z0=z0_rad / np.pi, y=y_rad / np.pi, z1=z1_rad / np.pi)
77+
78+
@classmethod
79+
def from_zyz_exponents(cls, z0: float, y: float, z1: float) -> 'cirq.PhasedXZGate':
80+
"""Create a PhasedXZGate from ZYZ exponents.
81+
82+
The returned gate is equivalent to $Z^z0 Y^y Z^z1$ (in time order).
83+
"""
84+
return PhasedXZGate(axis_phase_exponent=-z0 + 0.5, x_exponent=y, z_exponent=z0 + z1)
85+
7086
def _canonical(self) -> 'cirq.PhasedXZGate':
7187
x = self.x_exponent
7288
z = self.z_exponent

cirq-core/cirq/ops/phased_x_z_gate_test.py

+24
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,30 @@ def test_eq():
3434
eq.add_equality_group(cirq.PhasedXZGate(x_exponent=1, z_exponent=0, axis_phase_exponent=0))
3535

3636

37+
@pytest.mark.parametrize('z0_rad', [-np.pi / 5, 0, np.pi / 5, np.pi / 4, np.pi / 2, np.pi])
38+
@pytest.mark.parametrize('y_rad', [0, np.pi / 5, np.pi / 4, np.pi / 2, np.pi])
39+
@pytest.mark.parametrize('z1_rad', [-np.pi / 5, 0, np.pi / 5, np.pi / 4, np.pi / 2, np.pi])
40+
def test_from_zyz_angles(z0_rad: float, y_rad: float, z1_rad: float) -> None:
41+
q = cirq.q(0)
42+
phxz = cirq.PhasedXZGate.from_zyz_angles(z0_rad, y_rad, z1_rad)
43+
zyz = cirq.Circuit(cirq.rz(z0_rad).on(q), cirq.ry(y_rad).on(q), cirq.rz(z1_rad).on(q))
44+
cirq.testing.assert_allclose_up_to_global_phase(
45+
cirq.unitary(phxz), cirq.unitary(zyz), atol=1e-8
46+
)
47+
48+
49+
@pytest.mark.parametrize('z0', [-0.2, 0, 0.2, 0.25, 0.5, 1])
50+
@pytest.mark.parametrize('y', [0, 0.2, 0.25, 0.5, 1])
51+
@pytest.mark.parametrize('z1', [-0.2, 0, 0.2, 0.25, 0.5, 1])
52+
def test_from_zyz_exponents(z0: float, y: float, z1: float) -> None:
53+
q = cirq.q(0)
54+
phxz = cirq.PhasedXZGate.from_zyz_exponents(z0, y, z1)
55+
zyz = cirq.Circuit(cirq.Z(q) ** z0, cirq.Y(q) ** y, cirq.Z(q) ** z1)
56+
cirq.testing.assert_allclose_up_to_global_phase(
57+
cirq.unitary(phxz), cirq.unitary(zyz), atol=1e-8
58+
)
59+
60+
3761
def test_canonicalization():
3862
def f(x, z, a):
3963
return cirq.PhasedXZGate(x_exponent=x, z_exponent=z, axis_phase_exponent=a)

0 commit comments

Comments
 (0)