From baa9bf811c2336359ce9bbca621cef565320afc0 Mon Sep 17 00:00:00 2001 From: Smit Date: Sat, 9 Jan 2021 23:25:36 -0800 Subject: [PATCH 1/4] Support even powers of SWAP gate --- cirq/ops/swap_gates.py | 30 +++++++++++++++----- cirq/sim/clifford/clifford_simulator_test.py | 4 +++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/cirq/ops/swap_gates.py b/cirq/ops/swap_gates.py index 432475d6c7a..847b8600cfb 100644 --- a/cirq/ops/swap_gates.py +++ b/cirq/ops/swap_gates.py @@ -85,16 +85,32 @@ def _trace_distance_bound_(self) -> Optional[float]: return None return abs(np.sin(self._exponent * 0.5 * np.pi)) + def _has_stabilizer_effect_(self) -> Optional[bool]: + if self._is_parameterized_(): + return None + return self.exponent % 1 == 0 + def _act_on_(self, args): from cirq import ops, sim, protocols - if isinstance(args, sim.ActOnStabilizerCHFormArgs) and self._exponent % 2 == 1: - args.state.omega *= 1j ** (2 * self.global_shift * self._exponent) - protocols.act_on(ops.CNOT, args) - args.axes = args.axes[::-1] - protocols.act_on(ops.CNOT, args) - args.axes = args.axes[::-1] - protocols.act_on(ops.CNOT, args) + if isinstance(args, (sim.ActOnStabilizerCHFormArgs, sim.ActOnCliffordTableauArgs)): + if not protocols.has_stabilizer_effect(self): + return NotImplemented + if isinstance(args, sim.ActOnStabilizerCHFormArgs): + args.state.omega *= 1j ** (2 * self.global_shift * self._exponent) + + if self._exponent % 2 == 1: + protocols.act_on(ops.CNOT, args) + args.axes = args.axes[::-1] + protocols.act_on(ops.CNOT, args) + args.axes = args.axes[::-1] + protocols.act_on(ops.CNOT, args) + else: + # Any fractional exponent SWAP gate should have been rejected + # already. Any even exponent does not change anything except + # the global phase above. + assert self._exponent % 2 == 0 + return True return NotImplemented diff --git a/cirq/sim/clifford/clifford_simulator_test.py b/cirq/sim/clifford/clifford_simulator_test.py index 79c3969053a..d9c02baaddc 100644 --- a/cirq/sim/clifford/clifford_simulator_test.py +++ b/cirq/sim/clifford/clifford_simulator_test.py @@ -396,6 +396,7 @@ def test_swap(): circuit = cirq.Circuit( cirq.X(a), cirq.SWAP(a, b), + cirq.SWAP(a, b) ** 4, cirq.measure(a, key="a"), cirq.measure(b, key="b"), ) @@ -403,6 +404,9 @@ def test_swap(): assert not r["a"][0] assert r["b"][0] + with pytest.raises(NotImplementedError, match="CliffordSimulator doesn't support"): + cirq.CliffordSimulator().simulate((cirq.Circuit(cirq.SWAP(a, b) ** 3.5))) + def test_sample_seed(): q = cirq.NamedQubit('q') From fe46b038bf31a2c3f677d30906e5d9243fe7ab18 Mon Sep 17 00:00:00 2001 From: Smit Date: Sun, 10 Jan 2021 00:00:56 -0800 Subject: [PATCH 2/4] Add test for has_stabilizer_effect --- cirq/ops/swap_gates_test.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cirq/ops/swap_gates_test.py b/cirq/ops/swap_gates_test.py index 7a4e8d2b045..5c135f65723 100644 --- a/cirq/ops/swap_gates_test.py +++ b/cirq/ops/swap_gates_test.py @@ -75,6 +75,13 @@ def test_text_diagrams(): ) +def test_swap_has_stabilizer_effect(): + assert cirq.has_stabilizer_effect(cirq.SWAP) + assert cirq.has_stabilizer_effect(cirq.SWAP ** 2) + assert not cirq.has_stabilizer_effect(cirq.SWAP ** 0.5) + assert not cirq.has_stabilizer_effect(cirq.SWAP ** sympy.Symbol('foo')) + + def test_swap_unitary(): # yapf: disable np.testing.assert_almost_equal( From f1d229407ffc43d5a1e8138a0bc8b4913af0ac4a Mon Sep 17 00:00:00 2001 From: Smit Date: Sun, 10 Jan 2021 00:19:06 -0800 Subject: [PATCH 3/4] Address comments --- cirq/ops/swap_gates.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/cirq/ops/swap_gates.py b/cirq/ops/swap_gates.py index 847b8600cfb..91ab4580c25 100644 --- a/cirq/ops/swap_gates.py +++ b/cirq/ops/swap_gates.py @@ -94,7 +94,7 @@ def _act_on_(self, args): from cirq import ops, sim, protocols if isinstance(args, (sim.ActOnStabilizerCHFormArgs, sim.ActOnCliffordTableauArgs)): - if not protocols.has_stabilizer_effect(self): + if self._has_stabilizer_effect_(): return NotImplemented if isinstance(args, sim.ActOnStabilizerCHFormArgs): args.state.omega *= 1j ** (2 * self.global_shift * self._exponent) @@ -105,12 +105,8 @@ def _act_on_(self, args): protocols.act_on(ops.CNOT, args) args.axes = args.axes[::-1] protocols.act_on(ops.CNOT, args) - else: - # Any fractional exponent SWAP gate should have been rejected - # already. Any even exponent does not change anything except - # the global phase above. - assert self._exponent % 2 == 0 + # An even exponent does not change anything except the global phase above. return True return NotImplemented From cbf6b6bfaf9af9c50a8a85962c586c031fc1a984 Mon Sep 17 00:00:00 2001 From: Smit Date: Sun, 10 Jan 2021 00:20:21 -0800 Subject: [PATCH 4/4] Add not --- cirq/ops/swap_gates.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cirq/ops/swap_gates.py b/cirq/ops/swap_gates.py index 91ab4580c25..047778a629f 100644 --- a/cirq/ops/swap_gates.py +++ b/cirq/ops/swap_gates.py @@ -94,7 +94,7 @@ def _act_on_(self, args): from cirq import ops, sim, protocols if isinstance(args, (sim.ActOnStabilizerCHFormArgs, sim.ActOnCliffordTableauArgs)): - if self._has_stabilizer_effect_(): + if not self._has_stabilizer_effect_(): return NotImplemented if isinstance(args, sim.ActOnStabilizerCHFormArgs): args.state.omega *= 1j ** (2 * self.global_shift * self._exponent)