Example #1
0
def L_nonsecular_old(H_vib, A, eps, Gamma, T, J, time_units='cm', silent=False):
    #Construct non-secular liouvillian
    ti = time.time()
    d = H_vib.shape[0]
    evals, evecs = H_vib.eigenstates()
    X1, X2, X3, X4 = 0, 0, 0, 0
    for i in range(int(d)):
        for j in range(int(d)):
            eps_ij = abs(evals[i]-evals[j])
            A_ij = A.matrix_element(evecs[i].dag(), evecs[j])
            A_ji = (A.dag()).matrix_element(evecs[j].dag(), evecs[i])
            Occ = Occupation(eps_ij, T, time_units)
            IJ = evecs[i]*evecs[j].dag()
            JI = evecs[j]*evecs[i].dag()
            # 0.5*np.pi*alpha*(N+1)
            if abs(A_ij)>0 or abs(A_ji)>0:
                r_up = 2*np.pi*J(eps_ij, Gamma, eps)*Occ
                r_down = 2*np.pi*J(eps_ij, Gamma, eps)*(Occ+1)
                X3+= r_down*A_ij*IJ
                X4+= r_up*A_ij*IJ
                X1+= r_up*A_ji*JI
                X2+= r_down*A_ji*JI

    L = spre(A*X1) -sprepost(X1,A)+spost(X2*A)-sprepost(A,X2)
    L+= spre(A.dag()*X3)-sprepost(X3, A.dag())+spost(X4*A.dag())-sprepost(A.dag(), X4)
    if not silent:
        print(("It took ", time.time()-ti, " seconds to build the Non-secular RWA Liouvillian"))
    return -0.5*L
Example #2
0
def L_left_lindblad(H, PARAMS):
    I = qeye(PARAMS['N'])
    d_h = tensor(PARAMS['A_L'], I)
    J_leads = J_Lorentzian
    Lambda_up = lambda x :  Lamdba_complex_rate(x, J_leads, PARAMS['mu_L'], PARAMS['T_L'], PARAMS['Gamma_L'], 
                                                    PARAMS['delta_L'], PARAMS['Omega_L'], type='p', real_only=True)
    Lambda_down = lambda x :  Lamdba_complex_rate(x, J_leads, PARAMS['mu_L'], PARAMS['T_L'], PARAMS['Gamma_L'], 
                                                    PARAMS['delta_L'], PARAMS['Omega_L'], type='m', real_only=True)
    energies, states = H.eigenstates()
    
    L=0
    for i in range(len(energies)):
        for j in range(len(energies)):
            eta_ij = energies[i] - energies[j]
            if (abs(eta_ij)>0):# take limit of rates going to zero
                d_h_ij = d_h.matrix_element(states[i].dag(), states[j])
                d_h_ij_sq = d_h_ij*d_h_ij.conjugate() # real by construction
                if (abs(d_h_ij_sq)>0):  # No need to do anything if the matrix element is zero
                    
                    IJ = states[i]*states[j].dag()
                    JI = states[j]*states[i].dag()
                    JJ = states[j]*states[j].dag()
                    II = states[i]*states[i].dag()
                    rate_up = Lambda_up(-eta_ij) # evaluated at positive freq diffs
                    rate_down = Lambda_down(-eta_ij)
                    print(rate_down)
                    T1 = rate_up*spre(II)+rate_down*spre(JJ)
                    T2 = rate_up.conjugate()*spost(II)+rate_down.conjugate()*spost(JJ)
                    T3 = (rate_up*sprepost(JI, IJ)+rate_down*sprepost(IJ,JI))
                    L += d_h_ij_sq*(0.5*(T1 + T2) - T3)
    return -L
def L_full_secular(H_vib, A, eps, Gamma, T, J, time_units='cm', silent=False):
    '''
    Initially assuming that the vibronic eigenstructure has no
    degeneracy and the secular approximation has been made
    '''
    ti = time.time()
    d = H_vib.shape[0]
    L = 0
    eVals, eVecs = H_vib.eigenstates()
    A_dag = A.dag()
    terms = 0
    for l in range(int(d)):
        for m in range(int(d)):
            for p in range(int(d)):
                for q in range(int(d)):
                    secular_freq = (eVals[l] - eVals[m]) - (eVals[p] -
                                                            eVals[q])
                    if abs(secular_freq) < 1E-10:
                        terms += 1
                        A_lm = A.matrix_element(eVecs[l].dag(), eVecs[m])
                        A_lm_star = A_dag.matrix_element(
                            eVecs[m].dag(), eVecs[l])
                        A_pq = A.matrix_element(eVecs[p].dag(), eVecs[q])
                        A_pq_star = A_dag.matrix_element(
                            eVecs[q].dag(), eVecs[p])
                        coeff_1 = A_lm * A_pq_star
                        coeff_2 = A_lm_star * A_pq
                        eps_pq = abs(eVals[p] - eVals[q])
                        Occ = Occupation(eps_pq, T, time_units)
                        r_up = np.pi * J(eps_pq, Gamma, eps) * Occ
                        r_down = np.pi * J(eps_pq, Gamma, eps) * (Occ + 1)
                        LM = eVecs[l] * eVecs[m].dag()
                        ML = LM.dag()
                        PQ = eVecs[p] * eVecs[q].dag()
                        QP = PQ.dag()
                        """
                        if abs(secular_freq) !=0:
                            print (abs(secular_freq), r_up, A_lm, A_lm_star,
                                   A_pq, A_pq_star, r_down, l,m,p,q, m==q, l==p)
                        """
                        if abs(r_up * coeff_1) > 0:
                            L += r_up * coeff_1 * (spre(LM * QP) -
                                                   sprepost(QP, LM))
                        if abs(r_up * coeff_2) > 0:
                            L += r_up * coeff_2 * (spost(PQ * ML) -
                                                   sprepost(ML, PQ))
                        if abs(r_down * coeff_1) > 0:
                            L += r_down * coeff_1 * (spre(ML * PQ) -
                                                     sprepost(PQ, ML))
                        if abs(r_down * coeff_2) > 0:
                            L += r_down * coeff_2 * (spost(QP * LM) -
                                                     sprepost(LM, QP))
    if not silent:
        print(("It took ", time.time() - ti,
               " seconds to build the secular Liouvillian"))
        print((
            "Secular approximation kept {:0.2f}% of total ME terms. \n".format(
                100 * float(terms) / (d * d * d * d))))
    return -L
Example #4
0
def L_EM_lindblad(splitting, col_em, Gamma, T, J, time_units='cm', silent=False):
    # col_em is collapse operator
    ti = time.time()
    L = 0
    EMnb = Occupation(splitting, T, time_units)
    L+= 2*np.pi*J(splitting, Gamma, splitting)*(EMnb+1)*(sprepost(col_em, col_em.dag())-0.5*(spre(col_em.dag()*col_em) +spost(col_em.dag()*col_em)))
    L+= 2*np.pi*J(splitting, Gamma, splitting)*EMnb*(sprepost(col_em.dag(), col_em)-0.5*(spre(col_em*col_em.dag())+ spost(col_em*col_em.dag())))
    if not silent:
        print(("It took ", time.time()-ti, " seconds to build the electronic-Lindblad Liouvillian"))
    return L
Example #5
0
def liouvillian_build(H_0, A, gamma, wRC, T_C):
    # Now this function has to construct the liouvillian so that it can be passed to mesolve
    H_0, A, Chi, Xi = RCME_operators(H_0, A, gamma, beta_f(T_C))
    L = 0
    L -= spre(A * Chi)
    L += sprepost(A, Chi)
    L += sprepost(Chi, A)
    L -= spost(Chi * A)

    L += spre(A * Xi)
    L += sprepost(A, Xi)
    L -= sprepost(Xi, A)
    L -= spost(Xi * A)

    return L, Chi + Xi
Example #6
0
    def channel(self, loss, dephasing, verbose=False):
        data_kraus = loss.kraus
        ancilla_phase = loss.propagate(self.ancilla.dim, self.code.N,
                                       self.ancilla.N)
        nkraus = len(data_kraus)
        ndata_meas = len(self.data_meas.povm_elements)
        nancilla_meas = len(self.ancilla_meas.povm_elements)
        cmat1 = np.zeros((ndata_meas, nkraus, 2, 2), dtype=complex)
        cmat2 = np.zeros((nancilla_meas, nkraus, 2, 2), dtype=complex)

        # compute c1(x1|k;a;b), c2(x2|k;a;b) matrices
        for k, (n, p) in enumerate(zip(data_kraus, ancilla_phase)):
            cmat1[:, k, :, :] = np.reshape(
                 [qt.expect(m, n*dephasing(keta*ketb.dag())*n.dag())
                  for m in self.data_meas.povm_elements
                  for keta in [self.code.plus, self.code.minus]
                  for ketb in [self.code.plus, self.code.minus]],
                 cmat1[:, k, :, :].shape)
            cmat2[:, k, :, :] = np.reshape(
                 [qt.expect(m, p*keta*ketb.dag()*p.dag())
                  for m in self.ancilla_meas.povm_elements
                  for keta in [self.ancilla.plus, self.ancilla.minus]
                  for ketb in [self.ancilla.plus, self.ancilla.minus]],
                 cmat2[:, k, :, :].shape)

        # compute p1(x1|k;a), p2(x2|k;a) matrices
        pmat1 = np.diagonal(cmat1, axis1=2, axis2=3)
        pmat2 = np.diagonal(cmat2, axis1=2, axis2=3)

        # compute c(x1, x2| a, a', b') and p(x1, x2| a, b)
        cmat = np.moveaxis(np.tensordot(cmat1, cmat2, axes=([1], [1])), 3, 1)
        pmat = np.moveaxis(np.tensordot(pmat1, pmat2, axes=([1], [1])), 2, 1)

        # determine most likely a, b
        abmat = np.empty((ndata_meas, nancilla_meas), dtype=object)
        for x1 in range(ndata_meas):
            for x2 in range(nancilla_meas):
                idx = (x1, x2, Ellipsis)
                a, b = np.unravel_index(np.argmax(pmat[idx]),
                                        pmat[idx].shape)
                abmat[x1, x2] = (a, b)

        # construct channel
        channel = qt.Qobj()
        Paulis = np.array(
            [[self.code_out.identity,
              self.code_out.logical_Z_allspace],
             [self.code_out.logical_X_allspace,
              self.code_out.logical_X_allspace
              * self.code_out.logical_Z_allspace]],
            dtype=type(self.code_out.identity))
        for a1, a2 in np.ndindex(2, 2):
            for b1, b2 in np.ndindex(2, 2):
                for x1 in range(ndata_meas):
                    for x2 in range(nancilla_meas):
                        r = Paulis[abmat[x1, x2]].dag()
                        channel += (cmat[x1, x2, a1, b1, a2, b2]
                            * qt.sprepost(r*Paulis[a1, a2],
                                          Paulis[b1, b2].dag()*r.dag()))
        return 0.25*channel
Example #7
0
    def __init__(self, H_S, L1, L2, S_matrix=None, c_ops_markov=None,
                 options=None):

        if options is None:
            self.options = qt.Options()
        else:
            self.options = options

        self.H_S = H_S
        self.sysdims = H_S.dims
        if isinstance(L1, qt.Qobj):
            self.L1 = [L1]
        else:
            self.L1 = L1
        if isinstance(L2, qt.Qobj):
            self.L2 = [L2]
        else:
            self.L2 = L2
        if not len(self.L1) == len(self.L2):
            raise ValueError('L1 and L2 has to be of equal length.')
        if isinstance(c_ops_markov, qt.Qobj):
            self.c_ops_markov = [c_ops_markov]
        else:
            self.c_ops_markov = c_ops_markov

        if S_matrix is None:
            self.S_matrix = np.identity(len(self.L1))
        else:
            self.S_matrix = S_matrix
        # create system identity superoperator
        self.Id = qt.qeye(H_S.shape[0])
        self.Id.dims = self.sysdims
        self.Id = qt.sprepost(self.Id, self.Id)
        self.store_states = self.options.store_states
Example #8
0
    def test_sprepost(self):
        U1 = rand_unitary(3)
        U2 = rand_unitary(3)

        S1 = spre(U1) * spost(U2)
        S2 = sprepost(U1, U2)

        assert_(S1 == S2)
Example #9
0
def pauli_channel_2_qubit(num_of_paulis):
    paulis_probs = np.random.random_sample(num_of_paulis)
    paulis_probs = paulis_probs / sum(paulis_probs)
    channel = qt.Qobj()
    for i in range(num_of_paulis):
        pauli_rand = qt.tensor(g_1Q[rd.randint(0, 3)], g_1Q[rd.randint(0, 3)])
        channel += paulis_probs[i] * qt.sprepost(pauli_rand, pauli_rand)
    return channel
Example #10
0
 def encoder(self, kraus=False):
     if self._encoder is None:
         self._encoder = (self.zero * qt.basis(2, 0).dag() +
                          self.one * qt.basis(2, 1).dag())
     if kraus:
         return self._encoder
     else:
         return qt.sprepost(self._encoder, self._encoder.dag())
    def test_sprepost(self):
        U1 = rand_unitary(3)
        U2 = rand_unitary(3)

        S1 = spre(U1) * spost(U2)
        S2 = sprepost(U1, U2)

        assert_(S1 == S2)
Example #12
0
def test_dqd_current():
    "Counting statistics: current and current noise in a DQD model"

    G = 0
    L = 1
    R = 2

    sz = qutip.projection(3, L, L) - qutip.projection(3, R, R)
    sx = qutip.projection(3, L, R) + qutip.projection(3, R, L)
    sR = qutip.projection(3, G, R)
    sL = qutip.projection(3, G, L)

    w0 = 1
    tc = 0.6 * w0
    GammaR = 0.0075 * w0
    GammaL = 0.0075 * w0
    nth = 0.00
    eps_vec = np.linspace(-1.5 * w0, 1.5 * w0, 20)

    J_ops = [GammaR * qutip.sprepost(sR, sR.dag())]

    c_ops = [
        np.sqrt(GammaR * (1 + nth)) * sR,
        np.sqrt(GammaR * (nth)) * sR.dag(),
        np.sqrt(GammaL * (nth)) * sL,
        np.sqrt(GammaL * (1 + nth)) * sL.dag()
    ]

    current = np.zeros(len(eps_vec))
    noise = np.zeros(len(eps_vec))

    for n, eps in enumerate(eps_vec):
        H = (eps / 2 * sz + tc * sx)
        L = qutip.liouvillian(H, c_ops)
        rhoss = qutip.steadystate(L)
        current[n], noise[n] = qutip.countstat_current_noise(L, [],
                                                             rhoss=rhoss,
                                                             J_ops=J_ops)

        current2 = qutip.countstat_current(L, rhoss=rhoss, J_ops=J_ops)
        assert abs(current[n] - current2) < 1e-8

        current2 = qutip.countstat_current(L, c_ops, J_ops=J_ops)
        assert abs(current[n] - current2) < 1e-8

    current_target = (tc**2 * GammaR /
                      (tc**2 *
                       (2 + GammaR / GammaL) + GammaR**2 / 4 + eps_vec**2))
    noise_target = current_target * (
        1 - (8 * GammaL * tc**2 *
             (4 * eps_vec**2 * (GammaR - GammaL) + GammaR *
              (3 * GammaL * GammaR + GammaR**2 + 8 * tc**2)) /
             (4 * tc**2 * (2 * GammaL + GammaR) + GammaL * GammaR**2 +
              4 * eps_vec**2 * GammaL)**2))

    np.testing.assert_allclose(current, current_target, atol=1e-4)
    np.testing.assert_allclose(noise, noise_target, atol=1e-4)
Example #13
0
def liouvillian_build_new(H_0, A, gamma, wRC, T_C):
    # Now this function has to construct the liouvillian so that it can be passed to mesolve
    H_0, A, Chi, Xi = RCME_operators(H_0, A, gamma, beta_f(T_C))
    Z = Chi + Xi
    Z_dag = Z.dag()
    L = 0
    #L+=spre(A*Z_dag)
    #L-=sprepost(A, Z)
    #L-=sprepost(Z_dag, A)
    #L+=spost(Z_dag*A)

    L -= spre(A * Z_dag)
    L += sprepost(A, Z)
    L += sprepost(Z_dag, A)
    L -= spost(Z * A)

    print("new L built")
    return L, Z
def L_vib_lindblad(H_vib, A, eps, Gamma, T, J, time_units='cm', silent=False):
    '''
    Initially assuming that the vibronic eigenstructure has no
    degeneracy and the secular approximation has been made
    '''
    ti = time.time()
    d = H_vib.shape[0]
    ti = time.time()
    L = 0
    eig = H_vib.eigenstates()
    eVals = eig[0]
    eVecs = eig[1]  # come out like kets
    l = 0
    occs = []
    for i in range(int(d)):
        l = 0
        for j in range(int(d)):
            t_0 = time.time(
            )  # initial time reference for tracking slow calculations
            lam_ij = A.matrix_element(eVecs[i].dag(), eVecs[j])
            #lam_mn = (A.dag()).matrix_element(eVecs[n].dag(), eVecs[m])
            lam_ij_sq = lam_ij * lam_ij.conjugate()  # real by construction
            eps_ij = abs(eVals[i] - eVals[j])
            if abs(lam_ij_sq) > 0:
                IJ = eVecs[i] * eVecs[j].dag()
                JI = eVecs[j] * eVecs[i].dag()
                JJ = eVecs[j] * eVecs[j].dag()
                II = eVecs[i] * eVecs[i].dag()

                Occ = Occupation(eps_ij, T, time_units)
                r_up = 2 * np.pi * J(eps_ij, Gamma, eps) * Occ
                r_down = 2 * np.pi * J(eps_ij, Gamma, eps) * (Occ + 1)

                T1 = r_up * spre(II) + r_down * spre(JJ)
                T2 = r_up.conjugate() * spost(II) + r_down.conjugate() * spost(
                    JJ)
                T3 = (r_up * sprepost(JI, IJ) + r_down * sprepost(IJ, JI))
                L += lam_ij_sq * (0.5 * (T1 + T2) - T3)
                l += 1
    if not silent:
        print(("It took ", time.time() - ti,
               " seconds to build the vibronic Lindblad Liouvillian"))
    return -L
Example #15
0
def L_wc_analytic(detuning=0.,
                  Rabi=0,
                  alpha=0.,
                  w0=0.,
                  Gamma=0.,
                  T=0.,
                  tol=1e-7):
    energies, states = exciton_states(detuning, Rabi)
    dark_proj = states[0] * states[0].dag()
    bright_proj = states[1] * states[1].dag()
    ct_p = states[1] * states[0].dag()
    ct_m = states[0] * states[1].dag()
    cross_term = (ct_p + ct_m)
    epsilon = -detuning
    V = Rabi / 2

    eta = sqrt(epsilon**2 + 4 * V**2)

    # Bath 1 (only one bath)
    G = (lambda x: (DecayRate(x,
                              beta_f(T),
                              _J_underdamped,
                              Gamma,
                              w0,
                              imag_part=True,
                              alpha=alpha,
                              tol=tol)))
    G_0 = G(0.)
    G_p = G(eta)
    G_m = G(-eta)

    site_1 = (0.5 / eta) * ((eta + epsilon) * bright_proj +
                            (eta - epsilon) * dark_proj + 2 * V * cross_term)

    Z_1 = (0.5 / eta) * (G_0 * ((eta + epsilon) * bright_proj +
                                (eta - epsilon) * dark_proj) + 2 * V *
                         (ct_p * G_p + ct_m * G_m))

    L = -qt.spre(site_1 * Z_1) + qt.sprepost(Z_1, site_1)
    L += -qt.spost(Z_1.dag() * site_1) + qt.sprepost(site_1, Z_1.dag())

    return L
Example #16
0
def test_dqd_current():
    "Counting statistics: current and current noise in a DQD model"

    G = 0
    L = 1
    R = 2

    sz = projection(3, L, L) - projection(3, R, R)
    sx = projection(3, L, R) + projection(3, R, L)
    sR = projection(3, G, R)
    sL = projection(3, G, L)

    w0 = 1
    tc = 0.6 * w0
    GammaR = 0.0075 * w0
    GammaL = 0.0075 * w0
    nth = 0.00
    eps_vec = np.linspace(-1.5*w0, 1.5*w0, 20)

    J_ops = [GammaR * sprepost(sR, sR.dag())]

    c_ops = [np.sqrt(GammaR * (1 + nth)) * sR,
             np.sqrt(GammaR * (nth)) * sR.dag(),
             np.sqrt(GammaL * (nth)) * sL,
             np.sqrt(GammaL * (1 + nth)) * sL.dag(),
             ]

    I = np.zeros(len(eps_vec))
    S = np.zeros(len(eps_vec))

    for n, eps in enumerate(eps_vec):
        H = (eps/2 * sz + tc * sx)
        L = liouvillian(H, c_ops)
        rhoss = steadystate(L)
        I[n], S[n] = countstat_current_noise(L, [], rhoss=rhoss, J_ops=J_ops)

        I2 = countstat_current(L, rhoss=rhoss, J_ops=J_ops)
        assert_(abs(I[n] - I2) < 1e-8)

        I2 = countstat_current(L, c_ops, J_ops=J_ops)
        assert_(abs(I[n] - I2) < 1e-8)

    Iref = tc**2 * GammaR / (tc**2 * (2 + GammaR/GammaL) +
                             GammaR**2/4 + eps_vec**2)
    Sref = 1 * Iref * (
        1 - 8 * GammaL * tc**2 *
        (4 * eps_vec**2 * (GammaR - GammaL) +
         GammaR * (3 * GammaL * GammaR + GammaR**2 + 8*tc**2)) /
        (4 * tc**2 * (2 * GammaL + GammaR) + GammaL * GammaR**2 +
         4 * eps_vec**2 * GammaL)**2
    )

    assert_allclose(I, Iref, 1e-4)
    assert_allclose(S, Sref, 1e-4)
def L_non_rwa(H_vib,
              A,
              w_0,
              Gamma,
              T_EM,
              J,
              principal=False,
              silent=False,
              alpha=0.,
              tol=1e-5):
    ti = time.time()
    beta = beta_f(T_EM)
    eVals, eVecs = H_vib.eigenstates()
    #J=J_minimal # J_minimal(omega, Gamma, omega_0)
    d_dim = len(eVals)
    G = 0
    for i in range(d_dim):
        for j in range(d_dim):
            eta = eVals[i] - eVals[j]
            s = eVecs[i] * (eVecs[j].dag())
            #print A.matrix_element(eVecs[i].dag(), eVecs[j])
            overlap = A.matrix_element(eVecs[i].dag(), eVecs[j])
            s *= A.matrix_element(eVecs[i].dag(), eVecs[j])
            s *= DecayRate(eta,
                           beta,
                           J,
                           Gamma,
                           w_0,
                           imag_part=principal,
                           alpha=alpha,
                           tol=tol)
            G += s
    G_dag = G.dag()
    # Initialise liouvilliian
    L = qt.spre(A * G) - qt.sprepost(G, A)
    L += qt.spost(G_dag * A) - qt.sprepost(A, G_dag)
    if not silent:
        print(("Calculating non-RWA Liouvilliian took {} seconds.".format(
            time.time() - ti)))
    return -L
Example #18
0
def test_ttmsolve_jc_model():
    """
    Checks the output of ttmsolve using an example from Jaynes-Cumming model,
    which can also be found in the qutip-notebooks repository.
    """
    # Define Hamiltonian and states
    N, kappa, g = 3, 1.0, 10
    a = qt.tensor(qt.qeye(2), qt.destroy(N))
    sm = qt.tensor(qt.sigmam(), qt.qeye(N))
    sz = qt.tensor(qt.sigmaz(), qt.qeye(N))
    H = g * (a.dag() * sm + a * sm.dag())
    c_ops = [np.sqrt(kappa) * a]
    # identity superoperator
    Id = qt.tensor(qt.qeye(2), qt.qeye(N))
    E0 = qt.sprepost(Id, Id)
    # partial trace superoperator
    ptracesuper = qt.tensor_contract(E0, (1, N))
    # initial states
    rho0a = qt.ket2dm(qt.basis(2, 0))
    psi0c = qt.basis(N, 0)
    rho0c = qt.ket2dm(psi0c)
    rho0 = qt.tensor(rho0a, rho0c)
    superrho0cav = qt.sprepost(qt.tensor(qt.qeye(2), psi0c),
                               qt.tensor(qt.qeye(2), psi0c.dag()))

    # calculate exact solution using mesolve
    times = np.arange(0, 5.0, 0.1)
    exactsol = qt.mesolve(H, rho0, times, c_ops, [])
    exact_z = qt.expect(sz, exactsol.states)

    # solve using transfer method
    learning_times = np.arange(0, 2.0, 0.1)
    Et_list = qt.mesolve(H, E0, learning_times, c_ops, []).states
    learning_maps = [ptracesuper * (Et * superrho0cav) for Et in Et_list]
    ttmsol = ttmsolve(learning_maps, rho0a, times)
    ttm_z = qt.expect(qt.sigmaz(), ttmsol.states)

    # check that ttm result and exact solution are close in the learning times
    assert np.allclose(ttm_z, exact_z, atol=1e-5)
Example #19
0
def liouvillian(epsilon, delta, J, T):
    L = 0 # Initialise liouvilliian
    Z = 0 # initialise operator Z
    #beta = 1 /(T* 0.695)
    beta = 7.683/T
    eta = np.sqrt(epsilon**2 + delta**2)
    # Here I define the eigenstates of the H_s
    H = qt.Qobj([[-epsilon/2., delta/2],[delta/2, epsilon/2.]])
    eVecs = H.eigenstates()[1]
    psi_p = (1/np.sqrt(2*eta))*(np.sqrt(eta-epsilon)*qt.basis(2,0) + np.sqrt(eta+epsilon)*qt.basis(2,1))
    psi_m = (-1/np.sqrt(2*eta))*(np.sqrt(eta+epsilon)*qt.basis(2,0) - np.sqrt(eta-epsilon)*qt.basis(2,1))

    #print H.eigenstates()
    # Jake's eigenvectors
    #psi_p = (1/np.sqrt(2*eta))*(np.sqrt(eta+epsilon)*qt.basis(2,0) - np.sqrt(eta-epsilon)*qt.basis(2,1))
    #psi_m = (1/np.sqrt(2*eta))*(np.sqrt(eta-epsilon)*qt.basis(2,0) + np.sqrt(eta+epsilon)*qt.basis(2,1))

    sigma_z = (1/eta)*(epsilon*(psi_p*psi_p.dag()-psi_m*psi_m.dag()) + delta*(psi_p*psi_m.dag() + psi_m*psi_p.dag()))

    Z = (1/eta)*(epsilon*(psi_p*psi_p.dag()-psi_m*psi_m.dag() )*Gamma(0, beta, J) + delta*(Gamma(eta, beta, J)*psi_p*psi_m.dag() + Gamma(-eta,beta, J)*psi_m*psi_p.dag()))

    L +=  qt.spre(sigma_z*Z) - qt.sprepost(Z, sigma_z)
    L += qt.spost(Z.dag()*sigma_z) - qt.sprepost(sigma_z, Z.dag())
    return -L
Example #20
0
 def test_sprepost_td(self):
     "Superoperator: sprepost, time-dependent"
     # left QobjEvo
     assert_(sprepost(self.t1, self.q2)(.5) ==
             sprepost(self.t1(.5), self.q2))
     # left QobjEvo
     assert_(sprepost(self.q2, self.t1)(.5) ==
             sprepost(self.q2, self.t1(.5)))
     # left 2 QobjEvo, one cte
     assert_(sprepost(self.t1, self.t2)(.5) ==
             sprepost(self.t1(.5), self.t2(.5)))
Example #21
0
 def test_sprepost_td(self):
     "Superoperator: sprepost, time-dependent"
     # left QobjEvo
     assert_(sprepost(self.t1, self.q2)(.5) ==
             sprepost(self.t1(.5), self.q2))
     # left QobjEvo
     assert_(sprepost(self.q2, self.t1)(.5) ==
             sprepost(self.q2, self.t1(.5)))
     # left 2 QobjEvo, one cte
     assert_(sprepost(self.t1, self.t2)(.5) ==
             sprepost(self.t1(.5), self.t2(.5)))
Example #22
0
    def testMETDDecayAsArray(self):
        "mesolve: time-dependence as array with super as init cond"
        me_error = 1e-5

        N = 10
        a = destroy(N)
        H = a.dag() * a
        psi0 = basis(N, 9)
        rho0vec = operator_to_vector(psi0 * psi0.dag())
        E0 = sprepost(qeye(N), qeye(N))
        kappa = 0.2
        tlist = np.linspace(0, 10, 1000)
        c_op_list = [[a, np.sqrt(kappa * np.exp(-tlist))]]
        out1 = mesolve(H, psi0, tlist, c_op_list, [])
        out2 = mesolve(H, E0, tlist, c_op_list, [])
        fid = self.fidelitycheck(out1, out2, rho0vec)
        assert_(max(abs(1.0 - fid)) < me_error, True)
Example #23
0
    def testMETDDecayAsArray(self):
        "mesolve: time-dependence as array with super as init cond"
        me_error = 1e-5

        N = 10
        a = destroy(N)
        H = a.dag() * a
        psi0 = basis(N, 9)
        rho0vec = operator_to_vector(psi0 * psi0.dag())
        E0 = sprepost(qeye(N), qeye(N))
        kappa = 0.2
        tlist = np.linspace(0, 10, 1000)
        c_op_list = [[a, np.sqrt(kappa * np.exp(-tlist))]]
        out1 = mesolve(H, psi0, tlist, c_op_list, [])
        out2 = mesolve(H, E0, tlist, c_op_list, [])
        fid = self.fidelitycheck(out1, out2, rho0vec)
        assert_(max(abs(1.0 - fid)) < me_error, True)
Example #24
0
    def testMETDDecayAsPartFuncList(self):
        "mesolve: time-dep. as partial function list with super as init cond"
        me_error = 1e-5

        N = 10
        a = destroy(N)
        H = num(N)
        psi0 = basis(N, 9)
        rho0vec = operator_to_vector(psi0 * psi0.dag())
        E0 = sprepost(qeye(N), qeye(N))
        tlist = np.linspace(0, 10, 100)
        c_ops = [[[a, partial(lambda t, args, k: np.sqrt(k * np.exp(-t)), k=kappa)]] for kappa in [0.05, 0.1, 0.2]]

        for idx, kappa in enumerate([0.05, 0.1, 0.2]):
            out1 = mesolve(H, psi0, tlist, c_ops[idx], [])
            out2 = mesolve(H, E0, tlist, c_ops[idx], [])
            fid = self.fidelitycheck(out1, out2, rho0vec)
            assert_(max(abs(1.0 - fid)) < me_error, True)
Example #25
0
    def testMETDDecayAsStrList(self):
        "mesolve: time-dependence as string list with super as init cond"
        me_error = 1e-6

        N = 10  # number of basis states to consider
        a = destroy(N)
        H = a.dag() * a
        psi0 = basis(N, 9)  # initial state
        rho0vec = operator_to_vector(psi0 * psi0.dag())
        E0 = sprepost(qeye(N), qeye(N))
        kappa = 0.2  # coupling to oscillator
        c_op_list = [[a, 'sqrt(k*exp(-t))']]
        args = {'k': kappa}
        tlist = np.linspace(0, 10, 100)
        out1 = mesolve(H, psi0, tlist, c_op_list, [], args=args)
        out2 = mesolve(H, E0, tlist, c_op_list, [], args=args)
        fid = self.fidelitycheck(out1, out2, rho0vec)
        assert_(max(abs(1.0 - fid)) < me_error, True)
Example #26
0
    def testMETDDecayAsStrList(self):
        "mesolve: time-dependence as string list with super as init cond"
        me_error = 1e-6

        N = 10  # number of basis states to consider
        a = destroy(N)
        H = a.dag() * a
        psi0 = basis(N, 9)  # initial state
        rho0vec = operator_to_vector(psi0 * psi0.dag())
        E0 = sprepost(qeye(N), qeye(N))
        kappa = 0.2  # coupling to oscillator
        c_op_list = [[a, "sqrt(k*exp(-t))"]]
        args = {"k": kappa}
        tlist = np.linspace(0, 10, 100)
        out1 = mesolve(H, psi0, tlist, c_op_list, [], args=args)
        out2 = mesolve(H, E0, tlist, c_op_list, [], args=args)
        fid = self.fidelitycheck(out1, out2, rho0vec)
        assert_(max(abs(1.0 - fid)) < me_error, True)
Example #27
0
    def __init__(self,
                 H_S,
                 L1,
                 L2,
                 S_matrix=None,
                 c_ops_markov=None,
                 integrator='propagator',
                 parallel=False,
                 options=None):

        if options is None:
            self.options = qt.Options()
        else:
            self.options = options

        self.H_S = H_S
        self.sysdims = H_S.dims
        if isinstance(L1, qt.Qobj):
            self.L1 = [L1]
        else:
            self.L1 = L1
        if isinstance(L2, qt.Qobj):
            self.L2 = [L2]
        else:
            self.L2 = L2
        if not len(self.L1) == len(self.L2):
            raise ValueError('L1 and L2 has to be of equal length.')
        if isinstance(c_ops_markov, qt.Qobj):
            self.c_ops_markov = [c_ops_markov]
        else:
            self.c_ops_markov = c_ops_markov

        if S_matrix is None:
            self.S_matrix = np.identity(len(self.L1))
        else:
            self.S_matrix = S_matrix
        # create system identity superoperator
        self.Id = qt.qeye(H_S.shape[0])
        self.Id.dims = self.sysdims
        self.Id = qt.sprepost(self.Id, self.Id)
        self.store_states = self.options.store_states
        self.integrator = integrator
        self.parallel = parallel
Example #28
0
    def testMETDDecayAsPartFuncList(self):
        "mesolve: time-dep. as partial function list with super as init cond"
        me_error = 1e-5

        N = 10
        a = destroy(N)
        H = num(N)
        psi0 = basis(N, 9)
        rho0vec = operator_to_vector(psi0 * psi0.dag())
        E0 = sprepost(qeye(N), qeye(N))
        tlist = np.linspace(0, 10, 100)
        c_ops = [[[
            a, partial(lambda t, args, k: np.sqrt(k * np.exp(-t)), k=kappa)
        ]] for kappa in [0.05, 0.1, 0.2]]

        for idx, kappa in enumerate([0.05, 0.1, 0.2]):
            out1 = mesolve(H, psi0, tlist, c_ops[idx], [])
            out2 = mesolve(H, E0, tlist, c_ops[idx], [])
            fid = self.fidelitycheck(out1, out2, rho0vec)
            assert_(max(abs(1.0 - fid)) < me_error, True)
Example #29
0
def _generator(k, H, L1, L2, S=None, c_ops_markov=None):
    """
    Create a Liouvillian for a cascaded chain of k system copies
    """
    id = qt.qeye(H.dims[0][0])
    Id = qt.sprepost(id, id)
    if S is None:
        S = np.identity(len(L1))
    # create Lindbladian
    L = qt.Qobj()
    E0 = Id
    # first system
    L += qt.liouvillian(None, [_localop(c, 1, k) for c in L2])
    for l in range(1, k):
        # Identiy superoperator
        E0 = qt.composite(E0, Id)
        # Bare Hamiltonian
        Hl = _localop(H, l, k)
        L += qt.liouvillian(Hl, [])
        # Markovian Decay channels
        if c_ops_markov is not None:
            for c in c_ops_markov:
                cl = _localop(c, l, k)
                L += qt.liouvillian(None, [cl])
        # Cascade coupling
        c1 = np.array([_localop(c, l, k) for c in L1])
        c2 = np.array([_localop(c, l+1, k) for c in L2])
        c2dag = np.array([c.dag() for c in c2])
        Hcasc = -0.5j*np.dot(c2dag, np.dot(S, c1))
        Hcasc += Hcasc.dag()
        Lvec = c2 + np.dot(S, c1)
        L += qt.liouvillian(Hcasc, [c for c in Lvec])
    # last system
    L += qt.liouvillian(_localop(H, k, k), [_localop(c, k, k) for c in L1])
    if c_ops_markov is not None:
        for c in c_ops_markov:
            cl = _localop(c, k, k)
            L += qt.liouvillian(None, [cl])
    E0.dims = L.dims
    # return generator and identity superop E0
    return L, E0
Example #30
0
def _generator(k, H, L1, L2, S=None, c_ops_markov=None):
    """
    Create a Liouvillian for a cascaded chain of k system copies
    """
    id = qt.qeye(H.dims[0][0])
    Id = qt.sprepost(id, id)
    if S is None:
        S = np.identity(len(L1))
    # create Lindbladian
    L = qt.Qobj()
    E0 = Id
    # first system
    L += qt.liouvillian(None, [_localop(c, 1, k) for c in L2])
    for l in range(1, k):
        # Identiy superoperator
        E0 = qt.composite(E0, Id)
        # Bare Hamiltonian
        Hl = _localop(H, l, k)
        L += qt.liouvillian(Hl, [])
        # Markovian Decay channels
        if c_ops_markov is not None:
            for c in c_ops_markov:
                cl = _localop(c, l, k)
                L += qt.liouvillian(None, [cl])
        # Cascade coupling
        c1 = np.array([_localop(c, l, k) for c in L1])
        c2 = np.array([_localop(c, l+1, k) for c in L2])
        c2dag = np.array([c.dag() for c in c2])
        Hcasc = -0.5j*np.dot(c2dag, np.dot(S, c1))
        Hcasc += Hcasc.dag()
        Lvec = c2 + np.dot(S, c1)
        L += qt.liouvillian(Hcasc, [c for c in Lvec])
    # last system
    L += qt.liouvillian(_localop(H, k, k), [_localop(c, k, k) for c in L1])
    if c_ops_markov is not None:
        for c in c_ops_markov:
            cl = _localop(c, k, k)
            L += qt.liouvillian(None, [cl])
    E0.dims = L.dims
    # return generator and identity superop E0
    return L, E0
Example #31
0
    def jc_integrate(self, N, wc, wa, g, kappa, gamma, pump, psi0, use_rwa,
                     tlist):
        # Hamiltonian
        a = tensor(destroy(N), identity(2))
        sm = tensor(identity(N), destroy(2))

        # Identity super-operator
        E0 = sprepost(tensor(qeye(N), qeye(2)), tensor(qeye(N), qeye(2)))

        if use_rwa:
            # use the rotating wave approxiation
            H = wc * a.dag() * a + wa * sm.dag() * sm + g * (a.dag() * sm +
                                                             a * sm.dag())
        else:
            H = wc * a.dag() * a + wa * sm.dag() * sm + g * (a.dag() + a) * (
                sm + sm.dag())

        # collapse operators
        c_op_list = []

        n_th_a = 0.0  # zero temperature

        rate = kappa * (1 + n_th_a)
        c_op_list.append(np.sqrt(rate) * a)

        rate = kappa * n_th_a
        if rate > 0.0:
            c_op_list.append(np.sqrt(rate) * a.dag())

        rate = gamma
        if rate > 0.0:
            c_op_list.append(np.sqrt(rate) * sm)

        rate = pump
        if rate > 0.0:
            c_op_list.append(np.sqrt(rate) * sm.dag())

        # evolve and calculate expectation values
        output1 = mesolve(H, psi0, tlist, c_op_list, [])
        output2 = mesolve(H, E0, tlist, c_op_list, [])
        return output1, output2
Example #32
0
    def testMETDDecayAsFuncList(self):
        "mesolve: time-dependence as function list with super as init cond"
        me_error = 1e-6

        N = 10  # number of basis states to consider
        a = destroy(N)
        H = a.dag() * a
        psi0 = basis(N, 9)  # initial state
        rho0vec = operator_to_vector(psi0 * psi0.dag())
        E0 = sprepost(qeye(N), qeye(N))
        kappa = 0.2  # coupling to oscillator

        def sqrt_kappa(t, args):
            return np.sqrt(kappa * np.exp(-t))

        c_op_list = [[a, sqrt_kappa]]
        tlist = np.linspace(0, 10, 100)
        out1 = mesolve(H, psi0, tlist, c_op_list, [])
        out2 = mesolve(H, E0, tlist, c_op_list, [])

        fid = self.fidelitycheck(out1, out2, rho0vec)
        assert_(max(abs(1.0 - fid)) < me_error, True)
Example #33
0
    def testMETDDecayAsFuncList(self):
        "mesolve: time-dependence as function list with super as init cond"
        me_error = 1e-6

        N = 10  # number of basis states to consider
        a = destroy(N)
        H = a.dag() * a
        psi0 = basis(N, 9)  # initial state
        rho0vec = operator_to_vector(psi0 * psi0.dag())
        E0 = sprepost(qeye(N), qeye(N))
        kappa = 0.2  # coupling to oscillator

        def sqrt_kappa(t, args):
            return np.sqrt(kappa * np.exp(-t))

        c_op_list = [[a, sqrt_kappa]]
        tlist = np.linspace(0, 10, 100)
        out1 = mesolve(H, psi0, tlist, c_op_list, [])
        out2 = mesolve(H, E0, tlist, c_op_list, [])

        fid = self.fidelitycheck(out1, out2, rho0vec)
        assert_(max(abs(1.0 - fid)) < me_error, True)
Example #34
0
    def jc_integrate(self, N, wc, wa, g, kappa, gamma, pump, psi0, use_rwa, tlist):
        # Hamiltonian
        a = tensor(destroy(N), identity(2))
        sm = tensor(identity(N), destroy(2))

        # Identity super-operator
        E0 = sprepost(tensor(qeye(N), qeye(2)), tensor(qeye(N), qeye(2)))

        if use_rwa:
            # use the rotating wave approxiation
            H = wc * a.dag() * a + wa * sm.dag() * sm + g * (a.dag() * sm + a * sm.dag())
        else:
            H = wc * a.dag() * a + wa * sm.dag() * sm + g * (a.dag() + a) * (sm + sm.dag())

        # collapse operators
        c_op_list = []

        n_th_a = 0.0  # zero temperature

        rate = kappa * (1 + n_th_a)
        c_op_list.append(np.sqrt(rate) * a)

        rate = kappa * n_th_a
        if rate > 0.0:
            c_op_list.append(np.sqrt(rate) * a.dag())

        rate = gamma
        if rate > 0.0:
            c_op_list.append(np.sqrt(rate) * sm)

        rate = pump
        if rate > 0.0:
            c_op_list.append(np.sqrt(rate) * sm.dag())

        # evolve and calculate expectation values
        output1 = mesolve(H, psi0, tlist, c_op_list, [])
        output2 = mesolve(H, E0, tlist, c_op_list, [])
        return output1, output2
Example #35
0
    def testMETDDecayAsFunc(self):
        "mesolve: time-dependence as function with super as init cond"

        N = 10  # number of basis states to consider
        a = destroy(N)
        H = a.dag() * a
        rho0 = ket2dm(basis(N, 9))  # initial state
        rho0vec = operator_to_vector(rho0)
        E0 = sprepost(qeye(N), qeye(N))
        kappa = 0.2  # coupling to oscillator

        def Liouvillian_func(t, args):
            c = np.sqrt(kappa * np.exp(-t)) * a
            data = liouvillian(H, [c]).data
            return data

        tlist = np.linspace(0, 10, 100)
        args = {'kappa': kappa}
        out1 = mesolve(Liouvillian_func, rho0, tlist, [], [], args=args)
        out2 = mesolve(Liouvillian_func, E0, tlist, [], [], args=args)

        fid = self.fidelitycheck(out1, out2, rho0vec)
        assert_(max(abs(1.0 - fid)) < me_error, True)
Example #36
0
    def testMETDDecayAsFunc(self):
        "mesolve: time-dependence as function with super as init cond"

        N = 10  # number of basis states to consider
        a = destroy(N)
        H = a.dag() * a
        rho0 = ket2dm(basis(N, 9))  # initial state
        rho0vec = operator_to_vector(rho0)
        E0 = sprepost(qeye(N), qeye(N))
        kappa = 0.2  # coupling to oscillator

        def Liouvillian_func(t, args):
            c = np.sqrt(kappa * np.exp(-t)) * a
            data = liouvillian(H, [c]).data
            return data

        tlist = np.linspace(0, 10, 100)
        args = {"kappa": kappa}
        out1 = mesolve(Liouvillian_func, rho0, tlist, [], [], args=args)
        out2 = mesolve(Liouvillian_func, E0, tlist, [], [], args=args)

        fid = self.fidelitycheck(out1, out2, rho0vec)
        assert_(max(abs(1.0 - fid)) < me_error, True)
Example #37
0
 def decoder(self, kraus=False):
     S = self.encoder(kraus=True)
     if kraus:
         return S.dag()
     else:
         return qt.sprepost(S.dag(), S)
Example #38
0
def rcsolve(Hsys,
            psi0,
            tlist,
            e_ops,
            Q,
            wc,
            alpha,
            N,
            w_th,
            sparse=False,
            options=None):
    """
    Function to solve for an open quantum system using the
    reaction coordinate (RC) model.

    Parameters
    ----------
    Hsys: Qobj
        The system hamiltonian.
    psi0: Qobj
        Initial state of the system.
    tlist: List.
        Time over which system evolves.
    e_ops: list of :class:`qutip.Qobj` / callback function single
        Single operator or list of operators for which to evaluate
        expectation values.
    Q: Qobj
        The coupling between system and bath.
    wc: Float
        Cutoff frequency.
    alpha: Float
        Coupling strength.
    N: Integer
        Number of cavity fock states.
    w_th: Float
        Temperature.
    sparse: Boolean
        Optional argument to call the sparse eigenstates solver if needed.
    options : :class:`qutip.Options`
        With options for the solver.

    Returns
    -------
    output: Result
        System evolution.
    """
    if options is None:
        options = Options()

    dot_energy, dot_state = Hsys.eigenstates(sparse=sparse)
    deltaE = dot_energy[1] - dot_energy[0]
    if (w_th < deltaE / 2):
        warnings.warn("Given w_th might not provide accurate results")
    gamma = deltaE / (2 * np.pi * wc)
    wa = 2 * np.pi * gamma * wc  # reaction coordinate frequency
    g = np.sqrt(np.pi * wa * alpha / 2.0)  # reaction coordinate coupling
    nb = (1 / (np.exp(wa / w_th) - 1))

    # Reaction coordinate hamiltonian/operators

    dimensions = dims(Q)
    a = tensor(destroy(N), qeye(dimensions[1]))
    unit = tensor(qeye(N), qeye(dimensions[1]))
    Nmax = N * dimensions[1][0]
    Q_exp = tensor(qeye(N), Q)
    Hsys_exp = tensor(qeye(N), Hsys)
    e_ops_exp = [tensor(qeye(N), kk) for kk in e_ops]

    na = a.dag() * a
    xa = a.dag() + a

    # decoupled Hamiltonian
    H0 = wa * a.dag() * a + Hsys_exp
    # interaction
    H1 = (g * (a.dag() + a) * Q_exp)
    H = H0 + H1
    L = 0
    PsipreEta = 0
    PsipreX = 0

    all_energy, all_state = H.eigenstates(sparse=sparse)
    Apre = spre((a + a.dag()))
    Apost = spost(a + a.dag())
    for j in range(Nmax):
        for k in range(Nmax):
            A = xa.matrix_element(all_state[j].dag(), all_state[k])
            delE = (all_energy[j] - all_energy[k])
            if abs(A) > 0.0:
                if abs(delE) > 0.0:
                    X = (0.5 * np.pi * gamma *
                         (all_energy[j] - all_energy[k]) * (np.cosh(
                             (all_energy[j] - all_energy[k]) /
                             (2 * w_th)) / (np.sinh(
                                 (all_energy[j] - all_energy[k]) /
                                 (2 * w_th)))) * A)
                    eta = (0.5 * np.pi * gamma *
                           (all_energy[j] - all_energy[k]) * A)
                    PsipreX = PsipreX + X * all_state[j] * all_state[k].dag()
                    PsipreEta = PsipreEta + (eta * all_state[j] *
                                             all_state[k].dag())
                else:
                    X = 0.5 * np.pi * gamma * A * 2 * w_th
                    PsipreX = PsipreX + X * all_state[j] * all_state[k].dag()

    A = a + a.dag()
    L = ((-spre(A * PsipreX)) + (sprepost(A, PsipreX)) +
         (sprepost(PsipreX, A)) + (-spost(PsipreX * A)) +
         (spre(A * PsipreEta)) + (sprepost(A, PsipreEta)) +
         (-sprepost(PsipreEta, A)) + (-spost(PsipreEta * A)))

    # Setup the operators and the Hamiltonian and the master equation
    # and solve for time steps in tlist
    rho0 = (tensor(thermal_dm(N, nb), psi0))
    output = mesolve(H, rho0, tlist, [L], e_ops_exp, options=options)

    return output
Example #39
0
def secular_term(state_j, state_k):
    jk = state_j*state_k.dag()
    kj = jk.dag()
    jj = state_j*state_j.dag()
    return 2*sprepost(kj, jk) - (spre(jj) + spost(jj))
Example #40
0
def commutator_term2(O1, O2):
    # [rho*O1, O2]
    return spost(O1*O2)-sprepost(O2, O1)
Example #41
0
def rcsolve(Hsys, psi0, tlist, e_ops, Q, wc, alpha, N, w_th, sparse=False,
            options=None):
    """
    Function to solve for an open quantum system using the
    reaction coordinate (RC) model.

    Parameters
    ----------
    Hsys: Qobj
        The system hamiltonian.
    psi0: Qobj
        Initial state of the system.
    tlist: List.
        Time over which system evolves.
    e_ops: list of :class:`qutip.Qobj` / callback function single
        Single operator or list of operators for which to evaluate
        expectation values.
    Q: Qobj
        The coupling between system and bath.
    wc: Float
        Cutoff frequency.
    alpha: Float
        Coupling strength.
    N: Integer
        Number of cavity fock states.
    w_th: Float
        Temperature.
    sparse: Boolean
        Optional argument to call the sparse eigenstates solver if needed.
    options : :class:`qutip.Options`
        With options for the solver.

    Returns
    -------
    output: Result
        System evolution.
    """
    if options is None:
        options = Options()

    dot_energy, dot_state = Hsys.eigenstates(sparse=sparse)
    deltaE = dot_energy[1] - dot_energy[0]
    if (w_th < deltaE/2):
        warnings.warn("Given w_th might not provide accurate results")
    gamma = deltaE / (2 * np.pi * wc)
    wa = 2 * np.pi * gamma * wc  # reaction coordinate frequency
    g = np.sqrt(np.pi * wa * alpha / 2.0)  # reaction coordinate coupling
    nb = (1 / (np.exp(wa/w_th) - 1))

    # Reaction coordinate hamiltonian/operators

    dimensions = dims(Q)
    a = tensor(destroy(N), qeye(dimensions[1]))
    unit = tensor(qeye(N), qeye(dimensions[1]))
    Nmax = N * dimensions[1][0]
    Q_exp = tensor(qeye(N), Q)
    Hsys_exp = tensor(qeye(N), Hsys)
    e_ops_exp = [tensor(qeye(N), kk) for kk in e_ops]

    na = a.dag() * a
    xa = a.dag() + a

    # decoupled Hamiltonian
    H0 = wa * a.dag() * a + Hsys_exp
    # interaction
    H1 = (g * (a.dag() + a) * Q_exp)
    H = H0 + H1
    L = 0
    PsipreEta = 0
    PsipreX = 0

    all_energy, all_state = H.eigenstates(sparse=sparse)
    Apre = spre((a + a.dag()))
    Apost = spost(a + a.dag())
    for j in range(Nmax):
        for k in range(Nmax):
            A = xa.matrix_element(all_state[j].dag(), all_state[k])
            delE = (all_energy[j] - all_energy[k])
            if abs(A) > 0.0:
                if abs(delE) > 0.0:
                    X = (0.5 * np.pi * gamma*(all_energy[j] - all_energy[k])
                         * (np.cosh((all_energy[j] - all_energy[k]) /
                            (2 * w_th))
                         / (np.sinh((all_energy[j] - all_energy[k]) /
                            (2 * w_th)))) * A)
                    eta = (0.5 * np.pi * gamma *
                           (all_energy[j] - all_energy[k]) * A)
                    PsipreX = PsipreX + X * all_state[j] * all_state[k].dag()
                    PsipreEta = PsipreEta + (eta * all_state[j]
                                             * all_state[k].dag())
                else:
                    X = 0.5 * np.pi * gamma * A * 2 * w_th
                    PsipreX = PsipreX + X * all_state[j] * all_state[k].dag()

    A = a + a.dag()
    L = ((-spre(A * PsipreX)) + (sprepost(A, PsipreX))
         + (sprepost(PsipreX, A)) + (-spost(PsipreX * A))
         + (spre(A * PsipreEta)) + (sprepost(A, PsipreEta))
         + (-sprepost(PsipreEta, A)) + (-spost(PsipreEta * A)))

    # Setup the operators and the Hamiltonian and the master equation
    # and solve for time steps in tlist
    rho0 = (tensor(thermal_dm(N, nb), psi0))
    output = mesolve(H, rho0, tlist, [L], e_ops_exp, options=options)

    return output