Пример #1
0
def _pseudo_inverse_sparse(L, rhoss, method='splu', **pseudo_args):
    """
    Internal function for computing the pseudo inverse of an Liouvillian using
    sparse matrix methods. See pseudo_inverse for details.
    """

    N = np.prod(L.dims[0][0])

    rhoss_vec = operator_to_vector(rhoss)

    tr_op = tensor([identity(n) for n in L.dims[0][0]])
    tr_op_vec = operator_to_vector(tr_op)

    P = sp.kron(rhoss_vec.data, tr_op_vec.data.T, format='csr')
    I = sp.eye(N*N, N*N, format='csr')
    Q = I - P

    if pseudo_args['use_rcm']:
        perm = reverse_cuthill_mckee(L.data)
        A = sp_permute(L.data, perm, perm, 'csr')
        Q = sp_permute(Q, perm, perm, 'csr')
    else:
        if not settings.has_mkl:
            A = L.data.tocsc()
        A.sort_indices()
    
    if method == 'splu':
        if settings.has_mkl:
            LIQ = mkl_spsolve(A,Q.toarray())
        else:
            lu = sp.linalg.splu(A, permc_spec=pseudo_args['permc_spec'],
                            diag_pivot_thresh=pseudo_args['diag_pivot_thresh'],
                            options=dict(ILU_MILU=pseudo_args['ILU_MILU']))
            LIQ = lu.solve(Q.toarray())

    elif method == 'spilu':
        lu = sp.linalg.spilu(A, permc_spec=pseudo_args['permc_spec'],
                             fill_factor=pseudo_args['fill_factor'], 
                             drop_tol=pseudo_args['drop_tol'])
        LIQ = lu.solve(Q.toarray())

    else:
        raise ValueError("unsupported method '%s'" % method)

    R = sp.csr_matrix(Q * LIQ)

    if pseudo_args['use_rcm']:
        rev_perm = np.argsort(perm)
        R = sp_permute(R, rev_perm, rev_perm, 'csr')

    return Qobj(R, dims=L.dims)
Пример #2
0
def _pseudo_inverse_sparse(L, rhoss, method='splu', use_umfpack=False,
                           use_rcm=False):
    """
    Internal function for computing the pseudo inverse of an Liouvillian using
    sparse matrix methods. See pseudo_inverse for details.
    """

    N = np.prod(L.dims[0][0])

    rhoss_vec = operator_to_vector(rhoss)

    tr_op = tensor([identity(n) for n in L.dims[0][0]])
    tr_op_vec = operator_to_vector(tr_op)

    P = sp.kron(rhoss_vec.data, tr_op_vec.data.T, format='csc')
    I = sp.eye(N*N, N*N, format='csc')
    Q = I - P

    if use_rcm:
        perm = reverse_cuthill_mckee(L.data)
        A = sp_permute(L.data, perm, perm, 'csc').tocsc()
        Q = sp_permute(Q, perm, perm, 'csc')
        permc_spec = 'NATURAL'
    else:
        A = L.data.tocsc()
        A.sort_indices()
        permc_spec = 'COLAMD'

    if method == 'spsolve':
        sp.linalg.use_solver(assumeSortedIndices=True, useUmfpack=use_umfpack)
        LIQ = sp.linalg.spsolve(A, Q)

    elif method == 'splu':
        lu = sp.linalg.splu(A, permc_spec=permc_spec)
        LIQ = lu.solve(Q.toarray())

    elif method == 'spilu':
        lu = sp.linalg.spilu(A, permc_spec=permc_spec,
                             fill_factor=10, drop_tol=1e-8)
        LIQ = lu.solve(Q.toarray())

    else:
        raise ValueError("unsupported method '%s'" % method)

    R = sp.csc_matrix(Q * LIQ)

    if use_rcm:
        rev_perm = np.argsort(perm)
        R = sp_permute(R, rev_perm, rev_perm, 'csc')

    return Qobj(R, dims=L.dims)
Пример #3
0
    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)
Пример #4
0
    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)
Пример #5
0
    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)
Пример #6
0
    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)
Пример #7
0
    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)
Пример #8
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)
Пример #9
0
    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()
Пример #10
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)
Пример #11
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)
Пример #12
0
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
Пример #13
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)
Пример #14
0
    def testSuperJC(self):
        "mesolve: super vs. density matrix as initial condition"
        me_error = 1e-6

        use_rwa = True
        N = 4  # number of cavity fock states
        wc = 2 * np.pi * 1.0  # cavity frequency
        wa = 2 * np.pi * 1.0  # atom frequency
        g = 2 * np.pi * 0.1  # coupling strength
        kappa = 0.05  # cavity dissipation rate
        gamma = 0.001  # atom dissipation rate
        pump = 0.25  # atom pump rate

        # start with an excited atom and maximum number of photons
        n = N - 2
        psi0 = tensor(basis(N, n), basis(2, 1))
        rho0vec = operator_to_vector(psi0 * psi0.dag())
        tlist = np.linspace(0, 100, 50)

        out1, out2 = self.jc_integrate(N, wc, wa, g, kappa, gamma, pump, psi0, use_rwa, tlist)

        fid = self.fidelitycheck(out1, out2, rho0vec)
        assert_(max(abs(1.0 - fid)) < me_error, True)
Пример #15
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)
Пример #16
0
 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)))
Пример #17
0
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()
Пример #18
0
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()
Пример #19
0
def countstat_current_noise(L, c_ops, rhoss=None, J_ops=None, R=False):
    """
    Compute the cross-current noise spectrum for a list of collapse operators
    `c_ops` corresponding to monitored currents, given the system
    Liouvillian `L`. The current collapse operators `c_ops` should be part
    of the dissipative processes in `L`, but the `c_ops` given here does not
    necessarily need to be all collapse operators contributing to dissipation
    in the Liouvillian. Optionally, the steadystate density matrix `rhoss`
    and/or the pseudo inverse `R` of the Liouvillian `L`, and the current
    operators `J_ops` correpsonding to the current collapse operators `c_ops`
    can also be specified. If `R` is not given, the cross-current correlations
    will be computed directly without computing `R` explicitly. If either of
    `rhoss` and `J_ops` are omitted, they will be computed internally.

    Parameters
    ----------

    L : :class:`qutip.Qobj`
        Qobj representing the system Liouvillian.

    c_ops : array / list
        List of current collapse operators.

    rhoss : :class:`qutip.Qobj` (optional)
        The steadystate density matrix corresponding the system Liouvillian
        `L`.

    J_ops : array / list (optional)
        List of current superoperators.

    R : :class:`qutip.Qobj` (optional)
        Qobj representing the pseudo inverse of the system Liouvillian `L`.

    Returns
    --------
    I, S : tuple of arrays
        The currents `I` corresponding to each current collapse operator
        `c_ops` (or, equivalently, each current superopeator `J_ops`) and the
        zero-frequency cross-current correlation `S`.
    """

    if rhoss is None:
        rhoss = steadystate(L, c_ops)

    if J_ops is None:
        J_ops = [sprepost(c, c.dag()) for c in c_ops]

    rhoss_vec = mat2vec(rhoss.full()).ravel()

    N = len(J_ops)
    I = np.zeros(N)
    S = np.zeros((N, N))

    if R:
        if R is True:
            R = pseudo_inverse(L, rhoss)

        for i, Ji in enumerate(J_ops):
            for j, Jj in enumerate(J_ops):
                if i == j:
                    I[i] = expect_rho_vec(Ji.data, rhoss_vec, 1)
                    S[i, j] = I[i]

                S[i, j] -= expect_rho_vec((Ji * R * Jj + Jj * R * Ji).data,
                                          rhoss_vec, 1)
    else:
        N = np.prod(L.dims[0][0])

        rhoss_vec = operator_to_vector(rhoss)

        tr_op = tensor([identity(n) for n in L.dims[0][0]])
        tr_op_vec = operator_to_vector(tr_op)

        Pop = sp.kron(rhoss_vec.data, tr_op_vec.data.T, format='csc')
        Iop = sp.eye(N*N, N*N, format='csc')
        Q = Iop - Pop
        A = L.data.tocsc()
        rhoss_vec = mat2vec(rhoss.full()).ravel()

        for j, Jj in enumerate(J_ops):
            Qj = Q * Jj.data * rhoss_vec
            X_rho_vec = sp.linalg.splu(A, permc_spec='COLAMD').solve(Qj)
            for i, Ji in enumerate(J_ops):
                if i == j:
                    S[i, i] = I[i] = expect_rho_vec(Ji.data, rhoss_vec, 1)

                S[i, j] -= expect_rho_vec(Ji.data * Q, X_rho_vec, 1)

    return I, S
Пример #20
0
class TestHusimiQ:
    @pytest.mark.parametrize('xs', ["", 1, None], ids=['str', 'int', 'none'])
    def test_failure_if_non_arraylike_coordinates(self, xs):
        state = qutip.rand_ket(4)
        valid = np.linspace(-1, 1, 5)
        with pytest.raises(TypeError) as e:
            qutip.qfunc(state, xs, valid)
        assert "must be array-like" in e.value.args[0]
        with pytest.raises(TypeError) as e:
            qutip.qfunc(state, valid, xs)
        assert "must be array-like" in e.value.args[0]
        with pytest.raises(TypeError) as e:
            qutip.QFunc(xs, valid)
        assert "must be array-like" in e.value.args[0]
        with pytest.raises(TypeError) as e:
            qutip.QFunc(valid, xs)
        assert "must be array-like" in e.value.args[0]

    @pytest.mark.parametrize('ndim', [2, 3])
    def test_failure_if_coordinates_not_1d(self, ndim):
        state = qutip.rand_ket(4)
        valid = np.linspace(-1, 1, 5)
        bad = valid.reshape((-1, ) + (1, ) * (ndim - 1))
        with pytest.raises(ValueError) as e:
            qutip.qfunc(state, bad, valid)
        assert "must be 1D" in e.value.args[0]
        with pytest.raises(ValueError) as e:
            qutip.qfunc(state, valid, bad)
        assert "must be 1D" in e.value.args[0]
        with pytest.raises(ValueError) as e:
            qutip.QFunc(bad, valid)
        assert "must be 1D" in e.value.args[0]
        with pytest.raises(ValueError) as e:
            qutip.QFunc(valid, bad)
        assert "must be 1D" in e.value.args[0]

    @pytest.mark.parametrize('dm', [True, False], ids=['dm', 'ket'])
    def test_failure_if_tensor_hilbert_space(self, dm):
        if dm:
            state = qutip.rand_dm(4, dims=[[2, 2], [2, 2]])
        else:
            state = qutip.rand_ket(4, dims=[[2, 2], [1, 1]])
        xs = np.linspace(-1, 1, 5)
        with pytest.raises(ValueError) as e:
            qutip.qfunc(state, xs, xs)
        assert "must not have tensor structure" in e.value.args[0]
        with pytest.raises(ValueError) as e:
            qutip.QFunc(xs, xs)(state)
        assert "must not have tensor structure" in e.value.args[0]

    def test_QFunc_raises_if_insufficient_memory(self):
        xs = np.linspace(-1, 1, 11)
        state = qutip.rand_ket(4)
        qfunc = qutip.QFunc(xs, xs, memory=0)
        with pytest.raises(MemoryError) as e:
            qfunc(state)
        assert e.value.args[0].startswith("Refusing to precompute")

    def test_qfunc_warns_if_insufficient_memory(self):
        xs = np.linspace(-1, 1, 11)
        state = qutip.rand_dm(4)
        with pytest.warns(UserWarning) as e:
            qutip.qfunc(state, xs, xs, precompute_memory=0)
        assert (e[0].message.args[0].startswith(
            "Falling back to iterative algorithm"))

    @pytest.mark.parametrize('obj', [
        pytest.param(np.eye(2, dtype=np.complex128), id='ndarray'),
        pytest.param([[1, 0], [0, 1]], id='list'),
        pytest.param(1, id='int'),
    ])
    def test_failure_if_not_a_Qobj(self, obj):
        xs = np.linspace(-1, 1, 11)
        with pytest.raises(TypeError) as e:
            qutip.qfunc(obj, xs, xs)
        assert e.value.args[0].startswith("state must be Qobj")
        qfunc = qutip.QFunc(xs, xs)
        with pytest.raises(TypeError) as e:
            qfunc(obj)
        assert e.value.args[0].startswith("state must be Qobj")

    # Use indirection so that the tests can still be collected if there's a bug
    # in the generating QuTiP functions.
    @pytest.mark.parametrize('state', [
        pytest.param(lambda: qutip.rand_super(2), id='super'),
        pytest.param(lambda: qutip.rand_ket(2).dag(), id='bra'),
        pytest.param(lambda: 1j * qutip.rand_dm(2), id='non-dm operator'),
        pytest.param(lambda: qutip.Qobj([[1, 0], [0, 0]], dims=[[2], [2, 1]]),
                     id='nonsquare dm'),
        pytest.param(lambda: qutip.operator_to_vector(qutip.qeye(2)),
                     id='operator-ket'),
        pytest.param(lambda: qutip.operator_to_vector(qutip.qeye(2)).dag(),
                     id='operator-bra'),
    ])
    def test_failure_if_not_a_state(self, state):
        xs = np.linspace(-1, 1, 11)
        state = state()
        with pytest.raises(ValueError) as e:
            qutip.qfunc(state, xs, xs)
        assert (e.value.args[0].startswith(
            "state must be a ket or density matrix"))
        qfunc = qutip.QFunc(xs, xs)
        with pytest.raises(ValueError) as e:
            qfunc(state)
        assert (e.value.args[0].startswith(
            "state must be a ket or density matrix"))

    @pytest.mark.parametrize('g', [
        pytest.param(np.sqrt(2), id='natural units'),
        pytest.param(1, id='arb units'),
    ])
    @pytest.mark.parametrize('n_ys', [5, 101])
    @pytest.mark.parametrize('n_xs', [5, 101])
    @pytest.mark.parametrize('dm', [True, False], ids=['dm', 'ket'])
    @pytest.mark.parametrize('size', [5, 32])
    def test_function_and_class_are_equivalent(self, size, dm, n_xs, n_ys, g):
        xs = np.linspace(-1, 1, n_xs)
        ys = np.linspace(0, 2, n_ys)
        state = qutip.rand_dm(size) if dm else qutip.rand_ket(size)
        function = qutip.qfunc(state, xs, ys, g)
        class_ = qutip.QFunc(xs, ys, g)(state)
        np.testing.assert_allclose(function, class_)

    @pytest.mark.parametrize('g', [
        pytest.param(np.sqrt(2), id='natural units'),
        pytest.param(1, id='arb units'),
    ])
    @pytest.mark.parametrize('n_ys', [5, 101])
    @pytest.mark.parametrize('n_xs', [5, 101])
    @pytest.mark.parametrize('size', [5, 32])
    def test_iterate_and_precompute_are_equivalent(self, size, n_xs, n_ys, g):
        xs = np.linspace(-1, 1, n_xs)
        ys = np.linspace(0, 2, n_ys)
        state = qutip.rand_dm(size)
        iterate = qutip.qfunc(state, xs, ys, g, precompute_memory=None)
        precompute = qutip.qfunc(state, xs, ys, g, precompute_memory=np.inf)
        np.testing.assert_allclose(iterate, precompute)

    @pytest.mark.parametrize('initial_size', [5, 8])
    @pytest.mark.parametrize('dm', [True, False], ids=['dm', 'ket'])
    def test_same_class_can_take_many_sizes(self, dm, initial_size):
        xs = np.linspace(-1, 1, 11)
        ys = np.linspace(0, 2, 11)
        shape = np.meshgrid(xs, ys)[0].shape
        sizes = initial_size + np.array([0, 1, -1, 4])
        qfunc = qutip.QFunc(xs, ys)
        for size in sizes:
            state = qutip.rand_dm(size) if dm else qutip.rand_ket(size)
            out = qfunc(state)
            assert isinstance(out, np.ndarray)
            assert out.shape == shape

    @pytest.mark.parametrize('dm_first', [True, False])
    def test_same_class_can_mix_ket_and_dm(self, dm_first):
        dms = [True, False, True, False]
        if not dm_first:
            dms = dms[::-1]
        xs = np.linspace(-1, 1, 11)
        ys = np.linspace(0, 2, 11)
        shape = np.meshgrid(xs, ys)[0].shape
        qfunc = qutip.QFunc(xs, ys)
        for dm in dms:
            state = qutip.rand_dm(4) if dm else qutip.rand_ket(4)
            out = qfunc(state)
            assert isinstance(out, np.ndarray)
            assert out.shape == shape

    @pytest.mark.parametrize('n_ys', [5, 101])
    @pytest.mark.parametrize('n_xs', [5, 101])
    @pytest.mark.parametrize('mix', [0.1, 0.5])
    def test_qfunc_is_linear(self, n_xs, n_ys, mix):
        xs = np.linspace(-1, 1, n_xs)
        ys = np.linspace(-1, 1, n_ys)
        qfunc = qutip.QFunc(xs, ys)
        left, right = qutip.rand_dm(5), qutip.rand_dm(5)
        qleft, qright = qfunc(left), qfunc(right)
        qboth = qfunc(mix * left + (1 - mix) * right)
        np.testing.assert_allclose(mix * qleft + (1 - mix) * qright, qboth)

    @pytest.mark.parametrize('n_ys', [5, 101])
    @pytest.mark.parametrize('n_xs', [5, 101])
    @pytest.mark.parametrize('size', [5, 32])
    def test_ket_and_dm_give_same_result(self, n_xs, n_ys, size):
        xs = np.linspace(-1, 1, n_xs)
        ys = np.linspace(-1, 1, n_ys)
        state = qutip.rand_ket(size)
        qfunc = qutip.QFunc(xs, ys)
        np.testing.assert_allclose(qfunc(state), qfunc(state.proj()))

    @pytest.mark.parametrize('g', [
        pytest.param(np.sqrt(2), id='natural units'),
        pytest.param(1, id='arb units'),
    ])
    @pytest.mark.parametrize('ys', [
        pytest.param(np.linspace(-1, 1, 5), id='(-1,1,5)'),
        pytest.param(np.linspace(0, 2, 3), id='(0,2,3)'),
    ])
    @pytest.mark.parametrize('xs', [
        pytest.param(np.linspace(-1, 1, 5), id='(-1,1,5)'),
        pytest.param(np.linspace(0, 2, 3), id='(0,2,3)'),
    ])
    @pytest.mark.parametrize('size', [3, 5])
    def test_against_naive_implementation(self, xs, ys, g, size):
        state = qutip.rand_dm(size)
        state_np = state.full()
        x, y = np.meshgrid(xs, ys)
        alphas = 0.5 * g * (x + 1j * y)
        naive = np.empty(alphas.shape, dtype=np.float64)
        for i, alpha in enumerate(alphas.flat):
            coh = qutip.coherent(size, alpha, method='analytic').full()
            naive.flat[i] = (coh.conj().T @ state_np @ coh).real
        naive *= (0.5 * g)**2 / np.pi
        np.testing.assert_allclose(naive, qutip.qfunc(state, xs, ys, g))
        np.testing.assert_allclose(naive, qutip.QFunc(xs, ys, g)(state))
Пример #21
0
def countstat_current_noise(L, c_ops, wlist=None, rhoss=None, J_ops=None, 
                            sparse=True, method='direct'):
    """
    Compute the cross-current noise spectrum for a list of collapse operators
    `c_ops` corresponding to monitored currents, given the system
    Liouvillian `L`. The current collapse operators `c_ops` should be part
    of the dissipative processes in `L`, but the `c_ops` given here does not
    necessarily need to be all collapse operators contributing to dissipation
    in the Liouvillian. Optionally, the steadystate density matrix `rhoss`
    and the current operators `J_ops` correpsonding to the current collapse 
    operators `c_ops` can also be specified. If either of
    `rhoss` and `J_ops` are omitted, they will be computed internally.
    'wlist' is an optional list of frequencies at which to evaluate the noise 
    spectrum.  
    
    Note:
    The default method is a direct solution using dense matrices, as sparse 
    matrix methods fail for some examples of small systems.
    For larger systems it is reccomended to use the sparse solver
    with the direct method, as it avoids explicit calculation of the
    pseudo-inverse, as described in page 67 of "Electrons in nanostructures"
    C. Flindt, PhD Thesis, available online:
    http://orbit.dtu.dk/fedora/objects/orbit:82314/datastreams/file_4732600/content
    
    Parameters
    ----------

    L : :class:`qutip.Qobj`
        Qobj representing the system Liouvillian.

    c_ops : array / list
        List of current collapse operators.

    rhoss : :class:`qutip.Qobj` (optional)
        The steadystate density matrix corresponding the system Liouvillian
        `L`.
        
    wlist : array / list (optional)
        List of frequencies at which to evaluate (if none are given, evaluates 
        at zero frequency)

    J_ops : array / list (optional)
        List of current superoperators.

    sparse : bool
        Flag that indicates whether to use sparse or dense matrix methods when
        computing the pseudo inverse. Default is false, as sparse solvers
        can fail for small systems. For larger systems the sparse solvers
        are reccomended. 
        
        
    Returns
    --------
    I, S : tuple of arrays
        The currents `I` corresponding to each current collapse operator
        `c_ops` (or, equivalently, each current superopeator `J_ops`) and the
        zero-frequency cross-current correlation `S`.
    """

    if rhoss is None:
        rhoss = steadystate(L, c_ops)

    if J_ops is None:
        J_ops = [sprepost(c, c.dag()) for c in c_ops]

    

    N = len(J_ops)
    I = np.zeros(N)
    
    if wlist is None:
        S = np.zeros((N, N,1))
        wlist=[0.]
    else:
        S = np.zeros((N, N,len(wlist)))
        
    if sparse == False: 
        rhoss_vec = mat2vec(rhoss.full()).ravel()
        for k,w in enumerate(wlist):
            R = pseudo_inverse(L, rhoss=rhoss, w= w, sparse = sparse, method=method)
            for i, Ji in enumerate(J_ops):
                for j, Jj in enumerate(J_ops):
                    if i == j:
                        I[i] = expect_rho_vec(Ji.data, rhoss_vec, 1)
                        S[i, j,k] = I[i]
                    S[i, j,k] -= expect_rho_vec((Ji * R * Jj 
                                                + Jj * R * Ji).data,
                                                rhoss_vec, 1)
    else:
        if method == "direct":
            N = np.prod(L.dims[0][0])
            
            rhoss_vec = operator_to_vector(rhoss)
            
            tr_op = tensor([identity(n) for n in L.dims[0][0]])
            tr_op_vec = operator_to_vector(tr_op)
            
            Pop = sp.kron(rhoss_vec.data, tr_op_vec.data.T, format='csr')
            Iop = sp.eye(N*N, N*N, format='csr')
            Q = Iop - Pop
            
            for k,w in enumerate(wlist):
                
                if w != 0.0:    
                    L_temp = 1.0j*w*spre(tr_op) + L
                else: #At zero frequency some solvers fail for small systems.
                      #Adding a small finite frequency of order 1e-15
                      #helps prevent the solvers from throwing an exception.
                    L_temp =  1.0j*(1e-15)*spre(tr_op) + L
                    
                if not settings.has_mkl:
                    A = L_temp.data.tocsc()
                else:
                    A = L_temp.data.tocsr()
                    A.sort_indices()                      
                      
                rhoss_vec = mat2vec(rhoss.full()).ravel()               
                
                for j, Jj in enumerate(J_ops):
                    Qj = Q.dot( Jj.data.dot( rhoss_vec))
                    try:
                        if settings.has_mkl:
                            X_rho_vec_j = mkl_spsolve(A,Qj)                            
                        else:
                            X_rho_vec_j = sp.linalg.splu(A, permc_spec
                                                 ='COLAMD').solve(Qj)
                    except:
                        X_rho_vec_j = sp.linalg.lsqr(A,Qj)[0]
                    for i, Ji in enumerate(J_ops):
                        Qi = Q.dot( Ji.data.dot(rhoss_vec))
                        try:
                            if settings.has_mkl:                              
                                X_rho_vec_i = mkl_spsolve(A,Qi)  
                            else:
                                X_rho_vec_i = sp.linalg.splu(A, permc_spec
                                                     ='COLAMD').solve(Qi)
                        except:
                             X_rho_vec_i = sp.linalg.lsqr(A,Qi)[0]
                        if i == j:
                            I[i] = expect_rho_vec(Ji.data, 
                                                 rhoss_vec, 1)
                            S[j, i, k] = I[i]
                        
                        S[j, i, k] -= (expect_rho_vec(Jj.data * Q, 
                                        X_rho_vec_i, 1) 
                                        + expect_rho_vec(Ji.data * Q, 
                                        X_rho_vec_j, 1))

        else:
            rhoss_vec = mat2vec(rhoss.full()).ravel()
            for k,w in enumerate(wlist):

                R = pseudo_inverse(L,rhoss=rhoss, w= w, sparse = sparse, 
                                   method=method)
                                   
                for i, Ji in enumerate(J_ops):
                    for j, Jj in enumerate(J_ops):
                        if i == j:
                            I[i] = expect_rho_vec(Ji.data, rhoss_vec, 1)
                            S[i, j, k] = I[i]
                        S[i, j, k] -= expect_rho_vec((Ji * R * Jj 
                                                     + Jj * R * Ji).data,
                                                     rhoss_vec, 1)
    return I, S
Пример #22
0
def countstat_current_noise(L,
                            c_ops,
                            wlist=None,
                            rhoss=None,
                            J_ops=None,
                            sparse=True,
                            method='direct'):
    """
    Compute the cross-current noise spectrum for a list of collapse operators
    `c_ops` corresponding to monitored currents, given the system
    Liouvillian `L`. The current collapse operators `c_ops` should be part
    of the dissipative processes in `L`, but the `c_ops` given here does not
    necessarily need to be all collapse operators contributing to dissipation
    in the Liouvillian. Optionally, the steadystate density matrix `rhoss`
    and the current operators `J_ops` correpsonding to the current collapse 
    operators `c_ops` can also be specified. If either of
    `rhoss` and `J_ops` are omitted, they will be computed internally.
    'wlist' is an optional list of frequencies at which to evaluate the noise 
    spectrum.  
    
    Note:
    The default method is a direct solution using dense matrices, as sparse 
    matrix methods fail for some examples of small systems.
    For larger systems it is reccomended to use the sparse solver
    with the direct method, as it avoids explicit calculation of the
    pseudo-inverse, as described in page 67 of "Electrons in nanostructures"
    C. Flindt, PhD Thesis, available online:
    https://orbit.dtu.dk/fedora/objects/orbit:82314/datastreams/file_4732600/content
    
    Parameters
    ----------

    L : :class:`qutip.Qobj`
        Qobj representing the system Liouvillian.

    c_ops : array / list
        List of current collapse operators.

    rhoss : :class:`qutip.Qobj` (optional)
        The steadystate density matrix corresponding the system Liouvillian
        `L`.
        
    wlist : array / list (optional)
        List of frequencies at which to evaluate (if none are given, evaluates 
        at zero frequency)

    J_ops : array / list (optional)
        List of current superoperators.

    sparse : bool
        Flag that indicates whether to use sparse or dense matrix methods when
        computing the pseudo inverse. Default is false, as sparse solvers
        can fail for small systems. For larger systems the sparse solvers
        are reccomended. 
        
        
    Returns
    --------
    I, S : tuple of arrays
        The currents `I` corresponding to each current collapse operator
        `c_ops` (or, equivalently, each current superopeator `J_ops`) and the
        zero-frequency cross-current correlation `S`.
    """

    if rhoss is None:
        rhoss = steadystate(L, c_ops)

    if J_ops is None:
        J_ops = [sprepost(c, c.dag()) for c in c_ops]

    N = len(J_ops)
    I = np.zeros(N)

    if wlist is None:
        S = np.zeros((N, N, 1))
        wlist = [0.]
    else:
        S = np.zeros((N, N, len(wlist)))

    if sparse == False:
        rhoss_vec = mat2vec(rhoss.full()).ravel()
        for k, w in enumerate(wlist):
            R = pseudo_inverse(L,
                               rhoss=rhoss,
                               w=w,
                               sparse=sparse,
                               method=method)
            for i, Ji in enumerate(J_ops):
                for j, Jj in enumerate(J_ops):
                    if i == j:
                        I[i] = expect_rho_vec(Ji.data, rhoss_vec, 1)
                        S[i, j, k] = I[i]
                    S[i, j, k] -= expect_rho_vec(
                        (Ji * R * Jj + Jj * R * Ji).data, rhoss_vec, 1)
    else:
        if method == "direct":
            N = np.prod(L.dims[0][0])

            rhoss_vec = operator_to_vector(rhoss)

            tr_op = tensor([identity(n) for n in L.dims[0][0]])
            tr_op_vec = operator_to_vector(tr_op)

            Pop = sp.kron(rhoss_vec.data, tr_op_vec.data.T, format='csr')
            Iop = sp.eye(N * N, N * N, format='csr')
            Q = Iop - Pop

            for k, w in enumerate(wlist):

                if w != 0.0:
                    L_temp = 1.0j * w * spre(tr_op) + L
                else:  #At zero frequency some solvers fail for small systems.
                    #Adding a small finite frequency of order 1e-15
                    #helps prevent the solvers from throwing an exception.
                    L_temp = 1.0j * (1e-15) * spre(tr_op) + L

                if not settings.has_mkl:
                    A = L_temp.data.tocsc()
                else:
                    A = L_temp.data.tocsr()
                    A.sort_indices()

                rhoss_vec = mat2vec(rhoss.full()).ravel()

                for j, Jj in enumerate(J_ops):
                    Qj = Q.dot(Jj.data.dot(rhoss_vec))
                    try:
                        if settings.has_mkl:
                            X_rho_vec_j = mkl_spsolve(A, Qj)
                        else:
                            X_rho_vec_j = sp.linalg.splu(
                                A, permc_spec='COLAMD').solve(Qj)
                    except:
                        X_rho_vec_j = sp.linalg.lsqr(A, Qj)[0]
                    for i, Ji in enumerate(J_ops):
                        Qi = Q.dot(Ji.data.dot(rhoss_vec))
                        try:
                            if settings.has_mkl:
                                X_rho_vec_i = mkl_spsolve(A, Qi)
                            else:
                                X_rho_vec_i = sp.linalg.splu(
                                    A, permc_spec='COLAMD').solve(Qi)
                        except:
                            X_rho_vec_i = sp.linalg.lsqr(A, Qi)[0]
                        if i == j:
                            I[i] = expect_rho_vec(Ji.data, rhoss_vec, 1)
                            S[j, i, k] = I[i]

                        S[j, i,
                          k] -= (expect_rho_vec(Jj.data * Q, X_rho_vec_i, 1) +
                                 expect_rho_vec(Ji.data * Q, X_rho_vec_j, 1))

        else:
            rhoss_vec = mat2vec(rhoss.full()).ravel()
            for k, w in enumerate(wlist):

                R = pseudo_inverse(L,
                                   rhoss=rhoss,
                                   w=w,
                                   sparse=sparse,
                                   method=method)

                for i, Ji in enumerate(J_ops):
                    for j, Jj in enumerate(J_ops):
                        if i == j:
                            I[i] = expect_rho_vec(Ji.data, rhoss_vec, 1)
                            S[i, j, k] = I[i]
                        S[i, j, k] -= expect_rho_vec(
                            (Ji * R * Jj + Jj * R * Ji).data, rhoss_vec, 1)
    return I, S
Пример #23
0
        return noisy_cliffords[rand_int]

    # Some SPAM
    noise_operator_state_prep = unitary_channel(4, 0.8, 0.01)
    noise_operator_meas_op = unitary_channel(4, 0.8, 0.01)
    noise_operator_state_prep.dims = [[[2, 2], [2, 2]], [[2, 2], [2, 2]]]
    noise_operator_meas_op.dims = [[[2, 2], [2, 2]], [[2, 2], [2, 2]]]

    # Set the number of runs
    number_of_seq = 5000
    seq_length = 25

    # Set observable Q
    Q = qt.tensor(qt.sigmay() - qt.sigmaz(), qt.sigmay() - qt.sigmaz())
    Q.dims = [[2, 2], [2, 2]]
    Q = qt.operator_to_vector(Q)
    Q = noise_operator_meas_op * Q

    # Set initial state
    rho = qt.basis(4, 0) * qt.basis(4, 0).dag()
    rho.dims = [[2, 2], [2, 2]]
    rho = qt.operator_to_vector(rho)
    rho = noise_operator_state_prep * rho

    def fixed_func(m, c0, c1, c2, c3, e1):
        return (c0 + c1 * e1**(m - 1.) + c2 *
                (sub_unitarity_A_to_A(two_qubit_noise))**(m - 1.) + c3 *
                (sub_unitarity_B_to_B(two_qubit_noise))**(m - 1.))

    # Run!
    reference_standard_data = protocol(noisy_cliffords, rho, Q, seq_length,
Пример #24
0
 def to_pauli(self, H):
     H.dims = self.ops[0].dims
     HP = [(qt.operator_to_vector(H).dag() *
            qt.operator_to_vector(p))[0][0][0] for p in self.ops]
     return qt.Qobj(np.array(HP)) / np.sqrt(len(self.ops))
Пример #25
0
def ramsey_experiment(left_gate_list, right_gate_list, L, field_f, transition_f, nCounts, time_per_gate, gate_switching_time, \
                      experiment_sample_time, time_units=1e-6, noise_type=None, freq_list=0,amp_list=0, phase_list=0,\
                      start_f=0, stop_f=0, fluctuators=0, plot_noise = False):
    #left and right gate_lists: lists of the gates sandwiching the Gi gates
    #L: the number of Gi gates. If you want to vary this, make it a list
    #field_f: frequency of external field in Hz. To vary this, make it a list. Either L or field_f must vary.
    #transition_f: frequency of the qubit transition in Hz.
    #time_per_gate: total time to complete one Gx, Gy, Gi, or Gz
    #switching_time: additional time before you start any new gate or change gates
    #experiment_sample_time: time at which you trigger a single expeimrent (single count), usually 60 Hz triggered
    #nCounts: number of times to repeat one experiment (a single set of parameters)
    #time_units: baseline units (in seconds) for any additional drift noise signal you may want to add. Defaults to ms.

    #check that the input has something to be varied
    if type(L) == type(field_f):
        print("Error: Either L or field_f must vary over a range!")
        return None
    #this list will contain the varied parameter, either detuning in Hz or delay time in s
    varied_param = []

    if type(L) == list:
        total_experiments = len(L)
        experiment_list = []
        for l in L:
            experiment_list.append(left_gate_list + ['Gi'] * l +
                                   right_gate_list)
        field_f_list = [field_f] * total_experiments
        varied_param = [(time_per_gate * l + gate_switching_time) for l in L]

    else:
        total_experiments = len(field_f)
        experiment_list = [left_gate_list + ['Gi'] * L + right_gate_list
                           ] * total_experiments
        field_f_list = field_f
        varied_param = delta_list

    #create a noise object:
    if noise_type != None and noise_type == "Sine":
        total_time = total_experiments * nCounts * experiment_sample_time + 1  #assumes that every count is taken every 0.016 seconds; no experiment takes longer
        sig = _ns.NoiseSignalSine(time_unit=time_units)
        sig.configure_noise(resolution_factor=1,
                            freq_list=freq_list,
                            amp_list=amp_list,
                            phase_list=phase_list,
                            total_time=total_time / time_units)
        sig.init()

        if plot_noise == True:
            sig.plot_noise_signal()

    probs = [
    ]  #a list of total_expeirment* elements. Has the probability for each experiment set (assumes constant p for all nCounts)
    time_per_experiment_set = [
    ]  #has the time at the start of each experiment set
    ones_counts = []  #number of 1s counted for each experiment set
    angles = []  #total theta rotation for each experiment set
    ideal_angles = []  #has the ideal theta rotation for each experiment set
    transition_f_list = [
    ]  #list of the transition frequency at the start of each experiment set
    detuning_list = [
    ]  #list of the detuning at the start of each experiment set
    absolute_time = 0  #seconds
    rho0 = _qt.operator_to_vector(_qt.ket2dm(_qt.basis(2, 0)))
    rho1 = _qt.operator_to_vector(_qt.ket2dm(_qt.basis(2, 1)))

    for experiment_index in range(total_experiments):
        experiment = experiment_list[experiment_index]
        compressed_experiment = compress_gate_list(experiment)
        #the following line assumes that each count for each experiment set is triggered at 0.0167 seconds (no single gate sequence can be longer than 1/60)
        absolute_time += experiment_sample_time * nCounts
        #print("Starting experiment set {} at {} s".format(experiment_index, absolute_time))
        rho = rho0
        total_angle = 0
        total_ideal_angle = 0
        modified_transition_f = transition_f
        detuning = field_f_list[experiment_index] - modified_transition_f
        for gate_name, repetitions in compressed_experiment:
            if noise_type != None:
                if absolute_time >= total_time:
                    print("Abs time: {}, total_time: {}".format(
                        absolute_time, total_time))
                detuning_noise = sig[absolute_time / time_units]
            else:
                detuning_noise = 0
            if gate_name == 'Gx':
                angle = (np.pi / 2) * repetitions
                ideal_angle = (np.pi / 2) * repetitions
                rho = (_qt.to_super(_qt.rx(angle))) * rho
                #this section just keeps the angle between 0 and pi
                angle = angle % (2 * np.pi)
                ideal_angle = ideal_angle % (2 * np.pi)
                if angle > np.pi:
                    angle = 2 * np.pi - angle
                if angle < 0:
                    angle = 0 + abs(angle)
                if ideal_angle > np.pi:
                    ideal_angle = 2 * np.pi - ideal_angle
                if ideal_angle < 0:
                    ideal_angle = 0 + abs(ideal_angle)
            elif gate_name == 'Gy':
                angle = (np.pi / 2) * repetitions
                ideal_angle = (np.pi / 2) * repetitions
                rho = (_qt.to_super(_qt.ry(angle))) * rho
                #this section just keeps the angle between 0 and pi
                angle = angle % (2 * np.pi)
                ideal_angle = ideal_angle % (2 * np.pi)
                if angle > np.pi:
                    angle = 2 * np.pi - angle
                if angle < 0:
                    angle = 0 + abs(angle)
                if ideal_angle > np.pi:
                    ideal_angle = 2 * np.pi - ideal_angle
                if ideal_angle < 0:
                    ideal_angle = 0 + abs(ideal_angle)
            elif gate_name == "Gi":
                #print("starting {} with z-rotation 2pi*{:.2f}".format(gate_list_to_string(experiment), detuning*(time_per_gate*repetitions + gate_switching_time)))
                #make the transition frequency oscillate between a fraction of its nominal value
                modified_transition_f = transition_f * (1 + detuning_noise)
                detuning = field_f_list[
                    experiment_index] - modified_transition_f
                angle = 2 * np.pi * detuning * (time_per_gate * repetitions +
                                                gate_switching_time)
                rho = (_qt.to_super(_qt.rz(angle))) * rho
            total_angle += angle
            total_ideal_angle += ideal_angle

        #calculate probabilities of being in 1 after the all the gates in the experiment have been applied
        p1 = (rho.dag() * rho1).norm()
        #fix the p1 if it exceeds 1 due to rounding error
        if p1 > 1:
            p1 = 2 - p1
        #get nCounts of data (bits) for the experiment
        one_counts = np.random.binomial(nCounts, p1)
        angles.append(total_angle)
        ideal_angles.append(total_ideal_angle)
        probs.append(p1)
        ones_counts.append(one_counts)
        time_per_experiment_set.append(absolute_time)
        transition_f_list.append(modified_transition_f)
        detuning_list.append(detuning)

    return np.asarray(ones_counts), np.asarray(
        time_per_experiment_set), np.asarray(probs), np.asarray(varied_param)
Пример #26
0
def create_data(time_per_count, num_samples, num_counts, gate_list, time_unit, noise_type=None, walking_amp=None, telegraph_amp=None, \
                res=None, freq_list=None, amp_list=None, phase_list=None, start_f=None, stop_f=None, fluctuators=None, plot_noise=False, \
                add_noise=False, noise_object=None, dc_angle_offset=0, constant_linear_drift=0):
    #time_per_shot: time in seconds for a single (prep-gate-measure+delay)
    #num_samples: how many timestamps and strings of counts you want to have
    #num_counts: how many data points to create (how many ones and zeros) per sample (i.e. per timestamp) --> affects both time of a sample and precision
    #num_shots: how many times (shots) you apply (prep-gate_list-meas) to get one count (a single 0 or 1) --> determines the time of one count, but won't affect precision
    #gate_list: gates you want to do for your operation, entered as a list of strings
    #xerr,yerr,zerr: 2D tuples with overrotation amplitude in radians and frequency in Hz
    #constant linear drift: enter in rads/second
    rho0 = _qt.operator_to_vector(_qt.ket2dm(_qt.basis(2, 0)))
    rho1 = _qt.operator_to_vector(_qt.ket2dm(_qt.basis(2, 1)))
    zero_counts = []
    one_counts = []
    timestep = num_counts * time_per_count  #the time to get a full bitstring of zeros and ones for one sample, i.e. one timestamp
    timestamps = np.arange(
        timestep, num_samples * timestep,
        timestep)  #array of 1*timestep, 2*timestep,....(num_samples)*timestep
    probs = []
    total_time = (time_per_count * num_counts * num_samples) / time_unit

    sig = 0
    if noise_type == "Sine":
        #this function returns the noise object so you can enter it back in as a parameter
        # in the event that you call the function repeatedly for an identical set of parameters
        if noise_object != None:
            sig = noise_object
            #print("REUSING NOISE OBJECT")
            while total_time > sig.times[-1] + timestep:
                sig.next_interval()
                #print("Doing a NEXT INTERVAL")
        else:
            #print("INITIALIZING NEW NOISE")
            sig = _ns.NoiseSignalSine(time_unit=time_unit)
            sig.configure_noise(resolution_factor=res,
                                freq_list=freq_list,
                                amp_list=amp_list,
                                phase_list=phase_list,
                                total_time=total_time)
            sig.init()
            if add_noise != None:
                sig.add_random_noise(
                    add_noise
                )  #add normal noise with specified std deviation if requested
    elif noise_type == "Random Walk":
        sig = _ns.NoiseSignalRandomWalk(initial_seed=1234, time_unit=time_unit)
        sig.configure_noise(walking_amp, res, total_time)
        sig.init()
    elif noise_type == "Telegraph":
        sig = _ns.NoiseSignalTelegraph(initial_seed=1234, time_unit=time_unit)
        sig.configure_noise(exponent=1,
                            amplitude=telegraph_amp,
                            total_fluctuators=fluctuators,
                            start_freq=start_f,
                            stop_freq=stop_f,
                            total_time=total_time)
        sig.init()
        sig.interpolation_settings(do_interpolation=True,
                                   resolution_factor=res)

    if plot_noise == True:
        sig.plot_noise_signal()

    angle_list = []
    expected_angle_list = []

    compressed_gate_list = compress_gate_list(gate_list)
    for time in timestamps:
        noise_at_time = 0
        if noise_type != None:
            #print(time/time_unit)
            noise_at_time = sig[time / time_unit]
        rho = rho0
        total_angle = 0
        total_ideal_angle = 0

        for gate in compressed_gate_list:
            gate_name = gate[0]
            gate_repetitions = gate[1]
            '''
            Next step: calculate change in rotation error within each shot. Currently takes the time at the start of the experiment shot
            and applies that to all gates in one shot. Depending on the timescale of the error and time per shot, this simplification may need
            to be addressed so that each gate, say each Gx in (Gx)^11, has an error associated with its specific time, not the same error for
            all 11 Gx gates.
            '''

            if gate_name == 'Gx':
                angle = (
                    np.pi / 2 + noise_at_time
                ) * gate_repetitions + dc_angle_offset + constant_linear_drift * time
                ideal_angle = (
                    np.pi / 2
                ) * gate_repetitions + dc_angle_offset + constant_linear_drift * time
                rho = (_qt.to_super(_qt.rx(angle))) * rho
                #this section just keeps the angle between 0 and pi
                angle = angle % (2 * np.pi)
                ideal_angle = ideal_angle % (2 * np.pi)
                if angle > np.pi:
                    angle = 2 * np.pi - angle
                if angle < 0:
                    angle = 0 + abs(angle)
                if ideal_angle > np.pi:
                    ideal_angle = 2 * np.pi - ideal_angle
                if ideal_angle < 0:
                    ideal_angle = 0 + abs(ideal_angle)
            elif gate_name == 'Gy':
                angle = (
                    np.pi / 2 + noise_at_time
                ) * gate_repetitions + dc_angle_offset + constant_linear_drift * time
                ideal_angle = (
                    np.pi / 2
                ) * gate_repetitions + dc_angle_offset + constant_linear_drift * time
                rho = (_qt.to_super(_qt.ry(angle))) * rho
                #this section just keeps the angle between 0 and pi
                angle = angle % (2 * np.pi)
                ideal_angle = ideal_angle % (2 * np.pi)
                if angle > np.pi:
                    angle = 2 * np.pi - angle
                if angle < 0:
                    angle = 0 + abs(angle)
                if ideal_angle > np.pi:
                    ideal_angle = 2 * np.pi - ideal_angle
                if ideal_angle < 0:
                    ideal_angle = 0 + abs(ideal_angle)
            elif gate_name == 'Gz':
                angle = (
                    np.pi / 2 + noise_at_time
                ) * gate_repetitions + dc_angle_offset + constant_linear_drift * time
                ideal_angle = (
                    np.pi / 2
                ) * gate_repetitions + dc_angle_offset + constant_linear_drift * time
                rho = (_qt.to_super(_qt.rz(angle))) * rho
                #this section just keeps the angle between 0 and pi
                angle = angle % (2 * np.pi)
                ideal_angle = ideal_angle % (2 * np.pi)
                if angle > np.pi:
                    angle = 2 * np.pi - angle
                if angle < 0:
                    angle = 0 + abs(angle)
                if ideal_angle > np.pi:
                    ideal_angle = 2 * np.pi - ideal_angle
                if ideal_angle < 0:
                    ideal_angle = 0 + abs(ideal_angle)
            elif gate_name == "Gi":
                #apply only the oscillating drift angle, don't add it to pi/2
                angle = (
                    noise_at_time
                ) * gate_repetitions + dc_angle_offset + constant_linear_drift * time
                ideal_angle = 0 + dc_angle_offset + constant_linear_drift * time
                print("applying Gi with angle ", angle)
                rho = (_qt.to_super(_qt.rz(angle))) * rho
                angle = angle % (2 * np.pi)
                ideal_angle = 0
                if angle > np.pi:
                    angle = 2 * np.pi - angle
                if angle < 0:
                    angle = 0 + abs(angle)
                if ideal_angle > np.pi:
                    ideal_angle = 2 * np.pi - ideal_angle
                if ideal_angle < 0:
                    ideal_angle = 0 + abs(ideal_angle)
            total_angle += angle
            total_ideal_angle += ideal_angle

        #append the total rotation angle after timestamp 'time'
        angle_list.append(total_angle)
        expected_angle_list.append(total_ideal_angle)
        #calculate probabilities of being in 1 after the experiment has been applied
        p1 = (rho.dag() * rho1).norm()
        #fix the p1 if it exceeds 1 due to rounding error
        if p1 > 1:
            #print("p1 exceeds 1 for time {}".format(time))
            #print("prob is {}".format(p1))
            #print("Resetting to {}".format(2-p1))
            p1 = 2 - p1
        probs.append(p1)
        one_count = np.random.binomial(
            num_counts, p1
        )  #simulates a summation of the number of 1-counts you get in one bitstring sample
        zero_count = num_counts - one_count  #simulates summation of the number of 0-counts in one bitstring sample
        one_counts.append(one_count)
        zero_counts.append(zero_count)

    if plot_noise == True:
        plt.plot(timestamps,
                 np.asarray(expected_angle_list),
                 label="Ideal Angle",
                 ls='dashed',
                 color='orange')
        plt.plot(timestamps, np.asarray(angle_list), label="Drifting Angle")
        plt.legend()
        plt.xlabel("Time, seconds")
        plt.yticks(np.linspace(0, np.pi, 5),
                   ['0', '$\pi/4$', '$\pi/2$', '$3\pi/4$', '$\pi$'])
        plt.ylabel("Angle, radians\n(Displayed between 0 and $\pi$)")
        plt.title("Time-Dependent Rotation Angle after each {}".format(
            gate_list_to_string(gate_list)))
        plt.grid()
        plt.show()

        plt.figure(figsize=(15, 3))
        plt.plot(timestamps, probs)
        plt.ylim(0, 1)
        plt.xlim(timestamps[0], timestamps[-1])
        plt.xlabel("Time, seconds")
        plt.ylabel("Probability of Measuring State {1}")
        plt.title("Simulated {} with {} Noise".format(
            gate_list_to_string(gate_list), noise_type))
        plt.grid()
        plt.show()

    return (np.asarray(one_counts), np.asarray(zero_counts),
            np.asarray(timestamps), probs, np.asarray(expected_angle_list),
            np.asarray(angle_list), sig)
Пример #27
0
        def get_average_gate_fidelity(self, runs=500, target=None):
            """
            returns average gate fidelity
            Args
                runs (int) : number of runs to compute the average gate fidelity
                target (4x4 numpy array) : target unitary to compute fidelity
            """

            self.solver_obj.calculate_evolution(self.init, self.total_time,
                                                10000, 1)
            U_ideal = self.solver_obj.get_unitary()[0]
            self.solver_obj.add_noise_static(2 * np.pi * self.H_zeeman,
                                             18 * 1e-6)
            self.solver_obj.add_noise_generic(2 * np.pi * self.H_heisenberg,
                                              oneoverfnoise,
                                              self.exchange_dc / 100)
            self.solver_obj.calculate_evolution(self.init, self.total_time,
                                                10000, int(runs))

            U_list = self.solver_obj.get_unitary()

            # Calculate the averaged super operator in the Lioville superoperator form using column convention
            basis = [qt.basis(4, it) for it in range(4)]
            superoperator_basis = [
                basis_it1 * basis_it2.dag() for basis_it2 in basis
                for basis_it1 in basis
            ]
            averaged_map = np.zeros([16, 16], dtype=np.complex)
            for u in U_list:
                temp_U = qt.Qobj(u)
                output_density = list()
                for it in range(len(superoperator_basis)):
                    temp_vec = np.array(
                        qt.operator_to_vector(
                            temp_U * superoperator_basis[it] * temp_U.dag() /
                            float(runs)).full()).flatten()
                    output_density.append(np.array(temp_vec))
                averaged_map = np.add(averaged_map, np.array(output_density))

            # Define the target unitary operation
            if target is None:
                target = sp.linalg.expm(
                    -np.pi / 2. * 1j *
                    sp.sparse.diags([0., -1., -1., 0.]).todense())

            # get phase from optimizing noiseless unitary evolution
            def to_minimize_fidelity(theta):
                temp_z_gate = np.matmul(
                    sp.linalg.expm(-2 * np.pi * 1j * theta * self.H_zeeman),
                    U_ideal)
                temp_m = np.matmul(sp.conjugate(sp.transpose(target)),
                                   temp_z_gate)
                return np.real(1. - (sp.trace(
                    np.matmul(temp_m, sp.conjugate(sp.transpose(temp_m)))) +
                                     np.abs(sp.trace(temp_m))**2.) / 20.)

            ideal_phase = sp.optimize.minimize(
                to_minimize_fidelity,
                [self.delta_z * (self.total_time * 1e-9)],
                method='Nelder-Mead',
                tol=1e-6).x[0]

            target = np.matmul(
                sp.linalg.expm(2 * np.pi * 1j * ideal_phase * self.H_zeeman),
                target)

            # Change the shape of the averaged super operator to match the definitions used in QuTip (row convention)
            target = qt.Qobj(target)
            averaged_map = qt.Qobj(averaged_map).trans()
            averaged_map._type = 'super'
            averaged_map.dims = [[[4], [4]], [[4], [4]]]
            averaged_map.superrep = qt.to_super(target).superrep

            # Calculate the average gate fidelity of the superoperator with the target unitary gate

            fidelity = qt.average_gate_fidelity(averaged_map, target)
            return fidelity
Пример #28
0
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
Пример #29
0
 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)))
Пример #30
0
def _pseudo_inverse_sparse(L, rhoss, w=None, **pseudo_args):
    """
    Internal function for computing the pseudo inverse of an Liouvillian using
    sparse matrix methods. See pseudo_inverse for details.
    """

    N = np.prod(L.dims[0][0])

    rhoss_vec = operator_to_vector(rhoss)

    tr_op = tensor([identity(n) for n in L.dims[0][0]])
    tr_op_vec = operator_to_vector(tr_op)

    P = zcsr_kron(rhoss_vec.data, tr_op_vec.data.T)
    I = sp.eye(N * N, N * N, format='csr')
    Q = I - P

    if w is None:
        L = 1.0j * (1e-15) * spre(tr_op) + L
    else:
        if w != 0.0:
            L = 1.0j * w * spre(tr_op) + L
        else:
            L = 1.0j * (1e-15) * spre(tr_op) + L

    if pseudo_args['use_rcm']:
        perm = reverse_cuthill_mckee(L.data)
        A = sp_permute(L.data, perm, perm)
        Q = sp_permute(Q, perm, perm)
    else:
        if ss_args['solver'] == 'scipy':
            A = L.data.tocsc()
            A.sort_indices()

    if pseudo_args['method'] == 'splu':
        if settings.has_mkl:
            A = L.data.tocsr()
            A.sort_indices()
            LIQ = mkl_spsolve(A, Q.toarray())
        else:
            pspec = pseudo_args['permc_spec']
            diag_p_thresh = pseudo_args['diag_pivot_thresh']
            pseudo_args = pseudo_args['ILU_MILU']
            lu = sp.linalg.splu(A,
                                permc_spec=pspec,
                                diag_pivot_thresh=diag_p_thresh,
                                options=dict(ILU_MILU=pseudo_args))
            LIQ = lu.solve(Q.toarray())

    elif pseudo_args['method'] == 'spilu':
        lu = sp.linalg.spilu(A,
                             permc_spec=pseudo_args['permc_spec'],
                             fill_factor=pseudo_args['fill_factor'],
                             drop_tol=pseudo_args['drop_tol'])
        LIQ = lu.solve(Q.toarray())

    else:
        raise ValueError("unsupported method '%s'" % method)

    R = sp.csr_matrix(Q * LIQ)

    if pseudo_args['use_rcm']:
        rev_perm = np.argsort(perm)
        R = sp_permute(R, rev_perm, rev_perm, 'csr')

    return Qobj(R, dims=L.dims)
Пример #31
0
def to_pauli(H):
	global pauli_op_names, pauli_ops, pbasis
	HP = [(qt.operator_to_vector(H).dag()*qt.operator_to_vector(p))[0][0][0] for p in pauli_ops]
	V = qt.Qobj(np.array(HP))/np.sqrt(len(pauli_ops))
	H2 = sum([h*pauli_ops[i] for i, h in enumerate(V.full().T[0])])
	return V
Пример #32
0
]

e_lst_sm = [e_lst[0]]

ham_off = rest_ham + jc_ham

pulse_fun = lambda t, amp: jc.tanh_updown(t, amp, sigma, 5. * sigma, tau / 2. +
                                          5. * sigma)

pulse_dot_fun = lambda t, amp: jc.tanh_updown_dot(t, amp, sigma, 5. * sigma,
                                                  tau / 2. + 5. * sigma)

times = np.linspace(0., tau, steps)

if __name__ == '__main__':
    e_vecs = [qt.operator_to_vector(e_op).data.H for e_op in e_lst]
    e_cb = lambda rho: jc.expectation_cb(e_vecs, rho)

    sim_dict = {
        'ham_off': ham_off,
        'pulse_ham': pulse_ham,
        'pulse_fun': lambda t: pulse_fun(t, 90.),
        'pulse_dot_fun': lambda t: pulse_dot_fun(t, 90.),
        'c_ops': c_lst,
        'cb_func': jc.five_checks,
        'meas_op': np.sqrt(kappa) * a,
        'rho_init': qt.operator_to_vector(rho0).data.todense(),
        'times': times,
        'n_traj': 1
    }