Skip to content

Commit 2f07cc9

Browse files
authored
Fix the CZ ops on the Clifford Tableau Implementation (#4182)
Implementation idea of CZ is `CZ(q0, q1) = H(q1)CNOT(q0, q1)H(q1)` so the operations are just composition of these three. The problem happens at `rs` of tableau. Original implementation seemed merge the `rs` of `H` and `CNOT` together. But it is not equivalent. See the fix code. FYI, I discovered this because I keep encountering the failure in my Clifford decomposition test. I didn't realize it is the CZ implementation in the cirq has problem for a long time :(
1 parent 700a6c0 commit 2f07cc9

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

cirq-core/cirq/ops/common_gates.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1079,8 +1079,11 @@ def _act_on_(self, args: 'cirq.ActOnArgs', qubits: Sequence['cirq.Qid']):
10791079
tableau.zs[:, q2].copy(),
10801080
tableau.xs[:, q2].copy(),
10811081
)
1082+
tableau.rs[:] ^= tableau.xs[:, q2] & tableau.zs[:, q2]
10821083
tableau.rs[:] ^= (
1083-
tableau.xs[:, q1] & tableau.zs[:, q2] & (tableau.xs[:, q2] ^ tableau.zs[:, q1])
1084+
tableau.xs[:, q1]
1085+
& tableau.zs[:, q2]
1086+
& (~(tableau.xs[:, q2] ^ tableau.zs[:, q1]))
10841087
)
10851088
tableau.xs[:, q2] ^= tableau.xs[:, q1]
10861089
tableau.zs[:, q1] ^= tableau.zs[:, q2]

cirq-core/cirq/ops/common_gates_test.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,32 @@ def test_cz_act_on_tableau():
532532
cirq.act_on(cirq.CZ ** 1.5, args, cirq.LineQubit.range(2))
533533

534534

535+
def test_cz_act_on_equivalent_to_h_cx_h_tableau():
536+
args1 = cirq.ActOnCliffordTableauArgs(
537+
tableau=cirq.CliffordTableau(num_qubits=2),
538+
qubits=cirq.LineQubit.range(2),
539+
prng=np.random.RandomState(),
540+
log_of_measurement_results={},
541+
)
542+
args2 = cirq.ActOnCliffordTableauArgs(
543+
tableau=cirq.CliffordTableau(num_qubits=2),
544+
qubits=cirq.LineQubit.range(2),
545+
prng=np.random.RandomState(),
546+
log_of_measurement_results={},
547+
)
548+
cirq.act_on(cirq.S, args=args1, qubits=[cirq.LineQubit(1)], allow_decompose=False)
549+
cirq.act_on(cirq.S, args=args2, qubits=[cirq.LineQubit(1)], allow_decompose=False)
550+
551+
# Args1 uses H*CNOT*H
552+
cirq.act_on(cirq.H, args=args1, qubits=[cirq.LineQubit(1)], allow_decompose=False)
553+
cirq.act_on(cirq.CNOT, args=args1, qubits=cirq.LineQubit.range(2), allow_decompose=False)
554+
cirq.act_on(cirq.H, args=args1, qubits=[cirq.LineQubit(1)], allow_decompose=False)
555+
# Args2 uses CZ
556+
cirq.act_on(cirq.CZ, args=args2, qubits=cirq.LineQubit.range(2), allow_decompose=False)
557+
558+
assert args1.tableau == args2.tableau
559+
560+
535561
foo = sympy.Symbol('foo')
536562

537563

0 commit comments

Comments
 (0)