예제 #1
0
def countstat_current(L, c_ops=None, rhoss=None, J_ops=None):
    """
    Calculate the current corresponding a system Liouvillian `L` and a list of
    current collapse operators `c_ops` or current superoperators `J_ops`
    (either must be specified). Optionally the steadystate density matrix
    `rhoss` and a list of current superoperators `J_ops` can be specified. If
    either of these are omitted they are computed internally.

    Parameters
    ----------

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

    c_ops : array / list (optional)
        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.

    Returns
    --------
    I : array
        The currents `I` corresponding to each current collapse operator
        `c_ops` (or, equivalently, each current superopeator `J_ops`).
    """

    if J_ops is None:
        if c_ops is None:
            raise ValueError("c_ops must be given if J_ops is not")
        J_ops = [sprepost(c, c.dag()) for c in c_ops]

    if rhoss is None:
        if c_ops is None:
            raise ValueError("c_ops must be given if rhoss is not")
        rhoss = steadystate(L, c_ops)

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

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

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

    return I
예제 #2
0
def countstat_current(L, c_ops=None, rhoss=None, J_ops=None):
    """
    Calculate the current corresponding a system Liouvillian `L` and a list of
    current collapse operators `c_ops` or current superoperators `J_ops`
    (either must be specified). Optionally the steadystate density matrix
    `rhoss` and a list of current superoperators `J_ops` can be specified. If
    either of these are omitted they are computed internally.

    Parameters
    ----------

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

    c_ops : array / list (optional)
        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.

    Returns
    --------
    I : array
        The currents `I` corresponding to each current collapse operator
        `c_ops` (or, equivalently, each current superopeator `J_ops`).
    """

    if J_ops is None:
        if c_ops is None:
            raise ValueError("c_ops must be given if J_ops is not")
        J_ops = [sprepost(c, c.dag()) for c in c_ops]

    if rhoss is None:
        if c_ops is None:
            raise ValueError("c_ops must be given if rhoss is not")
        rhoss = steadystate(L, c_ops)

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

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

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

    return I
예제 #3
0
 def test_NeglectSmallKraus(self):
     """
     Superoperator: Convert Kraus to Choi matrix and back. Neglect tiny Kraus operators.
     """
     zero = asarray([[1], [0]], dtype=complex)
     one = asarray([[0], [1]], dtype=complex)
     zero_log = kron(kron(zero, zero), zero)
     one_log = kron(kron(one, one), one)
     # non-square Kraus operator (isometry)
     kraus = Qobj(zero_log @ zero.T + one_log @ one.T)
     super = sprepost(kraus, kraus.dag())
     # 1 non-zero Kraus operator the rest are zero
     sixteen_kraus_ops = to_kraus(super, tol=0.0)
     # default is tol=1e-9
     one_kraus_op = to_kraus(super)
     assert_(len(sixteen_kraus_ops) == 16 and len(one_kraus_op) == 1)
     assert_((one_kraus_op[0] - kraus).norm() < tol)
예제 #4
0
def to_super(q_oper):
    """
    Converts a Qobj representing a quantum map to the supermatrix (Liouville)
    representation.

    Parameters
    ----------
    q_oper : Qobj
        Superoperator to be converted to supermatrix representation. If
        ``q_oper`` is ``type="oper"``, then it is taken to act by conjugation,
        such that ``to_super(A) == sprepost(A, A.dag())``.

    Returns
    -------
    superop : Qobj
        A quantum object representing the same map as ``q_oper``, such that
        ``superop.superrep == "super"``.

    Raises
    ------
    TypeError
        If the given quantum object is not a map, or cannot be converted
        to supermatrix representation.
    """
    if q_oper.type == 'super':
        # Case 1: Already done.
        if q_oper.superrep == "super":
            return q_oper
        # Case 2: Can directly convert.
        elif q_oper.superrep == 'choi':
            return choi_to_super(q_oper)
        # Case 3: Need to go through Choi.
        elif q_oper.superrep == 'chi':
            return to_super(to_choi(q_oper))
        # Case 4: Something went wrong.
        else:
            raise ValueError(
                "Unrecognized superrep '{}'.".format(q_oper.superrep))
    elif q_oper.type == 'oper':  # Assume unitary
        return sprepost(q_oper, q_oper.dag())
    else:
        raise TypeError(
            "Conversion of Qobj with type = {0.type} "
            "and superrep = {0.superrep} to supermatrix not "
            "supported.".format(q_oper)
        )
예제 #5
0
def to_chi(q_oper):
    """
    Converts a Qobj representing a quantum map to a representation as a chi
    (process) matrix in the Pauli basis, such that the trace of the returned
    operator is equal to the dimension of the system.

    Parameters
    ----------
    q_oper : Qobj
        Superoperator to be converted to Chi representation. If
        ``q_oper`` is ``type="oper"``, then it is taken to act by conjugation,
        such that ``to_chi(A) == to_chi(sprepost(A, A.dag()))``.

    Returns
    -------
    chi : Qobj
        A quantum object representing the same map as ``q_oper``, such that
        ``chi.superrep == "chi"``.

    Raises
    ------
    TypeError: if the given quantum object is not a map, or cannot be converted
        to Chi representation.
    """
    if q_oper.type == 'super':
        # Case 1: Already done.
        if q_oper.superrep == 'chi':
            return q_oper
        # Case 2: Can directly convert.
        elif q_oper.superrep == 'choi':
            return choi_to_chi(q_oper)
        # Case 3: Need to go through Choi.
        elif q_oper.superrep == 'super':
            return to_chi(to_choi(q_oper))
        else:
            raise TypeError(q_oper.superrep)
    elif q_oper.type == 'oper':
        return to_chi(sprepost(q_oper, q_oper.dag()))
    else:
        raise TypeError(
            "Conversion of Qobj with type = {0.type} "
            "and superrep = {0.choi} to Choi not supported.".format(q_oper)
        )
예제 #6
0
 def test_NonSquareKrausSuperChoi(self):
     """
     Superoperator: Convert non-square Kraus operator to Super + Choi matrix and back.
     """
     zero = asarray([[1], [0]], dtype=complex)
     one = asarray([[0], [1]], dtype=complex)
     zero_log = kron(kron(zero, zero), zero)
     one_log = kron(kron(one, one), one)
     # non-square Kraus operator (isometry)
     kraus = Qobj(zero_log @ zero.T + one_log @ one.T)
     super = sprepost(kraus, kraus.dag())
     choi = to_choi(super)
     op1 = to_kraus(super)
     op2 = to_kraus(choi)
     op3 = to_super(choi)
     assert_(choi.type == "super" and choi.superrep == "choi")
     assert_(super.type == "super" and super.superrep == "super")
     assert_((op1[0] - kraus).norm() < 1e-8)
     assert_((op2[0] - kraus).norm() < 1e-8)
     assert_((op3 - super).norm() < 1e-8)
예제 #7
0
def to_choi(q_oper):
    """
    Converts a Qobj representing a quantum map to the Choi representation,
    such that the trace of the returned operator is equal to the dimension
    of the system.

    Parameters
    ----------
    q_oper : Qobj
        Superoperator to be converted to Choi representation. If
        ``q_oper`` is ``type="oper"``, then it is taken to act by conjugation,
        such that ``to_choi(A) == to_choi(sprepost(A, A.dag()))``.

    Returns
    -------
    choi : Qobj
        A quantum object representing the same map as ``q_oper``, such that
        ``choi.superrep == "choi"``.

    Raises
    ------
    TypeError: if the given quantum object is not a map, or cannot be converted
        to Choi representation.
    """
    if q_oper.type == 'super':
        if q_oper.superrep == 'choi':
            return q_oper
        if q_oper.superrep == 'super':
            return super_to_choi(q_oper)
        if q_oper.superrep == 'chi':
            return chi_to_choi(q_oper)
        else:
            raise TypeError(q_oper.superrep)
    elif q_oper.type == 'oper':
        return super_to_choi(sprepost(q_oper, q_oper.dag()))
    else:
        raise TypeError(
            "Conversion of Qobj with type = {0.type} "
            "and superrep = {0.choi} to Choi not supported.".format(q_oper)
        )
예제 #8
0
    def test_known_iscptp(self):
        """
        Superoperator: ishp, iscp, istp and iscptp known cases.
        """
        def case(qobj, shouldhp, shouldcp, shouldtp):
            hp = qobj.ishp
            cp = qobj.iscp
            tp = qobj.istp
            cptp = qobj.iscptp

            shouldcptp = shouldcp and shouldtp

            if (hp == shouldhp and cp == shouldcp and tp == shouldtp
                    and cptp == shouldcptp):
                return

            fails = []
            if hp != shouldhp:
                fails.append(("ishp", shouldhp, hp))
            if tp != shouldtp:
                fails.append(("istp", shouldtp, tp))
            if cp != shouldcp:
                fails.append(("iscp", shouldcp, cp))
            if cptp != shouldcptp:
                fails.append(("iscptp", shouldcptp, cptp))

            raise AssertionError("Expected {}.".format(" and ".join([
                "{} == {} (got {})".format(fail, expected, got)
                for fail, expected, got in fails
            ])))

        # Conjugation by a creation operator should
        # have be CP (and hence HP), but not TP.
        a = create(2).dag()
        S = sprepost(a, a.dag())
        case(S, True, True, False)

        # A single off-diagonal element should not be CP,
        # nor even HP.
        S = sprepost(a, a)
        case(S, False, False, False)

        # Check that unitaries are CPTP and HP.
        case(identity(2), True, True, True)
        case(sigmax(), True, True, True)

        # Check that unitaries on bipartite systems are CPTP and HP.
        case(tensor(sigmax(), identity(2)), True, True, True)

        # Check that a linear combination of bipartitie unitaries is CPTP and HP.
        S = (to_super(tensor(sigmax(), identity(2))) +
             to_super(tensor(identity(2), sigmay()))) / 2
        case(S, True, True, True)

        # The partial transpose map, whose Choi matrix is SWAP, is TP
        # and HP but not CP (one negative eigenvalue).
        W = Qobj(swap(), type='super', superrep='choi')
        case(W, True, False, True)

        # Subnormalized maps (representing erasure channels, for instance)
        # can be CP but not TP.
        subnorm_map = Qobj(identity(4) * 0.9, type='super', superrep='super')
        case(subnorm_map, True, True, False)

        # Check that things which aren't even operators aren't identified as
        # CPTP.
        case(basis(2), False, False, False)
예제 #9
0
    def test_known_iscptp(self):
        """
        Superoperator: ishp, iscp, istp and iscptp known cases.
        """
        def case(qobj, shouldhp, shouldcp, shouldtp):
            hp = qobj.ishp
            cp = qobj.iscp
            tp = qobj.istp
            cptp = qobj.iscptp

            shouldcptp = shouldcp and shouldtp

            if (
                hp == shouldhp and
                cp == shouldcp and
                tp == shouldtp and
                cptp == shouldcptp
            ):
                return

            fails = []
            if hp != shouldhp:
                fails.append(("ishp", shouldhp, hp))
            if tp != shouldtp:
                fails.append(("istp", shouldtp, tp))
            if cp != shouldcp:
                fails.append(("iscp", shouldcp, cp))
            if cptp != shouldcptp:
                fails.append(("iscptp", shouldcptp, cptp))

            raise AssertionError("Expected {}.".format(" and ".join([
                "{} == {} (got {})".format(fail, expected, got)
                for fail, expected, got in fails
            ])))

        # Conjugation by a creation operator should
        # have be CP (and hence HP), but not TP.
        a = create(2).dag()
        S = sprepost(a, a.dag())
        yield case, S, True, True, False

        # A single off-diagonal element should not be CP,
        # nor even HP.
        S = sprepost(a, a)
        yield case, S, False, False, False
        
        # Check that unitaries are CPTP and HP.
        yield case, identity(2), True, True, True
        yield case, sigmax(), True, True, True

        # The partial transpose map, whose Choi matrix is SWAP, is TP
        # and HP but not CP (one negative eigenvalue).
        W = Qobj(swap(), type='super', superrep='choi')
        yield case, W, True, False, True

        # Subnormalized maps (representing erasure channels, for instance)
        # can be CP but not TP.
        subnorm_map = Qobj(identity(4) * 0.9, type='super', superrep='super')
        yield case, subnorm_map, True, True, False

        # Check that things which aren't even operators aren't identified as
        # CPTP.
        yield case, basis(2), False, False, False
예제 #10
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
예제 #11
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
예제 #12
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
예제 #13
0
LC_iy = liouvillian(Hc[1])
LC_iz = liouvillian(Hc[2])
#LC_zi = liouvillian(Hc[4])
#LC_zy = liouvillian(Hc[5])
#LC_zz = liouvillian(Hc[6])



drift = L0
#ctrls = [LC_ix,LC_xi,LC_xx,LC_yy]#,LC_yi]
ctrls = [LC_ix,LC_iy,LC_iz,LC_zx]#,LC_ix,LC_iy,LC_iz,LC_zi,LC_zy,LC_zz]
#ctrls = [LC_zx,LC_ix,LC_iy,LC_yi]
#ctrls = [LC_zx,LC_ix,LC_iy,LC_yi]
nctrl = len(ctrls)

E0 = sprepost(U0,U0)
#E_targ = sprepost(cnot_gate,cnot_gate)
E_targ = sprepost(U_targ,U_targ)

# Fidelity error target
fid_err_targ = 1e-3
# Maximum iterations for the optisation algorithm
max_iter = 3500
# Maximum (elapsed) time allowed in seconds
max_wall_time = 1600
# Minimum gradient (sum of gradients squared)
# as this tends to 0 -> local minima has been found
min_grad = 1e-20
p_type = 'CUSTOM'
for evo_time in evo_times:
	n_ts = int(float(evo_time/0.222))
#Amplitude damping#
#Damping rate:
gamma = 0.3

# qutip column vectorisation
L0 = liouvillian(H0, [np.sqrt(gamma) * Sm])

#sigma X control
LC_x = liouvillian(Sx)
#sigma Y control
LC_y = liouvillian(Sy)
#sigma Z control
LC_z = liouvillian(Sz)

E0 = sprepost(Si, Si)
# target map 1
# E_targ = sprepost(had_gate, had_gate)
# target map 2
E_targ = sprepost(Sx, Sx)

psi0 = basis(2, 1)  # ground state
#psi0 = basis(2, 0) # excited state
rho0 = ket2dm(psi0)
print("rho0:\n{}\n".format(rho0))
rho0_vec = operator_to_vector(rho0)
print("rho0_vec:\n{}\n".format(rho0_vec))

# target state 1
# psi_targ = (basis(2, 0) + basis(2, 1)).unit()
# target state 2
예제 #15
0
class TestSuperopReps:
    """
    A test class for the QuTiP function for applying superoperators to
    subsystems.
    """
    def test_SuperChoiSuper(self, superoperator):
        """
        Superoperator: Converting superoperator to Choi matrix and back.
        """

        choi_matrix = to_choi(superoperator)
        test_supe = to_super(choi_matrix)

        # Assert both that the result is close to expected, and has the right
        # type.
        assert (test_supe - superoperator).norm() < tol
        assert choi_matrix.type == "super" and choi_matrix.superrep == "choi"
        assert test_supe.type == "super" and test_supe.superrep == "super"

    @pytest.mark.parametrize('dimension', [2, 4])
    def test_SuperChoiChiSuper(self, dimension):
        """
        Superoperator: Converting two-qubit superoperator through
        Choi and chi representations goes back to right superoperator.
        """
        superoperator = super_tensor(
            rand_super(dimension),
            rand_super(dimension),
        )

        choi_matrix = to_choi(superoperator)
        chi_matrix = to_chi(choi_matrix)
        test_supe = to_super(chi_matrix)

        # Assert both that the result is close to expected, and has the right
        # type.
        assert (test_supe - superoperator).norm() < tol
        assert choi_matrix.type == "super" and choi_matrix.superrep == "choi"
        assert chi_matrix.type == "super" and chi_matrix.superrep == "chi"
        assert test_supe.type == "super" and test_supe.superrep == "super"

    def test_ChoiKrausChoi(self, superoperator):
        """
        Superoperator: Convert superoperator to Choi matrix and back.
        """
        choi_matrix = to_choi(superoperator)
        kraus_ops = to_kraus(choi_matrix)
        test_choi = kraus_to_choi(kraus_ops)

        # Assert both that the result is close to expected, and has the right
        # type.
        assert (test_choi - choi_matrix).norm() < tol
        assert choi_matrix.type == "super" and choi_matrix.superrep == "choi"
        assert test_choi.type == "super" and test_choi.superrep == "choi"

    def test_NonSquareKrausSuperChoi(self):
        """
        Superoperator: Convert non-square Kraus operator to Super + Choi matrix
        and back.
        """
        zero = asarray([[1], [0]], dtype=complex)
        one = asarray([[0], [1]], dtype=complex)
        zero_log = kron(kron(zero, zero), zero)
        one_log = kron(kron(one, one), one)
        # non-square Kraus operator (isometry)
        kraus = Qobj(zero_log @ zero.T + one_log @ one.T)
        super = sprepost(kraus, kraus.dag())
        choi = to_choi(super)
        op1 = to_kraus(super)
        op2 = to_kraus(choi)
        op3 = to_super(choi)

        assert choi.type == "super" and choi.superrep == "choi"
        assert super.type == "super" and super.superrep == "super"
        assert (op1[0] - kraus).norm() < tol
        assert (op2[0] - kraus).norm() < tol
        assert (op3 - super).norm() < tol

    def test_NeglectSmallKraus(self):
        """
        Superoperator: Convert Kraus to Choi matrix and back. Neglect tiny
        Kraus operators.
        """
        zero = asarray([[1], [0]], dtype=complex)
        one = asarray([[0], [1]], dtype=complex)
        zero_log = kron(kron(zero, zero), zero)
        one_log = kron(kron(one, one), one)
        # non-square Kraus operator (isometry)
        kraus = Qobj(zero_log @ zero.T + one_log @ one.T)
        super = sprepost(kraus, kraus.dag())
        # 1 non-zero Kraus operator the rest are zero
        sixteen_kraus_ops = to_kraus(super, tol=0.0)
        # default is tol=1e-9
        one_kraus_op = to_kraus(super)
        assert len(sixteen_kraus_ops) == 16 and len(one_kraus_op) == 1
        assert (one_kraus_op[0] - kraus).norm() < tol

    def test_SuperPreservesSelf(self, superoperator):
        """
        Superoperator: to_super(q) returns q if q is already a
        supermatrix.
        """

        assert superoperator is to_super(superoperator)

    def test_ChoiPreservesSelf(self, superoperator):
        """
        Superoperator: to_choi(q) returns q if q is already Choi.
        """
        choi = to_choi(superoperator)
        assert choi is to_choi(choi)

    def test_random_iscptp(self, superoperator):
        """
        Superoperator: Randomly generated superoperators are
        correctly reported as CPTP and HP.
        """
        assert superoperator.iscptp
        assert superoperator.ishp

    # Conjugation by a creation operator
    a = create(2).dag()
    S = sprepost(a, a.dag())

    # A single off-diagonal element
    S_ = sprepost(a, a)

    # Check that a linear combination of bipartite unitaries is CPTP and HP.
    S_U = (to_super(tensor(sigmax(), identity(2))) +
           to_super(tensor(identity(2), sigmay()))) / 2

    # The partial transpose map, whose Choi matrix is SWAP
    ptr_swap = Qobj(swap(), type='super', superrep='choi')

    # Subnormalized maps (representing erasure channels, for instance)
    subnorm_map = Qobj(identity(4) * 0.9, type='super', superrep='super')

    @pytest.mark.parametrize(['qobj', 'shouldhp', 'shouldcp', 'shouldtp'], [
        pytest.param(S, True, True, False, id="conjugatio by create op"),
        pytest.param(S_, False, False, False, id="single off-diag"),
        pytest.param(identity(2), True, True, True, id="Identity"),
        pytest.param(sigmax(), True, True, True, id="Pauli X"),
        pytest.param(
            tensor(sigmax(), identity(2)),
            True,
            True,
            True,
            id="bipartite system",
        ),
        pytest.param(
            S_U,
            True,
            True,
            True,
            id="linear combination of bip. unitaries",
        ),
        pytest.param(ptr_swap, True, False, True, id="partial transpose map"),
        pytest.param(subnorm_map, True, True, False, id="subnorm map"),
        pytest.param(basis(2), False, False, False, id="not an operator"),
    ])
    def test_known_iscptp(self, qobj, shouldhp, shouldcp, shouldtp):
        """
        Superoperator: ishp, iscp, istp and iscptp known cases.
        """
        assert qobj.ishp == shouldhp
        assert qobj.iscp == shouldcp
        assert qobj.istp == shouldtp
        assert qobj.iscptp == (shouldcp and shouldtp)

    def test_choi_tr(self, dimension):
        """
        Superoperator: Trace returned by to_choi matches docstring.
        """
        assert abs(to_choi(identity(dimension)).tr() - dimension) <= tol

    def test_stinespring_cp(self, dimension):
        """
        Stinespring: A and B match for CP maps.
        """
        superop = rand_super_bcsz(dimension)
        A, B = to_stinespring(superop)

        assert norm(A - B) < tol

    @pytest.mark.repeat(3)
    def test_stinespring_agrees(self, dimension):
        """
        Stinespring: Partial Tr over pair agrees w/ supermatrix.
        """

        map = rand_super_bcsz(dimension)
        state = rand_dm_ginibre(dimension)

        S = to_super(map)
        A, B = to_stinespring(map)

        q1 = vector_to_operator(S * operator_to_vector(state))
        # FIXME: problem if Kraus index is implicitly
        #        ptraced!
        q2 = (A * state * B.dag()).ptrace((0, ))

        assert (q1 - q2).norm('tr') <= tol

    def test_stinespring_dims(self, dimension):
        """
        Stinespring: Check that dims of channels are preserved.
        """
        chan = super_tensor(to_super(sigmax()), to_super(qeye(dimension)))
        A, B = to_stinespring(chan)
        assert A.dims == [[2, dimension, 1], [2, dimension]]
        assert B.dims == [[2, dimension, 1], [2, dimension]]

    @pytest.mark.parametrize('dimension', [2, 4, 8])
    def test_chi_choi_roundtrip(self, dimension):

        superop = rand_super_bcsz(dimension)
        superop = to_chi(superop)
        rt_superop = to_chi(to_choi(superop))
        dif = norm(rt_superop - superop)

        assert dif == pytest.approx(0, abs=1e-7)
        assert rt_superop.type == superop.type
        assert rt_superop.dims == superop.dims

    chi_sigmax = [[0, 0, 0, 0], [0, 4, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
    chi_diag2 = [[4, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
    rotX_pi_4 = (-1j * sigmax() * pi / 4).expm()
    chi_rotX_pi_4 = [[2, 2j, 0, 0], [-2j, 2, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

    @pytest.mark.parametrize(['superop', 'chi_expected'], [
        pytest.param(sigmax(), chi_sigmax),
        pytest.param(to_super(sigmax()), chi_sigmax),
        pytest.param(qeye(2), chi_diag2),
        pytest.param(rotX_pi_4, chi_rotX_pi_4)
    ])
    def test_chi_known(self, superop, chi_expected):
        """
        Superoperator: Chi-matrix for known cases is correct.
        """
        chi_actual = to_chi(superop)
        chiq = Qobj(
            chi_expected,
            dims=[[[2], [2]], [[2], [2]]],
            superrep='chi',
        )
        assert (chi_actual - chiq).norm() < tol
    E0 = tensor(Si, Si)
    E_targ = tensor(had_gate, had_gate)

elif vectorization == 'column':

    # qutip column vectorisation
    L0 = liouvillian(H0, [np.sqrt(gamma) * Sm])

    #sigma X control
    LC_x = liouvillian(Sx)
    #sigma Y control
    LC_y = liouvillian(Sy)
    #sigma Z control
    LC_z = liouvillian(Sz)

    E0 = sprepost(Si, Si)
    E_targ = sprepost(had_gate, had_gate)

else:
    raise RuntimeError("No option for vectorization={}".format(vectorization))

print("L0:\n{}\n".format(L0))
print("LC_x:\n{}\n".format(LC_x))
print("LC_y:\n{}\n".format(LC_y))
print("LC_z:\n{}\n".format(LC_z))

#Drift
drift = L0

#Controls
ctrls = [LC_x, LC_z]