# How do I transform a $ZZ$ interaction unitary into a $\text{CZ}$ gate?

I have a unitary gate given as $$$$e^{-i\theta Z \otimes Z} = \cos(\theta)I - i \sin(\theta)Z \otimes Z\,.$$$$ When I insert $$\theta = \pi/4$$ I get the maximally entangling, $$$$e^{-i\frac{\pi}{4} Z \otimes Z} = \begin{pmatrix} \frac{1-i}{\sqrt{2}} & 0 & 0 & 0 \\ 0 & \frac{1+i}{\sqrt{2}} & 0 & 0 \\ 0 & 0 & \frac{1+i}{\sqrt{2}} & 0 \\ 0 & 0 & 0 & \frac{1-i}{\sqrt{2}} \\ \end{pmatrix}.$$$$

Say I want to construct a $$\text{CZ}$$ matrix with this gate and single-qubit rotations. How would I do this? In particular, what is the intuition behind this? For example, I know that it should probably use $$Z$$ operations on individual qubits since they won't introduce any off-diagonal terms.

Here's one approach. Let $$\text{diag}(a,b,c,d)$$ denote a $$4\times 4$$ matrix with $$a,b,c,d$$ along the diagonal. A nice property of diagonal matrices is they generate diagonal unitaries: $$$$\exp(i \theta \cdot \text{diag}(a,b,c,d)) = \text{diag}(e^{i\theta a}, e^{i\theta b}, e^{i\theta c}, e^{i\theta d}) \tag{1}.$$$$ Looking at $$\text{CZ} = \text{diag}(1, 1, 1, -1)$$, we see that we need some generator with $$a=b=c=0$$. Since $$\{II, IZ, ZI, ZZ\}$$ are a basis for diagonal matrices, we can build such a generator by just solving a linear system of equations: $$$$\begin{array}{ccccccc} I \otimes I &= \text{diag}(&1, &1, &1, &1&) \tag{2a-d}\\ I \otimes Z &= \text{diag}(&1, &-1, &1, &-1&) \\ Z \otimes I &= \text{diag}(&1, &1, &-1, &-1&) \\ Z \otimes Z &= \text{diag}(&1, &-1, &-1, &1&) \end{array}$$$$

The combination that has $$a=b=c=0$$ is \begin{align} |11\rangle \langle 11| &= \frac{1}{4}(I\otimes I - I\otimes Z - Z\otimes I + Z\otimes Z) \tag{3a}\\ &= \text{diag}(0, 0, 0, 1) \tag{3b} \end{align}

Using Eq. (1) to infer the generator for $$\text{CZ}$$, just substitute Eq. (3) and simplify: \begin{align} \text{CZ} &= \text{diag}(1, 1, 1, -1) \tag{4a} \\&= \exp(i \pi \cdot \text{diag}(0, 0, 0, 1)) \tag{4b} \\&= \exp\left(i \frac{\pi}{4} (I\otimes I - I\otimes Z - Z\otimes I + Z\otimes Z) \right) \tag{4c} \\&= \exp\left(i \frac{\pi}{4} I\otimes I\right) \exp\left( -i \frac{\pi}{4}( I\otimes Z)\right) \exp\left(-i \frac{\pi}{4}( Z\otimes I)\right)\exp \left( i \frac{\pi}{4}( Z\otimes Z) \right) \tag{4d} \\&= \exp\left(i \frac{\pi}{4} \right) \left[R_z \left(\frac{\pi}{2}\right) \otimes R_z \left(\frac{\pi}{2}\right)\right] \exp \left( i \frac{\pi}{4} ( Z\otimes Z) \right). \tag{4e} \end{align} Where I have used the fact that all of these diagonal generators commute with eachother to expand the exponential. The global phase doesn't matter, and I've used the convention $$R_Z(\theta) := \exp(-i \theta Z/2)$$.

• ah this is so nice Apr 2 at 2:22

To aid with some intuition/reasoning, let me take you through how I would manually do the calculation. We start with your matrix $$\begin{bmatrix} e^{-i\pi/4} & 0 & 0 & 0 \\ 0 & e^{i\pi/4} & 0 & 0 \\ 0 & 0 & e^{i\pi/4} & 0 \\ 0 & 0 & 0 & e^{-i\pi/4} \end{bmatrix}$$ Our aim is to make the diagonal elements real (in the first instance), and we have 3 parameters that we can use to do this:

• the global phase
• a $$Z$$ rotation on qubit 1, which I'll write in the form $$\begin{bmatrix} 1 & 0 \\ 0 & e^{i\gamma}\end{bmatrix}$$.
• a $$Z$$ rotation on qubit 2

The first trick is to find out how to manipulate these independently. So, notice that, of the 3 parameters, only the global phase affects the $$|00\rangle$$ basis. So, let's pull out a global phase of $$e^{-i\pi/4}$$, leaving $$e^{-i\pi/4}\begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & i & 0 & 0 \\ 0 & 0 & i & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}$$ Next, a phase rotation on qubit 1 affects the phase of $$|10\rangle$$ and not $$|01\rangle$$. So, let's apply one ($$S^\dagger\otimes I=\text{diag}(1,1,-i,-i)$$) with $$\gamma=-\pi/2$$ that will fix that element, leaving $$e^{-i\pi/4}\begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & i & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & -i \end{bmatrix}.$$ Symmetrically, a phase rotation on qubit 2 alters the phase of $$|01\rangle$$ without changing $$|00\rangle$$ or $$|10\rangle$$. So, set that to $$\gamma=-\pi/2$$ (another $$S^\dagger$$, $$I\otimes S^\dagger=\text{diag}(1,-i,1,-i)$$), to leave $$e^{-i\pi/4}\begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & -1 \end{bmatrix}.$$ This is exactly the controlled-phase you were hoping for.

• Would it be possible to write out the exact S operation you are doing? I think that it'd be helpful for the community. Apr 2 at 14:39

The $$ZZ$$ rotation gate you've given is an example of a maximally entangling operation.

I found the following circuit to implement it. I was surprised that you only need a single $$CZ$$ but it works. The pytket software package I'm using has a slightly different angle convention than you are using so read the angle $$0.5$$ as $$0.5 \pi$$.

from pytket import Circuit, OpType
from pytket.circuit.display import render_circuit_jupyter as draw
from pytket.passes import auto_rebase_pass, EulerAngleReduction

# Circuit with a single maximally entangling ZZ operation
circ = Circuit(2).ZZMax(0, 1)

# Rebase (aka convert to desired gateset)
rebase = auto_rebase_pass({OpType.CZ, OpType.Rx, OpType.Rz})
rebase.apply(circ)

# Simplify single qubit gates
EulerAngleReduction(OpType.Rz, OpType.Rx).apply(circ)

draw(circ)


The unitary matches the one you give

circ.get_unitary().round(3) # 1/sqrt(2) approx 0.707...


Note: I first rushed my answer and it was incorrect and confusing. I only tested the KAK decomposition for the ZZ gate, which is not entangling in itself, resulting in the KAK vector of (0,0,0). I believe the KAK perspective is useful and gives a methodical way to look at this compilation problem, as it highlights the structure of two-qubit unitaries in general.

However, the automation results in a more complicated answer, serving as a cautionary tale to use pen and paper when you can. It does not take into account the simplicity of dealing with diagonal gates (see other, simpler answers from @forky40 and @DaftWullie). Cirq's handling of global phases also complicates things more than I'd like it, it's still might be worthwhile for the community for reference.

The KAK decomposition is helpful in determining whether two two-qubit unitaries are equivalent or not up to local (single qubit) unitaries. The equivalence classes are characterized by their KAK vector, consisting of three real numbers, that correspond to angles of $$XX$$, $$YY$$ and $$ZZ$$ rotations.

The equivalence classes can be then visualized on a tetrahedron (note that in this paper they use a half angle convention, and $$CX \equiv CZ$$ corresponds to $$[\pi/2, 0,0]$$ KAK vector instead of $$[\pi/4, 0,0]$$ discussed below. Also see this blog post for a nice map of the tetrahedron.)

When two gates $$U_1=k_1 A_1 k_2$$ and $$U_2 = j_1 A_2 j_2$$ have the same KAK vector, then $$A_1=A_2$$. Thus, they can be converted into each other using $$U_2 = j_1 k_1^\dagger U_1 k_2^\dagger j_2$$.

$$\text{CZ}$$ and $$e^{-i \theta Z_1Z_2}$$ are equivalent up to local unitaries, but only at $$\theta = \pm \frac{\pi}{4}$$. I used Cirq to determine the KAK decomposition:

import cirq
cirq.kak_decomposition(scipy.linalg.expm(-cirq.unitary(cirq.ZZ)*1j * np.pi/ 4))


gives

cirq.KakDecomposition(
interaction_coefficients=(0.7853981633974483, 0.0, 0.0),
single_qubit_operations_before=(
np.array([[(-0.7071067811865475+0j), (0.7071067811865475+0j)], [(-0.7071067811865475+0j), (-0.7071067811865475+0j)]], dtype=np.dtype('complex128')),
np.array([[(-0.7071067811865475+0j), (0.7071067811865475+0j)], [(-0.7071067811865475+0j), (-0.7071067811865475+0j)]], dtype=np.dtype('complex128')),
),
single_qubit_operations_after=(
np.array([[0.7071067811865475j, 0.7071067811865475j], [0.7071067811865475j, -0.7071067811865475j]], dtype=np.dtype('complex128')),
np.array([[0.7071067811865475j, 0.7071067811865475j], [0.7071067811865475j, -0.7071067811865475j]], dtype=np.dtype('complex128')),
),
global_phase=1j)


, which translates to applying $$K_1K_2$$, then $$e^{i \frac{\pi}{4}X_1X_2}$$, and finally $$(iH_1) (iH_2)=-H_1H_2$$ up to a global phase of $$i$$, where $$K_1=K_2=XH$$, meaning applying a Hadamard gate first then an $$\text{X}$$ gate. The complication with the single qubit gates is due to the canonicalization of the KAK vector placing the exponent of the $$\text{XX}$$ operator in the positive quadrant.

For $$CZ$$ the KAK decomposition is:

cirq.KakDecomposition(
interaction_coefficients=(0.7853981633974483, 0.0, 0.0),
single_qubit_operations_before=(
np.array([[(0.2705980500730986+0.6532814824381883j), (-0.27059805007309845+0.6532814824381882j)], [(0.2705980500730986+0.6532814824381883j), (0.27059805007309845-0.6532814824381882j)]], dtype=np.dtype('complex128')),
np.array([[(0.2705980500730986-0.6532814824381883j), (0.27059805007309845+0.6532814824381882j)], [(-0.2705980500730986+0.6532814824381883j), (0.27059805007309845+0.6532814824381882j)]], dtype=np.dtype('complex128')),
),
single_qubit_operations_after=(
np.array([[(0.6532814824381883-0.2705980500730986j), (0.6532814824381883-0.2705980500730986j)], [(-0.6532814824381882-0.27059805007309845j), (0.6532814824381882+0.27059805007309845j)]], dtype=np.dtype('complex128')),
np.array([[(0.2705980500730986-0.6532814824381883j), (-0.2705980500730986+0.6532814824381883j)], [(0.27059805007309845+0.6532814824381882j), (0.27059805007309845+0.6532814824381882j)]], dtype=np.dtype('complex128')),
),
global_phase=(-0.7071067811865475+0.7071067811865476j))


which is to say that up to the global phase $$\frac{i-1}{\sqrt{2}}$$, using four local unitaries, the $$\text{CZ}$$ gate is also equivalent to $$e^{i \frac{\pi}{4} X_1X_2}$$.

So, our strategy is to invert the single qubit gates before and after the $$\text{ZZ}$$ gate and apply the single qubit gates for $$\text{CZ}$$, which can be decomposed further into Euler angle rotations.

kak_zz = cirq.kak_decomposition(scipy.linalg.expm(-cirq.unitary(cirq.ZZ)*1j * np.pi/ 4))
zyz1_zz = [cirq.deconstruct_single_qubit_matrix_into_angles(gate) for gate in kak_zz.single_qubit_operations_before]
zyz2_zz = [cirq.deconstruct_single_qubit_matrix_into_angles(gate) for gate in kak_zz.single_qubit_operations_after]

kak = cirq.kak_decomposition(cirq.CZ)

zyz1 = [cirq.deconstruct_single_qubit_matrix_into_angles(gate) for gate in kak.single_qubit_operations_before]
zyz2 = [cirq.deconstruct_single_qubit_matrix_into_angles(gate) for gate in kak.single_qubit_operations_after]

print("circuit:")

a,b = cirq.LineQubit.range(2)
circuit = cirq.Circuit(
cirq.rz(zyz1[0][0])(a),
cirq.ry(zyz1[0][1])(a),
cirq.rz(zyz1[0][2])(a),

cirq.rz(zyz1[1][0])(b),
cirq.ry(zyz1[1][1])(b),
cirq.rz(zyz1[1][2])(b),

# we invert the internal single qubit gates to get to the shared exp(i pi/4 XX)(a,b) rotation
cirq.X(a), cirq.H(a),
cirq.X(b), cirq.H(b),
# the ZZPowGate is our exp(-i pi/4 ZZ) rotation using Cirq's EigenGate convention.
# It equals to in circuit order H(a), X(a), H(b), X(b),exp(i pi/4 XX)(a,b), (iH(a)), (iH(b))
cirq.ZZPowGate(exponent=0.5, global_shift=-0.5)(a,b),
cirq.H(a), cirq.H(b),

cirq.rz(zyz2[0][0])(a),
cirq.ry(zyz2[0][1])(a),
cirq.rz(zyz2[0][2])(a),

cirq.rz(zyz2[1][0])(b),
cirq.ry(zyz2[1][1])(b),
cirq.rz(zyz2[1][2])(b),

)

# circuit = kak._decompose_(cirq.LineQubit.range(2))
print(circuit)
print("dropping empty ops:")
circuit = cirq.drop_negligible_operations(circuit)
print(circuit)

print("final unitary:")

np.set_printoptions(suppress=True, linewidth=300)
# we have to remove the KAK global phase
print(circuit.unitary() / kak.global_phase)
print("cirq.CZ unitary:")
print(cirq.unitary(cirq.CZ))


Resulting in:

circuit:
0: ───Rz(1.25π)───Ry(0.5π)───Rz(0)───X───H───ZZ───────H───Rz(π)────Ry(0.5π)───Rz(-0.75π)───
│
1: ───Rz(1.75π)───Ry(0.5π)───Rz(π)───X───H───ZZ^0.5───H───Rz(2π)───Ry(0.5π)───Rz(0.75π)────
dropping empty ops:
0: ───Rz(1.25π)───Ry(0.5π)───────────X───H───ZZ───────H───Rz(π)───Ry(0.5π)───Rz(-0.75π)───
│
1: ───Rz(1.75π)───Ry(0.5π)───Rz(π)───X───H───ZZ^0.5───H───────────Ry(0.5π)───Rz(0.75π)────
final unitary:
[[ 1.-0.j  0.-0.j -0.+0.j -0.-0.j]
[ 0.-0.j  1.-0.j -0.+0.j -0.-0.j]
[ 0.-0.j  0.-0.j  1.+0.j  0.-0.j]
[ 0.-0.j -0.+0.j  0.+0.j -1.-0.j]]
cirq.CZ unitary:
[[ 1.+0.j  0.+0.j  0.+0.j  0.+0.j]
[ 0.+0.j  1.+0.j  0.+0.j  0.+0.j]
[ 0.+0.j  0.+0.j  1.+0.j  0.+0.j]
[ 0.+0.j  0.+0.j  0.+0.j -1.+0.j]]


the unitaries are equivalent as desired. Further simplifications are of course possible.

• "the CZ gate is equivalent to $\exp(−i0.785XX+0.0YY+0.0ZZ)$" is that not also equivalent to $\exp(-i\theta ZZ)$ up to conjugation by $H \otimes H$? Apr 2 at 1:14
• Very true! I rewrote the post, thank you for the comment. Apr 2 at 21:41