Skip to content

Commit 0d55968

Browse files
authored
Make all non-analytical gate decompositions respect global phase (#5420)
Fixes #4275
1 parent f632769 commit 0d55968

6 files changed

+32
-32
lines changed

cirq-core/cirq/ops/common_gates.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -862,11 +862,11 @@ def _decompose_(self, qubits):
862862

863863
if self._exponent == 1:
864864
yield cirq.Y(q) ** 0.5
865-
yield cirq.XPowGate(global_shift=-0.25).on(q)
865+
yield cirq.XPowGate(global_shift=-0.25 + self.global_shift).on(q)
866866
return
867867

868868
yield YPowGate(exponent=0.25).on(q)
869-
yield XPowGate(exponent=self._exponent).on(q)
869+
yield XPowGate(exponent=self._exponent, global_shift=self.global_shift).on(q)
870870
yield YPowGate(exponent=-0.25).on(q)
871871

872872
def _circuit_diagram_info_(
@@ -1134,7 +1134,7 @@ def _decompose_into_clifford_with_qubits_(self, qubits):
11341134
def _decompose_(self, qubits):
11351135
c, t = qubits
11361136
yield YPowGate(exponent=-0.5).on(t)
1137-
yield CZ(c, t) ** self._exponent
1137+
yield cirq.CZPowGate(exponent=self._exponent, global_shift=self.global_shift).on(c, t)
11381138
yield YPowGate(exponent=0.5).on(t)
11391139

11401140
def _eigen_components(self) -> List[Tuple[float, np.ndarray]]:

cirq-core/cirq/ops/common_gates_test.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,7 @@ def test_phase_insensitive_eigen_gates_consistent_protocols(eigen_gate_type):
3333

3434
@pytest.mark.parametrize('eigen_gate_type', [cirq.CNotPowGate, cirq.HPowGate])
3535
def test_phase_sensitive_eigen_gates_consistent_protocols(eigen_gate_type):
36-
cirq.testing.assert_eigengate_implements_consistent_protocols(
37-
eigen_gate_type, ignoring_global_phase=True
38-
)
36+
cirq.testing.assert_eigengate_implements_consistent_protocols(eigen_gate_type)
3937

4038

4139
def test_cz_init():

cirq-core/cirq/ops/phased_iswap_gate_test.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,7 @@ def test_phased_iswap_has_consistent_protocols(phase_exponent, exponent, global_
141141
cirq.testing.assert_implements_consistent_protocols(
142142
cirq.PhasedISwapPowGate(
143143
phase_exponent=phase_exponent, exponent=exponent, global_shift=global_shift
144-
),
145-
ignoring_global_phase=False,
144+
)
146145
)
147146

148147

@@ -206,6 +205,4 @@ def test_givens_rotation_equivalent_circuit():
206205

207206
@pytest.mark.parametrize('angle_rads', (-np.pi / 5, 0.4, 2, np.pi))
208207
def test_givens_rotation_has_consistent_protocols(angle_rads):
209-
cirq.testing.assert_implements_consistent_protocols(
210-
cirq.givens(angle_rads), ignoring_global_phase=False
211-
)
208+
cirq.testing.assert_implements_consistent_protocols(cirq.givens(angle_rads))

cirq-core/cirq/ops/swap_gates_test.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,4 @@ def test_riswap_hamiltonian(angle_rads):
207207

208208
@pytest.mark.parametrize('angle_rads', (-np.pi / 5, 0.4, 2, np.pi))
209209
def test_riswap_has_consistent_protocols(angle_rads):
210-
cirq.testing.assert_implements_consistent_protocols(
211-
cirq.riswap(angle_rads), ignoring_global_phase=False
212-
)
210+
cirq.testing.assert_implements_consistent_protocols(cirq.riswap(angle_rads))

cirq-core/cirq/ops/three_qubit_gates.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
raw_types,
4343
swap_gates,
4444
raw_types,
45+
global_phase_op,
4546
)
4647

4748
if TYPE_CHECKING:
@@ -117,8 +118,13 @@ def _decompose_(self, qubits):
117118

118119
p = common_gates.T**self._exponent
119120
sweep_abc = [common_gates.CNOT(a, b), common_gates.CNOT(b, c)]
120-
121-
return [
121+
global_phase = 1j ** (2 * self.global_shift * self._exponent)
122+
global_phase_operation = (
123+
[global_phase_op.global_phase_operation(global_phase)]
124+
if protocols.is_parameterized(global_phase) or abs(global_phase - 1.0) > 0
125+
else []
126+
)
127+
return global_phase_operation + [
122128
p(a),
123129
p(b),
124130
p(c),
@@ -337,8 +343,13 @@ def _decompose_(self, qubits):
337343
]
338344
phase_solutions = phase_matrix_inverse.dot(shifted_angles_tail)
339345
p_gates = [pauli_gates.Z ** (solution / np.pi) for solution in phase_solutions]
340-
341-
return [
346+
global_phase = 1j ** (2 * self._diag_angles_radians[0] / np.pi)
347+
global_phase_operation = (
348+
[global_phase_op.global_phase_operation(global_phase)]
349+
if protocols.is_parameterized(global_phase) or abs(global_phase - 1.0) > 0
350+
else []
351+
)
352+
return global_phase_operation + [
342353
p_gates[0](a),
343354
p_gates[1](b),
344355
p_gates[2](c),
@@ -460,7 +471,7 @@ def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs') -> np.ndarray:
460471
def _decompose_(self, qubits):
461472
c1, c2, t = qubits
462473
yield common_gates.H(t)
463-
yield CCZ(c1, c2, t) ** self._exponent
474+
yield CCZPowGate(exponent=self._exponent, global_shift=self.global_shift).on(c1, c2, t)
464475
yield common_gates.H(t)
465476

466477
def _circuit_diagram_info_(

cirq-core/cirq/ops/three_qubit_gates_test.py

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,21 @@
2222

2323
@pytest.mark.parametrize('eigen_gate_type', [cirq.CCXPowGate, cirq.CCZPowGate])
2424
def test_eigen_gates_consistent_protocols(eigen_gate_type):
25-
cirq.testing.assert_eigengate_implements_consistent_protocols(
26-
eigen_gate_type, ignoring_global_phase=True
27-
)
25+
cirq.testing.assert_eigengate_implements_consistent_protocols(eigen_gate_type)
2826

2927

3028
@pytest.mark.parametrize(
31-
'gate,ignoring_global_phase',
29+
'gate',
3230
(
33-
(cirq.CSWAP, False),
34-
(cirq.ThreeQubitDiagonalGate([2, 3, 5, 7, 11, 13, 17, 19]), True),
35-
(cirq.ThreeQubitDiagonalGate([0, 0, 0, 0, 0, 0, 0, 0]), True),
36-
(cirq.CCX, False),
37-
(cirq.CCZ, False),
31+
(cirq.CSWAP),
32+
(cirq.ThreeQubitDiagonalGate([2, 3, 5, 7, 11, 13, 17, 19])),
33+
(cirq.ThreeQubitDiagonalGate([0, 0, 0, 0, 0, 0, 0, 0])),
34+
(cirq.CCX),
35+
(cirq.CCZ),
3836
),
3937
)
40-
def test_consistent_protocols(gate, ignoring_global_phase):
41-
cirq.testing.assert_implements_consistent_protocols(
42-
gate, ignoring_global_phase=ignoring_global_phase
43-
)
38+
def test_consistent_protocols(gate):
39+
cirq.testing.assert_implements_consistent_protocols(gate)
4440

4541

4642
def test_init():

0 commit comments

Comments
 (0)