Beispiel #1
0
    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))
Beispiel #2
0
 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
Beispiel #3
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:
        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
Beispiel #4
0
    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
Beispiel #5
0
    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
Beispiel #6
0
    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)
Beispiel #7
0
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
Beispiel #8
0
    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()
Beispiel #9
0
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
Beispiel #10
0
    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])
Beispiel #11
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
Beispiel #12
0
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
Beispiel #13
0
 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
Beispiel #14
0
    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
Beispiel #15
0
    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)
Beispiel #16
0
    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))
Beispiel #17
0
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
Beispiel #18
0
    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)
Beispiel #19
0
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
Beispiel #20
0
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)
Beispiel #21
0
    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
Beispiel #22
0
    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()
Beispiel #23
0
    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()
Beispiel #24
0
 def get_noise(self, N, proc_qobjevo, dims=None):
     return QobjEvo(self.op), []
Beispiel #25
0
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