def single_hamiltonian(cav_dim, w_1, w_c, g_factor): """Return a QObj denoting a hamiltonian for one qubit coupled to a cavity.""" return (w_c * qt.tensor(qt.num(cav_dim), I) + 0.5 * w_1 * qt.tensor(qt.qeye(cav_dim), I) + g_factor * qt.tensor(qt.create(cav_dim), SMinus) + g_factor * qt.tensor(qt.destroy(cav_dim), SPlus))
def __init__(self, N_field_levels, coupling=None, N_qubits=1): # basic parameters self.N_field_levels = N_field_levels self.N_qubits = N_qubits if coupling is None: self.g = 0 else: self.g = coupling # bare operators self.idcavity = qt.qeye(self.N_field_levels) self.idqubit = qt.qeye(2) self.a_bare = qt.destroy(self.N_field_levels) self.sm_bare = qt.sigmam() self.sz_bare = qt.sigmaz() self.sx_bare = qt.sigmax() self.sy_bare = qt.sigmay() # 1 atom 1 cavity operators self.jc_a = qt.tensor(self.a_bare, self.idqubit) self.jc_sm = qt.tensor(self.idcavity, self.sm_bare) self.jc_sx = qt.tensor(self.idcavity, self.sx_bare) self.jc_sy = qt.tensor(self.idcavity, self.sy_bare) self.jc_sz = qt.tensor(self.idcavity, self.sz_bare)
def construct_hamiltonian(self, number_of_spins, alpha): """ following example http://qutip.googlecode.com/svn/doc/2.0.0/html/examples/me/ex-24.html returns H0 - hamiltonian without the B field and y_list - list of sigma_y operators """ N = number_of_spins si = qeye(2) sx = sigmax() sy = sigmay() # constructing a list of operators sx_list and sy_list where # the operator sx_list[i] applies sigma_x on the ith particle and # identity to the rest sx_list = [] sy_list = [] for n in range(N): op_list = [] for m in range(N): op_list.append(si) op_list[n] = sx sx_list.append(tensor(op_list)) op_list[n] = sy sy_list.append(tensor(op_list)) # construct the hamiltonian H0 = 0 # ising coupling term, time independent for i in range(N): for j in range(N): if i < j: H0 -= abs(i - j) ** -alpha * sx_list[i] * sx_list[j] H1 = 0 for i in range(N): H1 -= sy_list[i] return H0, H1
def testJCZeroTemperature(): """ brmesolve: Jaynes-Cummings model, zero temperature """ N = 10 a = tensor(destroy(N), identity(2)) sm = tensor(identity(N), destroy(2)) psi0 = ket2dm(tensor(basis(N, 1), basis(2, 0))) a_ops = [(a + a.dag())] e_ops = [a.dag() * a, sm.dag() * sm] w0 = 1.0 * 2 * np.pi g = 0.05 * 2 * np.pi kappa = 0.05 times = np.linspace(0, 2 * 2 * np.pi / g, 1000) c_ops = [np.sqrt(kappa) * a] H = w0 * a.dag() * a + w0 * sm.dag() * sm + \ g * (a + a.dag()) * (sm + sm.dag()) res_me = mesolve(H, psi0, times, c_ops, e_ops) res_brme = brmesolve(H, psi0, times, a_ops, e_ops, spectra_cb=[lambda w: kappa * (w >= 0)]) for idx, e in enumerate(e_ops): diff = abs(res_me.expect[idx] - res_brme.expect[idx]).max() assert_(diff < 5e-2) # accept 5% error
def test_spectrum_espi_legacy(): """ correlation: legacy spectrum from es and pi methods """ # use JC model N = 4 wc = wa = 1.0 * 2 * np.pi g = 0.1 * 2 * np.pi kappa = 0.75 gamma = 0.25 n_th = 0.01 a = tensor(destroy(N), qeye(2)) sm = tensor(qeye(N), destroy(2)) H = wc * a.dag() * a + wa * sm.dag() * sm + \ g * (a.dag() * sm + a * sm.dag()) c_ops = [np.sqrt(kappa * (1 + n_th)) * a, np.sqrt(kappa * n_th) * a.dag(), np.sqrt(gamma) * sm] wlist = 2 * np.pi * np.linspace(0.5, 1.5, 100) with warnings.catch_warnings(): warnings.simplefilter("ignore") spec1 = spectrum_ss(H, wlist, c_ops, a.dag(), a) spec2 = spectrum_pi(H, wlist, c_ops, a.dag(), a) assert_(max(abs(spec1 - spec2)) < 1e-3)
def construct_hamiltonian(self, number_of_spins, alpha, B): ''' following example http://qutip.googlecode.com/svn/doc/2.0.0/html/examples/me/ex-24.html ''' N = number_of_spins si = qeye(2) sx = sigmax() sy = sigmay() #constructing a list of operators sx_list and sy_list where #the operator sx_list[i] applies sigma_x on the ith particle and #identity to the rest sx_list = [] sy_list = [] for n in range(N): op_list = [] for m in range(N): op_list.append(si) op_list[n] = sx sx_list.append(tensor(op_list)) op_list[n] = sy sy_list.append(tensor(op_list)) #construct the hamiltonian H = 0 #magnetic field term, hamiltonian is in units of J0 for i in range(N): H-= B * sy_list[i] #ising coupling term for i in range(N): for j in range(N): if i < j: H+= abs(i - j)**-alpha * sx_list[i] * sx_list[j] return H
def test_spectrum_espi(): """ correlation: comparing spectrum from es and pi methods """ # use JC model N = 4 wc = wa = 1.0 * 2 * np.pi g = 0.1 * 2 * np.pi kappa = 0.75 gamma = 0.25 n_th = 0.01 a = tensor(destroy(N), qeye(2)) sm = tensor(qeye(N), destroy(2)) H = wc * a.dag() * a + wa * sm.dag() * sm + \ g * (a.dag() * sm + a * sm.dag()) c_ops = [np.sqrt(kappa * (1 + n_th)) * a, np.sqrt(kappa * n_th) * a.dag(), np.sqrt(gamma) * sm] wlist = 2 * pi * np.linspace(0.5, 1.5, 100) spec1 = spectrum(H, wlist, c_ops, a.dag(), a, solver='es') spec2 = spectrum(H, wlist, c_ops, a.dag(), a, solver='pi') assert_(max(abs(spec1 - spec2)) < 1e-3)
def test_spectrum_esfft(): """ correlation: comparing spectrum from es and fft methods """ # use JC model N = 4 wc = wa = 1.0 * 2 * np.pi g = 0.1 * 2 * np.pi kappa = 0.75 gamma = 0.25 n_th = 0.01 a = tensor(destroy(N), qeye(2)) sm = tensor(qeye(N), destroy(2)) H = wc * a.dag() * a + wa * sm.dag() * sm + \ g * (a.dag() * sm + a * sm.dag()) c_ops = [np.sqrt(kappa * (1 + n_th)) * a, np.sqrt(kappa * n_th) * a.dag(), np.sqrt(gamma) * sm] with warnings.catch_warnings(): warnings.simplefilter("ignore") tlist = np.linspace(0, 100, 2500) corr = correlation_ss(H, tlist, c_ops, a.dag(), a) wlist1, spec1 = spectrum_correlation_fft(tlist, corr) spec2 = spectrum_ss(H, wlist1, c_ops, a.dag(), a) assert_(max(abs(spec1 - spec2)) < 1e-3)
def test_diagHamiltonian2(): """ Diagonalization of composite systems """ H1 = scipy.rand() * sigmax() + scipy.rand() * sigmay() +\ scipy.rand() * sigmaz() H2 = scipy.rand() * sigmax() + scipy.rand() * sigmay() +\ scipy.rand() * sigmaz() H = tensor(H1, H2) evals, ekets = H.eigenstates() for n in range(len(evals)): # assert that max(H * ket - e * ket) is small assert_equal(amax( abs((H * ekets[n] - evals[n] * ekets[n]).full())) < 1e-10, True) N1 = 10 N2 = 2 a1 = tensor(destroy(N1), qeye(N2)) a2 = tensor(qeye(N1), destroy(N2)) H = scipy.rand() * a1.dag() * a1 + scipy.rand() * a2.dag() * a2 + \ scipy.rand() * (a1 + a1.dag()) * (a2 + a2.dag()) evals, ekets = H.eigenstates() for n in range(len(evals)): # assert that max(H * ket - e * ket) is small assert_equal(amax( abs((H * ekets[n] - evals[n] * ekets[n]).full())) < 1e-10, True)
def test_enr_destory_full(): "Excitation-number-restricted state-space: full state space" a1, a2 = enr_destroy([4, 4], 4**2) b1, b2 = tensor(destroy(4), identity(4)), tensor(identity(4), destroy(4)) assert_(a1 == b1) assert_(a2 == b2)
def compute(N, wc, wa, glist, use_rwa): # Pre-compute operators for the hamiltonian a = tensor(destroy(N), qeye(2)) sm = tensor(qeye(N), destroy(2)) nc = a.dag() * a na = sm.dag() * sm idx = 0 na_expt = zeros(shape(glist)) nc_expt = zeros(shape(glist)) for g in glist: # recalculate the hamiltonian for each value of g if use_rwa: H = wc * nc + wa * na + g * (a.dag() * sm + a * sm.dag()) else: H = wc * nc + wa * na + g * (a.dag() + a) * (sm + sm.dag()) # find the groundstate of the composite system evals, ekets = H.eigenstates() psi_gnd = ekets[0] na_expt[idx] = expect(na, psi_gnd) nc_expt[idx] = expect(nc, psi_gnd) idx += 1 return nc_expt, na_expt, ket2dm(psi_gnd)
def rsb_flop(rho0, W, eta, delta, theta, phi, c_op_list = [], return_op_list = []): ''' Return values of atom and motion populations during red sideband Rabi flop for rotation angles theta. Calls numerical solution of master equation for the Jaynes-Cummings Hamiltonian. @ var rho0: initial density matrix @ var W: bare Rabi frequency @ var delta: detuning between atom and motion @ var theta: list of Rabi rotation angle (i.e. theta, or g*time) @ var phi: phase of the input laser pulse @ var c_op_list: list of collapse operators for the master equation treatment @ var return_op_list: list of population operators the values of which will be returned returns: time, populations of motional mode and atom ''' N = shape(rho0.data)[0]/2 # assume N Fock states and two atom states a = tensor(destroy(N), qeye(2)) sm = tensor( qeye(N), destroy(2)) Wrsb = destroy(N) one_then_zero = ([float(x<1) for x in range(N)]) Wrsb.data = csr_matrix( destroy(N).data.dot( np.diag( rabi_coupling(N,-1,eta) / np.sqrt(one_then_zero+np.linspace(0,N-1,N)) ) ) ) Arsb = tensor(Wrsb, qeye(2)) # use the rotating wave approxiation # Note that the regular a, a.dag() is used for the time evolution of the oscillator # Arsb is the destruction operator including the state dependent coupling strength H = delta * a.dag() * a + \ (1./2.) * W * (Arsb.dag() * sm * exp(1j*phi) + Arsb * sm.dag() * exp(-1j*phi)) if hasattr(theta, '__len__'): if len(theta)>1: # I need to be able to pass a list of length zero and not get an error time = theta/(eta*W) else: time = theta/(eta*W) output = mesolve(H, rho0, time, c_op_list, return_op_list) return time, output
def test_mc_dtypes2(): "Monte-carlo: check for correct dtypes (average_states=False)" # set system parameters kappa = 2.0 # mirror coupling gamma = 0.2 # spontaneous emission rate g = 1 # atom/cavity coupling strength wc = 0 # cavity frequency w0 = 0 # atom frequency wl = 0 # driving frequency E = 0.5 # driving amplitude N = 5 # number of cavity energy levels (0->3 Fock states) tlist = np.linspace(0, 10, 5) # times for expectation values # construct Hamiltonian ida = qeye(N) idatom = qeye(2) a = tensor(destroy(N), idatom) sm = tensor(ida, sigmam()) H = (w0 - wl) * sm.dag() * sm + (wc - wl) * a.dag() * a + \ 1j * g * (a.dag() * sm - sm.dag() * a) + E * (a.dag() + a) # collapse operators C1 = np.sqrt(2 * kappa) * a C2 = np.sqrt(gamma) * sm C1dC1 = C1.dag() * C1 C2dC2 = C2.dag() * C2 # intial state psi0 = tensor(basis(N, 0), basis(2, 1)) opts = Options(average_expect=False) data = mcsolve( H, psi0, tlist, [C1, C2], [C1dC1, C2dC2, a], ntraj=5, options=opts) assert_equal(isinstance(data.expect[0][0][1], float), True) assert_equal(isinstance(data.expect[0][1][1], float), True) assert_equal(isinstance(data.expect[0][2][1], complex), True)
def to_matrix(self, fd): n = num(fd) a = destroy(fd) ic = qeye(fd) sz = sigmaz() sm = sigmam() iq = qeye(2) ms = { "id": tensor(iq, ic), "a*ad" : tensor(iq, n), "a+hc" : tensor(iq, a), "sz" : tensor(sz, ic), "sm+hc" : tensor(sm, ic) } H0 = 0 H1s = [] for (p1, p2), v in self.coefs.items(): h = ms[p1] * ms[p2] try: term = float(v) * h if not term.isherm: term += term.dag() H0 += term except ValueError: H1s.append([h, v]) if not h.isherm: replacement = lambda m: '(-' + m.group() + ')' conj_v = re.sub('[1-9]+j', replacement, v) H1s.append([h.dag(), conj_v]) if H1s: return [H0] + H1s else: return H0
def carrier_flop(rho0, W, eta, delta, theta, phi, c_op_list = [], return_op_list = []): ''' Return values of atom and motion populations during carrier Rabi flop for rotation angles theta. Calls numerical solution of master equation. @ var rho0: initial density matrix @ var W: bare Rabi frequency @ var eta: Lamb-Dicke parameter @ var delta: detuning between atom and motion @ var theta: list of Rabi rotation angles (i.e. theta, or g*time) @ var phi: phase of the input laser pulse @ var c_op_list: list of collapse operators for the master equation treatment @ var return_op_list: list of population operators the values of which will be returned returns: time, populations of motional mode and atom ''' N = shape(rho0.data)[0]/2 # assume N Fock states and two atom states a = tensor(destroy(N), qeye(2)) Wc = qeye(N) Wc.data = csr_matrix( qeye(N).data.dot( np.diag(rabi_coupling(N,0,eta) ) ) ) sm = tensor( Wc, destroy(2)) # use the rotating wave approxiation H = delta * a.dag() * a + \ (1./2.)* W * (sm.dag()*exp(1j*phi) + sm*exp(-1j*phi)) if hasattr(theta, '__len__'): if len(theta)>1: # I need to be able to pass a list of length zero and not get an error time = theta/W else: time = theta/W output = mesolve(H, rho0, time, c_op_list, return_op_list) return time, output
def M_ops(N,j,i): k = Kspace(N) op = k[i]*k[j].dag() if i==j+1 or i==j-1: return qutip.tensor(B_ops(N,j,i),op) if i==j and (j==0 or j==N-1): return qutip.tensor(B_ops(N,j,i),op)
def collapse_operators(N, n_th_a, gamma_motion, gamma_motion_phi, gamma_atom): '''Collapse operators for the master equation of a single atom and a harmonic oscillator @ var N: size of the harmonic oscillator Hilbert space @ var n_th: temperature of the noise bath in quanta @ var gamma_motion: heating rate of the motion @ var gamma_motion_phi: dephasing rate of the motion @ var gamma_atom: decay rate of the atom returns: list of collapse operators for master equation solution of atom + harmonic oscillator ''' a = tensor(destroy(N), qeye(2)) sm = tensor(qeye(N), destroy(2)) c_op_list = [] rate = gamma_motion * (1 + n_th_a) if rate > 0.0: c_op_list.append(sqrt(rate) * a) rate = gamma_motion * n_th_a if rate > 0.0: c_op_list.append(sqrt(rate) * a.dag()) rate = gamma_motion_phi if rate > 0.0: c_op_list.append(sqrt(rate) * a.dag() * a) rate = gamma_atom if rate > 0.0: c_op_list.append(sqrt(rate) * sm) return c_op_list
def direct_hamiltonian(w_1, w_2, g_factor): """Return a QObj denoting a hamiltonian for two qubits interacting with the cavity mode eliminated.""" return ( 0.5 * w_1 * qt.tensor(SZ, I) + 0.5 * w_2 * qt.tensor(I, SZ) + g_factor * qt.tensor(SPlus, SMinus) + g_factor * qt.tensor(SMinus, SPlus))
def full_approx(cav_dim, w_1, w_2, w_c, g_factor): a = qt.destroy(cav_dim) num = a.dag() * a return ( g_factor * qt.tensor(qt.qeye(cav_dim), SMinus, SPlus) + g_factor * qt.tensor(qt.qeye(cav_dim), SPlus, SMinus) + w_c * qt.tensor(num, I, I) + 0.5 * w_1 * qt.tensor(qt.qeye(cav_dim), SZ, I) + 0.5 * w_2 * qt.tensor(qt.qeye(cav_dim), I, SZ))
def population_operators(N): '''Population operators for the master equation @ var N: size of the oscillator Hilbert space returns: list of population operators for the harmonic oscillator and the atom ''' a = tensor(destroy(N), qeye(2)) sm = tensor( qeye(N), destroy(2)) return [a.dag()*a, sm.dag()*sm]
def Ren_gate(carbon_nr, B_field=304.22): '''create a Ren gate for given carbon number, only interacting with the electron spin ''' U0, U1, U0id, U1id = nuclear_Ren_matrix(carbon_nr, B_field) Ren = qutip.tensor(rho0,U0)+qutip.tensor(rho1,U1) Ren_id = qutip.tensor(rho0,U0id)+qutip.tensor(rho1,U1id) return Ren, Ren_id
def interaction_picture(cav_dim, w_1, w_2, w_c, g_1, g_2): delta_1 = abs(w_1 - w_c) delta_2 = abs(w_2 - w_c) a = qt.destroy(cav_dim) H0 = qt.tensor(qt.qeye(cav_dim), I, I) H1 = [g_1 * qt.tensor(a.dag(),SMinus,I), 'exp(-1j *'+str(delta_1)+'*t)'] H2 = [g_2 * qt.tensor(a.dag(),I,SMinus), 'exp(-1j *'+str(delta_2)+'*t)'] H3 = [g_1 * qt.tensor(a,SPlus,I), 'exp(1j *'+str(delta_1)+'*t)'] H4 = [g_2 * qt.tensor(a,I,SPlus), 'exp(1j *'+str(delta_2)+'*t)'] return [H0,H1,H2,H3,H4]
def test_EntropyConcurrence(): "Concurrence" # check concurrence = 1 for maximal entangled (Bell) state bell = ket2dm( (tensor(basis(2), basis(2)) + tensor(basis(2, 1), basis(2, 1))).unit()) assert_equal(abs(concurrence(bell) - 1.0) < 1e-15, True) # check all concurrence values >=0 rhos = [rand_dm(4, dims=[[2, 2], [2, 2]]) for k in range(10)] for k in rhos: assert_equal(concurrence(k) >= 0, True)
def Hamiltonian_toymodel(theta, phi): ## Defining Constants omega = 1.4 * 10**6 m_b = 5.7883818066*10**-5 par=m_b*2.417990504024*10**11 # s-1/mT a1 = np.array([-.0989, -.0989, 1.7569]) * par # /mT a2 = np.array([0.0,0.0,1.0812]) * par H_a_zeeman_nt = omega * (Sx * mt.sin(theta) * mt.cos(phi) + Sy * mt.sin(theta) * mt. sin(phi) + Sz * mt.cos(theta)) Ha_zeeman = qt.tensor(H_a_zeeman_nt, qt.identity(3)) H_a_hfi = a1[0] * qt.tensor(Sx, I2_x) + a1[1] * qt.tensor(Sy, I2_y) + a1[2] * qt.tensor(Sz, I2_z) H_a = Ha_zeeman + H_a_hfi H_a_eigen, H_a_eigenstates = H_a.eigenstates() H_b_zeeman_nt = omega * (Sx * mt.sin(theta) * mt.cos(phi) + Sy * mt.sin(theta) * mt. sin(phi) + Sz * mt.cos(theta)) Hb_zeeman = qt.tensor(H_b_zeeman_nt, qt.identity(3)) H_b_hfi = a2[0] * qt.tensor(Sx, I2_x) + a2[1] * qt.tensor(Sy, I2_y) + a2[2] * qt.tensor(Sz, I2_z) H_b = Hb_zeeman + H_b_hfi H_b_eigen, H_b_eigenstates = H_b.eigenstates() return (H_a_eigen, H_a_eigenstates, H_b_eigen, H_b_eigenstates)
def getBasis (a,G) : #get the basis states according to the binary of a: 10 -> |10> dimG = G.shape[0] CareStateDim = int(log(dimG,2)) if a == 0: B = [qt.basis(2,0)]*(CareStateDim) return qt.tensor(B) c = binary(a) if dimG == 8: return qt.tensor(qt.basis(2,int(c[0])) , qt.basis(2,int(c[1])), qt.basis(2,int(c[2]))) if dimG == 4: return qt.tensor(qt.basis(2,int(c[1])) , qt.basis(2,int(c[2])))
def _localop(op, l, k): """ Create a local operator on the l'th system by tensoring with identity operators on all the other k-1 systems """ if l < 1 or l > k: raise IndexError('index l out of range') h = op I = qt.qeye(op.shape[0]) I.dims = op.dims for i in range(1, l): h = qt.tensor(I, h) for i in range(l+1, k+1): h = qt.tensor(h, I) return h
def ptracetest(): gamma = 1. neq = 2 psi0 = qt.basis(neq,neq-1) psi0 = qt.tensor(psi0,psi0) H = qt.tensor(qt.sigmax(),qt.sigmay()) c1 = np.sqrt(gamma)*qt.sigmax() e1 = np.sqrt(gamma)*qt.sigmaz() c_ops = [qt.tensor(c1,c1)] e_ops = [qt.tensor(e1,e1),qt.tensor(c1,c1)] #e_ops = [] tlist = np.linspace(0,10,100) ntraj = 2000 ptrace_sel = [0] sol_f90 = mcf90.mcsolve_f90(H,psi0,tlist,c_ops,e_ops,ntraj=ntraj, ptrace_sel=ptrace_sel,calc_entropy=True)
def get_M0(H,lindblads,tau): _dims = H.dims[0] J = qt.Qobj(np.zeros_like(H.data.todense()),dims=[_dims,_dims]) for Op in lindblads: J += Op.dag()*Op J *= 0.5 return qt.tensor([qt.qeye(dim) for dim in _dims]) - tau*(1j*H - J)
def build_S_total(n_spins,operator): _dims = [2]*n_spins op = qt.Qobj(dims=[_dims,_dims]) _id = np.identity(n_spins) for i in range(n_spins): op += qt.tensor([operator if el == 1 else I for el in _id[i,:]]) return op
def _pseudo_inverse_dense(L, rhoss, method='direct', **pseudo_args): """ Internal function for computing the pseudo inverse of an Liouvillian using dense matrix methods. See pseudo_inverse for details. """ if method == 'direct': rho_vec = np.transpose(mat2vec(rhoss.full())) tr_mat = tensor([identity(n) for n in L.dims[0][0]]) tr_vec = np.transpose(mat2vec(tr_mat.full())) N = np.prod(L.dims[0][0]) I = np.identity(N * N) P = np.kron(np.transpose(rho_vec), tr_vec) Q = I - P LIQ = np.linalg.solve(L.full(), Q) R = np.dot(Q, LIQ) return Qobj(R, dims=L.dims) elif method == 'numpy': return Qobj(np.linalg.pinv(L.full()), dims=L.dims) elif method == 'scipy': return Qobj(la.pinv(L.full()), dims=L.dims) elif method == 'scipy2': return Qobj(la.pinv2(L.full()), dims=L.dims) else: raise ValueError("Unsupported method '%s'. Use 'direct' or 'numpy'" % method)
&= \Liouville(t) \op{\rho}(t) \\ &= - i \left[\op{H}(t), \op{\rho}(t)\right] + \sum_{k=1,2} \left( \op{L}_{k} \op{\rho}(t) \op{L}_{k}^\dagger - \frac{1}{2} \op{L}_{k}^\dagger \op{L}_{k} \op{\rho}(t) - \frac{1}{2} \op{\rho}(t) \op{L}_{k}^\dagger \op{L}_{k} \right)\,. \end{split} $$ """ qutip.tensor(qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2)) def liouvillian(omega, g, gamma, beta): """Liouvillian for the coupled system of qubit and TLS""" H0_q = omega*0.5*(-qutip.operators.sigmaz()+qutip.qeye(2)) # drive qubit Hamiltonian H1_q = -0.5*qutip.operators.sigmax() # drift TLS Hamiltonian H0_T = qutip.tensor(omega*0.5*(-qutip.operators.sigmaz()+qutip.qeye(2)), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2))\ +qutip.tensor(qutip.qeye(2), omega*0.5*(-qutip.operators.sigmaz()+qutip.qeye(2)), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2))\ +qutip.tensor(qutip.qeye(2), qutip.qeye(2), omega*0.5*(-qutip.operators.sigmaz()+qutip.qeye(2)), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2))\ +qutip.tensor(qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), omega*0.5*(-qutip.operators.sigmaz()+qutip.qeye(2)), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2))\ +qutip.tensor(qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), omega*0.5*(-qutip.operators.sigmaz()+qutip.qeye(2)), qutip.qeye(2), qutip.qeye(2))\ +qutip.tensor(qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), omega*0.5*(-qutip.operators.sigmaz()+qutip.qeye(2)), qutip.qeye(2))\
def calc_throughput(scheme): state = scheme.state time = scheme.time simulation_type = "IP" if simulation_type == "IP": proj1 = qt.Qobj([[1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 1]]) proj2 = (1/2)*qt.Qobj([[1, 0, 0, 1], [0, 1, 1, 0], [0, 1, 1, 0], [1, 0, 0, 1]]) proj3 = (1/2)*qt.Qobj([[1, 0, 0, -1], [0, 1, 1, 0], [0, 1, 1, 0], [-1, 0, 0, 1]]) state00 = qt.Qobj([[1/2, 0, 0, 1/2], [0, 0, 0, 0], [0, 0, 0, 0], [1/2, 0, 0, 1/2]]) state01 = qt.Qobj([[1/2, 0, 0, -1/2], [0, 0, 0, 0], [0, 0, 0, 0], [-1/2, 0, 0, 1/2]]) state10 = (1/2)*qt.Qobj([[0, 0, 0, 0], [0, 1, 1, 0], [0, 1, 1, 0], [0, 0, 0, 0]]) state11 = (1/2)*qt.Qobj([[0, 0, 0, 0], [0, 1, -1, 0], [0, -1, 1, 0], [0, 0, 0, 0]]) proj1.dims = [[2, 2], [2, 2]] proj2.dims = [[2, 2], [2, 2]] proj3.dims = [[2, 2], [2, 2]] state00.dims = [[2, 2], [2, 2]] state01.dims = [[2, 2], [2, 2]] state10.dims = [[2, 2], [2, 2]] state11.dims = [[2, 2], [2, 2]] elif simulation_type == "MP": proj1 = qt.ket2dm(qt.basis(81, 28)) + qt.ket2dm(qt.basis(81, 12)) proj2 = qt.ket2dm(qt.basis(81, 28) + qt.basis(81, 12)) / 2 + \ qt.ket2dm(qt.basis(81, 28) - qt.basis(81, 12)) / 2 proj3 = qt.ket2dm(qt.basis(81, 28) + 1j*qt.basis(81, 12)) / 2 + \ qt.ket2dm(qt.basis(81, 28) - 1j*qt.basis(81, 12)) / 2 vec01 = qt.basis(9, 1) vec10 = qt.basis(9, 3) state00 = qt.ket2dm(qt.tensor(vec01, vec10) + qt.tensor(vec10, vec01))/2 state01 = qt.ket2dm(qt.tensor(vec01, vec10) - qt.tensor(vec10, vec01))/2 state10 = qt.ket2dm(qt.tensor(vec01, vec01) + qt.tensor(vec10, vec10))/2 state11 = qt.ket2dm(qt.tensor(vec01, vec01) - qt.tensor(vec10, vec10))/2 proj1.dims = [[9, 9], [9, 9]] proj2.dims = [[9, 9], [9, 9]] proj3.dims = [[9, 9], [9, 9]] state00.dims = [[9, 9], [9, 9]] state01.dims = [[9, 9], [9, 9]] state10.dims = [[9, 9], [9, 9]] state11.dims = [[9, 9], [9, 9]] bb84 = False if bb84: qber1 = (state * proj1).tr() qber2 = (state * proj2).tr() skf = max(1 - binary_entropy(qber1) - binary_entropy(qber2), 0) # calc secret_key fraction else: p00 = (state * state00).tr() p01 = (state * state01).tr() p10 = (state * state10).tr() p11 = (state * state11).tr() normalisation = p00+p01+p10+p11 # define P' distribution as in https://iopscience.iop.org/article/10.1088/2058-9565/aab31b, eq D1 to D8 Px0 = (p00+p01)**2 + (p10+p11)**2 Px1 = 1-Px0 p00n = (p00**2+p01**2)/Px0 p01n = (2*p00*p01)/Px0 p10n = (p10**2+p11**2)/Px0 p11n = (2*p10*p11)/Px0 if ((p00 + p01) * (p10 + p11)) == 0: Pbinary_entropy = 1 else: Pbinary_entropy = (p00 * p10 + p01 * p11) / ((p00 + p01) * (p10 + p11)) skf = max(1-entropy([p00, p01, p10, p11], base=2)+(Px1/2)*binary_entropy(Pbinary_entropy), (Px0/2)*(1-entropy([p00n, p01n, p10n, p11n], base=2)), 0) return skf/time
def fock_state_on(d: dict, fock_trunc: int, N_modes: int): ''' d={mode number: # of photons} In the bare eigen basis ''' # give me the value d[i] or 0 if d[i] does not exist return qutip.tensor(*[qutip.basis(fock_trunc, d.get(i, 0)) for i in range(N_modes)])
def testMeasurementsOverSeparableStateAreLocal(self): alice1outputs = [2, 2] alice2outputs = [2, 3] bobOutputs = [2, 2] scenario = SequentialBellScenario([alice1outputs, alice2outputs], bobOutputs) epsilon = 0 plus = 1 / np.sqrt(2) * (qt.basis(2, 0) + qt.basis(2, 1)) minus = 1 / np.sqrt(2) * (qt.basis(2, 0) - qt.basis(2, 1)) Kplus = np.cos(epsilon) * plus * plus.dag() + np.sin( epsilon) * minus * minus.dag() Kminus = -np.cos(epsilon) * minus * minus.dag() + np.sin( epsilon) * plus * plus.dag() alice1Krauss = [ projectorsForQubitObservable(createQubitObservable([0, 0, 1])), [Kplus, Kminus] ] alice2blochVectors = [[0, 0, 1]] alice2Observables = list( map(lambda bloch: createQubitObservable(bloch), alice2blochVectors)) alice2Effects = list( map( lambda qubitObservable: projectorsForQubitObservable( qubitObservable), alice2Observables)) trineAlice2 = [[0, 0, 1], [np.sin(2 * np.pi / 3), 0, np.cos(2 * np.pi / 3)], [np.sin(4 * np.pi / 3), 0, np.cos(4 * np.pi / 3)]] paulies = [qt.sigmax(), qt.sigmay(), qt.sigmaz()] alice2Effects.append( list( map( lambda bloch: effectForQubitPovm( 1 / 3, sum([paulies[i] * bloch[i] for i in range(3)])), trineAlice2))) mu = np.arctan(np.sin(2 * epsilon)) bobUnBlochVectors = [[np.sin(mu), 0, np.cos(mu)], [-np.sin(mu), 0, np.cos(mu)]] bobObservables = list( map(lambda bloch: createQubitObservable(bloch), bobUnBlochVectors)) bobEffects = list( map( lambda qubitObservable: projectorsForQubitObservable( qubitObservable), bobObservables)) psi = qt.tensor(qt.basis(2, 0), qt.basis(2, 0)) rho = psi * psi.dag() expectedCorrelations = {} for x1, x2, y in product(range(len(alice1outputs)), range(len(alice2outputs)), range(len(bobOutputs))): for a1, a2, b in product(range(alice1outputs[x1]), range(alice2outputs[x2]), range(bobOutputs[y])): postMeasrmntState = qt.tensor( alice1Krauss[x1][a1], qt.qeye(2)) * rho * (qt.tensor( alice1Krauss[x1][a1], qt.qeye(2))).dag() expectedCorrelations[(x1, x2), y, (a1, a2), b] = ( qt.tensor(alice2Effects[x2][a2], bobEffects[y][b]) * postMeasrmntState).tr().real expectedBehaviour = Behaviour(scenario, expectedCorrelations) polytope = BellPolytopeWithOneWayCommunication( SequentialBellPolytope(scenario)) self.assertTrue( polytope.contains(expectedBehaviour.getProbabilityList()))
def make_ops(nc, nq): a = qutip.tensor(qutip.qeye(nq), qutip.destroy(nc)) ad = a.dag() b = qutip.tensor(qutip.destroy(nq), qutip.qeye(nc)) bd = b.dag() return a, ad, b, bd
def define_useful_states(self): ''' standard init state for system ''' self.NV0_carbons_mixed = qutip.tensor([rho0] + [rhom] * self.num_carbons + [rhom_S1] * self.inc_nitrogen)
def e_N_op(self, e_operator, N_operator): ''' Helper function to embed e operator combined with an operator on carbons ''' return qutip.tensor([e_operator] + [Id] * self.num_carbons + [N_operator])
def e_C_op(self, e_operator, c_operator, c_num): ''' Helper function to embed e operator combined with an operator on carbons ''' return qutip.tensor([e_operator] + [Id] * (c_num - 1) + [c_operator] + [Id] * (self.num_carbons - c_num) + [Id_S1] * self.inc_nitrogen)
def N_op(self, N_operator): ''' Helper function to embed N operator with identities on other carbons ''' return qutip.tensor([Id] * (self.num_carbons + 1) + [N_operator])
def _p_op(size): return qutip.tensor( qutip.qeye(2), qutip.qeye(2), 1j / np.sqrt(2) * (qutip.create(size) - qutip.destroy(size)))
def e_op(self, operator): ''' Helper function to embed e operator with identities on carbons ''' return qutip.tensor([operator] + [Id] * self.num_carbons + [Id_S1] * self.inc_nitrogen)
# Get the auxiliary density matrices from the full Hierarchy ADOs aux_2_list, indices1 = get_aux_matrices(hsolver_no_matsubara.full_hierarchy, 2, Nc, 2) aux_2_list_matsubara, indices2 = get_aux_matrices(hsolver_matsubara.full_hierarchy, 2, Nc, 4) virtual_photon_heom_no_matsubara = np.array([aux.tr() for aux in aux_2_list[1]]) virtual_photon_heom_matsubara = np.array([aux.tr() for aux in aux_2_list_matsubara[8]]) # ======================================= # Compute the population from pseudomode # ======================================= print("pseudomode") lam2 = np.sqrt(lam_renorm) Ncav = 4 # Construct the pseudomode operators with one extra underdamped pseudomode sx = tensor(sigmax(), qeye(Ncav)) sm = tensor(destroy(2).dag(), qeye(Ncav)) sz = tensor(sigmaz(), qeye(Ncav)) a = tensor(qeye(2), destroy (Ncav)) Hsys = 0.5*wq*sz + 0.5*delta*sx + omega*a.dag()*a + lam2*sx*(a + a.dag()) initial_ket = basis(2, 1) psi0=tensor(initial_ket, basis(Ncav, 0)) options = Options(nsteps=1500, store_states=True, atol=1e-13, rtol=1e-13) c_ops = [np.sqrt(bath_broad)*a] e_ops = [sz, sm.dag(), a, a.dag(), a.dag()*a, a**2, a.dag()**2] pseudomode_no_mats = mesolve(Hsys, psi0, tlist, c_ops, e_ops, options=options) output = (pseudomode_no_mats.expect[0] + 1)/2 # Construct the pseudomode operators with three extra pseudomodes
LAST = bytearray() LAST.append(0) numQ = 3 #number of qubits measureQ = 0 #index of qubit being measured #----------------------------------------------------------------------------- #Initial state state = qt.basis(2**numQ, 1) state = state.unit() #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- #Gates (operate on state from highest to lowest) gates = [] gates.append(qt.tensor(snot(), snot(), snot())) #gates.append(qt.tensor(qt.qeye(4), qt.sigmax())) #constant f ex. 1 #gates.append(qt.qeye(8)) #constant f ex. 2 #gates.append(cnot(numQ, 0, 2)) #balanced f ex. 1 gates.append(qt.tensor(qt.qeye(2), cnot())) #balanced f ex. 2 gates.append(qt.tensor(snot(), snot(), qt.qeye(2))) #----------------------------------------------------------------------------- def emulate(): ser = serial.Serial('COM4', 115200, timeout=1) #open COM4 port at 115200 baud count = 0 gateCount = 0 outState = qt.basis(2**numQ) - qt.basis( 2**numQ) #empty state of appropriate size
def generate_xy_states(L, times): H = get_hamiltonian('xy', dict(L=L)) psi0 = qt.tensor([qt.basis(2,0), qt.basis(2,1)]*(L//2) + [qt.basis(2,0)] * (L%2)) return do_evolution(psi0, H, times)
a_mode = abs(mode) remove = np.exp(0.5 * lamb_dicke * lamb_dicke) coefficients = remove * relative_rabi_range(lamb_dicke, 0, size - a_mode, a_mode) coefficients = 1j**a_mode * coefficients indices = np.arange(max(0, -mode), min(size, size - mode), dtype=np.int32) indptr = np.empty(size + 1, dtype=np.int32) if mode < 0: indptr[:mode] = np.arange(1 + size - a_mode, dtype=np.int32) indptr[mode:] = size - a_mode else: indptr[:mode] = 0 indptr[mode:] = np.arange(1 + size - a_mode, dtype=np.int32) return qutip.Qobj(fast_csr_matrix((coefficients, indices, indptr))) Sy = qutip.tensor(qutip.sigmay(), qutip.qeye(2))\ + qutip.tensor(qutip.qeye(2), qutip.sigmay()) gg = qutip.tensor(qutip.basis(2, 1), qutip.basis(2, 1)) ee = qutip.tensor(qutip.basis(2, 0), qutip.basis(2, 0)) ge = qutip.tensor(qutip.basis(2, 1), qutip.basis(2, 0)) eg = qutip.tensor(qutip.basis(2, 0), qutip.basis(2, 1)) def _x_op(size): return qutip.tensor( qutip.qeye(2), qutip.qeye(2), np.sqrt(0.5) * (qutip.create(size) + qutip.destroy(size))) def _p_op(size):
""" Train PPO agent to do Fock state N=2 preparation with universal gate sequence. The episodes start from vacuum, and characteristic function tomography measurements are performed in the end to assign reward. """ root_dir = r'E:\data\gkp_sims\PPO\ECD\fock4_fock' root_dir = os.path.join(root_dir, '7') # Params for environment env_kwargs = {'control_circuit': 'ECD_control', 'init': 'vac', 'T': 8, 'N': 50} # Params for reward function target_state = qt.tensor(qt.basis(2, 0), qt.basis(50, 4)) reward_kwargs = { 'reward_mode': 'fock', 'target_state': target_state, 'N_msmt': 10, 'error_prob': 0.5 } reward_kwargs_eval = { 'reward_mode': 'overlap', 'target_state': target_state, 'postselect_0': False } # Params for action wrapper
def get_gs(nsites, ph_levels): basis = [] for i in range(nsites): basis.append(qutip.states.basis(2)) basis.append(qutip.states.basis(ph_levels)) return qutip.tensor(basis)
def a(p): return qt.tensor(qt.destroy(p.N), qt.qeye(p.J))
loss = 1.2 num_steps = 1 max_time = 10 date = list(str(datetime.datetime.now())[:19]) date[13] = '-' date[16] = '-' ''' SUPER IMPORTANT: change the filepath to wherever you want the plots saved ''' filepath = 'C:/Users/Wang Lab/Documents/qutip/out/wigner_test/' + ''.join( date) + '/' if not os.path.exists(filepath): os.makedirs(filepath) a = qt.tensor(qt.destroy(NA), qt.qeye(NB)) b = qt.tensor(qt.qeye(NB), qt.destroy(NA)) PJ = (1j * np.pi * a.dag() * a).expm() * (1j * np.pi * b.dag() * b).expm() H = drive * a * b + drive.conjugate() * a.dag() * b.dag() psi0 = (qt.tensor(qt.coherent(NA, alpha), qt.coherent(NB, alpha)) - qt.tensor(qt.coherent(NA, -alpha), qt.coherent(NB, -alpha))).unit() #psi0 = qt.tensor(qt.fock(NA, 0), qt.fock(NB, 0)) ''' Solve the system ''' times = np.linspace(0.0, max_time, num_steps) opts = qt.Options(store_states=True, nsteps=10000) print(opts) print('solving...')
def Jm(p): j_destroy = np.diag(np.sqrt(np.arange(1, p.J)), 1) return qt.tensor(qt.qeye(p.N), qt.Qobj(j_destroy))
def permute_matrix(c, t, matrix, rho): # For a given two-qubit gate in the form, find the matrix of dimension corresponding to rho such that # the two-qubit gate operations on c and t. e.g., permute_matrix(4,1,cnot,rho) will apply a cnot gate # between qubits 4 and 1, with 4 the control and 1 the target # Get shape and number of qubits shape = rho.shape n = int(np.log2(shape[0])) # Create list in binary from 0 to 2^n-1, corresponding to the orthonormal computational basis bitstr_list = [] for ii in range(0, np.power(2, n)): bitstr = bin(ii)[2:].zfill(n) bitstr = list(bitstr) bitstr_list.append(bitstr) # Now swap all entries of the binary list according to the given c and t # Notice that we have to be careful of the order we do this in, due to noncommutativity of permutations # That's why we have the overabundance of if statements. if c != 2 and t != 1: for ii in range(0, np.power(2, n)): swap1 = bitstr_list[ii][0] swap2 = bitstr_list[ii][c - 1] bitstr_list[ii][0] = swap2 bitstr_list[ii][c - 1] = swap1 for ii in range(0, np.power(2, n)): swap1 = bitstr_list[ii][1] swap2 = bitstr_list[ii][t - 1] bitstr_list[ii][1] = swap2 bitstr_list[ii][t - 1] = swap1 elif c == 2 and t == 1: for ii in range(0, np.power(2, n)): swap1 = bitstr_list[ii][0] swap2 = bitstr_list[ii][c - 1] bitstr_list[ii][0] = swap2 bitstr_list[ii][c - 1] = swap1 elif c == 2 and t != 1: for ii in range(0, np.power(2, n)): swap1 = bitstr_list[ii][1] swap2 = bitstr_list[ii][t - 1] bitstr_list[ii][1] = swap2 bitstr_list[ii][t - 1] = swap1 for ii in range(0, np.power(2, n)): swap1 = bitstr_list[ii][0] swap2 = bitstr_list[ii][c - 1] bitstr_list[ii][0] = swap2 bitstr_list[ii][c - 1] = swap1 elif c != 2 and t == 1: for ii in range(0, np.power(2, n)): swap1 = bitstr_list[ii][0] swap2 = bitstr_list[ii][c - 1] bitstr_list[ii][0] = swap2 bitstr_list[ii][c - 1] = swap1 for ii in range(0, np.power(2, n)): swap1 = bitstr_list[ii][1] swap2 = bitstr_list[ii][t - 1] bitstr_list[ii][1] = swap2 bitstr_list[ii][t - 1] = swap1 list_of_permutations = np.zeros(np.power(2, n)) for ii in range(0, np.power(2, n)): list_of_permutations[ii] = int(''.join(bitstr_list[ii]), 2) permutation_matrix = np.zeros((np.power(2, n), np.power(2, n))) for ii in range(0, np.power(2, n)): for iii in range(0, np.power(2, n)): if ii == list_of_permutations[iii]: permutation_matrix[ii][iii] = 1 permutation_matrix = qt.Qobj(permutation_matrix) permutation_matrix.dims = rho.dims for ii in range(0, n - 2): matrix = qt.tensor(matrix, qt.identity(2)) matrix.dims = rho.dims # permute matrix permuted_matrix = permutation_matrix * matrix * permutation_matrix.trans() rho = permuted_matrix * rho * permuted_matrix.dag() return rho
(rand(dec_mag), rand(dec_mag), rand(dec_mag)) ] dec_mat = np.array([ [ rand() for jj in range(3) ] for kk in range(3) ]) h_rand = { (ll,mm,nn) : rand() for ll, mm, nn in itertools.product(range(3), repeat = 3) if ll + mm + nn <= 2 } for op, val in h_rand.items(): h_rand[op] = ( h_rand[op] + np.conj(h_rand[op[::-1]]) ) / 2 h_rand[op[::-1]] = np.conj(h_rand[op]) track_ops = [ (ll,mm,nn) for ll, mm, nn in itertools.product(range(3), repeat = 3) if ll + mm + nn <= 2 ] ### construct operators for exact simulation II = qt.tensor([I2]*N) ZZ = 0 * II s_z_j = [] s_p_j = [] s_m_j = [] for jj in range(N): s_z_j.append(qt.tensor([ I2 ] * jj + [ qt.sigmaz()/2 ] + [ I2 ] * (N-jj-1))) s_p_j.append(qt.tensor([ I2 ] * jj + [ qt.sigmap() ] + [ I2 ] * (N-jj-1))) s_m_j.append(qt.tensor([ I2 ] * jj + [ qt.sigmam() ] + [ I2 ] * (N-jj-1))) S_p = sum(s_p_j) S_m = sum(s_m_j) S_z = sum(s_z_j) S_x = 1/2 * ( S_p + S_m ) S_y = -1j/2 * ( S_p - S_m )
def liouvillian(omega, g, gamma, beta): """Liouvillian for the coupled system of qubit and TLS""" H0_q = omega*0.5*(-qutip.operators.sigmaz()+qutip.qeye(2)) # drive qubit Hamiltonian H1_q = -0.5*qutip.operators.sigmax() # drift TLS Hamiltonian H0_T = qutip.tensor(omega*0.5*(-qutip.operators.sigmaz()+qutip.qeye(2)), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2))\ +qutip.tensor(qutip.qeye(2), omega*0.5*(-qutip.operators.sigmaz()+qutip.qeye(2)), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2))\ +qutip.tensor(qutip.qeye(2), qutip.qeye(2), omega*0.5*(-qutip.operators.sigmaz()+qutip.qeye(2)), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2))\ +qutip.tensor(qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), omega*0.5*(-qutip.operators.sigmaz()+qutip.qeye(2)), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2))\ +qutip.tensor(qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), omega*0.5*(-qutip.operators.sigmaz()+qutip.qeye(2)), qutip.qeye(2), qutip.qeye(2))\ +qutip.tensor(qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), omega*0.5*(-qutip.operators.sigmaz()+qutip.qeye(2)), qutip.qeye(2))\ +qutip.tensor(qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), omega*0.5*(-qutip.operators.sigmaz()+qutip.qeye(2))) # Lift Hamiltonians to joint system operators H0 = qutip.tensor(H0_q, qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2)) + qutip.tensor(qutip.qeye(2), H0_T) H1 = qutip.tensor(H1_q, qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2), qutip.qeye(2)) # qubit-TLS interaction H_int = g*(qutip.tensor(qutip.destroy(2),qutip.create(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2))\ +qutip.tensor(qutip.create(2),qutip.destroy(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2))\ +qutip.tensor(qutip.destroy(2),qutip.qeye(2),qutip.create(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2))\ +qutip.tensor(qutip.create(2),qutip.qeye(2),qutip.destroy(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2))\ +qutip.tensor(qutip.destroy(2),qutip.qeye(2),qutip.qeye(2),qutip.create(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2))\ +qutip.tensor(qutip.create(2),qutip.qeye(2),qutip.qeye(2),qutip.destroy(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2))\ +qutip.tensor(qutip.destroy(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.create(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2))\ +qutip.tensor(qutip.create(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.destroy(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2))\ +qutip.tensor(qutip.destroy(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.create(2),qutip.qeye(2),qutip.qeye(2))\ +qutip.tensor(qutip.create(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.destroy(2),qutip.qeye(2),qutip.qeye(2))\ +qutip.tensor(qutip.destroy(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.create(2),qutip.qeye(2))\ +qutip.tensor(qutip.create(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.destroy(2),qutip.qeye(2))\ +qutip.tensor(qutip.destroy(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.create(2))\ +qutip.tensor(qutip.create(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.destroy(2))) # convert Hamiltonians to QuTiP objects H0 = qutip.Qobj(H0 + H_int) H1 = qutip.Qobj(H1) # Define Lindblad operators N = 1.0 / (np.exp(beta * omega) - 1.0) # Cooling on TLS L1 = np.sqrt(gamma * (N + 1)) * qutip.tensor(qutip.destroy(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),\ qutip.qeye(2),qutip.qeye(2),qutip.qeye(2)) # Heating on TLS L2 = np.sqrt(gamma * N) *qutip.tensor(qutip.create(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),qutip.qeye(2),\ qutip.qeye(2)) # convert Lindblad operators to QuTiP objects L1 = qutip.Qobj(L1) L2 = qutip.Qobj(L2) # generate the Liouvillian L0 = qutip.liouvillian(H=H0, c_ops=[L1, L2]) L1 = qutip.liouvillian(H=H1) # Shift the qubit and TLS into resonance by default eps0 = lambda t, args: 8 return [L0, [L1, eps0]]
def test_3_state_to_state(self): """ control.pulseoptim: state-to-state transfer linear initial pulse used assert that goal is achieved """ # 2 qubits with Ising interaction # some arbitary coupling constants alpha = [0.9, 0.7] beta = [0.8, 0.9] Sx = sigmax() Sz = sigmaz() H_d = (alpha[0] * tensor(Sx, identity(2)) + alpha[1] * tensor(identity(2), Sx) + beta[0] * tensor(Sz, identity(2)) + beta[1] * tensor(identity(2), Sz)) H_c = [tensor(Sz, Sz)] q1_0 = q2_0 = Qobj([[1], [0]]) q1_T = q2_T = Qobj([[0], [1]]) psi_0 = tensor(q1_0, q2_0) psi_T = tensor(q1_T, q2_T) n_ts = 10 evo_time = 18 # Run the optimisation result = cpo.optimize_pulse_unitary(H_d, H_c, psi_0, psi_T, n_ts, evo_time, fid_err_targ=1e-10, init_pulse_type='LIN', gen_stats=True) assert_(result.goal_achieved, msg="State-to-state goal not achieved. " "Terminated due to: {}, with infidelity: {}".format( result.termination_reason, result.fid_err)) assert_almost_equal(result.fid_err, 0.0, decimal=10, err_msg="Hadamard infidelity too high") #Try with Qobj propagation result = cpo.optimize_pulse_unitary(H_d, H_c, psi_0, psi_T, n_ts, evo_time, fid_err_targ=1e-10, init_pulse_type='LIN', dyn_params={'oper_dtype': Qobj}, gen_stats=True) assert_(result.goal_achieved, msg="State-to-state goal not achieved " "(Qobj propagation)" "Terminated due to: {}, with infidelity: {}".format( result.termination_reason, result.fid_err))
return phaseDiff,pop11,pop02 Ej1 = 17 Ej2 = 22 Ec1 = 0.27 Ec2 = 0.27 g=0.015 #/2pi Q1=Tunabletransmon(EC=Ec1, EJmax=Ej1) Q2=Tunabletransmon(EC=Ec2, EJmax=Ej2) QQ=QQ(Q1,Q2,g) #ini_state=iniState2Qsys(Q1.Nq,Q2.Nq,1,1) Nq=3 ini_coeff = [0,1e-9,0,1e-9,1,0,0,0,0] # 11 ini_state = ini_coeff[0]*qt.tensor(ket(Nq,0), ket(Nq,0)) \ + ini_coeff[1]*qt.tensor(ket(Nq,0), ket(Nq,1)) \ + ini_coeff[2]*qt.tensor(ket(Nq,0), ket(Nq,2)) \ + ini_coeff[3]*qt.tensor(ket(Nq,1), ket(Nq,0)) \ + ini_coeff[4]*qt.tensor(ket(Nq,1), ket(Nq,1)) \ + ini_coeff[5]*qt.tensor(ket(Nq,1), ket(Nq,2)) \ + ini_coeff[6]*qt.tensor(ket(Nq,2), ket(Nq,0)) \ + ini_coeff[7]*qt.tensor(ket(Nq,2), ket(Nq,1)) \ + ini_coeff[8]*qt.tensor(ket(Nq,2), ket(Nq,2)) ini_state_rho=iniState2Qsys(Q1.Nq,Q2.Nq,1,1,mode='rho') print(ini_state_rho) Iq1=qt.qeye(Nq) Hq1_lab=QQ.Hq1*(2*pi)
def test_4_lindbladian(self): """ control.pulseoptim: amplitude damping channel Lindbladian dynamics assert that fidelity error is below threshold """ Sx = sigmax() Sz = sigmaz() Si = identity(2) Sd = Qobj(np.array([[0, 1], [0, 0]])) Sm = Qobj(np.array([[0, 0], [1, 0]])) Sd_m = Qobj(np.array([[1, 0], [0, 0]])) gamma = 0.1 L0_Ad = gamma * (2 * tensor(Sm, Sd.trans()) - (tensor(Sd_m, Si) + tensor(Si, Sd_m.trans()))) LC_x = -1j * (tensor(Sx, Si) - tensor(Si, Sx)) LC_z = -1j * (tensor(Sz, Si) - tensor(Si, Sz)) drift = L0_Ad ctrls = [LC_z, LC_x] n_ctrls = len(ctrls) initial = tensor(Si, Si) had_gate = hadamard_transform(1) target_DP = tensor(had_gate, had_gate) n_ts = 10 evo_time = 5 result = cpo.optimize_pulse(drift, ctrls, initial, target_DP, n_ts, evo_time, fid_err_targ=1e-3, max_iter=200, init_pulse_type='LIN', gen_stats=True) assert_(result.fid_err < 0.1, msg="Fidelity higher than expected") # Repeat with Qobj propagation result = cpo.optimize_pulse(drift, ctrls, initial, target_DP, n_ts, evo_time, fid_err_targ=1e-3, max_iter=200, init_pulse_type='LIN', dyn_params={'oper_dtype': Qobj}, gen_stats=True) assert_(result.fid_err < 0.1, msg="Fidelity higher than expected (Qobj propagation)") # Check same result is achieved using the create objects method optim = cpo.create_pulse_optimizer(drift, ctrls, initial, target_DP, n_ts, evo_time, fid_err_targ=1e-3, init_pulse_type='LIN', gen_stats=True) dyn = optim.dynamics p_gen = optim.pulse_generator init_amps = np.zeros([n_ts, n_ctrls]) for j in range(n_ctrls): init_amps[:, j] = p_gen.gen_pulse() dyn.initialize_controls(init_amps) # Check the exact gradient func = optim.fid_err_func_wrapper grad = optim.fid_err_grad_wrapper x0 = dyn.ctrl_amps.flatten() grad_diff = check_grad(func, grad, x0) assert_almost_equal(grad_diff, 0.0, decimal=7, err_msg="Frechet gradient outside tolerance") result2 = optim.run_optimization() assert_almost_equal(result.fid_err, result2.fid_err, decimal=3, err_msg="Direct and indirect methods produce " "different results for ADC")
def test_1_unitary(self): """ control.pulseoptim: Hadamard and QFT gate with linear initial pulses assert that goal is achieved and fidelity error is below threshold """ # Hadamard H_d = sigmaz() H_c = [sigmax()] U_0 = identity(2) U_targ = hadamard_transform(1) n_ts = 10 evo_time = 10 # Run the optimisation result = cpo.optimize_pulse_unitary(H_d, H_c, U_0, U_targ, n_ts, evo_time, fid_err_targ=1e-10, init_pulse_type='LIN', gen_stats=True) assert_(result.goal_achieved, msg="Hadamard goal not achieved. " "Terminated due to: {}, with infidelity: {}".format( result.termination_reason, result.fid_err)) assert_almost_equal(result.fid_err, 0.0, decimal=10, err_msg="Hadamard infidelity too high") #Try without stats result = cpo.optimize_pulse_unitary(H_d, H_c, U_0, U_targ, n_ts, evo_time, fid_err_targ=1e-10, init_pulse_type='LIN', gen_stats=False) assert_(result.goal_achieved, msg="Hadamard goal not achieved " "(no stats). " "Terminated due to: {}, with infidelity: {}".format( result.termination_reason, result.fid_err)) #Try with Qobj propagation result = cpo.optimize_pulse_unitary(H_d, H_c, U_0, U_targ, n_ts, evo_time, fid_err_targ=1e-10, init_pulse_type='LIN', dyn_params={'oper_dtype': Qobj}, gen_stats=True) assert_(result.goal_achieved, msg="Hadamard goal not achieved " "(Qobj propagation). " "Terminated due to: {}, with infidelity: {}".format( result.termination_reason, result.fid_err)) # Check same result is achieved using the create objects method optim = cpo.create_pulse_optimizer(H_d, H_c, U_0, U_targ, n_ts, evo_time, fid_err_targ=1e-10, dyn_type='UNIT', init_pulse_type='LIN', gen_stats=True) dyn = optim.dynamics init_amps = optim.pulse_generator.gen_pulse().reshape([-1, 1]) dyn.initialize_controls(init_amps) # Check the exact gradient func = optim.fid_err_func_wrapper grad = optim.fid_err_grad_wrapper x0 = dyn.ctrl_amps.flatten() grad_diff = check_grad(func, grad, x0) assert_almost_equal(grad_diff, 0.0, decimal=7, err_msg="Unitary gradient outside tolerance") result2 = optim.run_optimization() assert_almost_equal(result.fid_err, result2.fid_err, decimal=10, err_msg="Direct and indirect methods produce " "different results for Hadamard") # QFT Sx = sigmax() Sy = sigmay() Sz = sigmaz() Si = 0.5 * identity(2) H_d = 0.5 * (tensor(Sx, Sx) + tensor(Sy, Sy) + tensor(Sz, Sz)) H_c = [tensor(Sx, Si), tensor(Sy, Si), tensor(Si, Sx), tensor(Si, Sy)] #n_ctrls = len(H_c) U_0 = identity(4) # Target for the gate evolution - Quantum Fourier Transform gate U_targ = qft.qft(2) result = cpo.optimize_pulse_unitary(H_d, H_c, U_0, U_targ, n_ts, evo_time, fid_err_targ=1e-9, init_pulse_type='LIN', gen_stats=True) assert_(result.goal_achieved, msg="QFT goal not achieved. " "Terminated due to: {}, with infidelity: {}".format( result.termination_reason, result.fid_err)) assert_almost_equal(result.fid_err, 0.0, decimal=7, err_msg="QFT infidelity too high") # check bounds result2 = cpo.optimize_pulse_unitary(H_d, H_c, U_0, U_targ, n_ts, evo_time, fid_err_targ=1e-9, amp_lbound=-1.0, amp_ubound=1.0, init_pulse_type='LIN', gen_stats=True) assert_((result2.final_amps >= -1.0).all() and (result2.final_amps <= 1.0).all(), msg="Amplitude bounds exceeded for QFT")
def _x_op(size): return qutip.tensor( qutip.qeye(2), qutip.qeye(2), np.sqrt(0.5) * (qutip.create(size) + qutip.destroy(size)))
def c_op(self, operator, c_num): ''' Helper function to embed c operator with identities on other carbons ''' return qutip.tensor([Id] * c_num + [operator] + [Id] * (self.num_carbons - c_num) + [Id_S1] * self.inc_nitrogen)
def direct_hamiltonian(w_1, w_2, g_factor): """Return a QObj denoting a hamiltonian for two qubits interacting with the cavity mode eliminated.""" return (0.5 * w_1 * qt.tensor(SZ, I) + 0.5 * w_2 * qt.tensor(I, SZ) + g_factor * qt.tensor(SPlus, SMinus) + g_factor * qt.tensor(SMinus, SPlus))