示例#1
0
def sp_reshape(A, shape, format='csr'):
    """
    Reshapes a sparse matrix.

    Parameters
    ----------
    A : sparse_matrix
        Input matrix in any format
    shape : list/tuple
        Desired shape of new matrix
    format : string {'csr','coo','csc','lil'}
        Optional string indicating desired output format

    Returns
    -------
    B : csr_matrix
        Reshaped sparse matrix

    References
    ----------

        http://stackoverflow.com/questions/16511879/reshape-sparse-matrix-efficiently-python-scipy-0-12

    """
    if not hasattr(shape, '__len__') or len(shape) != 2:
        raise ValueError('Shape must be a list of two integers')

    C = A.tocoo()
    nrows, ncols = C.shape
    size = nrows * ncols
    new_size = shape[0] * shape[1]

    if new_size != size:
        raise ValueError('Total size of new array must be unchanged.')

    flat_indices = ncols * C.row + C.col
    new_row, new_col = divmod(flat_indices, shape[1])

    if format == 'csr':
        return arr_coo2fast(C.data, new_row, new_col, shape[0], shape[1])
    else:
        B = sp.coo_matrix((C.data, (new_row, new_col)), shape=shape)
        if format == 'coo':
            return B
        elif format == 'csc':
            return B.tocsc()
        elif format == 'lil':
            return B.tolil()
        else:
            raise ValueError('Return format not valid.')
示例#2
0
def sp_reshape(A, shape, format='csr'):
    """
    Reshapes a sparse matrix.

    Parameters
    ----------
    A : sparse_matrix
        Input matrix in any format
    shape : list/tuple
        Desired shape of new matrix
    format : string {'csr','coo','csc','lil'}
        Optional string indicating desired output format

    Returns
    -------
    B : csr_matrix
        Reshaped sparse matrix

    References
    ----------

        http://stackoverflow.com/questions/16511879/reshape-sparse-matrix-efficiently-python-scipy-0-12

    """
    if not hasattr(shape, '__len__') or len(shape) != 2:
        raise ValueError('Shape must be a list of two integers')

    C = A.tocoo()
    nrows, ncols = C.shape
    size = nrows * ncols
    new_size = shape[0] * shape[1]

    if new_size != size:
        raise ValueError('Total size of new array must be unchanged.')

    flat_indices = ncols * C.row + C.col
    new_row, new_col = divmod(flat_indices, shape[1])

    if format == 'csr':
        return arr_coo2fast(C.data, new_row, new_col, shape[0], shape[1])
    else:
        B = sp.coo_matrix((C.data, (new_row, new_col)), shape=shape)
        if format == 'coo':
            return B
        elif format == 'csc':
            return B.tocsc()
        elif format == 'lil':
            return B.tolil()
        else:
            raise ValueError('Return format not valid.')
示例#3
0
def bloch_redfield_tensor(H, a_ops, spectra_cb=None, c_ops=[], use_secular=True, sec_cutoff=0.1):
    """
    Calculate the Bloch-Redfield tensor for a system given a set of operators
    and corresponding spectral functions that describes the system's coupling
    to its environment.

    .. note::

        This tensor generation requires a time-independent Hamiltonian.

    Parameters
    ----------

    H : :class:`qutip.qobj`
        System Hamiltonian.

    a_ops : list of :class:`qutip.qobj`
        List of system operators that couple to the environment.

    spectra_cb : list of callback functions
        List of callback functions that evaluate the noise power spectrum
        at a given frequency.

    c_ops : list of :class:`qutip.qobj`
        List of system collapse operators.

    use_secular : bool
        Flag (True of False) that indicates if the secular approximation should
        be used.
    
    sec_cutoff : float {0.1}
        Threshold for secular approximation.

    Returns
    -------

    R, kets: :class:`qutip.Qobj`, list of :class:`qutip.Qobj`

        R is the Bloch-Redfield tensor and kets is a list eigenstates of the
        Hamiltonian.

    """
    
    if not (spectra_cb is None):
        warnings.warn("The use of spectra_cb is depreciated.", DeprecationWarning)
        _a_ops = []
        for kk, a in enumerate(a_ops):
            _a_ops.append([a,spectra_cb[kk]])
        a_ops = _a_ops
    
    # Sanity checks for input parameters
    if not isinstance(H, Qobj):
        raise TypeError("H must be an instance of Qobj")

    for a in a_ops:
        if not isinstance(a[0], Qobj) or not a[0].isherm:
            raise TypeError("Operators in a_ops must be Hermitian Qobj.")

    if c_ops is None:
        c_ops = []

    # use the eigenbasis
    evals, ekets = H.eigenstates()

    N = len(evals)
    K = len(a_ops)
    
    #only Lindblad collapse terms
    if K==0:
        Heb = qdiags(evals,0,dims=H.dims)
        L = liouvillian(Heb, c_ops=[c_op.transform(ekets) for c_op in c_ops])
        return L, ekets
    
    
    A = np.array([a_ops[k][0].transform(ekets).full() for k in range(K)])
    Jw = np.zeros((K, N, N), dtype=complex)

    # pre-calculate matrix elements and spectral densities
    # W[m,n] = real(evals[m] - evals[n])
    W = np.real(evals[:,np.newaxis] - evals[np.newaxis,:])

    for k in range(K):
        # do explicit loops here in case spectra_cb[k] can not deal with array arguments
        for n in range(N):
            for m in range(N):
                Jw[k, n, m] = a_ops[k][1](W[n, m])

    dw_min = np.abs(W[W.nonzero()]).min()

    # pre-calculate mapping between global index I and system indices a,b
    Iabs = np.empty((N*N,3),dtype=int)
    for I, Iab in enumerate(Iabs):
        # important: use [:] to change array values, instead of creating new variable Iab
        Iab[0]  = I
        Iab[1:] = vec2mat_index(N, I)

    # unitary part + dissipation from c_ops (if given):
    Heb = qdiags(evals,0,dims=H.dims)
    L = liouvillian(Heb, c_ops=[c_op.transform(ekets) for c_op in c_ops])
    
    # dissipative part:
    rows = []
    cols = []
    data = []
    for I, a, b in Iabs:
        # only check use_secular once per I
        if use_secular:
            # only loop over those indices J which actually contribute
            Jcds = Iabs[np.where(np.abs(W[a, b] - W[Iabs[:,1], Iabs[:,2]]) < dw_min * sec_cutoff)]
        else:
            Jcds = Iabs
        for J, c, d in Jcds:
            elem = 0+0j
            # summed over k, i.e., each operator coupling the system to the environment
            elem += 0.5 * np.sum(A[:, a, c] * A[:, d, b] * (Jw[:, c, a] + Jw[:, d, b]))
            if b==d:
                #                  sum_{k,n} A[k, a, n] * A[k, n, c] * Jw[k, c, n])
                elem -= 0.5 * np.sum(A[:, a, :] * A[:, :, c] * Jw[:, c, :])
            if a==c:
                #                  sum_{k,n} A[k, d, n] * A[k, n, b] * Jw[k, d, n])
                elem -= 0.5 * np.sum(A[:, d, :] * A[:, :, b] * Jw[:, d, :])
            if elem != 0:
                rows.append(I)
                cols.append(J)
                data.append(elem)

    R = arr_coo2fast(np.array(data, dtype=complex),
                    np.array(rows, dtype=np.int32),
                    np.array(cols, dtype=np.int32), N**2, N**2)
    
    L.data = L.data + R
    
    return L, ekets
示例#4
0
def _permute(Q, order):
    Qcoo = Q.data.tocoo()

    if Q.isket:
        cy_index_permute(Qcoo.row, np.array(Q.dims[0], dtype=np.int32),
                         np.array(order, dtype=np.int32))

        new_dims = [[Q.dims[0][i] for i in order], Q.dims[1]]

    elif Q.isbra:
        cy_index_permute(Qcoo.col, np.array(Q.dims[1], dtype=np.int32),
                         np.array(order, dtype=np.int32))

        new_dims = [Q.dims[0], [Q.dims[1][i] for i in order]]

    elif Q.isoper:
        cy_index_permute(Qcoo.row, np.array(Q.dims[0], dtype=np.int32),
                         np.array(order, dtype=np.int32))
        cy_index_permute(Qcoo.col, np.array(Q.dims[1], dtype=np.int32),
                         np.array(order, dtype=np.int32))

        new_dims = [[Q.dims[0][i] for i in order],
                    [Q.dims[1][i] for i in order]]

    elif Q.isoperket:
        # For superoperators, we expect order to be something like
        # [[0, 2], [1, 3]], which tells us to permute according to
        # [0, 2, 1 ,3], and then group indices according to the length
        # of each sublist.
        # As another example,
        # permuting [[[1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3]]] by
        # [[0, 3], [1, 4], [2, 5]] should give
        # [[[1, 1], [2, 2], [3, 3]], [[1, 1], [2, 2], [3, 3]]].
        #
        # Get the breakout of the left index into dims.
        # Since this is a super, the left index itself breaks into left
        # and right indices, each of which breaks down further.
        # The best way to deal with that here is to flatten dims.

        flat_order = np.array(sum(order, []), dtype=np.int32)
        q_dims = np.array(sum(Q.dims[0], []), dtype=np.int32)

        cy_index_permute(Qcoo.row, q_dims, flat_order)

        # Finally, we need to restructure the now-decomposed left index
        # into left and right subindices, so that the overall dims we return
        # are of the form specified by order.

        new_dims = [q_dims[i] for i in flat_order]
        new_dims = list(_chunk_dims(new_dims, order))
        new_dims = [new_dims, [1]]

    elif Q.isoperbra:
        flat_order = np.array(sum(order, []), dtype=np.int32)
        q_dims = np.array(sum(Q.dims[1], []), dtype=np.int32)

        cy_index_permute(Qcoo.col, q_dims, flat_order)

        new_dims = [q_dims[i] for i in flat_order]
        new_dims = list(_chunk_dims(new_dims, order))
        new_dims = [[1], new_dims]

    elif Q.issuper:
        flat_order = np.array(sum(order, []), dtype=np.int32)
        q_dims = np.array(sum(Q.dims[0], []), dtype=np.int32)

        cy_index_permute(Qcoo.row, q_dims, flat_order)
        cy_index_permute(Qcoo.col, q_dims, flat_order)

        new_dims = [q_dims[i] for i in flat_order]
        new_dims = list(_chunk_dims(new_dims, order))
        new_dims = [new_dims, new_dims]

    else:
        raise TypeError('Invalid quantum object for permutation.')

    return arr_coo2fast(Qcoo.data, Qcoo.row, Qcoo.col, Qcoo.shape[0],
                        Qcoo.shape[1]), new_dims
示例#5
0
def _permute(Q, order):
    if Q.isket:
        dims, perm = _perm_inds(Q.dims[0], order)
        nzs = Q.data.nonzero()[0]
        wh = np.where(perm == nzs)[0]
        data = np.ones(len(wh), dtype=complex)
        cols = perm[wh].T[0]
        perm_matrix = arr_coo2fast(data, wh.astype(np.int32),
                                   cols.astype(np.int32), Q.shape[0],
                                   Q.shape[0])
        return perm_matrix * Q.data, Q.dims

    elif Q.isbra:
        dims, perm = _perm_inds(Q.dims[1], order)
        nzs = Q.data.nonzero()[1]
        wh = np.where(perm == nzs)[0]
        data = np.ones(len(wh), dtype=complex)
        rows = perm[wh].T[0]
        perm_matrix = arr_coo2fast(data, rows.astype(np.int32),
                                   wh.astype(np.int32), Q.shape[1], Q.shape[1])
        return Q.data * perm_matrix, Q.dims

    elif Q.isoper:
        dims, perm = _perm_inds(Q.dims[0], order)
        data = np.ones(Q.shape[0], dtype=complex)
        rows = np.arange(Q.shape[0], dtype=np.int32)
        perm_matrix = arr_coo2fast(data, rows, (perm.T[0]).astype(np.int32),
                                   Q.shape[1], Q.shape[1])
        dims_part = list(dims[order])
        dims = [dims_part, dims_part]
        return (perm_matrix * Q.data) * perm_matrix.T, dims

    elif Q.issuper or Q.isoperket:
        # For superoperators, we expect order to be something like
        # [[0, 2], [1, 3]], which tells us to permute according to
        # [0, 2, 1 ,3], and then group indices according to the length
        # of each sublist.
        # As another example,
        # permuting [[[1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3]]] by
        # [[0, 3], [1, 4], [2, 5]] should give
        # [[[1, 1], [2, 2], [3, 3]], [[1, 1], [2, 2], [3, 3]]].
        #
        # Get the breakout of the left index into dims.
        # Since this is a super, the left index itself breaks into left
        # and right indices, each of which breaks down further.
        # The best way to deal with that here is to flatten dims.
        flat_order = sum(order, [])
        q_dims_left = sum(Q.dims[0], [])
        dims, perm = _perm_inds(q_dims_left, flat_order)
        dims = dims.flatten()

        data = np.ones(Q.shape[0], dtype=complex)
        rows = np.arange(Q.shape[0], dtype=np.int32)

        perm_matrix = arr_coo2fast(data, rows, (perm.T[0]).astype(np.int32),
                                   Q.shape[0], Q.shape[0])

        dims_part = list(dims[flat_order])

        # Finally, we need to restructure the now-decomposed left index
        # into left and right subindices, so that the overall dims we return
        # are of the form specified by order.
        dims_part = list(_chunk_dims(dims_part, order))
        perm_left = (perm_matrix * Q.data)
        if Q.type == 'operator-ket':
            return perm_left, [dims_part, [1]]
        elif Q.type == 'super':
            return perm_left * perm_matrix.T, [dims_part, dims_part]
    else:
        raise TypeError('Invalid quantum object for permutation.')
示例#6
0
def _permute(Q, order):
    Qcoo = Q.data.tocoo()
    
    if Q.isket:
        cy_index_permute(Qcoo.row,
                         np.array(Q.dims[0], dtype=np.int32),
                         np.array(order, dtype=np.int32))
        
        new_dims = [[Q.dims[0][i] for i in order], Q.dims[1]]

    elif Q.isbra:
        cy_index_permute(Qcoo.col,
                         np.array(Q.dims[1], dtype=np.int32),
                         np.array(order, dtype=np.int32))
        
        new_dims = [Q.dims[0], [Q.dims[1][i] for i in order]]

    elif Q.isoper:
        cy_index_permute(Qcoo.row,
                         np.array(Q.dims[0], dtype=np.int32),
                         np.array(order, dtype=np.int32))
        cy_index_permute(Qcoo.col,
                         np.array(Q.dims[1], dtype=np.int32),
                         np.array(order, dtype=np.int32))
        
        new_dims = [[Q.dims[0][i] for i in order], [Q.dims[1][i] for i in order]]
    
    elif Q.isoperket:
    	# For superoperators, we expect order to be something like
        # [[0, 2], [1, 3]], which tells us to permute according to
        # [0, 2, 1 ,3], and then group indices according to the length
        # of each sublist.
        # As another example,
        # permuting [[[1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3]]] by
        # [[0, 3], [1, 4], [2, 5]] should give
        # [[[1, 1], [2, 2], [3, 3]], [[1, 1], [2, 2], [3, 3]]].
        #
        # Get the breakout of the left index into dims.
        # Since this is a super, the left index itself breaks into left
        # and right indices, each of which breaks down further.
        # The best way to deal with that here is to flatten dims.
        
        flat_order = np.array(sum(order, []), dtype=np.int32)
        q_dims = np.array(sum(Q.dims[0], []), dtype=np.int32)
        
        cy_index_permute(Qcoo.row, q_dims, flat_order)
        
        # Finally, we need to restructure the now-decomposed left index
        # into left and right subindices, so that the overall dims we return
        # are of the form specified by order.
        
        new_dims = [q_dims[i] for i in flat_order]
        new_dims = list(_chunk_dims(new_dims, order))
        new_dims = [new_dims, [1]]
    
    elif Q.isoperbra:
        flat_order = np.array(sum(order, []), dtype=np.int32)
        q_dims = np.array(sum(Q.dims[1], []), dtype=np.int32)
        
        cy_index_permute(Qcoo.col, q_dims, flat_order)
        
        new_dims = [q_dims[i] for i in flat_order]
        new_dims = list(_chunk_dims(new_dims, order))
        new_dims = [[1], new_dims]
    
    elif Q.issuper:
        flat_order = np.array(sum(order, []), dtype=np.int32)
        q_dims = np.array(sum(Q.dims[0], []), dtype=np.int32)
        
        cy_index_permute(Qcoo.row, q_dims, flat_order)
        cy_index_permute(Qcoo.col, q_dims, flat_order)
        
        new_dims = [q_dims[i] for i in flat_order]
        new_dims = list(_chunk_dims(new_dims, order))
        new_dims = [new_dims, new_dims]
        
    else:
        raise TypeError('Invalid quantum object for permutation.')
    
    return arr_coo2fast(Qcoo.data, Qcoo.row, Qcoo.col, Qcoo.shape[0], Qcoo.shape[1]), new_dims
示例#7
0
def _permute(Q, order):
    if Q.isket:
        dims, perm = _perm_inds(Q.dims[0], order)
        nzs = Q.data.nonzero()[0]
        wh = np.where(perm == nzs)[0]
        data = np.ones(len(wh), dtype=complex)
        cols = perm[wh].T[0]
        perm_matrix = arr_coo2fast(data, wh.astype(np.int32), cols.astype(np.int32), 
                                Q.shape[0], Q.shape[0])
        return perm_matrix * Q.data, Q.dims

    elif Q.isbra:
        dims, perm = _perm_inds(Q.dims[1], order)
        nzs = Q.data.nonzero()[1]
        wh = np.where(perm == nzs)[0]
        data = np.ones(len(wh), dtype=complex)
        rows = perm[wh].T[0]
        perm_matrix = arr_coo2fast(data, rows.astype(np.int32), wh.astype(np.int32),
                                    Q.shape[1], Q.shape[1])
        return Q.data * perm_matrix, Q.dims

    elif Q.isoper:
        dims, perm = _perm_inds(Q.dims[0], order)
        data = np.ones(Q.shape[0], dtype=complex)
        rows = np.arange(Q.shape[0], dtype=np.int32)
        perm_matrix = arr_coo2fast(data, rows, (perm.T[0]).astype(np.int32),
                                    Q.shape[1], Q.shape[1])
        dims_part = list(dims[order])
        dims = [dims_part, dims_part]
        return (perm_matrix * Q.data) * perm_matrix.T, dims

    elif Q.issuper or Q.isoperket:
        # For superoperators, we expect order to be something like
        # [[0, 2], [1, 3]], which tells us to permute according to
        # [0, 2, 1 ,3], and then group indices according to the length
        # of each sublist.
        # As another example,
        # permuting [[[1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3]]] by
        # [[0, 3], [1, 4], [2, 5]] should give
        # [[[1, 1], [2, 2], [3, 3]], [[1, 1], [2, 2], [3, 3]]].
        #
        # Get the breakout of the left index into dims.
        # Since this is a super, the left index itself breaks into left
        # and right indices, each of which breaks down further.
        # The best way to deal with that here is to flatten dims.
        flat_order = sum(order, [])
        q_dims_left = sum(Q.dims[0], [])
        dims, perm = _perm_inds(q_dims_left, flat_order)
        dims = dims.flatten()

        data = np.ones(Q.shape[0], dtype=complex)
        rows = np.arange(Q.shape[0], dtype=np.int32)

        perm_matrix = arr_coo2fast(data, rows, (perm.T[0]).astype(np.int32),
                                    Q.shape[0], Q.shape[0])

        dims_part = list(dims[flat_order])

        # Finally, we need to restructure the now-decomposed left index
        # into left and right subindices, so that the overall dims we return
        # are of the form specified by order.
        dims_part = list(_chunk_dims(dims_part, order))
        perm_left = (perm_matrix * Q.data)
        if Q.type == 'operator-ket':
            return perm_left, [dims_part, [1]]
        elif Q.type == 'super':
            return perm_left * perm_matrix.T, [dims_part, dims_part]
    else:
        raise TypeError('Invalid quantum object for permutation.')