From b4fa354429d14eb74f83fbf91a7cf78017f6d632 Mon Sep 17 00:00:00 2001 From: Tanuj Khattar Date: Sat, 28 May 2022 16:24:46 -0700 Subject: [PATCH 1/3] Make all non-analytical decompositions respect global phase --- cirq-core/cirq/ops/common_gates.py | 6 +++--- cirq-core/cirq/ops/common_gates_test.py | 4 +--- cirq-core/cirq/ops/phased_iswap_gate_test.py | 7 ++----- cirq-core/cirq/ops/swap_gates_test.py | 4 +--- cirq-core/cirq/ops/three_qubit_gates.py | 9 +++++++- cirq-core/cirq/ops/three_qubit_gates_test.py | 22 ++++++++------------ 6 files changed, 24 insertions(+), 28 deletions(-) diff --git a/cirq-core/cirq/ops/common_gates.py b/cirq-core/cirq/ops/common_gates.py index 813d9e271af..bf12af444e3 100644 --- a/cirq-core/cirq/ops/common_gates.py +++ b/cirq-core/cirq/ops/common_gates.py @@ -862,11 +862,11 @@ def _decompose_(self, qubits): if self._exponent == 1: yield cirq.Y(q) ** 0.5 - yield cirq.XPowGate(global_shift=-0.25).on(q) + yield cirq.XPowGate(global_shift=-0.25 + self.global_shift).on(q) return yield YPowGate(exponent=0.25).on(q) - yield XPowGate(exponent=self._exponent).on(q) + yield XPowGate(exponent=self._exponent, global_shift=self.global_shift).on(q) yield YPowGate(exponent=-0.25).on(q) def _circuit_diagram_info_( @@ -1134,7 +1134,7 @@ def _decompose_into_clifford_with_qubits_(self, qubits): def _decompose_(self, qubits): c, t = qubits yield YPowGate(exponent=-0.5).on(t) - yield CZ(c, t) ** self._exponent + yield cirq.CZPowGate(exponent=self._exponent, global_shift=self.global_shift).on(c, t) yield YPowGate(exponent=0.5).on(t) def _eigen_components(self) -> List[Tuple[float, np.ndarray]]: diff --git a/cirq-core/cirq/ops/common_gates_test.py b/cirq-core/cirq/ops/common_gates_test.py index bead8592348..eaf2bf94500 100644 --- a/cirq-core/cirq/ops/common_gates_test.py +++ b/cirq-core/cirq/ops/common_gates_test.py @@ -33,9 +33,7 @@ def test_phase_insensitive_eigen_gates_consistent_protocols(eigen_gate_type): @pytest.mark.parametrize('eigen_gate_type', [cirq.CNotPowGate, cirq.HPowGate]) def test_phase_sensitive_eigen_gates_consistent_protocols(eigen_gate_type): - cirq.testing.assert_eigengate_implements_consistent_protocols( - eigen_gate_type, ignoring_global_phase=True - ) + cirq.testing.assert_eigengate_implements_consistent_protocols(eigen_gate_type) def test_cz_init(): diff --git a/cirq-core/cirq/ops/phased_iswap_gate_test.py b/cirq-core/cirq/ops/phased_iswap_gate_test.py index 073dd1a2939..9ee390c12cc 100644 --- a/cirq-core/cirq/ops/phased_iswap_gate_test.py +++ b/cirq-core/cirq/ops/phased_iswap_gate_test.py @@ -141,8 +141,7 @@ def test_phased_iswap_has_consistent_protocols(phase_exponent, exponent, global_ cirq.testing.assert_implements_consistent_protocols( cirq.PhasedISwapPowGate( phase_exponent=phase_exponent, exponent=exponent, global_shift=global_shift - ), - ignoring_global_phase=False, + ) ) @@ -206,6 +205,4 @@ def test_givens_rotation_equivalent_circuit(): @pytest.mark.parametrize('angle_rads', (-np.pi / 5, 0.4, 2, np.pi)) def test_givens_rotation_has_consistent_protocols(angle_rads): - cirq.testing.assert_implements_consistent_protocols( - cirq.givens(angle_rads), ignoring_global_phase=False - ) + cirq.testing.assert_implements_consistent_protocols(cirq.givens(angle_rads)) diff --git a/cirq-core/cirq/ops/swap_gates_test.py b/cirq-core/cirq/ops/swap_gates_test.py index 4cf7dc7cb61..61892eed148 100644 --- a/cirq-core/cirq/ops/swap_gates_test.py +++ b/cirq-core/cirq/ops/swap_gates_test.py @@ -207,6 +207,4 @@ def test_riswap_hamiltonian(angle_rads): @pytest.mark.parametrize('angle_rads', (-np.pi / 5, 0.4, 2, np.pi)) def test_riswap_has_consistent_protocols(angle_rads): - cirq.testing.assert_implements_consistent_protocols( - cirq.riswap(angle_rads), ignoring_global_phase=False - ) + cirq.testing.assert_implements_consistent_protocols(cirq.riswap(angle_rads)) diff --git a/cirq-core/cirq/ops/three_qubit_gates.py b/cirq-core/cirq/ops/three_qubit_gates.py index df7133acef1..b39602ac3b5 100644 --- a/cirq-core/cirq/ops/three_qubit_gates.py +++ b/cirq-core/cirq/ops/three_qubit_gates.py @@ -42,6 +42,7 @@ raw_types, swap_gates, raw_types, + global_phase_op, ) if TYPE_CHECKING: @@ -119,6 +120,9 @@ def _decompose_(self, qubits): sweep_abc = [common_gates.CNOT(a, b), common_gates.CNOT(b, c)] return [ + global_phase_op.global_phase_operation( + (1j) ** (2 * self.global_shift * self._exponent) + ), p(a), p(b), p(c), @@ -339,6 +343,9 @@ def _decompose_(self, qubits): p_gates = [pauli_gates.Z ** (solution / np.pi) for solution in phase_solutions] return [ + global_phase_op.global_phase_operation( + 1j ** (2 * self._diag_angles_radians[0] / np.pi) + ), p_gates[0](a), p_gates[1](b), p_gates[2](c), @@ -460,7 +467,7 @@ def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs') -> np.ndarray: def _decompose_(self, qubits): c1, c2, t = qubits yield common_gates.H(t) - yield CCZ(c1, c2, t) ** self._exponent + yield CCZPowGate(exponent=self._exponent, global_shift=self.global_shift).on(c1, c2, t) yield common_gates.H(t) def _circuit_diagram_info_( diff --git a/cirq-core/cirq/ops/three_qubit_gates_test.py b/cirq-core/cirq/ops/three_qubit_gates_test.py index c8660cb2f26..40597d3609f 100644 --- a/cirq-core/cirq/ops/three_qubit_gates_test.py +++ b/cirq-core/cirq/ops/three_qubit_gates_test.py @@ -22,25 +22,21 @@ @pytest.mark.parametrize('eigen_gate_type', [cirq.CCXPowGate, cirq.CCZPowGate]) def test_eigen_gates_consistent_protocols(eigen_gate_type): - cirq.testing.assert_eigengate_implements_consistent_protocols( - eigen_gate_type, ignoring_global_phase=True - ) + cirq.testing.assert_eigengate_implements_consistent_protocols(eigen_gate_type) @pytest.mark.parametrize( - 'gate,ignoring_global_phase', + 'gate', ( - (cirq.CSWAP, False), - (cirq.ThreeQubitDiagonalGate([2, 3, 5, 7, 11, 13, 17, 19]), True), - (cirq.ThreeQubitDiagonalGate([0, 0, 0, 0, 0, 0, 0, 0]), True), - (cirq.CCX, False), - (cirq.CCZ, False), + (cirq.CSWAP), + (cirq.ThreeQubitDiagonalGate([2, 3, 5, 7, 11, 13, 17, 19])), + (cirq.ThreeQubitDiagonalGate([0, 0, 0, 0, 0, 0, 0, 0])), + (cirq.CCX), + (cirq.CCZ), ), ) -def test_consistent_protocols(gate, ignoring_global_phase): - cirq.testing.assert_implements_consistent_protocols( - gate, ignoring_global_phase=ignoring_global_phase - ) +def test_consistent_protocols(gate): + cirq.testing.assert_implements_consistent_protocols(gate) def test_init(): From a5e6fbc95dd819bc4a4319b9a3faca3c6b8fb6c6 Mon Sep 17 00:00:00 2001 From: Tanuj Khattar Date: Tue, 31 May 2022 09:59:02 -0700 Subject: [PATCH 2/3] Fix failing tests --- cirq-core/cirq/ops/three_qubit_gates.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/cirq-core/cirq/ops/three_qubit_gates.py b/cirq-core/cirq/ops/three_qubit_gates.py index b39602ac3b5..3df9796eb9e 100644 --- a/cirq-core/cirq/ops/three_qubit_gates.py +++ b/cirq-core/cirq/ops/three_qubit_gates.py @@ -118,11 +118,13 @@ def _decompose_(self, qubits): p = common_gates.T**self._exponent sweep_abc = [common_gates.CNOT(a, b), common_gates.CNOT(b, c)] - - return [ - global_phase_op.global_phase_operation( - (1j) ** (2 * self.global_shift * self._exponent) - ), + global_phase = (1j) ** (2 * self.global_shift * self._exponent) + global_phase_operation = ( + [global_phase_op.global_phase_operation(global_phase)] + if protocols.is_parameterized(global_phase) or abs(global_phase - 1.0) > 0 + else [] + ) + return global_phase_operation + [ p(a), p(b), p(c), @@ -341,11 +343,13 @@ def _decompose_(self, qubits): ] phase_solutions = phase_matrix_inverse.dot(shifted_angles_tail) p_gates = [pauli_gates.Z ** (solution / np.pi) for solution in phase_solutions] - - return [ - global_phase_op.global_phase_operation( - 1j ** (2 * self._diag_angles_radians[0] / np.pi) - ), + global_phase = 1j ** (2 * self._diag_angles_radians[0] / np.pi) + global_phase_operation = ( + [global_phase_op.global_phase_operation(global_phase)] + if protocols.is_parameterized(global_phase) or abs(global_phase - 1.0) > 0 + else [] + ) + return global_phase_operation + [ p_gates[0](a), p_gates[1](b), p_gates[2](c), From f96c0ca4b86d262850476f0c913c1aca7147b728 Mon Sep 17 00:00:00 2001 From: Tanuj Khattar Date: Tue, 31 May 2022 10:15:18 -0700 Subject: [PATCH 3/3] Fix nit --- cirq-core/cirq/ops/three_qubit_gates.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cirq-core/cirq/ops/three_qubit_gates.py b/cirq-core/cirq/ops/three_qubit_gates.py index 3df9796eb9e..409e862ea63 100644 --- a/cirq-core/cirq/ops/three_qubit_gates.py +++ b/cirq-core/cirq/ops/three_qubit_gates.py @@ -118,7 +118,7 @@ def _decompose_(self, qubits): p = common_gates.T**self._exponent sweep_abc = [common_gates.CNOT(a, b), common_gates.CNOT(b, c)] - global_phase = (1j) ** (2 * self.global_shift * self._exponent) + global_phase = 1j ** (2 * self.global_shift * self._exponent) global_phase_operation = ( [global_phase_op.global_phase_operation(global_phase)] if protocols.is_parameterized(global_phase) or abs(global_phase - 1.0) > 0