A control chip can only produce two kinds of pulse: turns about z and turns about y. The claim is that every single-qubit gate can still be made from them: for every 2\times 2 unitary matrix U there are real angles a, b, c, d with
U = e^{ia}\,R_z(b)\,R_y(c)\,R_z(d),\qquad R_y(\theta)=\begin{pmatrix}\cos\frac\theta2&-\sin\frac\theta2\\\sin\frac\theta2&\cos\frac\theta2\end{pmatrix},\quad R_z(\theta)=\begin{pmatrix}e^{-i\theta/2}&0\\0&e^{i\theta/2}\end{pmatrix}.
Here i is 1j, the products are ordinary matrix products (as a circuit: R_z(d) acts first, then R_y(c), then R_z(b)), and e^{ia} multiplies every entry.
Write zyz_angles(u) that takes a unitary matrix u (a list of rows, u[row][col]) and returns a tuple (a, b, c, d) of real numbers with
- -\pi < a \le \pi, \ -\pi < b \le \pi, \ 0 \le c \le \pi, \ -\pi < d \le \pi (a slack of
1e-9is allowed at every end), - every entry of e^{ia}R_z(b)R_y(c)R_z(d) within
1e-6of the same entry ofu. The global phase counts here: it is part of the answer.
Some matrices have more than one valid answer (for a diagonal u, c = 0 and only b + d matters); any valid answer is accepted. The checker rebuilds the matrix from your angles and says how far off it is.
Examples
Input: u = [[0.7071067811865475, 0.7071067811865475], [0.7071067811865475, -0.7071067811865475]]
Output (one valid answer): (1.5707963267948966, 0.0, 1.5707963267948966, 3.141592653589793)
Explanation: Ry(pi/2) Rz(pi) = [[-0.7071j, -0.7071j], [-0.7071j, 0.7071j]], and e^{i pi/2} = i
turns that into H.
Input: u = [[0, 1], [1, 0]]
Output (one valid answer): (1.5707963267948966, -1.5707963267948966, 3.141592653589793, 1.5707963267948966)
Input: u = [[1, 0], [0, 1j]]
Output (one valid answer): (0.7853981633974483, 0.7853981633974483, 0.0, 0.7853981633974483)
Explanation: c = 0 leaves Rz(b) Rz(d) = Rz(pi/2), and e^{i pi/4} Rz(pi/2) = diag(1, i).
Constraints
uis unitary (within1e-9)
Goals
- Write any single-qubit unitary as a phase times Rz, Ry, Rz rotations
- Recover the angles from the sizes and phases of the matrix entries
- Bring angles into stated ranges without changing the matrix