# Is it possible to push back an $H$ gate to a $CZ$ gate?

Given the above scenario. Is it possible to "push back" the $$H$$ gate operation to occur before $$CZ$$?

Formally I am looking for some operation $$CZ\cdot(U_1\otimes U_2) = H\cdot CZ$$.

• can't you just compute ${\rm CZ} \,H\, {\rm CZ}$?
– glS
Jun 29 at 17:55
• @glS and then prove it can't be decomposed into single qubit gates. Jun 29 at 21:21

The Hadamard and the CZ gates don't commute with each other. So, it is not possible to just push it back straightforwardly. If you are still interested in obtaining a unitary U such that: $$H.CZ=CZ.U$$, that is possible. In particular, you can use the propagation relations $$H=\frac{X+Z}{\sqrt{2}}\;,\quad CZ_{a,b}\,X_a\,CZ_{a,b}=X_aZ_b$$ to arrive at the required unitary $$U=\frac{X_1Z_2+Z_1}{\sqrt{2}}$$.

• Could you explain further how you arrived to that 𝑈? Also I checked this using Qiskit and it works but as explained it is not possible to transpile 𝑈 without adding an additional two qubit gate. Jul 1 at 7:46

No, it's not possible. Not without changing the CZ to a CX.

In particular, consider an X error, on the top qubit, crossing from right to left. If the Hadamard is there then the X error turns into a Z error which commutes with the CZ so it exits left with no term on the bottom qubit.

If the CZ is the rightmost operation, then the X error first crosses the CZ creating a Z kickback on the bottom qubit. This non-identity term on the bottom qubit can't be removed by further single qubit operations.

Error kickback onto other qubits is an observable property, so it can't be the case that a single-qubit-gates-then-CZ circuit correctly implements the CZ-then-H circuit.

You can also check this by brute force search. Since the circuit is clifford, you only need to iterate over all the possible Clifford operations that meet your requirements:

import stim

def find_equivalent():
CZ: stim.Tableau = stim.Tableau.from_named_gate("CZ")
goal: stim.Tableau = CZ.copy()
goal.append(stim.Tableau.from_named_gate("H"), [0])

single_qubit_cliffords = []
for x in "XYZ":
for z in "XYZ":
if x != z:
for sign1 in [+1, -1]:
for sign2 in [+1, -1]:
single_qubit_cliffords.append(
stim.Tableau.from_conjugated_generators(
xs=[sign1 * stim.PauliString(x)],
zs=[sign2 * stim.PauliString(z)],
)
)

for g1 in single_qubit_cliffords:
for g2 in single_qubit_cliffords:
achieved = CZ * (g1 + g2)  # Note: + is direct sum (diagonal concatenation)
if goal == achieved:
return g1, g2

$$$$
`