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)))
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)))
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}