Ejemplo n.º 1
2
def test_partial_transpose_bipartite():
    """partial transpose of bipartite systems"""

    rho = Qobj(np.arange(16).reshape(4, 4), dims=[[2, 2], [2, 2]])

    # no transpose
    rho_pt = partial_transpose(rho, [0, 0])
    assert_(np.abs(np.max(rho_pt.full() - rho.full())) < 1e-12)

    # partial transpose subsystem 1
    rho_pt = partial_transpose(rho, [1, 0])
    rho_pt_expected = np.array([[0, 1,  8,  9],
                                [4, 5, 12, 13],
                                [2, 3, 10, 11],
                                [6, 7, 14, 15]])
    assert_(np.abs(np.max(rho_pt.full() - rho_pt_expected)) < 1e-12)

    # partial transpose subsystem 2
    rho_pt = partial_transpose(rho, [0, 1])
    rho_pt_expected = np.array([[0, 4, 2, 6],
                                [1, 5, 3, 7],
                                [8, 12, 10, 14],
                                [9, 13, 11, 15]])
    assert_(np.abs(np.max(rho_pt.full() - rho_pt_expected)) < 1e-12)

    # full transpose
    rho_pt = partial_transpose(rho, [1, 1])
    assert_(np.abs(np.max(rho_pt.full() - rho.trans().full())) < 1e-12)
Ejemplo n.º 2
0
def schm_decompo(to_decomp):
    """ Schmidt decompo of states/operators - split it in two even partites"""
    if is_ket(to_decomp):
        init_type = 'ket'
        data = to_decomp.full()
        d = int(np.sqrt(np.size(data)))
        data = np.reshape(data, [d, d])
        
    elif is_oper(to_decomp):
        init_type = 'oper'
        data = custom_reorder_2q(to_decomp.full())
    
    else:
        data=to_decomp
        if(np.ndim(data) == 1): init_type = 'ket'
        elif (np.ndim(data) == 1) and (data.shape[0] == data.shape[1]): init_type = 'oper'
        else: raise SystemError('data type/shape not understood: {} / {}'.format)
        
    U, D, Vdag = np.linalg.svd(data)
    V = np.transpose(Vdag)
    res = []
    for i, d in enumerate(D):
        if(d>1e-6):
            if(init_type == 'ket'):
                u = Qobj(np.array(U[:, i])[:, np.newaxis])
                v = Qobj(np.array(V[:, i])[:, np.newaxis])
                res.append((d, u, v))
            elif(init_type == 'oper'):
                u = Qobj(devect(U[:, i]))
                v = Qobj(devect(V[:, i]))
                res.append((d, u, v))
    return res
Ejemplo n.º 3
0
    def _compute_prop_grad(self, k, j, compute_prop=True):
        """
        Calculate the gradient of propagator wrt the control amplitude
        in the timeslot using the exponentiation of the the augmented
        matrix.
        The propagtor is calculated for 'free' in this method
        and hence it is returned if compute_prop==True
        Returns:
            [prop], prop_grad
        """
        dyn = self.parent
        dg = dyn._get_phased_dyn_gen(k)
        aug = self._get_aug_mat(k, j)

        if dyn.oper_dtype == Qobj:
            aug_exp = aug.expm()
            prop_grad = Qobj(aug_exp.data[:dg.shape[0], dg.shape[1]:],
                             dims=dyn.dyn_dims)
            if compute_prop:
                prop = Qobj(aug_exp.data[:dg.shape[0], :dg.shape[1]],
                            dims=dyn.dyn_dims)
        else:
            aug_exp = la.expm(aug)
            prop_grad = aug_exp[:dg.shape[0], dg.shape[1]:]
            if compute_prop:
                prop = aug_exp[:dg.shape[0], :dg.shape[1]]

        if compute_prop:
            return prop, prop_grad
        else:
            return prop_grad
Ejemplo n.º 4
0
 def selector(num):
     up_x = Qobj([1, 1]).unit().dag()
     down_x = Qobj([1, -1]).unit().dag()
     if num == 0:
         return up_x
     else:
         return down_x
Ejemplo n.º 5
0
def test_score(params, x, y):
    """Calculates the average fidelity 
    between the predicted and output 
    kets for a given on the whole dataset.
       
    Args:
        params (obj:`np.ndarray`): parameters 
            :math:`\t` and :math:`\tau` in :math:
            `U^{\dagger} U(\vec{t},\vec{\tau})`
        inputs (obj:`np.ndarray`): input kets 
            :math:`|\psi_{l} \rangle` in the dataset 
        outputs (obj:`np.ndarray`): output kets 
            :math:`U(\vec{t}, \vec{\tau})
            |ket_{input}\rangle` in the dataset
           
       Returns:
           float: fidelity between :math:`U(\vec{t}, 
               \vec{\tau})|ket_{input} \rangle` and the output
               (label) kets for parameters :math:`\vec{t},
               \vec{\tau}` averaged over the entire training set.
       """
    fidel = 0
    for i in range(train_len):
        pred = np.matmul(make_unitary(N, params), x[i])
        step_fidel = fidelity(Qobj(pred), Qobj(y[i]))
        fidel += step_fidel

    return fidel / train_len
Ejemplo n.º 6
0
    def test_superradiant(self):
        """
        PIQS: Test the calculation of the superradiant state density matrix.

        The state is |N/2, 0> for N even and |N/2, 0.5> for N odd.
        The matrix has size (O(N^2), O(N^2)) in Dicke basis ('dicke').
        The matrix has size (2^N, 2^N) in the uncoupled basis ('uncoupled').
        """
        N = 3
        true_state = np.zeros((6, 6))
        true_state[1, 1] = 1
        true_state = Qobj(true_state)
        test_state = superradiant(N)
        assert_equal(test_state, true_state)
        N = 4
        true_state = np.zeros((9, 9))
        true_state[2, 2] = 1
        true_state = Qobj(true_state)
        test_state = superradiant(N)
        assert_equal(test_state, true_state)

        # uncoupled
        test_state_uncoupled = superradiant(2, basis="uncoupled")
        assert_array_equal(test_state_uncoupled.dims, [[2, 2], [2, 2]])
        assert_array_equal(test_state_uncoupled.shape, (4, 4))
        assert_almost_equal(test_state_uncoupled.full()[1, 1], 1+0j)
Ejemplo n.º 7
0
def schm_decompo(to_decomp):
    """ Schmidt decompo of states/operators - split it in two even partites"""
    if (type(to_decomp) == Qobj):
        if (to_decomp.type == 'ket'):
            init_type = 'ket'
            data = to_decomp.full()
            dsquare = np.size(data)
            d = int(np.sqrt(dsquare))
            data = np.reshape(data, [d, d])

        elif (to_decomp.type == 'oper'):
            init_type = 'oper'
            data = to_decomp.full()
            data = custom_reorder(data)
    else:
        data = to_decomp
    U, D, Vdag = np.linalg.svd(data)
    V = np.transpose(Vdag)
    res = []
    for i, d in enumerate(D):
        if (d > 1e-6):
            if (init_type == 'ket'):
                u = Qobj(np.array(U[:, i])[:, np.newaxis])
                v = Qobj(np.array(V[:, i])[:, np.newaxis])
                res.append((d, u, v))
            elif (init_type == 'oper'):
                u = Qobj(devect(U[:, i]))
                v = Qobj(devect(V[:, i]))
                res.append((d, u, v))
    return res
Ejemplo n.º 8
0
def propagator_steadystate(U):
    """Find the steady state for successive applications of the propagator :math:`U`.
    
    Parameters
    ----------
    U : qobj 
        Operator representing the propagator.
    
    Returns
    ------- 
    a : qobj
        Instance representing the steady-state vector.
    
    """

    evals,evecs = la.eig(U.full())

    ev_min, ev_idx = get_min_and_index(abs(evals-1.0))

    N = int(sqrt(len(evals)))

    evecs = evecs.T
    rho = Qobj(vec2mat(evecs[ev_idx]))

    return rho * (1 / real(rho.tr()))
Ejemplo n.º 9
0
def expand_state(state: Qobj, dims):
    num_focks = dims[0][1]
    old_num_focks = state.dims[0][1]
    new_full = zeros((2 * num_focks, 1), dtype=complex)
    new_full[0:old_num_focks, 0] = state.full()[0:old_num_focks, 0]
    new_full[num_focks:num_focks + old_num_focks, 0] = state.full()[old_num_focks: , 0]
    return Qobj(new_full, dims=dims)
Ejemplo n.º 10
0
def d_sum(a: Qobj, b: Qobj) -> Qobj:
    """Perform the direct sum, or kroenecker sum of two matrices.
        Specifically here we use quantum objects. A direct sum
        simply involves taking two matrices and putting them in either 
        corner of a larger zero matrix.
        d_sum(a,b) :
        [ a   0 ]
        [ 0   b ]

    Args:
        a (Qobj): First matrix
        b (Qobj): Second matrix

    Returns:
        Qobj: Resulting matrix
    """
    tot_size = [a.shape[0] + b.shape[0], a.shape[1] + b.shape[1]]
    matrix = np.zeros(tot_size, dtype=complex)
    if isinstance(a, Qobj):
        a = a.full()
    if isinstance(b, Qobj):
        b = b.full()
    for i, row in enumerate(a):
        for j, val in enumerate(row):
            matrix[i][j] = val
    for i, row in enumerate(b):
        for j, val in enumerate(row):
            matrix[i + a.shape[0]][j + a.shape[1]] = val
    return Qobj(matrix)
Ejemplo n.º 11
0
def propagator_steadystate(U):
    """Find the steady state for successive applications of the propagator :math:`U`.
    
    Parameters
    ----------
    U : qobj 
        Operator representing the propagator.
    
    Returns
    ------- 
    a : qobj
        Instance representing the steady-state vector.
    
    """

    evals, evecs = la.eig(U.full())

    ev_min, ev_idx = get_min_and_index(abs(evals - 1.0))

    N = int(sqrt(len(evals)))

    evecs = evecs.T
    rho = Qobj(vec2mat(evecs[ev_idx]))

    return rho * (1 / real(rho.tr()))
Ejemplo n.º 12
0
    def solve_method_2(input_):
        t = 1e-6

        def Omega(_t: float, *args) -> float:
            if _t <= 0 or _t >= t:
                return 0
            # scaling = 1 / 100
            scaling = input_
            return np.sin(_t / t * np.pi) * scaling

        t_list = np.linspace(0, t, 500)
        Omegas = np.array([Omega(_t) for _t in t_list])

        area = simpson(Omegas, t_list)
        print(f"Area: {area}")

        time_independent_terms = Qobj(
            np.zeros((3, 3)) + Vdd * 1e9 * rcrt @ rcrt.T)
        Omega_coeff_terms = Qobj((rcrt @ rc1t.T + rc1t @ rcrt.T) / 2)

        solver = mesolve(
            [time_independent_terms, [Omega_coeff_terms, Omega]],
            psi_0,
            t_list,
            options=Options(store_states=True, nsteps=20000),
        )
        c_r1 = np.abs(solver.states[-1].data[1, 0])
        return c_r1
Ejemplo n.º 13
0
def test_povm():
    """
    Test if povm formulation works correctly by checking probabilities for
    the quantum state discrimination example
    """

    coeff = (sqrt(2) / (1 + sqrt(2)))

    E_1 = coeff * ket2dm(basis(2, 1))
    E_2 = coeff * ket2dm((basis(2, 0) - basis(2, 1)) / (sqrt(2)))
    E_3 = identity(2) - E_1 - E_2

    M_1 = Qobj(scipy.linalg.sqrtm(E_1))
    M_2 = Qobj(scipy.linalg.sqrtm(E_2))
    M_3 = Qobj(scipy.linalg.sqrtm(E_3))

    ket1 = basis(2, 0)
    ket2 = (basis(2, 0) + basis(2, 1)) / (sqrt(2))

    dm1 = ket2dm(ket1)
    dm2 = ket2dm(ket2)

    M = [M_1, M_2, M_3]

    _, probabilities = measurement_statistics_povm(ket1, M)
    np.testing.assert_allclose(probabilities, [0, 0.293, 0.707], 0.001)

    _, probabilities = measurement_statistics_povm(ket2, M)
    np.testing.assert_allclose(probabilities, [0.293, 0, 0.707], 0.001)

    _, probabilities = measurement_statistics_povm(dm1, M)
    np.testing.assert_allclose(probabilities, [0, 0.293, 0.707], 0.001)

    _, probabilities = measurement_statistics_povm(dm2, M)
    np.testing.assert_allclose(probabilities, [0.293, 0, 0.707], 0.001)
Ejemplo n.º 14
0
def rand_ket(N,density=1,dims=None):
    """Creates a random Nx1 sparse ket vector.
    
    Parameters
    ----------
    N : int
        Number of rows for output quantum operator.
    density : float
        Density between [0,1] of output ket state.
    
    Returns
    -------
    oper : qobj
        Nx1 ket state quantum operator.
        
    Other Parameters
    ----------------
    dims : list 
        Dimensions of quantum object.  Used for specifying
        tensor structure. Default is dims=[[N],[1]].
    
    
    """
    if dims:
        _check_dims(dims,N,1)
    X = sp.rand(N,1,density,format='csr')
    X.data=X.data-0.5
    Y=X.copy()
    Y.data=1.0j*np.random.random(len(X.data))-(0.5+0.5j)
    X=X+Y
    X=Qobj(X)
    if dims:
        return Qobj(X/X.norm(),dims=dims,shape=[N,1])
    else:
        return Qobj(X/X.norm())
Ejemplo n.º 15
0
    def __init__(self,
                 interaction: LaserInteraction,
                 init_state: Qobj,
                 target_state: Qobj,
                 num_steps: int,
                 energy_weight: float = 0,
                 max_energy: float = 0,
                 step_duration: float = 1):
        assert isinstance(init_state, Qobj)
        assert init_state.isket
        assert isinstance(target_state, Qobj)
        assert target_state.isket
        assert isinstance(interaction, LaserInteraction)

        self._interaction = interaction
        self._init_state = init_state.full()
        self._target_state = target_state.full()
        self._num_steps = num_steps
        self._energy_weight = energy_weight
        self._max_energy = max_energy
        self._step_duration = step_duration

        self._c_ops = [op.full() for op in interaction.control_operators]

        self._optim_records = []

        self._cache_param_vec = None
        self._cache_evolved_state = None
Ejemplo n.º 16
0
    def test_k(self):
        """
        lattice: Test the method Lattice1d.k().
        """
        L = 7
        lattice_L123 = Lattice1d(num_cell=L,
                                 boundary="periodic",
                                 cell_num_site=1,
                                 cell_site_dof=[2, 3])
        kq = lattice_L123.k()
        kop = np.zeros((L, L), dtype=complex)
        for row in range(L):
            for col in range(L):
                if row == col:
                    kop[row, col] = (L - 1) / 2
                else:
                    kop[row,
                        col] = 1 / (np.exp(2j * np.pi * (row - col) / L) - 1)

        kt = np.kron(kop * 2 * np.pi / L, np.eye(6))
        dim_H = [[2, 2, 3], [2, 2, 3]]
        kt = Qobj(kt, dims=dim_H)

        [k_q, Vq] = kq.eigenstates()
        [k_t, Vt] = kt.eigenstates()
        k_tC = k_t - 2 * np.pi / L * ((L - 1) // 2)
        # k_ts = [(i-(L-1)//2)*2*np.pi/L for i in range(L)]
        # k_w = np.kron((np.array(k_ts)).T, np.ones((1,6)))
        assert_((np.abs(k_tC - k_q) < 1E-13).all())
Ejemplo n.º 17
0
    def test_cell_periodic_parts(self):
        """
        lattice: Test the method Lattice1d.array_of_unk().
        """
        # Coupled Resonator Optical Waveguide(CROW) Example(PhysRevB.99.224201)
        J = 2
        eta = np.pi / 4
        H_cell = Qobj(np.array([[0, J * np.sin(eta)], [J * np.sin(eta), 0]]))
        inter_cell_T0 = (J / 2) * Qobj(
            np.array([[np.exp(eta * 1j), 0], [0, np.exp(-eta * 1j)]]))
        inter_cell_T1 = (J / 2) * Qobj(np.array([[0, 1], [1, 0]]))

        inter_cell_T = [inter_cell_T0, inter_cell_T1]

        CROW_lattice = Lattice1d(num_cell=4,
                                 boundary="periodic",
                                 cell_num_site=1,
                                 cell_site_dof=[2],
                                 Hamiltonian_of_cell=H_cell,
                                 inter_hop=inter_cell_T)
        (kxA, val_kns) = CROW_lattice.get_dispersion()
        (knxA, vec_kns) = CROW_lattice.cell_periodic_parts()
        (knxA, qH_ks) = CROW_lattice.bulk_Hamiltonians()
        for i in range(4):
            for j in range(2):
                if val_kns[j][i] == 0:
                    E_V = Qobj(vec_kns[i, j, :])
                    eE_V = qH_ks[i] * E_V
                    assert_(np.max(abs(eE_V)) < 1.0E-12)
                else:
                    E_V = Qobj(vec_kns[i, j, :])
                    eE_V = qH_ks[i] * E_V
                    qE_V = np.divide(eE_V, E_V)
                    oE = val_kns[j][i] * np.ones((2, 1))
                    assert_(np.max(abs(oE - qE_V)) < 1.0E-12)
Ejemplo n.º 18
0
def split_AB(m, block_info, n, as_qobj=False):
    """Split a sparse matrix into two block-diagonal matrices

    Args:
        m (scipy.sparse.spmatrix or qutip.Qobj): The sparse matrix to operate
            on
        block_info (np.ndarray): Array of block size information
        n (int): dimension of `m`

    Returns:
        tuple[scipy.sparse.csr_matrix]: a tuple of two sparse matrices, where
        each matrix is block-diagonal

    Assumptions on `m`:
        - contains data only in the upper triangle
        - consists of rectangular blocks sitting on the diagonal

    The size of the rectangular blocks is specified in the `block_info` array
    (0 values in that array are discarded). The values in `block_info` is the
    number of rows in each consecutive block.

    The matrix is split in such a way that alternating blocks are separated
    into alternating result matrices. This guarantees that the two resulting
    matrices are block diagonal (with only the upper-left quadrant of each
    block non-zero)
    """
    if isinstance(m, Qobj):
        m = m.data
    assert (scipy.sparse.triu(m) - m).nnz == 0
    m_coo = m.tocoo()
    assert np.all(np.sort(m_coo.row) == m_coo.row)
    assert block_info.dtype == np.int32
    data, row, col, nnz = m_coo.data, m_coo.row, m_coo.col, m_coo.nnz
    block_info = iter([n for n in block_info if n != 0])
    selector = 1
    n_row_limit = next(block_info) - 1  # how far can we look ahead?
    AB = {
        0: {'data': [], 'row': [], 'col': []},
        1: {'data': [], 'row': [], 'col': []},
    }
    for k in range(nnz):
        i = row[k]
        j = col[k]
        v = data[k]
        if i > n_row_limit:
            n_row_limit += next(block_info)
            selector = (selector + 1) % 2  # toggle 0↔1
        AB[selector]['data'].append(v)
        AB[selector]['row'].append(i)
        AB[selector]['col'].append(j)
    res = tuple(
        scipy.sparse.coo_matrix(
            (np.array(d['data']), (np.array(d['row']), np.array(d['col']))),
            shape=(n, n),
        ).tocsr()
        for d in [AB[0], AB[1]]
    )
    if as_qobj:
        res = Qobj(res[0]), Qobj(res[1])
    return res
Ejemplo n.º 19
0
    def test_excited(self):
        """
        PIQS: Test the calculation of the totally excited state density matrix.

        The matrix has size (O(N^2), O(N^2)) in Dicke basis ('dicke').
        The matrix has size (2^N, 2^N) in the uncoupled basis ('uncoupled').
        """
        N = 3
        true_state = np.zeros((6, 6))
        true_state[0, 0] = 1
        true_state = Qobj(true_state)

        test_state = excited(N)
        assert_equal(test_state, true_state)

        N = 4
        true_state = np.zeros((9, 9))
        true_state[0, 0] = 1
        true_state = Qobj(true_state)

        test_state = excited(N)
        assert_equal(test_state, true_state)

        # uncoupled
        test_state_uncoupled = excited(2, basis="uncoupled")
        assert_array_equal(test_state_uncoupled.dims, [[2, 2], [2, 2]])
        assert_array_equal(test_state_uncoupled.shape, (4, 4))
        assert_almost_equal(test_state_uncoupled.full()[0, 0], 1+0j)
Ejemplo n.º 20
0
def rand_unitary(N, density=0.75, dims=None):
    """Creates a random NxN sparse unitary quantum object.
    
    Uses :math:`\exp(-iH)` where H is a randomly generated 
    Hermitian operator.
    
    Parameters
    ----------
    N : int
        Shape of output quantum operator.
    density : float
        Density between [0,1] of output Unitary operator.
    
    Returns
    -------
    oper : qobj
        NxN Unitary quantum operator.
        
    Other Parameters
    ----------------
    dims : list 
        Dimensions of quantum object.  Used for specifying
        tensor structure. Default is dims=[[N],[N]].
    
    
    """
    if dims:
        _check_dims(dims, N, N)
    U = (-1.0j * rand_herm(N, density)).expm()
    if dims:
        return Qobj(U, dims=dims, shape=[N, N])
    else:
        return Qobj(U)
Ejemplo n.º 21
0
 def test_extract(self):
     ados = self.mk_ados([2, 3], max_depth=2)
     rho, ado_soln = self.mk_rho_and_soln(ados, [[2], [2]])
     ado_state = HierarchyADOsState(rho, ados, ado_soln)
     ado_state.extract((0, 0)) == rho
     ado_state.extract(0) == rho
     ado_state.extract((0, 1)) == Qobj(ado_soln[1, :], dims=rho.dims)
     ado_state.extract(1) == Qobj(ado_soln[1, :], dims=rho.dims)
 def __init__(self, matrix: Qobj):
     matrix.isherm = True
     self.H = matrix
     self.N = N_from_qobj(matrix)
     self.npH = qobj_to_np(self.H)
     self.min_eigenvalue = matrix.eigenenergies()[0]
     self.classical_psi0 = min(range(2**self.N), key=lambda i: expected_value(self.npH, classical_state(self.N, i)))
     self.classical_psi0_bitstring = ('{:0' + str(self.N) + 'b}').format(self.classical_psi0)
Ejemplo n.º 23
0
    def test_lindbladian(self):
        """
        PIQS: Test the generation of the Lindbladian matrix.
        """
        N = 1
        gCE = 0.5
        gCD = 0.5
        gCP = 0.5
        gE = 0.1
        gD = 0.1
        gP = 0.1

        system = Dicke(N=N, emission=gE, pumping=gP, dephasing=gD,
                       collective_emission=gCE, collective_pumping=gCP,
                       collective_dephasing=gCD)

        lindbladian = system.lindbladian()
        Ldata = np.zeros((4, 4), dtype="complex")
        Ldata[0] = [-0.6, 0, 0, 0.6]
        Ldata[1] = [0, -0.9, 0, 0]
        Ldata[2] = [0, 0, -0.9, 0]
        Ldata[3] = [0.6, 0, 0, -0.6]

        lindbladian_correct = Qobj(Ldata, dims=[[[2], [2]], [[2], [2]]],
                                   shape=(4, 4))
        assert_array_almost_equal(lindbladian.data.toarray(), Ldata)
        N = 2
        gCE = 0.5
        gCD = 0.5
        gCP = 0.5
        gE = 0.1
        gD = 0.1
        gP = 0.1
        system = Dicke(N=N, emission=gE, pumping=gP, dephasing=gD,
                       collective_emission=gCE, collective_pumping=gCP,
                       collective_dephasing=gCD)

        lindbladian = system.lindbladian()

        Ldata = np.zeros((16, 16), dtype="complex")
        Ldata[0][0], Ldata[0][5], Ldata[0][15] = -1.2, 1.1, 0.1
        Ldata[1, 1], Ldata[1, 6] = -2, 1.1
        Ldata[2, 2] = -2.2999999999999998
        Ldata[4, 4], Ldata[4, 9] = -2, 1.1
        Ldata[5, 0], Ldata[5, 5], Ldata[5, 10], Ldata[5, 15] = (1.1, -2.25,
                                                                1.1, 0.05)
        Ldata[6, 1], Ldata[6, 6] = 1.1, -2
        Ldata[8, 8] = -2.2999999999999998
        Ldata[9, 4], Ldata[9, 9] = 1.1, -2
        Ldata[10, 5], Ldata[10, 10], Ldata[10, 15] = 1.1, -1.2, 0.1
        Ldata[15, 0], Ldata[15, 5], Ldata[15, 10], Ldata[15, 15] = (0.1,
                                                                    0.05,
                                                                    0.1,
                                                                    -0.25)
        lindbladian_correct = Qobj(Ldata, dims=[[[4], [4]], [[4], [4]]],
                                   shape=(16, 16))
        assert_array_almost_equal(lindbladian.data.toarray(), Ldata)
Ejemplo n.º 24
0
def qobj_to_np(obj: Qobj) -> np.ndarray:
    if obj.isket:
        return obj.full().flatten()
    elif obj.isbra:
        return obj.full().flatten().conj()
    elif obj.isoper:
        return obj.full()
    else:
        raise ValueError("Qobj is not ket or bra")
Ejemplo n.º 25
0
def split_AB_blocks(m, block_info, n, as_qobj=False):
    """Split a sparse matrix into two block-diagonal matrices

    Args:
        m (scipy.sparse.spmatrix): The sparse matrix to operator on
        block_info (np.ndarray): Array of block size information
        n (int): dimension of `m`

    Returns:
        tuple[list[scipy.sparse.csr_matrix]]: a tuple of two "buckets" A, B
        ...

    Assumptions on `m`:
        - contains data only in the upper triangle
        - consists of rectangular blocks sitting on the diagonal

    TODO
    """
    if isinstance(m, Qobj):
        m = m.data
    assert (scipy.sparse.triu(m) - m).nnz == 0
    m_coo = m.tocoo()
    assert np.all(np.sort(m_coo.row) == m_coo.row)
    assert block_info.dtype == np.int32
    data, row, col, nnz = m_coo.data, m_coo.row, m_coo.col, m_coo.nnz
    block_info = iter([n for n in block_info if n != 0])
    selector = 0
    n_row_limit = next(block_info) - 1  # how far can we look ahead?
    AB = {0: [], 1: []}
    block_data, block_row, block_col = [], [], []
    for k in range(nnz):
        i = row[k]
        j = col[k]
        v = data[k]
        if i > n_row_limit:
            n_row_limit += next(block_info)
            selector = (selector + 1) % 2  # toggle 0↔1
            if len(block_data) > 0:
                block = scipy.sparse.coo_matrix(
                    (block_data, (block_row, block_col)), shape=(n, n)
                )
                if as_qobj:
                    block = Qobj(block)
                AB[selector].append(block)
                block_data, block_row, block_col = [], [], []
        block_data.append(v)
        block_row.append(i)
        block_col.append(j)
    if len(block_data) > 0:
        selector = (selector + 1) % 2  # toggle 0↔1
        block = scipy.sparse.coo_matrix(
            (block_data, (block_row, block_col)), shape=(n, n)
        )
        if as_qobj:
            block = Qobj(block)
        AB[selector].append(block)
    return AB[0], AB[1]
Ejemplo n.º 26
0
def test_Transformation4():
    "Transform 10-level imag to eigenbasis and back"
    N = 10
    H1 = Qobj(1j * (0.5 - scipy.rand(N, N)))
    H1 = H1 + H1.dag()
    evals, ekets = H1.eigenstates()
    Heb = H1.transform(ekets)        # eigenbasis (should be diagonal)
    H2 = Heb.transform(ekets, True)  # back to original basis
    assert_equal((H1 - H2).norm() < 1e-6, True)
Ejemplo n.º 27
0
def test_Transformation4():
    "Transform 10-level imag to eigenbasis and back"
    N = 10
    H1 = Qobj(1j * (0.5 - scipy.rand(N, N)))
    H1 = H1 + H1.dag()
    evals, ekets = H1.eigenstates()
    Heb = H1.transform(ekets)  # eigenbasis (should be diagonal)
    H2 = Heb.transform(ekets, True)  # back to original basis
    assert_equal((H1 - H2).norm() < 1e-6, True)
Ejemplo n.º 28
0
    def get_dispersion(self, knpoints=0):
        """
        Returns dispersion relationship for the lattice with the specified
        number of unit cells with a k array and a band energy array.

        Returns
        -------
        knxa : np.array
            knxA[j][0] is the jth good Quantum number k.

        val_kns : np.array
            val_kns[j][:] is the array of band energies of the jth band good at
            all the good Quantum numbers of k.
        """
        # The _k_space_calculations() function is not used for get_dispersion
        # because we calculate the infinite crystal dispersion in
        # plot_dispersion using this coode and we do not want to calculate
        # all the eigen-values, eigenvectors of the bulk Hamiltonian for too
        # many points, as is done in the _k_space_calculations() function.
        if self.period_bnd_cond_x == 0:
            raise Exception("The lattice is not periodic.")
        if knpoints == 0:
            knpoints = self.num_cell

        a = 1  # The unit cell length is always considered 1
        kn_start = 0
        kn_end = 2*np.pi/a
        val_kns = np.zeros((self._length_of_unit_cell, knpoints), dtype=float)
        knxA = np.zeros((knpoints, 1), dtype=float)
        G0_H = self._H_intra
#        knxA = np.roll(knxA, np.floor_divide(knpoints, 2))

        for ks in range(knpoints):
            knx = kn_start + (ks*(kn_end-kn_start)/knpoints)

            if knx >= np.pi:
                knxA[ks, 0] = knx - 2 * np.pi
            else:
                knxA[ks, 0] = knx
        knxA = np.roll(knxA, np.floor_divide(knpoints, 2))

        for ks in range(knpoints):
            kx = knxA[ks, 0]
            H_ka = G0_H
            k_cos = [[kx]]
            for m in range(len(self._H_inter_list)):
                r_cos = self._inter_vec_list[m]
                kr_dotted = np.dot(k_cos, r_cos)
                H_int = self._H_inter_list[m]*np.exp(kr_dotted*1j)[0]
                H_ka = H_ka + H_int + H_int.dag()
            H_k = csr_matrix(H_ka)
            qH_k = Qobj(H_k)
            (vals, veks) = qH_k.eigenstates()
            val_kns[:, ks] = vals[:]
        return (knxA, val_kns)
Ejemplo n.º 29
0
    def solve(self, rho0, tlist, options=None, progress=None):
        """
        Solve the Hierarchy equations of motion for the given initial
        density matrix and time.
        """
        if options is None:
            options = Options()

        output = Result()
        output.solver = "hsolve"
        output.times = tlist
        output.states = []
        output.states.append(Qobj(rho0))

        dt = np.diff(tlist)
        rho_he = np.zeros(self.hshape, dtype=np.complex)
        rho_he[0] = rho0.full().ravel("F")
        rho_he = rho_he.flatten()

        self.rhs()
        L_helems = self.L_helems.asformat("csr")
        r = ode(cy_ode_rhs)
        r.set_f_params(L_helems.data, L_helems.indices, L_helems.indptr)
        r.set_integrator(
            "zvode",
            method=options.method,
            order=options.order,
            atol=options.atol,
            rtol=options.rtol,
            nsteps=options.nsteps,
            first_step=options.first_step,
            min_step=options.min_step,
            max_step=options.max_step,
        )

        r.set_initial_value(rho_he, tlist[0])
        dt = np.diff(tlist)
        n_tsteps = len(tlist)

        if progress:
            bar = progress(total=n_tsteps - 1)
        for t_idx, t in enumerate(tlist):
            if t_idx < n_tsteps - 1:
                r.integrate(r.t + dt[t_idx])
                r1 = r.y.reshape(self.hshape)
                r0 = r1[0].reshape(self.N, self.N).T
                output.states.append(Qobj(r0))

                r_heom = r.y.reshape(self.hshape)
                self.full_hierarchy.append(r_heom)

                if progress:
                    bar.update()
        return output
Ejemplo n.º 30
0
    def __init__(self,N):
        self.N = N
        self.dims = [2]*self.N
        self.ansatzes = []
        self.structures = []
        self.para = []

        self.qc = None      # Generate circuit on demand

        self.statein = Qobj()
        self.stateout = Qobj()
Ejemplo n.º 31
0
    def sync(self,
             state=None,
             t_bath=None,
             y_0=None,
             hu=None,
             htl=None,
             e_ops=None,
             args=None):
        """ sync data into kernel environment. """
        assert self.compiled

        self.synced = False

        self._validate_sync_args(state, t_bath, y_0, hu, htl, e_ops)

        if state is not None:
            self.state = npmat_manylike(self.system.h0, state)
        if hu is not None:
            self.hu = npmat_manylike(self.system.h0, hu)
        if t_bath is not None:
            self.t_bath = vectorize(t_bath, dtype=QOP.T_FLOAT)
            assert np.all(self.t_bath >= 0)
        if y_0 is not None:
            self.y_0 = vectorize(y_0, dtype=QOP.T_FLOAT)
            assert np.all(self.y_0 >= 0)
        if args is not None:
            self.args = args
            #assert np.all(self.args >= 0)

        # XXX todo make observables listable
        if self.n_e_ops > 0 and e_ops is not None:
            self.e_ops = npmat_manylike(self.system.h0, e_ops)
            assert len(self.e_ops) == self.n_e_ops
            self.q_e_ops = [Qobj(e) for e in self.e_ops]

        # XXX todo make time dependent operators listable
        if self.n_htl > 0 and htl is not None:
            self.htl = list(htl)
            assert len(self.htl) == self.n_htl
            self.q_htl = [[Qobj(sqmat(ht[0])), ht[1]] for ht in self.htl]

        # normalize all buffers such that length are the same.
        tb = self.t_bath if self.t_bath is not None else [0.0]
        self.q_state, \
        self.q_hu, \
        self.n_dst, \
        self.r_y_0 = self._sync_fill_up(
            q_state = [Qobj(s) for s in self.state],
            q_hu    = [Qobj(hu) for hu in self.hu],
            n_dst   = [boson_stat(t) for t in tb],
            r_y_0   = self.y_0 if self.y_0 is not None else np.array([0.0], dtype=QOP.T_FLOAT))

        self.synced = True
Ejemplo n.º 32
0
    def sweep_diagonalize_full_Hamiltonian(self, sweep_variable):
        """Diagonalizes the coupled circuit and resonator Hamiltonian.

        Args:
            sweep_variable (str): Name of the parameter to sweep.

        Returns:
           None. 

        """

        a = tensor(destroy(sim_settings.NFOCK),
                   qeye(self.keig))  # annihilation operator
        adg = a.dag()  # creation operator

        # Create the resonator Hamiltonian in the resonator + qubit basis.
        H_resonator = self.f_resonator * (adg * a)

        sweep_vector = getattr(self, sweep_variable + '_ls')

        sweep_evals = []
        sweep_idx = 0
        for sweep_point in tqdm(sweep_vector):

            # Create the qubit Hamiltonian in the resonator + qubit basis.
            H = Qobj(diags(self.evals[sweep_idx, :]))
            H_qubit = tensor(qeye(sim_settings.NFOCK), H)

            # Create the coupling Hamiltonian in the resonator + qubit basis.
            H_coupling = tensor(qeye(sim_settings.NFOCK),
                                Qobj(self.g[sweep_idx, :, :])) * (a + adg)

            # Create the full Hamiltonian.
            H_full = H_qubit + H_resonator + H_coupling

            # Diagonalize the full Hamiltonian.
            evals, _ = H_full.eigenstates(sparse=False,
                                          sort='low',
                                          eigvals=self.keig *
                                          sim_settings.NFOCK,
                                          tol=sim_settings.DIAG_TOL)
            evals = evals - evals[0]

            sweep_evals.append(
                dict(evals_full=evals))  # Append the result to the list.
            sweep_idx += 1

        # Convert the list to the attribute.
        setattr(self, 'evals_full',
                self.extract_results('evals_full', sweep_evals))

        return
Ejemplo n.º 33
0
 def test_basis(self):
     """
     lattice: Test the method Lattice1d.basis().
     """
     lattice_3242 = Lattice1d(num_cell=3,
                              boundary="periodic",
                              cell_num_site=2,
                              cell_site_dof=[4, 2])
     psi0 = lattice_3242.basis(1, 0, [2, 1])
     psi0dag_a = np.zeros((1, 48), dtype=complex)
     psi0dag_a[0, 21] = 1
     psi0dag = Qobj(psi0dag_a, dims=[[1, 1, 1, 1], [3, 2, 4, 2]])
     assert_(psi0 == psi0dag.dag())
Ejemplo n.º 34
0
    def test_ghz(self):
        """
        PIQS: Test the calculation of the density matrix of the GHZ state.

        PIQS: Test for N = 2 in the 'dicke' and in the 'uncoupled' basis.
        """
        ghz_dicke = Qobj([[0.5, 0, 0.5, 0], [0, 0, 0, 0],
                          [0.5, 0, 0.5, 0], [0, 0, 0, 0]])
        ghz_uncoupled = Qobj([[0.5, 0, 0, 0.5], [0, 0, 0, 0],
                              [0, 0, 0, 0], [0.5, 0, 0, 0.5]])
        ghz_uncoupled.dims = [[2, 2], [2, 2]]
        assert_equal(ghz(2), ghz_dicke)
        assert_equal(ghz(2, "uncoupled"), ghz_uncoupled)
Ejemplo n.º 35
0
    def test_ghz(self):
        """
        PIQS: Test the calculation of the density matrix of the GHZ state.

        PIQS: Test for N = 2 in the 'dicke' and in the 'uncoupled' basis.
        """
        ghz_dicke = Qobj([[0.5, 0, 0.5, 0], [0, 0, 0, 0],
                          [0.5, 0, 0.5, 0], [0, 0, 0, 0]])
        ghz_uncoupled = Qobj([[0.5, 0, 0, 0.5], [0, 0, 0, 0],
                              [0, 0, 0, 0], [0.5, 0, 0, 0.5]])
        ghz_uncoupled.dims = [[2, 2], [2, 2]]
        assert_equal(ghz(2), ghz_dicke)
        assert_equal(ghz(2, "uncoupled"), ghz_uncoupled)
Ejemplo n.º 36
0
 def test_lindbladian_dims(self):
     """
     PIQS: Test the calculation of the lindbladian matrix.
     """
     true_L = [[-4, 0, 0, 3], [0, -3.54999995, 0, 0],
               [0, 0, -3.54999995, 0], [4, 0, 0, -3]]
     true_L = Qobj(true_L)
     true_L.dims = [[[2], [2]], [[2], [2]]]
     N = 1
     test_dicke = _Dicke(N=N, pumping=1, collective_pumping=2,
                         emission=1, collective_emission=3,
                         dephasing=0.1)
     test_L = test_dicke.lindbladian()
     assert_array_almost_equal(test_L.full(), true_L.full())
     assert_array_equal(test_L.dims, true_L.dims)
Ejemplo n.º 37
0
def rand_herm(N,density=0.75,dims=None):
    """Creates a random NxN sparse Hermitian quantum object.
    
    Uses :math:`H=X+X^{+}` where :math:`X` is
    a randomly generated quantum operator with a given `density`.
    
    Parameters
    ----------
    N : int
        Shape of output quantum operator.
    density : float
        Density etween [0,1] of output Hermitian operator.
    
    Returns
    -------
    oper : qobj
        NxN Hermitian quantum operator.
        
    Other Parameters
    ----------------
    dims : list 
        Dimensions of quantum object.  Used for specifying
        tensor structure. Default is dims=[[N],[N]].
    
    
    """
    if dims:
        _check_dims(dims,N,N)
    # to get appropriate density of output
    # Hermitian operator must convert via:
    herm_density=2.0*arcsin(density)/pi
    
    X = sp.rand(N,N,herm_density,format='csr')
    X.data=X.data-0.5
    Y=X.copy()
    Y.data=1.0j*np.random.random(len(X.data))-(0.5+0.5j)
    X=X+Y
    X=Qobj(X)
    if dims:
        return Qobj((X+X.dag())/2.0,dims=dims,shape=[N,N])
    else:
        return Qobj((X+X.dag())/2.0)
Ejemplo n.º 38
0
def floquet_master_equation_tensor(Alist, f_energies):
    """
    Construct a tensor that represents the master equation in the floquet
    basis (with constant Hamiltonian and collapse operators).
    
    Simplest RWA approximation [Grifoni et al, Phys.Rep. 304 229 (1998)]
    """

    if isinstance(Alist, list):
        # Alist can be a list of rate matrices corresponding
        # to different operators that couple to the environment
        N, M = shape(Alist[0])
    else:
        # or a simple rate matrix, in which case we put it in a list
        Alist = [Alist]
        N, M = shape(Alist[0])
      
    R = Qobj(scipy.sparse.csr_matrix((N*N,N*N)), [[N,N], [N,N]], [N*N,N*N])

    R.data=R.data.tolil()      
    for I in range(N*N):
        a,b = vec2mat_index(N, I)
        for J in range(N*N):
            c,d = vec2mat_index(N, J)

            R.data[I,J] = - 1.0j * (f_energies[a]-f_energies[b]) * (a == c) * (b == d)
                    
            for A in Alist:               
                s1 = s2 = 0
                for n in range(N):
                    s1 += A[a,n] * (n == c) * (n == d) - A[n,a] * (a == c) * (a == d)
                    s2 += (A[n,a] + A[n,b]) * (a == c) * (b == d)
                       
                dR = (a == b) * s1 - 0.5 * (1 - (a == b)) * s2
                            
                if dR != 0.0:
                    R.data[I,J] += dR

    R.data=R.data.tocsr()
    return R                   
Ejemplo n.º 39
0
    def _compute_prop_grad(self, k, j, compute_prop=True):
        """
        Calculate the gradient of propagator wrt the control amplitude
        in the timeslot.

        Returns:
            [prop], prop_grad
        """
        dyn = self.parent
        dyn._ensure_decomp_curr(k)

        if compute_prop:
            prop = self._compute_propagator(k)

        if dyn.oper_dtype == Qobj:
            # put control dyn_gen in combined dg diagonal basis
            cdg =  (dyn._get_dyn_gen_eigenvectors_adj(k)*
                        dyn._get_phased_ctrl_dyn_gen(k, j)*
                        dyn._dyn_gen_eigenvectors[k])
            # multiply (elementwise) by timeslice and factor matrix
            cdg = Qobj(np.multiply(cdg.full()*dyn.tau[k],
                        dyn._dyn_gen_factormatrix[k]), dims=dyn.dyn_dims)
            # Return to canonical basis
            prop_grad = (dyn._dyn_gen_eigenvectors[k]*cdg*
                        dyn._get_dyn_gen_eigenvectors_adj(k))
        else:
            # put control dyn_gen in combined dg diagonal basis
            cdg =  dyn._get_dyn_gen_eigenvectors_adj(k).dot(
                        dyn._get_phased_ctrl_dyn_gen(k, j)).dot(
                        dyn._dyn_gen_eigenvectors[k])
            # multiply (elementwise) by timeslice and factor matrix
            cdg = np.multiply(cdg*dyn.tau[k], dyn._dyn_gen_factormatrix[k])
            # Return to canonical basis
            prop_grad = dyn._dyn_gen_eigenvectors[k].dot(cdg).dot(
                        dyn._get_dyn_gen_eigenvectors_adj(k))

        if compute_prop:
            return prop, prop_grad
        else:
            return prop_grad
Ejemplo n.º 40
0
def spre(A):
    """Superoperator formed from pre-multiplication by operator A.
    
    Parameters
    ----------
    A : qobj
        Quantum operator for pre-multiplication.
    
    Returns
    --------
    super :qobj
        Superoperator formed from input quantum object.
    
    """
    if not isoper(A):
        raise TypeError("Input is not a quantum object")
    d = A.dims[1]
    S = Qobj()
    S.dims = [[A.dims[0][:], d[:]], [A.dims[1][:], d[:]]]
    S.shape = [prod(S.dims[0][0]) * prod(S.dims[0][1]), prod(S.dims[1][0]) * prod(S.dims[1][1])]
    S.data = sp.kron(sp.identity(prod(d)), A.data, format="csr")
    return S
Ejemplo n.º 41
0
def spost(A):
	"""Superoperator formed from post-multiplication by operator A

    Parameters
    ----------
    A : qobj
        Quantum operator for post multiplication.
    
    Returns
    -------
    super : qobj
       Superoperator formed from input qauntum object.
	"""
	if not isoper(A):
		raise TypeError('Input is not a quantum object')

	d=A.dims[0]
	S=Qobj()
	S.dims=[[d[:],A.dims[1][:]],[d[:],A.dims[0][:]]]
	S.shape=[prod(S.dims[0][0])*prod(S.dims[0][1]),prod(S.dims[1][0])*prod(S.dims[1][1])]
	S.data=sp.kron(A.data.T,sp.identity(prod(d)))
	return Qobj(S)
    def probabilities(self, out_state, sort=False):
        
        state_copy = out_state.full().copy()
        length = state_copy.shape[0]-len(self.state.indistinguishable_states)
        new_state = np.zeros((length,1),dtype=np.complex128)
        new_dict = {}
        
        for i,(label,dim) in enumerate(self.state.reduced_label_map.iteritems()):
            
            reverse_label = "_".join(label.split('_')[::-1])
            if (label, reverse_label) in self.state.indistinguishable_states.keys():
                if (label, reverse_label) not in new_dict.keys():
                    new_key = (label, reverse_label)
                    new_dict[new_key] = np.complex128(0)
                    dims_to_add = self.state.indistinguishable_states[(label, reverse_label)]
                    for dim in dims_to_add:
                        new_dict[new_key] += state_copy[dim]
            else:
                if (label) not in new_dict.keys():
                    if (reverse_label) not in new_dict.keys():
                        if (label, reverse_label) not in self.state.indistinguishable_states.keys():
                            if (reverse_label, label) not in self.state.indistinguishable_states.keys():
                                new_dict[(label)] = state_copy[dim]
        
        new_state  = np.array(new_dict.values())
        new_qstate = Qobj(new_state).unit()
        prob_array = new_qstate.conj().full()*new_qstate.full()
    
        probs = {lab: prob                  for  lab,prob  in  zip(new_dict.keys(), prob_array)}
        probs = {lab: prob.real.tolist()[0] for  lab,prob  in  probs.iteritems()               }

        # Check that probabilities add to one
        np.testing.assert_almost_equal(sum(probs.values()),1.0,decimal=5)

        # Return list if sort=True, else return dict
        if sort:
            return sorted(probs.items(), key=lambda x:x[1])
        else:
            return probs
Ejemplo n.º 43
0
def liouvillian_fast(H, c_op_list):
    """Assembles the Liouvillian superoperator from a Hamiltonian 
    and a ``list`` of collapse operators. Like liouvillian, but with an 
    experimental implementation which avoids creating extra Qobj instances,
    which can be advantageous for large systems.
    
    Parameters
    ----------
    H : qobj
        System Hamiltonian.
        
    c_op_list : array_like 
        A ``list`` or ``array`` of collpase operators.
    
    Returns
    -------
    L : qobj
        Louvillian superoperator.

    .. note::

        Experimental.
    
    """
    d = H.dims[1]
    L = Qobj()
    L.dims = [[H.dims[0][:], d[:]], [H.dims[1][:], d[:]]]
    L.shape = [prod(L.dims[0][0]) * prod(L.dims[0][1]), prod(L.dims[1][0]) * prod(L.dims[1][1])]
    L.data = -1j * (
        sp.kron(sp.identity(prod(d)), H.data, format="csr") - sp.kron(H.data.T, sp.identity(prod(d)), format="csr")
    )

    n_op = len(c_op_list)
    for m in range(0, n_op):
        L.data = L.data + sp.kron(sp.identity(prod(d)), c_op_list[m].data, format="csr") * sp.kron(
            c_op_list[m].data.T.conj().T, sp.identity(prod(d)), format="csr"
        )
        cdc = c_op_list[m].data.T.conj() * c_op_list[m].data
        L.data = L.data - 0.5 * sp.kron(sp.identity(prod(d)), cdc, format="csr")
        L.data = L.data - 0.5 * sp.kron(cdc.T, sp.identity(prod(d)), format="csr")
    return L
Ejemplo n.º 44
0
    def test_liouvillian(self):
        """
        PIQS: Test the calculation of the liouvillian matrix.
        """
        true_L = [[-4, 0, 0, 3], [0, -3.54999995, 0, 0],
                  [0, 0, -3.54999995, 0], [4, 0, 0, -3]]
        true_L = Qobj(true_L)
        true_L.dims = [[[2], [2]], [[2], [2]]]
        true_H = [[1. + 0.j, 1. + 0.j], [1. + 0.j, -1. + 0.j]]
        true_H = Qobj(true_H)
        true_H.dims = [[[2], [2]]]
        true_liouvillian = [[-4, -1.j, 1.j, 3],
                            [-1.j, -3.54999995 + 2.j, 0, 1.j],
                            [1.j, 0, -3.54999995 - 2.j, -1.j],
                            [4, +1.j, -1.j, -3]]
        true_liouvillian = Qobj(true_liouvillian)
        true_liouvillian.dims = [[[2], [2]], [[2], [2]]]
        N = 1
        test_piqs = Dicke(hamiltonian=sigmaz() + sigmax(), N=N,
                          pumping=1, collective_pumping=2, emission=1,
                          collective_emission=3, dephasing=0.1)
        test_liouvillian = test_piqs.liouvillian()
        test_hamiltonian = test_piqs.hamiltonian
        assert_array_almost_equal(
            test_liouvillian.full(),
            true_liouvillian.full())
        assert_array_almost_equal(test_hamiltonian.full(), true_H.full())
        assert_array_equal(test_liouvillian.dims, test_liouvillian.dims)

        # no Hamiltonian
        test_piqs = Dicke(N=N,
                          pumping=1, collective_pumping=2, emission=1,
                          collective_emission=3, dephasing=0.1)
        liouv = test_piqs.liouvillian()
        lindblad = test_piqs.lindbladian()
        assert_equal(liouv, lindblad)
Ejemplo n.º 45
0
def generic_ode_solve(r, psi0, tlist, expt_ops, opt, state_vectorize):
    """
    Internal function for solving ODEs.
    """
    
    #
    # prepare output array
    # 
    n_tsteps  = len(tlist)
    dt        = tlist[1]-tlist[0]
       
    output = Odedata()
    output.times = tlist
        
    if isinstance(expt_ops, FunctionType):
        n_expt_op = 0
        expt_callback = True
        
    elif isinstance(expt_ops, list):
  
        n_expt_op = len(expt_ops)
        expt_callback = False

        if n_expt_op == 0:
            output.states = []
        else:
            output.expect = []
            output.num_expect = n_expt_op
            for op in expt_ops:
                if op.isherm and psi0.isherm:
                    output.expect.append(zeros(n_tsteps))
                else:
                    output.expect.append(zeros(n_tsteps,dtype=complex))

    else:
        raise TypeError("Expectation parameter must be a list or a function")
   
    #
    # start evolution
    #
    psi = Qobj(psi0)

    t_idx = 0
    for t in tlist:
        if not r.successful():
            break;

        psi.data = state_vectorize(r.y)

        if expt_callback:
            # use callback method
            expt_ops(t, Qobj(psi))
        else:
            # calculate all the expectation values, or output rho if no operators
            if n_expt_op == 0:
                output.states.append(Qobj(psi)) # copy psi/rho
            else:
                for m in range(0, n_expt_op):
                    output.expect[m][t_idx] = expect(expt_ops[m], psi)

        r.integrate(r.t + dt)
        t_idx += 1
        
    if not opt.rhs_reuse and odeconfig.tdname != None:
        try:
            os.remove(odeconfig.tdname+".pyx")
        except:
            print('Error removing '+str(odeconfig.tdname)+".pyx file")
            pass

    return output
Ejemplo n.º 46
0
    def test_lindbladian(self):
        """
        Optimise pulse for amplitude damping channel with Lindbladian dyn
        assert that fidelity error is below threshold
        """

        Sx = sigmax()
        Sz = sigmaz()
        Si = identity(2)
        
        Sd = Qobj(np.array([[0, 1], [0, 0]]))
        Sm = Qobj(np.array([[0, 0], [1, 0]]))
        Sd_m = Qobj(np.array([[1, 0], [0, 0]]))
        
        gamma = 0.1
        L0_Ad = gamma*(2*tensor(Sm, Sd.trans()) - 
                    (tensor(Sd_m, Si) + tensor(Si, Sd_m.trans())))
        LC_x = -1j*(tensor(Sx, Si) - tensor(Si, Sx))
        LC_z = -1j*(tensor(Sz, Si) - tensor(Si, Sz))
        
        drift = L0_Ad
        ctrls = [LC_z, LC_x]
        n_ctrls = len(ctrls)
        initial = tensor(Si, Si)
        had_gate = hadamard_transform(1)
        target_DP = tensor(had_gate, had_gate)

        n_ts = 10
        evo_time = 5
        
        result = cpo.optimize_pulse(drift, ctrls, initial, target_DP, 
                        n_ts, evo_time, 
                        fid_err_targ=1e-3, 
                        max_iter=200,
                        init_pulse_type='LIN', 
                        gen_stats=True)
        assert_(result.fid_err < 0.1, 
                msg="Fidelity higher than expected")
                
        # Repeat with Qobj propagation
        result = cpo.optimize_pulse(drift, ctrls, initial, target_DP, 
                        n_ts, evo_time, 
                        fid_err_targ=1e-3, 
                        max_iter=200,
                        init_pulse_type='LIN', 
                        dyn_params={'oper_dtype':Qobj},
                        gen_stats=True)
        assert_(result.fid_err < 0.1, 
                msg="Fidelity higher than expected (Qobj propagation)")
                
        # Check same result is achieved using the create objects method
        optim = cpo.create_pulse_optimizer(drift, ctrls, 
                        initial, target_DP,
                        n_ts, evo_time, 
                        fid_err_targ=1e-3, 
                        init_pulse_type='LIN', 
                        gen_stats=True)
        dyn = optim.dynamics

        p_gen = optim.pulse_generator
        init_amps = np.zeros([n_ts, n_ctrls])
        for j in range(n_ctrls):
            init_amps[:, j] = p_gen.gen_pulse()
        dyn.initialize_controls(init_amps)

        # Check the exact gradient
        func = optim.fid_err_func_wrapper
        grad = optim.fid_err_grad_wrapper
        x0 = dyn.ctrl_amps.flatten()
        grad_diff = check_grad(func, grad, x0)
        assert_almost_equal(grad_diff, 0.0, decimal=7,
                            err_msg="Frechet gradient outside tolerance")

        result2 = optim.run_optimization()
        assert_almost_equal(result.fid_err, result2.fid_err, decimal=3, 
                            err_msg="Direct and indirect methods produce "
                                    "different results for ADC")
Ejemplo n.º 47
0
def floquet_markov_mesolve(R, ekets, rho0, tlist, e_ops, opt=None):
    """
    Solve the dynamics for the system using the Floquet-Markov master equation.   
    """

    if opt == None:
        opt = Odeoptions()

    if opt.tidy:
        R.tidyup()

    #
    # check initial state
    #
    if isket(rho0):
        # Got a wave function as initial state: convert to density matrix.
        rho0 = ket2dm(rho0)
       
    #
    # prepare output array
    # 
    n_tsteps  = len(tlist)
    dt        = tlist[1]-tlist[0]
       
    output = Odedata()
    output.times = tlist
        
    if isinstance(e_ops, FunctionType):
        n_expt_op = 0
        expt_callback = True
        
    elif isinstance(e_ops, list):
  
        n_expt_op = len(e_ops)
        expt_callback = False

        if n_expt_op == 0:
            output.states = []
        else:
            output.expect = []
            output.num_expect = n_expt_op
            for op in e_ops:
                if op.isherm:
                    output.expect.append(zeros(n_tsteps))
                else:
                    output.expect.append(zeros(n_tsteps,dtype=complex))

    else:
        raise TypeError("Expectation parameter must be a list or a function")


    #
    # transform the initial density matrix and the e_ops opterators to the
    # eigenbasis: from computational basis to the floquet basis
    #
    if ekets != None:
        rho0 = rho0.transform(ekets, True)
        if isinstance(e_ops, list):
            for n in arange(len(e_ops)):             # not working
                e_ops[n] = e_ops[n].transform(ekets) #

    #
    # setup integrator
    #
    initial_vector = mat2vec(rho0.full())
    r = scipy.integrate.ode(cyq_ode_rhs)
    r.set_f_params(R.data.data, R.data.indices, R.data.indptr)
    r.set_integrator('zvode', method=opt.method, order=opt.order,
                              atol=opt.atol, rtol=opt.rtol,
                              max_step=opt.max_step)
    r.set_initial_value(initial_vector, tlist[0])

    #
    # start evolution
    #
    rho = Qobj(rho0)

    t_idx = 0
    for t in tlist:
        if not r.successful():
            break;

        rho.data = vec2mat(r.y)

        if expt_callback:
            # use callback method
            e_ops(t, Qobj(rho))
        else:
            # calculate all the expectation values, or output rho if no operators
            if n_expt_op == 0:
                output.states.append(Qobj(rho)) # copy psi/rho
            else:
                for m in range(0, n_expt_op):
                    output.expect[m][t_idx] = expect(e_ops[m], rho) # basis OK?

        r.integrate(r.t + dt)
        t_idx += 1
          
    return output
import qutip.logging_utils as logging
logger = logging.get_logger()
#QuTiP control modules
import qutip.control.pulseoptim as cpo

example_name = 'Lindblad'
log_level = logging.INFO

# ****************************************************************
# Define the physics of the problem
Sx = sigmax()
Sy = sigmay()
Sz = sigmaz()
Si = identity(2)

Sd = Qobj(np.array([[0, 1],
             [0, 0]]))
Sm = Qobj(np.array([[0, 0],
             [1, 0]]))
Sd_m = Qobj(np.array([[1, 0],
              [0, 0]]))
Sm_d = Qobj(np.array([[0, 0],
              [0, 1]]))

#Amplitude damping#
#Damping rate:
gamma = 0.1
L0_Ad = gamma*(2*tensor(Sm, Sd.trans()) - 
            (tensor(Sd_m, Si) + tensor(Si, Sd_m.trans())))
#sigma X control
LC_x = -1j*(tensor(Sx, Si) - tensor(Si, Sx))
#sigma Y control
Ejemplo n.º 49
0
def steady(L,maxiter=100,tol=1e-6,method='solve'):
	"""Steady state for the evolution subject to the 
	supplied Louvillian.
    
    Parameters
    ----------
    L : qobj
        Liouvillian superoperator.
              
    maxiter : int 
        Maximum number of iterations to perform, default = 100.

    tol : float 
        Tolerance used by iterative solver, default = 1e-6.
    
    method : str
        Method for solving linear equations. Direct solver 'solve' (default) or 
        iterative biconjugate gradient method 'bicg'.
    
    Returns
    --------
    ket : qobj
        Ket vector for steady state.
    
    Notes
    -----
    Uses the inverse power method. 
    See any Linear Algebra book with an iterative methods section.
    
    """
	eps=finfo(float).eps
	if (not isoper(L)) & (not issuper(L)):
		raise TypeError('Steady states can only be found for operators or superoperators.')
	rhoss=Qobj()
	sflag=issuper(L)
	if sflag:
		rhoss.dims=L.dims[0]
		rhoss.shape=[prod(rhoss.dims[0]),prod(rhoss.dims[1])]
	else:
		rhoss.dims=[L.dims[0],1]
		rhoss.shape=[prod(rhoss.dims[0]),1]
	n=prod(rhoss.shape)
	L1=L.data+eps*_sp_inf_norm(L)*sp.eye(n,n,format='csr')
	v=randn(n,1)
	it=0
	while (la.norm(L.data*v,np.inf)>tol) and (it<maxiter):
		if method=='bicg':
		    v,check=bicg(L1,v,tol=tol)
		else:
		    v=spsolve(L1,v,use_umfpack=False)
		v=v/la.norm(v,np.inf)
		it+=1
	if it>=maxiter:
		raise ValueError('Failed to find steady state after ' + str(maxiter) +' iterations')
	#normalise according to type of problem
	if sflag:
		trow=sp.eye(rhoss.shape[0],rhoss.shape[0],format='lil')
		trow=trow.reshape((1,n)).tocsr()
		data=v/sum(trow.dot(v))
	else:
		data=data/la.norm(v)
	data=reshape(data,(rhoss.shape[0],rhoss.shape[1])).T
	data=sp.csr_matrix(data)
	rhoss.data=0.5*(data+data.conj().T)
	#data=sp.triu(data,format='csr')#take only upper triangle
	#rhoss.data=0.5*sp.eye(rhoss.shape[0],rhoss.shape[1],format='csr')*(data+data.conj().T) #output should be hermitian, but not guarenteed using iterative meth
	if qset.auto_tidyup:
	    return Qobj(rhoss).tidyup()
	else:
	    return Qobj(rhoss)
Ejemplo n.º 50
0
def bloch_redfield_solve(R, ekets, rho0, tlist, e_ops=[], opt=None):
    """
    Evolve the ODEs defined by Bloch-Redfeild master equation.
    """

    if opt == None:
        opt = Odeoptions()
        opt.nsteps = 2500  # 

    if opt.tidy:
        R.tidyup()

    #
    # check initial state
    #
    if isket(rho0):
        # Got a wave function as initial state: convert to density matrix.
        rho0 = rho0 * rho0.dag()
       
    #
    # prepare output array
    # m
    n_e_ops  = len(e_ops)
    n_tsteps = len(tlist)
    dt       = tlist[1]-tlist[0]

    if n_e_ops == 0:
        result_list = []
    else:
        result_list = []
        for op in e_ops:
            if op.isherm and rho0.isherm:
                result_list.append(zeros(n_tsteps))
            else:
                result_list.append(zeros(n_tsteps,dtype=complex))


    #
    # transform the initial density matrix and the e_ops opterators to the
    # eigenbasis
    #
    if ekets != None:
        rho0 = rho0.transform(ekets)
        for n in arange(len(e_ops)):
            e_ops[n] = e_ops[n].transform(ekets, False)

    #
    # setup integrator
    #
    initial_vector = mat2vec(rho0.full())
    r = scipy.integrate.ode(cyq_ode_rhs)
    r.set_f_params(R.data.data, R.data.indices, R.data.indptr)
    r.set_integrator('zvode', method=opt.method, order=opt.order,
                              atol=opt.atol, rtol=opt.rtol, #nsteps=opt.nsteps,
                              #first_step=opt.first_step, min_step=opt.min_step,
                              max_step=opt.max_step)
    r.set_initial_value(initial_vector, tlist[0])

    #
    # start evolution
    #
    rho = Qobj(rho0)

    t_idx = 0
    for t in tlist:
        if not r.successful():
            break;

        rho.data = vec2mat(r.y)
        
        # calculate all the expectation values, or output rho if no operators
        if n_e_ops == 0:
            result_list.append(Qobj(rho))
        else:
            for m in range(0, n_e_ops):
                result_list[m][t_idx] = expect(e_ops[m], rho)

        r.integrate(r.t + dt)
        t_idx += 1
          
    return result_list