enter image description here

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$.

  • 2
    $\begingroup$ can't you just compute ${\rm CZ} \,H\, {\rm CZ}$? $\endgroup$
    – glS
    Jun 29 at 17:55
  • 3
    $\begingroup$ @glS and then prove it can't be decomposed into single qubit gates. $\endgroup$ 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}}$.

  • $\begingroup$ 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. $\endgroup$
    – Mauricio
    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]:
                                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

    raise ValueError("Not found")


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.