Skip to content

Commit d8598dc

Browse files
authored
Support even powers of SWAP gate in CliffordSimulator (#3661)
#3659 adds support for odd powers
1 parent 3c566d2 commit d8598dc

File tree

3 files changed

+30
-7
lines changed

3 files changed

+30
-7
lines changed

cirq/ops/swap_gates.py

+19-7
Original file line numberDiff line numberDiff line change
@@ -85,16 +85,28 @@ def _trace_distance_bound_(self) -> Optional[float]:
8585
return None
8686
return abs(np.sin(self._exponent * 0.5 * np.pi))
8787

88+
def _has_stabilizer_effect_(self) -> Optional[bool]:
89+
if self._is_parameterized_():
90+
return None
91+
return self.exponent % 1 == 0
92+
8893
def _act_on_(self, args):
8994
from cirq import ops, sim, protocols
9095

91-
if isinstance(args, sim.ActOnStabilizerCHFormArgs) and self._exponent % 2 == 1:
92-
args.state.omega *= 1j ** (2 * self.global_shift * self._exponent)
93-
protocols.act_on(ops.CNOT, args)
94-
args.axes = args.axes[::-1]
95-
protocols.act_on(ops.CNOT, args)
96-
args.axes = args.axes[::-1]
97-
protocols.act_on(ops.CNOT, args)
96+
if isinstance(args, (sim.ActOnStabilizerCHFormArgs, sim.ActOnCliffordTableauArgs)):
97+
if not self._has_stabilizer_effect_():
98+
return NotImplemented
99+
if isinstance(args, sim.ActOnStabilizerCHFormArgs):
100+
args.state.omega *= 1j ** (2 * self.global_shift * self._exponent)
101+
102+
if self._exponent % 2 == 1:
103+
protocols.act_on(ops.CNOT, args)
104+
args.axes = args.axes[::-1]
105+
protocols.act_on(ops.CNOT, args)
106+
args.axes = args.axes[::-1]
107+
protocols.act_on(ops.CNOT, args)
108+
109+
# An even exponent does not change anything except the global phase above.
98110
return True
99111

100112
return NotImplemented

cirq/ops/swap_gates_test.py

+7
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,13 @@ def test_text_diagrams():
7575
)
7676

7777

78+
def test_swap_has_stabilizer_effect():
79+
assert cirq.has_stabilizer_effect(cirq.SWAP)
80+
assert cirq.has_stabilizer_effect(cirq.SWAP ** 2)
81+
assert not cirq.has_stabilizer_effect(cirq.SWAP ** 0.5)
82+
assert not cirq.has_stabilizer_effect(cirq.SWAP ** sympy.Symbol('foo'))
83+
84+
7885
def test_swap_unitary():
7986
# yapf: disable
8087
np.testing.assert_almost_equal(

cirq/sim/clifford/clifford_simulator_test.py

+4
Original file line numberDiff line numberDiff line change
@@ -397,13 +397,17 @@ def test_swap():
397397
circuit = cirq.Circuit(
398398
cirq.X(a),
399399
cirq.SWAP(a, b),
400+
cirq.SWAP(a, b) ** 4,
400401
cirq.measure(a, key="a"),
401402
cirq.measure(b, key="b"),
402403
)
403404
r = cirq.CliffordSimulator().sample(circuit)
404405
assert not r["a"][0]
405406
assert r["b"][0]
406407

408+
with pytest.raises(NotImplementedError, match="CliffordSimulator doesn't support"):
409+
cirq.CliffordSimulator().simulate((cirq.Circuit(cirq.SWAP(a, b) ** 3.5)))
410+
407411

408412
def test_sample_seed():
409413
q = cirq.NamedQubit('q')

0 commit comments

Comments
 (0)