Beispiel #1
0
def pro_avfid_superoperator_compsubspace(U, L1):
    """
    Average process (gate) fidelity in the qubit computational subspace for two qutrits
    Leakage has to be taken into account, see Woods & Gambetta
    """

    if U.type == 'oper':
        inner = U.dag() * U_target
        part_idx = [0, 1, 3, 4]  # only computational subspace
        ptrace = 0
        for i in part_idx:
            ptrace += inner[i, i]
        dim = 4  # 2 qubits comp subspace

        return np.real(
            ((np.abs(ptrace))**2 + dim * (1 - L1)) / (dim * (dim + 1)))

    elif U.type == 'super':
        kraus_form = qtp.to_kraus(U)
        dim = 4  # 2 qubits in the computational subspace
        part_idx = [0, 1, 3, 4]  # only computational subspace
        psum = 0
        for A_k in kraus_form:
            ptrace = 0
            inner = U_target_diffdims.dag(
            ) * A_k  # otherwise dimension mismatch
            for i in part_idx:
                ptrace += inner[i, i]
            psum += (np.abs(ptrace))**2

        return np.real((dim * (1 - L1) + psum) / (dim * (dim + 1)))
def pro_avfid_superoperator_compsubspace(U, L1):
    """
    Average process (gate) fidelity in the qubit computational subspace for two qutrits.
    Leakage has to be taken into account, see Woods & Gambetta.
    The function assumes that the computational subspace (:= the 4 energy levels chosen as the two qubits) is given by 
            the standard basis |0> /otimes |0>, |0> /otimes |1>, |1> /otimes |0>, |1> /otimes |1>.
            If this is not the case, one need to change the basis to that one, before calling this function.
    """

    if U.type == 'oper':
        inner = U.dag() * U_target
        part_idx = [0, 1, 3, 4]  # only computational subspace
        ptrace = 0
        for i in part_idx:
            ptrace += inner[i, i]
        dim = 4  # 2 qubits comp subspace

        return np.real(
            ((np.abs(ptrace))**2 + dim * (1 - L1)) / (dim * (dim + 1)))

    elif U.type == 'super':
        kraus_form = qtp.to_kraus(U)
        dim = 4  # 2 qubits in the computational subspace
        part_idx = [0, 1, 3, 4]  # only computational subspace
        psum = 0
        for A_k in kraus_form:
            ptrace = 0
            inner = U_target_diffdims.dag(
            ) * A_k  # otherwise dimension mismatch
            for i in part_idx:
                ptrace += inner[i, i]
            psum += (np.abs(ptrace))**2

        return np.real((dim * (1 - L1) + psum) / (dim * (dim + 1)))
def pro_avfid_superoperator_compsubspace_phasecorrected(U, L1, phases):
    """
    Average process (gate) fidelity in the qubit computational subspace for two qutrits
    Leakage has to be taken into account, see Woods & Gambetta
    The phase is corrected with Z rotations considering both transmons as qubits. The correction is done perfectly.
    The function assumes that the computational subspace (:= the 4 energy levels chosen as the two qubits) is given by 
            the standard basis |0> /otimes |0>, |0> /otimes |1>, |1> /otimes |0>, |1> /otimes |1>.
            If this is not the case, one need to change the basis to that one, before calling this function.
    """

    Ucorrection = qtp.Qobj(
        [[np.exp(-1j * np.deg2rad(phases[0])), 0, 0, 0, 0, 0, 0, 0, 0],
         [0, np.exp(-1j * np.deg2rad(phases[1])), 0, 0, 0, 0, 0, 0, 0],
         [0, 0, np.exp(-1j * np.deg2rad(phases[0])), 0, 0, 0, 0, 0, 0],
         [0, 0, 0, np.exp(-1j * np.deg2rad(phases[2])), 0, 0, 0, 0, 0],
         [
             0, 0, 0, 0,
             np.exp(-1j * np.deg2rad(phases[3] - phases[-1])), 0, 0, 0, 0
         ], [0, 0, 0, 0, 0,
             np.exp(-1j * np.deg2rad(phases[2])), 0, 0, 0],
         [0, 0, 0, 0, 0, 0,
          np.exp(-1j * np.deg2rad(phases[0])), 0, 0],
         [0, 0, 0, 0, 0, 0, 0,
          np.exp(-1j * np.deg2rad(phases[1])), 0],
         [0, 0, 0, 0, 0, 0, 0, 0,
          np.exp(-1j * np.deg2rad(phases[0]))]],
        type='oper',
        dims=[[3, 3], [3, 3]])

    if U.type == 'oper':
        U = Ucorrection * U
        inner = U.dag() * U_target
        part_idx = [0, 1, 3, 4]  # only computational subspace
        ptrace = 0
        for i in part_idx:
            ptrace += inner[i, i]
        dim = 4  # 2 qubits comp subspace

        return np.real(
            ((np.abs(ptrace))**2 + dim * (1 - L1)) / (dim * (dim + 1)))

    elif U.type == 'super':
        U = qtp.to_super(Ucorrection) * U
        kraus_form = qtp.to_kraus(U)
        dim = 4  # 2 qubits in the computational subspace
        part_idx = [0, 1, 3, 4]  # only computational subspace
        psum = 0
        for A_k in kraus_form:
            ptrace = 0
            inner = U_target_diffdims.dag(
            ) * A_k  # otherwise dimension mismatch
            for i in part_idx:
                ptrace += inner[i, i]
            psum += (np.abs(ptrace))**2

        return np.real((dim * (1 - L1) + psum) / (dim * (dim + 1)))
Beispiel #4
0
def pro_avfid_superoperator_compsubspace_phasecorrected(U, L1, phases):
    """
    Average process (gate) fidelity in the qubit computational subspace for two qutrits
    Leakage has to be taken into account, see Woods & Gambetta
    The phase is corrected with Z rotations considering both transmons as qubits
    """

    Ucorrection = qtp.Qobj(
        [[np.exp(-1j * np.deg2rad(phases[0])), 0, 0, 0, 0, 0, 0, 0, 0],
         [0, np.exp(-1j * np.deg2rad(phases[1])), 0, 0, 0, 0, 0, 0, 0],
         [0, 0, np.exp(-1j * np.deg2rad(phases[0])), 0, 0, 0, 0, 0, 0],
         [0, 0, 0, np.exp(-1j * np.deg2rad(phases[2])), 0, 0, 0, 0, 0],
         [
             0, 0, 0, 0,
             np.exp(-1j * np.deg2rad(phases[3] - phases[-1])), 0, 0, 0, 0
         ], [0, 0, 0, 0, 0,
             np.exp(-1j * np.deg2rad(phases[2])), 0, 0, 0],
         [0, 0, 0, 0, 0, 0,
          np.exp(-1j * np.deg2rad(phases[0])), 0, 0],
         [0, 0, 0, 0, 0, 0, 0,
          np.exp(-1j * np.deg2rad(phases[1])), 0],
         [0, 0, 0, 0, 0, 0, 0, 0,
          np.exp(-1j * np.deg2rad(phases[0]))]],
        type='oper',
        dims=[[3, 3], [3, 3]])

    if U.type == 'oper':
        U = Ucorrection * U
        inner = U.dag() * U_target
        part_idx = [0, 1, 3, 4]  # only computational subspace
        ptrace = 0
        for i in part_idx:
            ptrace += inner[i, i]
        dim = 4  # 2 qubits comp subspace

        return np.real(
            ((np.abs(ptrace))**2 + dim * (1 - L1)) / (dim * (dim + 1)))

    elif U.type == 'super':
        U = qtp.to_super(Ucorrection) * U
        kraus_form = qtp.to_kraus(U)
        dim = 4  # 2 qubits in the computational subspace
        part_idx = [0, 1, 3, 4]  # only computational subspace
        psum = 0
        for A_k in kraus_form:
            ptrace = 0
            inner = U_target_diffdims.dag(
            ) * A_k  # otherwise dimension mismatch
            for i in part_idx:
                ptrace += inner[i, i]
            psum += (np.abs(ptrace))**2

        return np.real((dim * (1 - L1) + psum) / (dim * (dim + 1)))
Beispiel #5
0
def qobj_to_rust_style(qobj, expect_state=False):
    import qutip as qt
    import numpy as np
    data = None
    n_qubits = 1
    # Figure out what kind of qobj we have and convert accordingly.
    if qobj.type == 'oper':
        n_qubits = len(qobj.dims[0])
        data = {
            'Mixed' if expect_state else 'Unitary':
            arr_to_rust_style(qobj.data.todense())
        }
    elif qobj.type == 'super':
        n_qubits = len(qobj.dims[0][0])
        data = {
            'KrausDecomposition':
            arr_to_rust_style(
                np.array([op.data.todense() for op in qt.to_kraus(qobj)]))
        }
    return {"n_qubits": n_qubits, "data": data}