# Source code for qubiter.UnitaryMat

```import numpy as np
from qubiter.OneQubitGate import *

[docs]class UnitaryMat:
"""
This class contains only static methods and no constructor. It contains
some functions associated with unitary matrices.

Note that any numpy array called arr can be saved and loaded from a text
file called file_name using

np.savetxt(file_name, arr)
and
"""

[docs]    @staticmethod
def is_unitary(arr):
"""
Returns True iff arr is a numpy array that represents a unitary
matrix.

Parameters
----------
arr : np.ndarray

Returns
-------
bool

"""
num_rows = arr.shape[0]
assert arr.shape == (num_rows, num_rows)
err = np.linalg.norm(np.dot(arr, arr.conj().T) -
np.identity(num_rows))
return err < 1e-6

[docs]    @staticmethod
"""
Assuming that arr is a unitary matrix, this function returns delta
such that arr = exp(i*delta) arr1, where arr1 is a special unitary
matrix (det(arr1) = 1).

Parameters
----------
arr : np.ndarray

Returns
-------
float

"""
det = np.linalg.det(arr)
c = det.real
s = det.imag
num_rows = arr.shape[0]
return np.arctan2(s, c)/num_rows

[docs]    @staticmethod
"""
This function returns a numpy array arr = exp(i*delta)exp(
i*rot_rads*sig_w) such that unit_vec = [wx, wy, wz] is a unit vector
and sig_w = wx*sigx + wy*sigy + wz*sigz.

params_from_u2() maps arr -> (delta, rot_rads, unit_vec). This
function maps (delta, rot_rads, unit_vec) -> arr so it is the
inverse of params_from_u2(). But be careful, because delta, rot_rads
are not single valued, they are only valid mod 2*pi.

Parameters
----------
delta : float
unit_vec : list[float]

Returns
-------
np.ndarray

"""
return arr

[docs]    @staticmethod
def params_from_u2(arr):
"""
Assuming that arr is a U(2) matrix, this function returns the
parameters (delta, rot_rads, unit_vec) such that arr = exp(
i*delta)exp( i*rot_rads*sig_w) such that unit_vec = [wx, wy, wz] is
a unit vector and sig_w = wx*sigx + wy*sigy + wz*sigz.

Parameters
----------
arr : np.ndarray

Returns
-------
float, float, list[float]

"""
arr1 = arr/np.exp(1j*delta)

cw = arr1[0, 0].real

wx = arr1[0, 1].imag
wy = arr1[0, 1].real
wz = arr1[0, 0].imag

sw = np.sqrt(wx**2 + wy**2 + wz**2)
wx /= sw
wy /= sw
wz /= sw

unit_vec = [wx, wy, wz]

[docs]    @staticmethod
def u2_zyz_decomp(arr):
"""
Assuming that arr is a U(2) matrix, this function returns (delta,

arr = exp(i*delta)*

If change axes by x->y, y->z, z->x, get xzx decomp with same angles.

Parameters
----------
arr : np.ndarray

Returns
-------
float, float, float, float

"""
[wx, wy, wz] = unit_vec

theta1 = np.arctan2(wz*sw, cw)
theta2 = np.arctan2(wx, wy)
np.sqrt(cw**2 + (wz*sw)**2))

if __name__ == "__main__":
from qubiter.FouSEO_writer import *

def main():
unit_vec = np.array([1, 2, 3])
unit_vec = unit_vec/np.linalg.norm(unit_vec)
unit_vec = list(unit_vec)
delta = 3
print("delta in=", delta)
print("unit_vec in=", unit_vec)
print("arr_in:\n", arr_in)
print("delta out=", delta1)
print("unit_vec out=", unit_vec1)
print("arr_out=\n", arr_out)

UnitaryMat.u2_zyz_decomp(arr_in)
ah = np.conj(a)