def rhot(self, rho0, t, tau): """ Compute the reduced system density matrix :math:`\\rho(t)` Parameters ---------- rho0 : :class:`qutip.Qobj` initial density matrix or state vector (ket) t : float current time tau : float time-delay Returns ------- : :class:`qutip.Qobj` density matrix at time :math:`t` """ if qt.isket(rho0): rho0 = qt.ket2dm(rho0) E = self.propagator(t, tau) rhovec = qt.operator_to_vector(rho0) return qt.vector_to_operator(E*rhovec)
def testOperatorVectorNotSquare(self): """ Superoperator: Operator - vector - operator conversion for non-square matrix. """ op1 = Qobj(np.random.rand(6).reshape((3, 2))) op2 = vector_to_operator(operator_to_vector(op1)) assert_((op1 - op2).norm() < 1e-8)
def testOperatorVector(self): """ Superoperator: Operator - vector - operator conversion. """ N = 3 rho1 = rand_dm(N) rho2 = vector_to_operator(operator_to_vector(rho1)) assert_((rho1 - rho2).norm() < 1e-8)
def testOperatorVectorTensor(self): """ Superoperator: Operator - vector - operator conversion with a tensor product state. """ Na = 3 Nb = 2 rhoa = rand_dm(Na) rhob = rand_dm(Nb) rho1 = tensor(rhoa, rhob) rho2 = vector_to_operator(operator_to_vector(rho1)) assert_((rho1 - rho2).norm() < 1e-8)
def testOperatorUnitaryTransform(self): """ Superoperator: Unitary transformation with operators and superoperators """ N = 3 rho = rand_dm(N) U = rand_unitary(N) rho1 = U * rho * U.dag() rho2_vec = spre(U) * spost(U.dag()) * operator_to_vector(rho) rho2 = vector_to_operator(rho2_vec) assert_((rho1 - rho2).norm() < 1e-8)
def testOperatorSpostAppl(self): """ Superoperator: apply operator and superoperator from right (spost) """ N = 3 rho = rand_dm(N) U = rand_unitary(N) rho1 = rho * U rho2_vec = spost(U) * operator_to_vector(rho) rho2 = vector_to_operator(rho2_vec) assert_((rho1 - rho2).norm() < 1e-8)
def testOperatorSpreAppl(self): """ Superoperator: apply operator and superoperator from left (spre) """ N = 3 rho = rand_dm(N) U = rand_unitary(N) rho1 = U * rho rho2_vec = spre(U) * operator_to_vector(rho) rho2 = vector_to_operator(rho2_vec) assert_((rho1 - rho2).norm() < 1e-8)
def _target_outputs_from_inputs_open_map(self, input_states): raise NotImplementedError('Not implemented yet') # Note that in case of an open map target, all target states are # density matrices, instead of just kets like they would when the # target is a unitary gate. target_states = [] for psi in input_states: # the open evolution is implemented vectorizing density # matrices and maps: `A * rho * B` becomes # `unvec(vec(tensor(A, B.T)) * vec(rho))`. vec_dm_ket = qutip.operator_to_vector(qutip.ket2dm(psi)) evolved_ket = self.target_gate * vec_dm_ket evolved_ket = qutip.vector_to_operator(evolved_ket) target_states.append(evolved_ket) return target_states
def prune_eigenstates(self, liouvillian): """Remove spurious eigenvalues and eigenvectors of the Liouvillian. Spurious means that the given eigenvector has elements outside of the block-diagonal matrix. Parameters ---------- liouvillian_eigenstates: list A list with the eigenvalues and eigenvectors of the Liouvillian including spurious ones. Returns ------- correct_eigenstates: list The list with the correct eigenvalues and eigenvectors of the Liouvillian. """ liouvillian_eigenstates = liouvillian.eigenstates() N = self.N block_mat = block_matrix(N) nnz_tuple_bm = [(i, j) for i, j in zip(*block_mat.nonzero())] # 0. Create a copy of the eigenvalues to approximate values eig_val, eig_vec = liouvillian_eigenstates tol = 10 eig_val_round = np.round(eig_val, tol) # 2. Use 'block_matrix(N)' to remove eigenvectors with matrix # elements # outside of the block matrix. forbidden_eig_index = [] for k in range(0, len(eig_vec)): dm = vector_to_operator(eig_vec[k]) nnz_tuple = [(i, j) for i, j in zip(*dm.data.nonzero())] for i in nnz_tuple: if i not in nnz_tuple_bm: if np.round(dm[i], tol) != 0: forbidden_eig_index.append(k) forbidden_eig_index = np.array(list(set(forbidden_eig_index))) # 3. Remove the forbidden eigenvalues and eigenvectors. correct_eig_val = np.delete(eig_val, forbidden_eig_index) correct_eig_vec = np.delete(eig_vec, forbidden_eig_index) correct_eigenstates = correct_eig_val, correct_eig_vec return correct_eigenstates
def outfieldcorr(self, rho0, blist, tlist, tau, c1=None, c2=None): r""" Compute output field expectation value <O_n(tn)...O_2(t2)O_1(t1)> for times t1,t2,... and O_i = I, b_out, b_out^\dagger, b_loop, b_loop^\dagger Parameters ---------- rho0 : :class:`qutip.Qobj` initial density matrix or state vector (ket). blist : array_like List of integers specifying the field operators: 0: I (nothing) 1: b_out 2: b_out^\dagger 3: b_loop 4: b_loop^\dagger tlist : array_like list of corresponding times t1,..,tn at which to evaluate the field operators tau : float time-delay c1 : :class:`qutip.Qobj` system collapse operator that couples to the in-loop field in question (only needs to be specified if self.L1 has more than one element) c2 : :class:`qutip.Qobj` system collapse operator that couples to the output field in question (only needs to be specified if self.L2 has more than one element) Returns ------- : complex expectation value of field correlation function """ E = self.outfieldpropagator(blist, tlist, tau) rhovec = qt.operator_to_vector(rho0) return (qt.vector_to_operator(E*rhovec)).tr()
def outfieldcorr(self, rho0, blist, tlist, tau, c1=None, c2=None): """ Compute output field expectation value <O_n(tn)...O_2(t2)O_1(t1)> for times t1,t2,... and O_i = I, b_out, b_out^\dagger, b_loop, b_loop^\dagger Parameters ---------- rho0 : :class:`qutip.Qobj` initial density matrix or state vector (ket). blist : array_like List of integers specifying the field operators: 0: I (nothing) 1: b_out 2: b_out^\dagger 3: b_loop 4: b_loop^\dagger tlist : array_like list of corresponding times t1,..,tn at which to evaluate the field operators tau : float time-delay c1 : :class:`qutip.Qobj` system collapse operator that couples to the in-loop field in question (only needs to be specified if self.L1 has more than one element) c2 : :class:`qutip.Qobj` system collapse operator that couples to the output field in question (only needs to be specified if self.L2 has more than one element) Returns ------- : complex expectation value of field correlation function """ E = self.outfieldpropagator(blist, tlist, tau) rhovec = qt.operator_to_vector(rho0) return (qt.vector_to_operator(E*rhovec)).tr()
def rhot(rho0,t,tau,H_S,L1,L2,Id,options=qt.Options()): """ Compute rho(t) """ k= int(t/tau)+1 s = t-(k-1)*tau rhovec = qt.operator_to_vector(rho0) G1,E0 = generator(k,H_S,L1,L2) E = integrate(G1,E0,0.,s,opt=options) if k>1: G2,null = generator(k-1,H_S,L1,L2) G2 = qt.composite(Id,G2) E = integrate(G2,E,s,tau,opt=options) E.dims = E0.dims E = TensorQobj(E) for l in range(k-1): E = E.loop() sol = qt.vector_to_operator(E*rhovec) return sol
def test_operator_vector_td(self): "Superoperator: operator_to_vector, time-dependent" assert_(operator_to_vector(self.t1)(.5) == operator_to_vector(self.t1(.5))) vec = operator_to_vector(self.t1) assert_(vector_to_operator(vec)(.5) == vector_to_operator(vec(.5)))
def fidelitycheck(self, out1, out2, rho0vec): fid = np.zeros(len(out1.states)) for i, E in enumerate(out2.states): rhot = vector_to_operator(E * rho0vec) fid[i] = fidelity(out1.states[i], rhot) return fid
def ttmsolve(dynmaps, rho0, times, e_ops=[], learningtimes=None, tensors=None, **kwargs): """ Solve time-evolution using the Transfer Tensor Method, based on a set of precomputed dynamical maps. Parameters ---------- dynmaps : list of :class:`qutip.Qobj` List of precomputed dynamical maps (superoperators), or a callback function that returns the superoperator at a given time. rho0 : :class:`qutip.Qobj` Initial density matrix or state vector (ket). times : array_like list of times :math:`t_n` at which to compute :math:`\\rho(t_n)`. Must be uniformily spaced. e_ops : list of :class:`qutip.Qobj` / callback function single operator or list of operators for which to evaluate expectation values. learningtimes : array_like list of times :math:`t_k` for which we have knowledge of the dynamical maps :math:`E(t_k)`. tensors : array_like optional list of precomputed tensors :math:`T_k` kwargs : dictionary Optional keyword arguments. See :class:`qutip.nonmarkov.ttm.TTMSolverOptions`. Returns ------- output: :class:`qutip.solver.Result` An instance of the class :class:`qutip.solver.Result`. """ opt = TTMSolverOptions(dynmaps=dynmaps, times=times, learningtimes=learningtimes, **kwargs) diff = None if isket(rho0): rho0 = ket2dm(rho0) output = Result() e_sops_data = [] if callable(e_ops): n_expt_op = 0 expt_callback = True else: try: tmp = e_ops[:] del tmp n_expt_op = len(e_ops) expt_callback = False if n_expt_op == 0: # fall back on storing states opt.store_states = True for op in e_ops: e_sops_data.append(spre(op).data) if op.isherm and rho0.isherm: output.expect.append(np.zeros(len(times))) else: output.expect.append(np.zeros(len(times), dtype=complex)) except TypeError: raise TypeError("Argument 'e_ops' should be a callable or" + "list-like.") if tensors is None: tensors, diff = _generatetensors(dynmaps, learningtimes, opt=opt) rho0vec = operator_to_vector(rho0) K = len(tensors) states = [rho0vec] for n in range(1, len(times)): states.append(None) for k in range(n): if n-k < K: states[-1] += tensors[n-k]*states[k] for i, r in enumerate(states): if opt.store_states or expt_callback: if r.type == 'operator-ket': states[i] = vector_to_operator(r) else: states[i] = r if expt_callback: # use callback method e_ops(times[i], states[i]) for m in range(n_expt_op): if output.expect[m].dtype == complex: output.expect[m][i] = expect_rho_vec(e_sops_data[m], r, 0) else: output.expect[m][i] = expect_rho_vec(e_sops_data[m], r, 1) output.solver = "ttmsolve" output.times = times output.ttmconvergence = diff if opt.store_states: output.states = states return output
def ttmsolve(dynmaps, rho0, times, e_ops=[], learningtimes=None, tensors=None, **kwargs): """ Solve time-evolution using the Transfer Tensor Method, based on a set of precomputed dynamical maps. Parameters ---------- dynmaps : list of :class:`qutip.Qobj` List of precomputed dynamical maps (superoperators), or a callback function that returns the superoperator at a given time. rho0 : :class:`qutip.Qobj` Initial density matrix or state vector (ket). times : array_like list of times :math:`t_n` at which to compute :math:`\\rho(t_n)`. Must be uniformily spaced. e_ops : list of :class:`qutip.Qobj` / callback function single operator or list of operators for which to evaluate expectation values. learningtimes : array_like list of times :math:`t_k` for which we have knowledge of the dynamical maps :math:`E(t_k)`. tensors : array_like optional list of precomputed tensors :math:`T_k` kwargs : dictionary Optional keyword arguments. See :class:`qutip.nonmarkov.ttm.TTMSolverOptions`. Returns ------- output: :class:`qutip.solver.Result` An instance of the class :class:`qutip.solver.Result`. """ opt = TTMSolverOptions(dynmaps=dynmaps, times=times, learningtimes=learningtimes, **kwargs) diff = None if isket(rho0): rho0 = ket2dm(rho0) output = Result() e_sops_data = [] if callable(e_ops): n_expt_op = 0 expt_callback = True else: try: tmp = e_ops[:] del tmp n_expt_op = len(e_ops) expt_callback = False if n_expt_op == 0: # fall back on storing states opt.store_states = True for op in e_ops: e_sops_data.append(spre(op).data) if op.isherm and rho0.isherm: output.expect.append(np.zeros(len(times))) else: output.expect.append(np.zeros(len(times), dtype=complex)) except TypeError: raise TypeError("Argument 'e_ops' should be a callable or" + "list-like.") if tensors is None: tensors, diff = _generatetensors(dynmaps, learningtimes, opt=opt) if rho0.isoper: # vectorize density matrix rho0vec = operator_to_vector(rho0) else: # rho0 might be a super in which case we should not vectorize rho0vec = rho0 K = len(tensors) states = [rho0vec] for n in range(1, len(times)): states.append(None) for k in range(n): if n-k < K: states[-1] += tensors[n-k]*states[k] for i, r in enumerate(states): if opt.store_states or expt_callback: if r.type == 'operator-ket': states[i] = vector_to_operator(r) else: states[i] = r if expt_callback: # use callback method e_ops(times[i], states[i]) for m in range(n_expt_op): if output.expect[m].dtype == complex: output.expect[m][i] = expect_rho_vec(e_sops_data[m], r, 0) else: output.expect[m][i] = expect_rho_vec(e_sops_data[m], r, 1) output.solver = "ttmsolve" output.times = times output.ttmconvergence = diff if opt.store_states: output.states = states return output
def current_from_L(L_dict, n_c_RC): ss = steadystate(L_dict['H_S'], [L_dict['L']]) return -(qt.vector_to_operator(L_dict['L_R'] * qt.operator_to_vector(ss)) * n_c_RC).tr()
def current_from_ss(ss, L_R, n_c_RC): return -(qt.vector_to_operator(L_R * qt.operator_to_vector(ss)) * n_c_RC).tr()
def test_operator_vector_td(self): "Superoperator: operator_to_vector, time-dependent" assert_( operator_to_vector(self.t1)(.5) == operator_to_vector(self.t1(.5))) vec = operator_to_vector(self.t1) assert_(vector_to_operator(vec)(.5) == vector_to_operator(vec(.5)))