def TestRandomNoise(self): """ Test for the white noise """ tlist = np.array([1, 2, 3, 4, 5, 6]) coeff = np.array([1, 1, 1, 1, 1, 1]) dummy_qobjevo = QobjEvo(sigmaz(), tlist=tlist) mean = 0. std = 0.5 ops = [sigmaz(), sigmax()] proc_qobjevo = QobjEvo( [[sigmaz(), coeff], [sigmax(), coeff], [sigmay(), coeff]], tlist=tlist) # random noise with external operators gaussnoise = RandomNoise(ops=ops, loc=mean, scale=std) noise = gaussnoise.get_noise(N=1, proc_qobjevo=dummy_qobjevo) assert_allclose(noise.ops[1].qobj, sigmax()) assert_allclose(len(noise.ops[1].coeff), len(tlist)) assert_allclose(len(noise.ops), len(ops)) # random noise with operators from proc_qobjevo gaussnoise = RandomNoise(loc=mean, scale=std) noise = gaussnoise.get_noise(N=1, proc_qobjevo=proc_qobjevo) assert_allclose(noise.ops[1].qobj, sigmax()) assert_(len(noise.ops[0].coeff) == len(tlist)) assert_(len(noise.ops) == len(proc_qobjevo.ops)) # random noise with dt and other random number generator gaussnoise = RandomNoise(lam=0.1, dt=0.2, rand_gen=np.random.poisson) assert_(gaussnoise.rand_gen is np.random.poisson) noise = gaussnoise.get_noise(N=1, proc_qobjevo=proc_qobjevo) assert_allclose(noise.tlist, np.linspace(1, 6, int(5 / 0.2) + 1))
def _get_qobjevo_helper(self, spline_kind, dims): """ Please refer to `_Evoelement.get_qobjevo` for documentation. """ mat = self.get_qobj(dims) if self.tlist is None and self.coeff is None: qu = QobjEvo(mat) * 0. elif isinstance(self.coeff, bool): if self.coeff: if self.tlist is None: qu = QobjEvo(mat, tlist=self.tlist) else: qu = QobjEvo([mat, np.ones(len(self.tlist))], tlist=self.tlist) else: qu = QobjEvo(mat * 0., tlist=self.tlist) else: if spline_kind == "step_func": args = {"_step_func_coeff": True} if len(self.coeff) == len(self.tlist) - 1: self.coeff = np.concatenate([self.coeff, [0.]]) elif spline_kind == "cubic": args = {"_step_func_coeff": False} else: # The spline will follow other pulses or # use the default value of QobjEvo args = {} qu = QobjEvo([mat, self.coeff], tlist=self.tlist, args=args) return qu
def _mesolve_QobjEvo(H, c_ops, tlist, args, opt): """ Prepare the system for the solver, H can be an QobjEvo. """ H_td = QobjEvo(H, args, tlist=tlist) if not issuper(H_td.cte): L_td = liouvillian(H_td) else: L_td = H_td for op in c_ops: op_td = QobjEvo(op, args, tlist=tlist) if not issuper(op_td.cte): op_td = lindblad_dissipator(op_td) L_td += op_td if opt.rhs_with_state: L_td._check_old_with_state() nthread = opt.openmp_threads if opt.use_openmp else 0 L_td.compile(omp=nthread) ss = SolverSystem() ss.H = L_td ss.makefunc = _qobjevo_set solver_safe["mesolve"] = ss return ss
def __init__(self, e_ops=[], super_=False): # take care of expectation values, if any self.isfunc = False self.e_ops_dict = False self.raw_e_ops = e_ops self.e_ops_qoevo = [] self.e_num = 0 self.e_ops_isherm = [] if isinstance(e_ops, (Qobj, QobjEvo)): e_ops = [e_ops] elif isinstance(e_ops, dict): self.e_ops_dict = e_ops e_ops = [e for e in e_ops.values()] self.e_ops = e_ops if isinstance(e_ops, list): self.e_num = len(e_ops) self.e_ops_isherm = [e.isherm for e in e_ops] if not super_: self.e_ops_qoevo = np.array([QobjEvo(e) for e in e_ops], dtype=object) else: self.e_ops_qoevo = np.array([QobjEvo(spre(e)) for e in e_ops], dtype=object) [op.compile() for op in self.e_ops_qoevo] elif callable(e_ops): self.isfunc = True self.e_num = 1
def _compatible_coeff(self, qobjevo_list): """ Combine a list of `:class:qutip.QobjEvo` into one, different tlist will be merged. """ # TODO This method can be eventually integrated into QobjEvo, for # which a more through test is required # no qobjevo if not qobjevo_list: return _dummy_qobjevo(self.dims) all_tlists = [qu.tlist for qu in qobjevo_list if qu.tlist is not None] # all tlists are None if not all_tlists: return sum(qobjevo_list, _dummy_qobjevo(self.dims)) new_tlist = np.unique(np.sort(np.hstack(all_tlists))) for i, qobjevo in enumerate(qobjevo_list): H_list = qobjevo.to_list() for j, H in enumerate(H_list): # cte part or not array_like coeffs if isinstance(H, Qobj) or (not isinstance(H[1], np.ndarray)): continue op, coeffs = H new_coeff = _fill_coeff( coeffs, qobjevo.tlist, new_tlist, self.spline_kind) H_list[j] = [op, new_coeff] # create a new qobjevo with the old arguments qobjevo_list[i] = QobjEvo( H_list, tlist=new_tlist, args=qobjevo.args) qobjevo = sum(qobjevo_list, _dummy_qobjevo(self.dims)) qobjevo = _merge_id_evo(qobjevo) return qobjevo
def get_noise(self, N, proc_qobjevo=None, dims=None): """ Return the quantum objects representing the noise. Parameters ---------- N: int The number of component systems. proc_qobjevo: :class:`qutip.QobjEvo`, optional If no operator is defined in the noise object, `proc_qobjevo` will be used as operators, otherwise the operators in the object is used. dims: list, optional The dimension of the components system, the default value is [2,2...,2] for qubits system. Returns ------- noise_qobjevo: :class:`qutip.QobjEvo` A :class:`qutip.Qobj` representing the noise. """ if dims is None: dims = [2] * N # If new operators are given if self.ops is not None: if self.cyclic_permutation: ops = [] for op in self.ops: ops += expand_operator(oper=op, N=N, targets=self.targets, dims=dims, cyclic_permutation=True) else: ops = [ expand_operator(oper=op, N=N, targets=self.targets, dims=dims) for op in self.ops ] # If no operators given, use operators in the processor elif proc_qobjevo is not None: # If there is a constant part if proc_qobjevo.cte.norm() > 1.e-15: ops = [proc_qobjevo.cte] else: ops = [] ops += [ele.qobj for ele in proc_qobjevo.ops] else: raise ValueError("No operators found.") if len(ops) > len(self.coeffs): raise ValueError("The number of coefficient has to be larger than" "{}".format(len(ops))) return QobjEvo([[ops[i], self.coeffs[i]] for i in range(len(ops))], tlist=self.tlist)
def _dummy_qobjevo(dims, **kwargs): """ Create a dummy :class":`qutip.QobjEvo` with a constant zero Hamiltonian. This is used since empty QobjEvo is not yet supported. """ dummy = QobjEvo(tensor([identity(d) for d in dims]) * 0., **kwargs) return dummy
def make_diag_system(self, H, c_ops): ss = SolverSystem() ss.td_c_ops = [] ss.td_n_ops = [] H_ = H.copy() H_ *= -1j for c in c_ops: H_ += -0.5 * c.dag() * c w, v = np.linalg.eig(H_.full()) arg = np.argsort(np.abs(w)) eig = w[arg] U = v.T[arg].T Ud = U.T.conj() for c in c_ops: c_diag = Qobj(Ud @ c.full() @ U, dims=c.dims) cevo = QobjEvo(c_diag) cdc = cevo._cdc() cevo.compile() cdc.compile() ss.td_c_ops.append(cevo) ss.td_n_ops.append(cdc) ss.H_diag = eig ss.Ud = Ud ss.U = U ss.args = {} ss.type = "Diagonal" solver_safe["mcsolve"] = ss if self.e_ops and not self.e_ops.isfunc: e_ops = [ Qobj(Ud @ e.full() @ U, dims=e.dims) for e in self.e_ops.e_ops ] self.e_ops = ExpectOps(e_ops) self.ss = ss self.reset()
def _merge_qobjevo(qobjevo_list, full_tlist=None): """ Combine a list of `:class:qutip.QobjEvo` into one, different tlist will be merged. """ # TODO This method can be eventually integrated into QobjEvo, for # which a more thorough test is required # no qobjevo if not qobjevo_list: raise ValueError("qobjevo_list is empty.") if full_tlist is None: full_tlist = _find_common_tlist(qobjevo_list) spline_types_num = set() args = {} for qu in qobjevo_list: if isinstance(qu, QobjEvo): try: spline_types_num.add(qu.args["_step_func_coeff"]) except Exception: pass args.update(qu.args) if len(spline_types_num) > 1: raise ValueError("Cannot merge Qobjevo with different spline kinds.") for i, qobjevo in enumerate(qobjevo_list): if isinstance(qobjevo, Qobj): qobjevo_list[i] = QobjEvo(qobjevo) qobjevo = qobjevo_list[i] for j, ele in enumerate(qobjevo.ops): if isinstance(ele.coeff, np.ndarray): new_coeff = _fill_coeff(ele.coeff, qobjevo.tlist, full_tlist, args) qobjevo_list[i].ops[j].coeff = new_coeff qobjevo_list[i].tlist = full_tlist qobjevo = sum(qobjevo_list) return qobjevo
def TestControlAmpNoise(self): """ Test for the control amplitude noise """ tlist = np.array([1, 2, 3, 4, 5, 6]) coeff = np.array([1, 1, 1, 1, 1, 1]) # use external operators and no expansion dummy_qobjevo = QobjEvo(sigmaz(), tlist=tlist) connoise = ControlAmpNoise(ops=sigmax(), coeffs=[coeff], tlist=tlist) noise = connoise.get_noise(N=1, proc_qobjevo=dummy_qobjevo) assert_allclose(noise.ops[0].qobj, sigmax()) assert_allclose(noise.tlist, tlist) assert_allclose(noise.ops[0].coeff, coeff) dummy_qobjevo = QobjEvo(tensor([sigmaz(), sigmaz()]), tlist=tlist) connoise = ControlAmpNoise(ops=[sigmay()], coeffs=[coeff], tlist=tlist, targets=1) noise = connoise.get_noise(N=2, proc_qobjevo=dummy_qobjevo) assert_allclose(noise.ops[0].qobj, tensor([qeye(2), sigmay()])) # use external operators with expansion dummy_qobjevo = QobjEvo(sigmaz(), tlist=tlist) connoise = ControlAmpNoise(ops=sigmaz(), coeffs=[coeff] * 2, tlist=tlist, cyclic_permutation=True) noise = connoise.get_noise(N=2, proc_qobjevo=dummy_qobjevo) assert_allclose(noise.ops[0].qobj, tensor([sigmaz(), qeye(2)])) assert_allclose(noise.ops[1].qobj, tensor([qeye(2), sigmaz()])) # use proc_qobjevo proc_qobjevo = QobjEvo([[sigmaz(), coeff]], tlist=tlist) connoise = ControlAmpNoise(coeffs=[coeff], tlist=tlist) noise = connoise.get_noise(N=2, proc_qobjevo=proc_qobjevo) assert_allclose(noise.ops[0].qobj, sigmaz()) assert_allclose(noise.ops[0].coeff, coeff[0])
def _mesolve_QobjEvo(H, c_ops, tlist, args, opt): """ Prepare the system for the solver, H can be an QobjEvo. """ H_td = QobjEvo(H, args, tlist=tlist) if not issuper(H_td.cte): L_td = liouvillian(H_td) else: L_td = H_td for op in c_ops: # We want to avoid passing tlist where it isn't necessary, to allow a # Hamiltonian/Liouvillian which already _has_ time-dependence not equal # to the mesolve evaluation times to be used in conjunction with # time-independent c_ops. If we _always_ pass it, it may appear to # QobjEvo that there is a tlist mismatch, even though it is not used. if isinstance(op, Qobj): op_td = QobjEvo(op) elif isinstance(op, QobjEvo): op_td = QobjEvo(op, args) else: op_td = QobjEvo(op, args, tlist=tlist) if not issuper(op_td.cte): op_td = lindblad_dissipator(op_td) L_td += op_td if opt.rhs_with_state: L_td._check_old_with_state() nthread = opt.openmp_threads if opt.use_openmp else 0 L_td.compile(omp=nthread) ss = SolverSystem() ss.H = L_td ss.makefunc = _qobjevo_set solver_safe["mesolve"] = ss return ss
def _sesolve_QobjEvo(H, tlist, args, opt): """ Prepare the system for the solver, H can be an QobjEvo. """ H_td = -1.0j * QobjEvo(H, args, tlist=tlist) if opt.rhs_with_state: H_td._check_old_with_state() nthread = opt.openmp_threads if opt.use_openmp else 0 H_td.compile(omp=nthread) ss = SolverSystem() ss.H = H_td ss.makefunc = _qobjevo_set solver_safe["sesolve"] = ss return ss
def _convert_h_sys(self, H_sys): """ Process input system Hamiltonian, converting and raising as needed. """ if isinstance(H_sys, (Qobj, QobjEvo)): pass elif isinstance(H_sys, list): try: H_sys = QobjEvo(H_sys) except Exception as err: raise ValueError( "Hamiltonian (H_sys) of type list cannot be converted to" " QObjEvo") from err else: raise TypeError( f"Hamiltonian (H_sys) has unsupported type: {type(H_sys)!r}") return H_sys
def get_noise(self, N, dims=None): """ Return the quantum objects representing the noise. Parameters ---------- N: int The number of component systems. dims: list, optional The dimension of the components system, the default value is [2,2...,2] for qubits system. Returns ------- qobjevo_list: list A list of :class:`qutip.Qobj` or :class:`qutip.QobjEvo` representing the decoherence noise. """ if dims is None: dims = [2] * N qobj_list = [] for i, c_op in enumerate(self.c_ops): if self.all_qubits: qobj_list += expand_operator(oper=c_op, N=N, targets=self.targets, dims=dims, cyclic_permutation=True) else: qobj_list.append( expand_operator(oper=c_op, N=N, targets=self.targets, dims=dims)) # time-independent if self.coeffs is None: return qobj_list # time-dependent if self.tlist is None: raise ValueError("tlist is required for time-dependent noise.") qobjevo_list = [] for i, temp in enumerate(qobj_list): self._check_coeff_num(self.coeffs, len(qobj_list)) qobjevo_list.append( QobjEvo([qobj_list[i], self.coeffs[i]], tlist=self.tlist)) return qobjevo_list
def get_unitary_qobjevo(self, args=None): """ Create a :class:`qutip.QobjEvo` without any noise that can be given to the QuTiP open system solver. Parameters ---------- args: dict, optional Arguments for :class:`qutip.QobjEvo` Returns ------- unitary_qobjevo: :class:`qutip.QobjEvo` The :class:`qutip.QobjEvo` representation of the unitary evolution. """ # check validity self._is_coeff_valid() if args is None: args = {} else: args = args # set step function if self.coeffs is None: coeffs = np.empty((0, 0)) elif self.spline_kind == "step_func": args.update({"_step_func_coeff": True}) if self.coeffs.shape[1] == len(self.tlist) - 1: coeffs = np.hstack([self.coeffs, self.coeffs[:, -1:]]) else: coeffs = self.coeffs elif self.spline_kind == "cubic": args.update({"_step_func_coeff": False}) coeffs = self.coeffs else: raise ValueError( "No option for spline_kind '{}'.".format(self.spline_kind)) H_list = [] for op_ind in range(len(self.ctrls)): H_list.append( [self.ctrls[op_ind], coeffs[op_ind]]) if not H_list: return _dummy_qobjevo(self.dims, tlist=self.tlist, args=args) else: return QobjEvo(H_list, tlist=self.tlist, args=args)
def test_random_noise(self): """ Test for the white noise """ tlist = np.array([1, 2, 3, 4, 5, 6]) coeff = np.array([1, 1, 1, 1, 1, 1]) dummy_qobjevo = QobjEvo(sigmaz(), tlist=tlist) mean = 0. std = 0.5 pulses = [ Pulse(sigmaz(), 0, tlist, coeff), Pulse(sigmax(), 0, tlist, coeff * 2), Pulse(sigmay(), 0, tlist, coeff * 3) ] # random noise with operators from proc_qobjevo gaussnoise = RandomNoise(dt=0.1, rand_gen=np.random.normal, loc=mean, scale=std) noisy_pulses, systematic_noise = \ gaussnoise.get_noisy_dynamics(pulses=pulses) assert_allclose(noisy_pulses[2].qobj, sigmay()) assert_allclose(noisy_pulses[1].coherent_noise[0].qobj, sigmax()) assert_allclose(len(noisy_pulses[0].coherent_noise[0].tlist), len(noisy_pulses[0].coherent_noise[0].coeff)) # random noise with dt and other random number generator pulses = [ Pulse(sigmaz(), 0, tlist, coeff), Pulse(sigmax(), 0, tlist, coeff * 2), Pulse(sigmay(), 0, tlist, coeff * 3) ] gaussnoise = RandomNoise(lam=0.1, dt=0.2, rand_gen=np.random.poisson) assert_(gaussnoise.rand_gen is np.random.poisson) noisy_pulses, systematic_noise = \ gaussnoise.get_noisy_dynamics(pulses=pulses) assert_allclose(noisy_pulses[0].coherent_noise[0].tlist, np.linspace(1, 6, int(5 / 0.2) + 1)) assert_allclose(noisy_pulses[1].coherent_noise[0].tlist, np.linspace(1, 6, int(5 / 0.2) + 1)) assert_allclose(noisy_pulses[2].coherent_noise[0].tlist, np.linspace(1, 6, int(5 / 0.2) + 1))
def _mesolve_func_td(L_func, c_op_list, rho0, tlist, args, opt): """ Evolve the density matrix using an ODE solver with time dependent Hamiltonian. """ if type(c_op_list) is list: c_ops = [] for op in c_op_list: op_td = QobjEvo(op, args, tlist=tlist, copy=False) if not issuper(op_td.cte): c_ops += [lindblad_dissipator(op_td)] else: c_ops += [op_td] if c_op_list: c_ops_ = [sum(c_ops)] else: c_ops_ = [] elif callable(c_op_list): c_ops_ = c_op_list if opt.rhs_with_state: state0 = rho0.full().ravel("F") obj = L_func(0., state0, args) if not issuper(obj): L_func = _LiouvillianFromFunc(L_func, c_ops_).H2L_with_state else: L_func = _LiouvillianFromFunc(L_func, c_ops_).L_with_state else: obj = L_func(0., args) if callable(c_ops_): if not issuper(obj): L_func = _LiouvillianFromFunc(L_func, c_ops_).H2L_c else: L_func = _LiouvillianFromFunc(L_func, c_ops_).L_c else: if not issuper(obj): L_func = _LiouvillianFromFunc(L_func, c_ops_).H2L else: L_func = _LiouvillianFromFunc(L_func, c_ops_).L ss = SolverSystem() ss.L = L_func ss.makefunc = _Lfunc_set solver_safe["mesolve"] = ss return ss
def get_ideal_qobjevo(self, dims): """ Get the QobjEvo representation of the drift Hamiltonian. Parameters ---------- dims: int or list Dimension of the system. If int, we assume it is the number of qubits in the system. If list, it is the dimension of the component systems. Returns ------- ideal_evo: :class:`qutip.QobjEvo` A `QobjEvo` representing the drift evolution. """ if not self.drift_hamiltonians: self.drift_hamiltonians = [_EvoElement(None, None)] qu_list = [QobjEvo(evo.get_qobj(dims)) for evo in self.drift_hamiltonians] return _merge_qobjevo(qu_list)
def _mesolve_func_td(L_func, c_op_list, rho0, tlist, args, opt): """ Evolve the density matrix using an ODE solver with time dependent Hamiltonian. """ c_ops = [] for op in c_op_list: td = QobjEvo(op, args, tlist=tlist, copy=False) c_ops.append(td if td.cte.issuper else lindblad_dissipator(td)) c_ops_ = [sum(c_ops)] if c_op_list else [] L_api = _LiouvillianFromFunc(L_func, c_ops_, rho0.dims) if opt.rhs_with_state: obj = L_func(0., rho0.full().ravel("F"), args) L_func = L_api.L_with_state if issuper(obj) else L_api.H2L_with_state else: obj = L_func(0., args) L_func = L_api.L if issuper(obj) else L_api.H2L ss = SolverSystem() ss.L = L_func ss.makefunc = _Lfunc_set solver_safe["mesolve"] = ss return ss
def _merge_id_evo(qobjevo): """ Merge identical Hamiltonians in the :class":`qutip.QobjEvo`. coeffs must all have the same length """ H_list = qobjevo.to_list() new_H_list = [] op_list = [] coeff_list = [] for H in H_list: # H = [op, coeff] # cte part or not array_like coeffs if isinstance(H, Qobj) or (not isinstance(H[1], np.ndarray)): new_H_list.append(deepcopy(H)) continue op, coeffs = H # Qobj is not hashable, so cannot be used as key in dict try: p = op_list.index(op) coeff_list[p] += coeffs except ValueError: op_list.append(op) coeff_list.append(coeffs) new_H_list += [[op_list[i], coeff_list[i]] for i in range(len(op_list))] return QobjEvo(new_H_list, tlist=qobjevo.tlist, args=qobjevo.args)
def __init__(self, e_ops=[], super_=False): # take care of expectation values, if any self.isfunc = False self.e_ops_dict = False self.raw_e_ops = e_ops self.e_ops_qoevo = [] self.e_num = 0 self.e_ops_isherm = [] if isinstance(e_ops, (Qobj, QobjEvo)): e_ops = [e_ops] elif isinstance(e_ops, dict): self.e_ops_dict = e_ops e_ops = [e for e in e_ops.values()] self.e_ops = e_ops if isinstance(e_ops, list): self.e_num = len(e_ops) e_ops_qoevo = [] e_ops_isherm = [] for e in e_ops: if isinstance(e, (Qobj, QobjEvo)): e_ops_isherm.append(e.isherm) e_ops_qoevo_entry = None if not super_: e_ops_qoevo_entry = QobjEvo(e) else: e_ops_qoevo_entry = QobjEvo(spre(e)) e_ops_qoevo_entry.compile() e_ops_qoevo.append(e_ops_qoevo_entry) elif callable(e): e_ops_isherm.append(None) e_ops_qoevo.append(e) else: raise TypeError("Expectation value list entry needs to be " "either a function either an operator") self.e_ops_isherm = e_ops_isherm self.e_ops_qoevo = np.array(e_ops_qoevo, dtype=object) elif callable(e_ops): self.isfunc = True self.e_num = 1
def make_system(self, H, c_ops, tlist=None, args={}, options=None): if options is None: options = self.options else: self.options = options var = _collapse_args(args) ss = SolverSystem() ss.td_c_ops = [] ss.td_n_ops = [] ss.args = args ss.col_args = var if type(c_ops) is list: for c in c_ops: # Accounts for nested list format of c_ops cevo = QobjEvo(c, args, tlist=tlist) cdc = cevo._cdc() cevo.compile() cdc.compile() ss.td_c_ops.append(cevo) ss.td_n_ops.append(cdc) if isinstance(H, (list, Qobj, QobjEvo)): H_td = QobjEvo(H, args, tlist=tlist) H_td *= -1j for c in ss.td_n_ops: H_td += -0.5 * c if options.rhs_with_state: H_td._check_old_with_state() H_td.compile() ss.H_td = H_td ss.makefunc = _qobjevo_set ss.set_args = _qobjevo_args # <- redundant ss.type = "QobjEvo" elif callable(H): ss.h_func = H ss.Hc_td = -0.5 * sum(ss.td_n_ops) ss.Hc_td.compile() ss.with_state = options.rhs_with_state ss.makefunc = _func_set ss.set_args = _func_args # <- redundant ss.type = "callback" else: raise Exception("Format of c_ops not supported.") solver_safe["mcsolve"] = ss self.ss = ss self.reset()
def make_system(self, H, c_ops, tlist=None, args={}, options=None): if options is None: options = self.options else: self.options = options var = _collapse_args(args) ss = SolverSystem() ss.td_c_ops = [] ss.td_n_ops = [] ss.args = args ss.col_args = var for c in c_ops: cevo = QobjEvo(c, args, tlist=tlist) cdc = cevo._cdc() cevo.compile() cdc.compile() ss.td_c_ops.append(cevo) ss.td_n_ops.append(cdc) try: H_td = QobjEvo(H, args, tlist=tlist) H_td *= -1j for c in ss.td_n_ops: H_td += -0.5 * c if options.rhs_with_state: H_td._check_old_with_state() H_td.compile() ss.H_td = H_td ss.makefunc = _qobjevo_set ss.set_args = _qobjevo_args ss.type = "QobjEvo" except: ss.h_func = H ss.Hc_td = -0.5 * sum(ss.td_n_ops) ss.Hc_td.compile() ss.with_state = options.rhs_with_state ss.makefunc = _func_set ss.set_args = _func_args ss.type = "callback" solver_safe["mcsolve"] = ss self.ss = ss self.reset()
def get_noise(self, N, proc_qobjevo, dims=None): return QobjEvo(self.op), []
def liouvillian(H, c_ops=[], data_only=False, chi=None): """Assembles the Liouvillian superoperator from a Hamiltonian and a ``list`` of collapse operators. Like liouvillian, but with an experimental implementation which avoids creating extra Qobj instances, which can be advantageous for large systems. Parameters ---------- H : Qobj or QobjEvo System Hamiltonian. c_ops : array_like of Qobj or QobjEvo A ``list`` or ``array`` of collapse operators. Returns ------- L : Qobj or QobjEvo Liouvillian superoperator. """ if isinstance(c_ops, (Qobj, QobjEvo)): c_ops = [c_ops] if chi and len(chi) != len(c_ops): raise ValueError('chi must be a list with same length as c_ops') h = None if H is not None: if isinstance(H, QobjEvo): h = H.cte else: h = H if h.isoper: op_dims = h.dims op_shape = h.shape elif h.issuper: op_dims = h.dims[0] op_shape = [np.prod(op_dims[0]), np.prod(op_dims[0])] else: raise TypeError("Invalid type for Hamiltonian.") else: # no hamiltonian given, pick system size from a collapse operator if isinstance(c_ops, list) and len(c_ops) > 0: if isinstance(c_ops[0], QobjEvo): c = c_ops[0].cte else: c = c_ops[0] if c.isoper: op_dims = c.dims op_shape = c.shape elif c.issuper: op_dims = c.dims[0] op_shape = [np.prod(op_dims[0]), np.prod(op_dims[0])] else: raise TypeError("Invalid type for collapse operator.") else: raise TypeError("Either H or c_ops must be given.") sop_dims = [[op_dims[0], op_dims[0]], [op_dims[1], op_dims[1]]] sop_shape = [np.prod(op_dims), np.prod(op_dims)] spI = fast_identity(op_shape[0]) td = False L = None if isinstance(H, QobjEvo): td = True def H2L(H): if H.isoper: return -1.0j * (spre(H) - spost(H)) else: return H L = H.apply(H2L) data = L.cte.data elif isinstance(H, Qobj): if H.isoper: Ht = H.data.T data = -1j * zcsr_kron(spI, H.data) data += 1j * zcsr_kron(Ht, spI) else: data = H.data else: data = fast_csr_matrix(shape=(sop_shape[0], sop_shape[1])) td_c_ops = [] for idx, c_op in enumerate(c_ops): if isinstance(c_op, QobjEvo): td = True if c_op.const: c_ = c_op.cte elif chi: td_c_ops.append(lindblad_dissipator(c_op, chi=chi[idx])) continue else: td_c_ops.append(lindblad_dissipator(c_op)) continue else: c_ = c_op if c_.issuper: data = data + c_.data else: cd = c_.data.H c = c_.data if chi: data = data + np.exp(1j * chi[idx]) * \ zcsr_kron(c.conj(), c) else: data = data + zcsr_kron(c.conj(), c) cdc = cd * c cdct = cdc.T data = data - 0.5 * zcsr_kron(spI, cdc) data = data - 0.5 * zcsr_kron(cdct, spI) if not td: if data_only: return data else: L = Qobj() L.dims = sop_dims L.data = data L.superrep = 'super' return L else: if not L: l = Qobj() l.dims = sop_dims l.data = data l.superrep = 'super' L = QobjEvo(l) else: L.cte.data = data for c_op in td_c_ops: L += c_op return L