# How to quickly calculate the custom U3 gate parameters $\theta, \phi$ and $\lambda$ for any unitary?

In IBM Qiskit and Quantum Experience, the custom U3 gate is defined as

$$U(\theta, \phi, \lambda) = \begin{pmatrix} \cos\left(\frac{\theta}{2}\right) & -e^{i\lambda} \sin\left(\frac{\theta}{2}\right) \\ e^{i\phi} \sin\left(\frac{\theta}{2}\right) & e^{i(\lambda + \phi)} \cos\left(\frac{\theta}{2}\right) \end{pmatrix}$$

Is there any way to quickly obtain the parameters $$\theta, \phi$$ and $$\lambda$$ for any arbitrary $$2\times 2$$ unitary $$X$$? I know it's possible to write up a lengthy program which could do this, but is there already a similar program out there? Any of the common programming languages would be fine.

Related: What are theta, phi and lambda in cu1(theta, ctl, tgt) and cu3(theta, phi, lam, ctl, tgt)? What are the rotation matrices being used?

# Python - Sympy

It could be done in python using sympy. I am not really an expert and maybe there could be ways to optimize this, but the following works fine for me. Assuming you have the matrix $$\begin{bmatrix}a & b\\ c & d\end{bmatrix}$$

My program

from sympy import *

def get_angles(a, b, c, d):
if im(a) == 0:
print("Not phasing")
s = _compute_angles(a, b, c, d)
res = _final_constraint(s)
if len(res) != 0:
return res
print("Phasing by first element...")
matr = Matrix([[a, b], [c, d]])
ph = arg(matr)
matr_phased = simplify(matr/(cos(ph) + I*sin(ph)))
s = _compute_angles(matr_phased, matr_phased, matr_phased,
matr_phased)
return _final_constraint(s)

def _compute_angles(a, b, c, d):
theta, phi, lamb = symbols('\\theta \\phi \\lambda', real=True)
a_eq = Eq(cos(theta / 2), a)
b_eq = Eq(-exp(I * lamb) * sin(theta / 2), b)
c_eq = Eq(exp(I * phi) * sin(theta / 2), c)
d_eq = Eq(exp(I * (phi + lamb)) * cos(theta / 2), d)
return solve([a_eq, b_eq, c_eq, d_eq], [theta, phi, lamb], dict=True)

def _final_constraint(result):
res = []
for sol in result:
for k, v in sol.items():
if str(k) == '\\theta' and (v < 0 or v > pi):
break
elif str(k) == '\\phi' and (v < 0 or v >= 2 * pi):
break
res.append(simplify(sol))
return res


Note that for Qiskit U matrix you should only check if the first number is imaginary and, if it so, you could divide the whole matrix by it. It is not really necessary to divide by the determinant, provided that the matrix represent indeed a valid quantum gate (or, said differently, the magnitude are all less than 1).

To avoid Python evaluation of fractions, instead of simply using 1/2 a common trick is to use S(1)/2 or Rational(1,2)

## Examples

### A generic unitary

get_angles(sqrt(S(1)/5), sqrt(S(4)/5), -sqrt(S(4)/5), sqrt(S(1)/5)) returns

$$\left[ \left\{ \lambda : \pi, \ \phi : \pi, \ \theta : 2 \operatorname{acos}{\left(\frac{\sqrt{5}}{5} \right)}\right\}\right]$$

### Pauli-Y matrix

$$\begin{bmatrix} 0 & -i \\ i & 0 \end{bmatrix}$$

get_angles(0, -I, I, 0) returns $$\left[ \left\{ \lambda : \frac{\pi}{2}, \ \phi : \frac{\pi}{2}, \ \theta : \pi\right\}\right]$$

### $$\sqrt{NOT}$$

sqnot = Matrix([[1+I, 1-I], [1-I, 1+I]]) * Rational(1,2)
get_angles(sqnot, sqnot, sqnot, sqnot)


$$\left[ \left\{ \lambda : \frac{\pi}{2}, \ \phi : \frac{3 \pi}{2}, \ \theta : \frac{\pi}{2}\right\}\right]$$

### Matrix of Sanchayan Dutta answer

get_angles(-1/sqrt(2), I/sqrt(2), I/sqrt(2), -1/sqrt(2)) $$\left[ \left\{ \lambda : \frac{\pi}{2}, \ \phi : \frac{3 \pi}{2}, \ \theta : \frac{\pi}{2}\right\}\right]$$

• Nice! Note that there are some edge cases though. Like when $a$ lies outside the range of $\cos(\theta/2)$. Moreover, you'd have to place the restrictions $0\leq \theta \leq \pi$ and $0 \leq \phi <2\pi$. – Sanchayan Dutta May 26 at 15:50
• @SanchayanDutta which edge cases are you referring to? For the restrictions, you are right. I have not been able to place them yet, if I simply those equations in the solve function sympy returns an empty result. As I said, I am not really an expert on sympy, but I'll try to figure out something. – tigerjack89 May 26 at 16:14
• Say, your code wouldn't work for 1/2[[1+i,1-i],[1-i,1+i]] i.e. the square root of NOT. – Sanchayan Dutta May 26 at 16:17
• @SanchayanDutta well, I think this is a limitation of Qiskit. If I remember correctly, the square root of not is implemented by an $R_Z(\pi/2)$ sandwiched between two H gates. I don't know if they can implement it directly. – tigerjack89 May 26 at 17:53
• @SanchayanDutta I think this is the final version – tigerjack89 May 29 at 15:13

# Mathematica

With help from Mathematica SE, I managed to put this together (assuming Z is our 2 × 2 unitary):

U = {{Cos[\[Theta]/
2], -E^(I \[Lambda]) Sin[\[Theta]/
2]}, {E^(I \[Phi]) Sin[\[Theta]/2],
E^(I (\[Lambda] + \[Phi])) Cos[\[Theta]/2]}};
FullSimplify[
Reduce[Z == U && 0 <= \[Phi] < 2 Pi && 0 <= \[Theta] <= Pi &&
0 <= \[Lambda] < 2 Pi, {\[Theta], \[Phi], \[Lambda]}]]


Note that you'll need to define Z beforehand. Say, if $$Z=\begin{pmatrix}-\frac{1}{\sqrt 2} & \frac{i}{\sqrt 2} \\ \frac{i}{\sqrt 2} & -\frac{1}{\sqrt 2} \end{pmatrix}$$, the corresponding code is:

Z = {{-1/Sqrt, I/Sqrt}, {I/Sqrt, -1/Sqrt}};
Z = Z/Sqrt[Det[Z]];
Z = Simplify[Z/Exp[I Arg[Z[[1, 1]]]]];
U = {{Cos[\[Theta]/
2], -E^(I \[Lambda]) Sin[\[Theta]/
2]}, {E^(I \[Phi]) Sin[\[Theta]/2],
E^(I (\[Lambda] + \[Phi])) Cos[\[Theta]/2]}};
FullSimplify[
Reduce[Z == U && 0 <= \[Phi] < 2 Pi && 0 <= \[Theta] <= Pi &&
0 <= \[Lambda] < 2 Pi, {\[Theta], \[Phi], \[Lambda]}]]


and the solution is:

2 \[Theta] == \[Pi] && 2 \[Phi] == 3 \[Pi] && 2 \[Lambda] == \[Pi]


Note that the matrix $$U(\pi/2,3\pi/2,\pi/2)$$ differs by a phase factor from $$Z$$. This is because of the transformation due to

Z = Z/Sqrt[Det[Z]];
Z = Simplify[Z/Exp[I Arg[Z[[1, 1]]]]];


which is meant to deal with those cases where $$Z_{11}$$ exceeds the range of $$\cos(\frac{\theta}{2})$$. I've discussed about this here. Remember that $$0\leq \theta \leq \pi$$ and $$0 \leq \phi <2\pi$$ according to the documentation.

P.S: You can run this code on Mathematica Cloud now cf. Wolfram Releases the Wolfram Engine for Developers!!

• what about taking the traces $\mathrm{Tr}(U\sigma_i)$ for the different Pauli matrices $\sigma_i$ to get the components of the matrix and then just applying $\arccos$ etc where necessary? (I'm asking in case you already considered that but it didn't suit you for some reason) – glS May 26 at 9:55
• I didn't think about that before. Anyway, the traces you mention don't really look "nice". Say $\mathrm{Tr}(U\sigma_1) = -e^{i\lambda}\sin(\frac{\theta}{2})+e^{i\phi}\sin(\frac{\theta}{2})$. There is more than one variable involved in each such trace; a simple arcsin/arccos wouldn't work...at least the way I'm seeing it. – Sanchayan Dutta May 26 at 10:25

# Qiskit

You can also do this directly from Qiskit using this piece of code

from qiskit.quantum_info.synthesis import euler_angles_1q
from scipy.linalg import sqrtm
import numpy as np

x_matrix = np.array([[0, 1], [1, 0]])
x_90_matrix = sqrtm(x_matrix)
# Returns (theta, phi, lambda)
euler_angles_1q(x_90_matrix)
Out: (1.5707963267948966, -1.5707963267948966, 1.5707963267948966)

an_matr = np.array([[-1/sqrt(2), 1j/sqrt(2)], [1j/sqrt(2), -1/sqrt(2)]]
euler_angles_1q(an_matr)
Out: (1.5707963267948966, 4.71238898038469, 1.5707963267948966



Thanks to the Qiskit slack channel for this hint. For those interested, here there is the source code of the euler_angles_1q function.