Source code for qubiter.OneQubitGate

import sys
if 'autograd.numpy' not in sys.modules:
    import numpy as np
    print('loaded OneQubitGate, WITHOUT autograd.numpy')
else:
    print('loaded OneQubitGate, WITH autograd.numpy')
    from qubiter.adv_applications.setup_autograd import pu2
    print('pu2 in dir', 'pu2' in dir())
    print('pu2 in sys.modules', 'pu2' in sys.modules)
    import autograd.numpy as np


[docs]class OneQubitGate: """ This class has no attributes or constructor. It is simply a collection of static methods, all of which return a complex 2 by 2 matrix (numpy array or array from some other tensor library). In cases where the entries of the matrix are all real, an is_quantum bool option is given to choose between a float or complex array. All gates have a tensor library `lib` option. lib equals 'np' for numpy, 'tf' for tensorflow Attributes ---------- """
[docs] @staticmethod def get_mat(lib, mat_dict, dtype=None): """ Internal function that creates a tensor of type lib, based on a dict mat_dict. Parameters ---------- lib : str mat_dict : dict dtype : dtype | None Returns ------- np.ndarray """ lili = [[mat_dict['00'], mat_dict['01']], [mat_dict['10'], mat_dict['11']]] if lib == 'np': return np.array(lili, dtype=dtype) elif lib == 'tf': import tensorflow as tf convert = tf.convert_to_tensor return convert(lili, dtype=tf.complex128) else: assert False, "unsupported tensor lib"
[docs] @staticmethod def const_dict(x): """ Returns dictionary with all values equal to x. Dict is destined to fill a future 2-dim matrix. Parameters ---------- x : Returns ------- dict """ return {'00': x, '01': x, '10': x, '11': x}
[docs] @staticmethod def get_fun(lib, fun_name, lib_to_fun_name=None): """ If lib is 'np', this method returns eval(lib + '.' + fun_name). Else, if lib is not 'np' then: if lib_to_fun_name is None, it returns eval(lib + '.' + fun_name), but if lib_to_fun_name is not None, it returns eval(lib + '.' + lib_to_fun_name[lib]). It aborts if lib_to_fun_name[ lib] doesn't exist. Parameters ---------- lib : str tensor library, either 'np' for numpy or 'tp' for tensorflow fun_name : str function name lib_to_fun_name : dict[str, str] dictionary mapping lib to fun_name. For example {'tf': 'cos'} Returns ------- function """ if lib == 'tf': import tensorflow as tf if lib == 'np' or lib_to_fun_name is None: fun = eval(lib + '.' + fun_name) else: assert lib in lib_to_fun_name fun = eval(lib + '.' + lib_to_fun_name[lib]) if lib == 'tf': fun1 = lambda x: tf.cast(fun(x), dtype=tf.complex128) else: fun1 = fun return fun1
[docs] @staticmethod def had2(is_quantum=True, lib='np'): """ Returns 2 dimensional Hadamard matrix (sigma_x + sigma_z)/sqrt(2). Parameters ---------- is_quantum : bool lib : str Returns ------- np.ndarray """ if not is_quantum: ty = np.float64 else: ty = np.complex128 x = 1/np.sqrt(2) mat_dict = OneQubitGate.const_dict(x) mat_dict['11'] = -x return OneQubitGate.get_mat(lib, mat_dict, dtype=ty)
[docs] @staticmethod def P_0(is_quantum=True, lib='np'): """ Returns projection operator ``P_0 = |0><0| = nbar``, where ``|0> = [ 1, 0]^T`` and ``|1> = [0, 1]^T``, T = transpose Parameters ---------- is_quantum : bool lib : str Returns ------- np.ndarray """ if not is_quantum: ty = np.float64 else: ty = np.complex128 mat_dict = OneQubitGate.const_dict(0) mat_dict['00'] = 1 return OneQubitGate.get_mat(lib, mat_dict, dtype=ty)
[docs] @staticmethod def P_1(is_quantum=True, lib='np'): """ Returns projection operator ``P_1 = |1><1| = n``, where ``|0> = [1, 0]^T`` and ``|1> = [0, 1]^T``, T = transpose Parameters ---------- is_quantum : bool lib : str Returns ------- np.ndarray """ if not is_quantum: ty = np.float64 else: ty = np.complex128 mat_dict = OneQubitGate.const_dict(0) mat_dict['11'] = 1 return OneQubitGate.get_mat(lib, mat_dict, dtype=ty)
[docs] @staticmethod def P_0_phase_fac(ang_rads, lib='np'): """ Returns exp(1j*ang_rads*P_0) = [[x, 0],[0, 1]] with x = exp(1j*ang_rads) Parameters ---------- ang_rads : float lib : str Returns ------- np.ndarray """ if 'autograd.numpy' in sys.modules: tlist = [0.]*4 tlist[0] = ang_rads/2 tlist[3] = ang_rads/2 return np.exp(1j*ang_rads/2)*pu2(*tlist) mat_dict = OneQubitGate.const_dict(0) x = OneQubitGate.get_fun(lib, 'exp')(1j * ang_rads) mat_dict['00'] = x mat_dict['11'] = 1 return OneQubitGate.get_mat(lib, mat_dict)
[docs] @staticmethod def P_1_phase_fac(ang_rads, lib='np'): """ Returns exp(1j*ang_rads*P_1) = [[1, 0],[0, x]] with x = exp(1j*ang_rads) Parameters ---------- ang_rads : float lib : str Returns ------- np.ndarray """ if 'autograd.numpy' in sys.modules: tlist = [0.]*4 tlist[0] = -ang_rads/2 tlist[3] = -ang_rads/2 return np.exp(1j*ang_rads/2)*pu2(*tlist) mat_dict = OneQubitGate.const_dict(0) x = OneQubitGate.get_fun(lib, 'exp')(1j * ang_rads) mat_dict['11'] = x mat_dict['00'] = 1 return OneQubitGate.get_mat(lib, mat_dict)
[docs] @staticmethod def phase_fac(ang_rads, lib='np'): """ Returns exp(1j*ang_rads*I_2) = [[x, 0],[0, x]] with x = exp(1j*ang_rads) Parameters ---------- ang_rads : float lib : str Returns ------- np.ndarray """ if 'autograd.numpy' in sys.modules: tlist = [0.]*4 tlist[0] = ang_rads return pu2(*tlist) mat_dict = OneQubitGate.const_dict(0) x = OneQubitGate.get_fun(lib, 'exp')(1j * ang_rads) mat_dict['11'] = x mat_dict['00'] = x return OneQubitGate.get_mat(lib, mat_dict)
[docs] @staticmethod def rot(rad_ang_x, rad_ang_y, rad_ang_z, lib='np'): """ Returns exp(1j*(rad_ang_x*sig_x + rad_ang_y*sig_y + rad_ang_z*sig_z)) where rad_ang_x is an angle in radians and sig_x is the x Pauli matrix, etc. Parameters ---------- rad_ang_x : float rad_ang_y : float rad_ang_z : float lib : str Returns ------- np.ndarray """ if 'autograd.numpy' in sys.modules: tlist = [0., rad_ang_x, rad_ang_y, rad_ang_z] return pu2(*tlist) mat_dict = OneQubitGate.const_dict(0) vec = [rad_ang_x, rad_ang_y, rad_ang_z] n = OneQubitGate.get_fun(lib, 'sqrt')( vec[0]**2 + vec[1]**2 + vec[2]**2) if abs(n) < 1e-8: mat_dict['00'] = 1 mat_dict['11'] = 1 else: nx = rad_ang_x/n ny = rad_ang_y/n nz = rad_ang_z/n c = OneQubitGate.get_fun(lib, 'cos')(n) s = OneQubitGate.get_fun(lib, 'sin')(n) mat_dict['00'] = c + 1j*s*nz mat_dict['01'] = s*ny + 1j*s*nx mat_dict['10'] = -s*ny + 1j*s*nx mat_dict['11'] = c - 1j*s*nz return OneQubitGate.get_mat(lib, mat_dict)
[docs] @staticmethod def rot_ax(rad_ang, axis, lib='np'): """ Returns exp(1j*rad_ang*sig_n) where n = x if axis = 1, n = y if axis = 2 and n = z if axis = 3 Parameters ---------- rad_ang : float axis : int lib : str Returns ------- np.ndarray """ if 'autograd.numpy' in sys.modules: assert axis in [1, 2, 3] tlist = [0.]*4 tlist[axis] = rad_ang # print('mmbbvv', axis, pu2(*tlist)) return pu2(*tlist) mat_dict = OneQubitGate.const_dict(0) c = OneQubitGate.get_fun(lib, 'cos')(rad_ang) s = OneQubitGate.get_fun(lib, 'sin')(rad_ang) if axis == 1: mat_dict['00'] = c mat_dict['01'] = 1j*s mat_dict['10'] = 1j*s mat_dict['11'] = c elif axis == 2: mat_dict['00'] = c mat_dict['01'] = s mat_dict['10'] = -s mat_dict['11'] = c elif axis == 3: mat_dict['00'] = c + 1j*s mat_dict['11'] = c - 1j*s else: assert False, "axis not in [1,2,3]" return OneQubitGate.get_mat(lib, mat_dict)
[docs] @staticmethod def sigx(is_quantum=True, lib='np'): """ Returns sigma_x Pauli matrix. Parameters ---------- is_quantum : bool lib : str Returns ------- np.ndarray """ if not is_quantum: ty = np.float64 else: ty = np.complex128 mat_dict = OneQubitGate.const_dict(0) mat_dict['01'] = 1 mat_dict['10'] = 1 return OneQubitGate.get_mat(lib, mat_dict, dtype=ty)
[docs] @staticmethod def sigy(lib='np'): """ Returns sigma_y Pauli matrix. Parameters ---------- lib : str Returns ------- np.ndarray """ mat_dict = OneQubitGate.const_dict(0) mat_dict['01'] = -1j mat_dict['10'] = 1j return OneQubitGate.get_mat(lib, mat_dict)
[docs] @staticmethod def sigz(is_quantum=True, lib='np'): """ Returns sigma_z Pauli matrix. Parameters ---------- is_quantum : bool lib : str Returns ------- np.ndarray """ if not is_quantum: ty = np.float64 else: ty = np.complex128 mat_dict = OneQubitGate.const_dict(0) mat_dict['00'] = 1 mat_dict['11'] = -1 return OneQubitGate.get_mat(lib, mat_dict, dtype=ty)
[docs] @staticmethod def mat_S(herm=False, lib='np'): """ Returns [[1, 0],[0, x*sign]] where x=exp(j*pi/2)=j where sign = 1 if herm=False and sign = -1 if herm=True. Parameters ---------- herm : bool lib : str Returns ------- np.ndarray """ if not herm: sign = 1 else: sign = -1 return OneQubitGate.P_1_phase_fac(sign*np.pi/2, lib=lib)
[docs] @staticmethod def mat_Sdag(lib='np'): """ returns ``S^\dag``. Parameters ---------- lib : str Returns ------- np.ndarray """ return OneQubitGate.mat_S(True, lib=lib)
[docs] @staticmethod def mat_T(herm=False, lib='np'): """ Returns [[1, 0],[0, exp(j*pi/4*sign)]] where sign = 1 if herm=False and sign = -1 if herm=True. Parameters ---------- herm : bool lib : str Returns ------- np.ndarray """ if not herm: sign = 1 else: sign = -1 return OneQubitGate.P_1_phase_fac(sign*np.pi/4, lib=lib)
[docs] @staticmethod def mat_Tdag(lib='np'): """ returns ``T^\dag``. Parameters ---------- lib : str Returns ------- np.ndarray """ return OneQubitGate.mat_T(True, lib=lib)
[docs] @staticmethod def u2(rads0, rads1, rads2, rads3, lib='np'): """ Returns arbitrary 2-dim unitary matrix (U(2) group) parametrized as follows: exp(1j*(rads0 + rads1*sig_x + rads2*sig_y + rads3*sig_z)) where rads1 is an angle in radians and sig_x is the x Pauli matrix, etc. Parameters ---------- rads0 : float rads1 : float rads2 : float rads3 : float lib : str Returns ------- np.ndarray """ if 'autograd.numpy' in sys.modules: tlist = [rads0, rads1, rads2, rads3] return pu2(*tlist) return OneQubitGate.get_fun(lib, 'exp')(1j * rads0) * \ OneQubitGate.rot(rads1, rads2, rads3, lib=lib)
if __name__ == "__main__": def main(): print('sigx= ', OneQubitGate.sigx(is_quantum=False)) print('sigy= ', OneQubitGate.sigy()) print('sigz= ', OneQubitGate.sigz()) print('had2= ', OneQubitGate.had2()) print('P_0= ', OneQubitGate.P_0()) print('P_1= ', OneQubitGate.P_1()) print('P_0_phase_fac= ', OneQubitGate.P_0_phase_fac(10)) print('P_1_phase_fac= ', OneQubitGate.P_1_phase_fac(10)) print('phase_fac= ', OneQubitGate.phase_fac(10)) mat = OneQubitGate.rot(10, 20, 30) print('rot*rot^H= ', np.dot(mat, mat.conj().T)) mat = OneQubitGate.rot_ax(10, 1) print('rotx*rotx^H= ', np.dot(mat, mat.conj().T)) mat = OneQubitGate.rot_ax(10, 2) print('roty*roty^H= ', np.dot(mat, mat.conj().T)) mat = OneQubitGate.rot_ax(10, 3) print('rotz*rotz^H= ', np.dot(mat, mat.conj().T)) print('mat_S=', OneQubitGate.mat_S()) print('mat_Sdag=', OneQubitGate.mat_Sdag()) print('mat_T=', OneQubitGate.mat_T()) print('mat_Tdag=', OneQubitGate.mat_Tdag()) print('u2(5, 10, 20, 30)=', OneQubitGate.u2(5, 10, 20, 30)) main()