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$.
Quantum Computing Stack Exchange is a question and answer site for engineers, scientists, programmers, and computing professionals interested in quantum computing. It only takes a minute to sign up.
Sign up to join this communityGiven 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$.
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}}$.
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
raise ValueError("Not found")
print(find_equivalent())
```