def RhoFinal(Nrealmax, Detection, args, fig_rhofinal=True, fig_qm=False): # This function returns the density matrix of the cavities, computed with a number of real atoms from 0 to Nrealmax # 'Detection' is the list of detected atoms (post-selection) # Initialization : if Nreal = 0, RhoFinal is the null matrix (0 photon in the cavities) Rho_final = Quantum_map(0, Detection, args, fig_qm) * ProbaNumberRealAtoms(0, args) # Compute the final density matrix by considering all possible numbers of real atoms if Nrealmax > 0: for Nreal in range(1,Nrealmax+1): Rho_final += Quantum_map(Nreal, Detection, args, fig_qm) * ProbaNumberRealAtoms(Nreal, args) # Normalization N_detected = len(Detection) normalisation_parameter = 0 for i in range(N_detected): # We renormalize by considering the cases when there are less real than detected atoms (absurd cases) normalisation_parameter += ProbaNumberRealAtoms(i, args) Rho_final = Rho_final / (1 - normalisation_parameter) # Check that the trace of Rho_final is equal to 1 trace = 0 for i in range(args['NH1'] * args['NH2']): trace += Rho_final[i,i] if 1.0 - trace > 0.01: print ("\n The trace of the density matrix is "+str(np.float(int(round(trace.real*100))/100))) print ("WARNING : the trace should be equal to 1 !! Take a bigger number of atoms (compared to mu)") # Plot if fig_rhofinal: qt.hinton(Rho_final) plt.suptitle("State of the cavities for detection "+str(Detection)) if args['NH1'] == 3 and args['NH2'] == 3: plt.text(-28.8,1.02,np.float(int(round(Rho_final[0,0].real*1000))/1000)) plt.text(-26.3,0.885,np.float(int(round(Rho_final[1,1].real*1000))/1000)) plt.text(-23.5,0.75,np.float(int(round(Rho_final[2,2].real*1000))/1000)) plt.text(-20.7,0.615,np.float(int(round(Rho_final[3,3].real*1000))/1000)) plt.text(-17.9,0.48,np.float(int(round(Rho_final[4,4].real*1000))/1000)) plt.text(-15.2,0.345,np.float(int(round(Rho_final[5,5].real*1000))/1000)) plt.text(-12.4,0.21,np.float(int(round(Rho_final[6,6].real*1000))/1000)) plt.text(-9.6,0.075,np.float(int(round(Rho_final[7,7].real*1000))/1000)) plt.text(-6.8,-0.06,np.float(int(round(Rho_final[8,8].real*1000))/1000)) plt.text(-20.9,0.885,np.float(int(round(Rho_final[1,3].real*1000))/1000)) plt.text(-26.4,0.615,np.float(int(round(Rho_final[3,1].real*1000))/1000)) plt.text(-30,-0.2,r"prepared state = "+str(args['prepared_state'])+", $\eta_{prep_g}$ = " \ +str(args['eta_prep_g'])+", $\eta_{prep_e}$ = "+str(args['eta_prep_e'])+", $\mu$ = "+str(args['mu']) \ +", $\epsilon$ = "+str(args['epsilon'])+", $\eta_{g}$ = "+str(args['eta_g'])+", $\eta_{e}$ = "+str(args['eta_e'])) plt.show() return Rho_final
def save_fig(state, figname): fig, ax = qt.hinton(state, [ '00', '01', '10', '11', ], [ '00', '01', '10', '11', ]) plt.savefig('state_hinton_' + str(figname) + '.png') fig, ax = qt.matrix_histogram(state, [ '00', '01', '10', '11', ], [ '00', '01', '10', '11', ]) plt.savefig('state_hist_' + str(figname) + '.png') np.savetxt('state_' + str(figname), state, header='density matrix data, 00,01,10,11')
def KrausOperator(Ideal_detection, args): # Create a Kraus operator corresponding to the list 'Ideal_Detection" Tensor_components = [] for atom in Ideal_detection: if atom == 'e': Tensor_components += [qt.basis(2, 0) * qt.basis(2, 0).dag() ] # State for an atom ideally detected in e if atom == 'g': Tensor_components += [qt.basis(2, 1) * qt.basis(2, 1).dag() ] # State for an atom ideally detected in g Tensor_components += [qt.qeye(args['NH1']), qt.qeye(args['NH2'])] # State for both cavities if False: qt.hinton(qt.tensor(Tensor_components)) plt.suptitle("Kraus operator for the detection " + str(Ideal_detection)) plt.show() return qt.tensor(Tensor_components)
def visualize_dm(rho, atomIncluded = True): ''' make a hinton diagram for density matrix of an atom + motion (atomIncluded = True), or only motion (atomIncluded = False) @ var rho: the density matrix @ var atomIncluded: flag to determine whether the input density matrix has an atom state included or not ''' if atomIncluded: N = shape(rho0.data)[0]/2 # assume N Fock states and two atom states lbls_list = [[str(d) for d in range(N)], ["u", "d"]] else: N = shape(rho.data)[0] # assume N Fock states lbls_list = [[str(d) for d in range(N)]] xlabels = [] for inds in tomography._index_permutations([len(lbls) for lbls in lbls_list]): xlabels.append("".join([lbls_list[k][inds[k]] for k in range(len(lbls_list))])) ax = hinton(rho, xlabels=xlabels, ylabels=xlabels) show()
def visualize_dm(rho, atomIncluded=True): ''' make a hinton diagram for density matrix of an atom + motion (atomIncluded = True), or only motion (atomIncluded = False) @ var rho: the density matrix @ var atomIncluded: flag to determine whether the input density matrix has an atom state included or not ''' if atomIncluded: N = shape(rho0.data)[0] / 2 # assume N Fock states and two atom states lbls_list = [[str(d) for d in range(N)], ["u", "d"]] else: N = shape(rho.data)[0] # assume N Fock states lbls_list = [[str(d) for d in range(N)]] xlabels = [] for inds in tomography._index_permutations( [len(lbls) for lbls in lbls_list]): xlabels.append("".join( [lbls_list[k][inds[k]] for k in range(len(lbls_list))])) ax = hinton(rho, xlabels=xlabels, ylabels=xlabels) show()
Coeffs = {} Cavity_states = [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] for i in range(N_plots): print("\nDensity matrix for " + str(varying_param) + " = " + str(Range[i * step]) + "\n") Coeffs[i] = [] for j in range(0, 9): Coeffs[i] += [Density_matrices[i][j, j]] print("coeff " + str(Cavity_states[j]) + " = " + str(Coeffs[i][j])) # GLOBAL PLOT # Plot all density matrices for i in reversed(range(0, N_plots)): qt.hinton(Density_matrices[i]) plt.suptitle("Density matrix with " + str(varying_param) + " = " + str(Range[i * step]) + ", for detection : " + str(Detection) + ", without contrast") if args['NH1'] == 3 and args['NH2'] == 3: plt.text( -28.9, 1.02, np.float(int(round(Density_matrices[i][0, 0].real * 100)) / 100)) plt.text( -26.1, 0.885, np.float(int(round(Density_matrices[i][1, 1].real * 100)) / 100)) plt.text( -23.3, 0.75, np.float(int(round(Density_matrices[i][2, 2].real * 100)) / 100)) plt.text( -20.5, 0.615,
def DensityMatrixAfterInteraction(atomic_states, args, figs_interaction = True): # atomic_states must be a list of 'e' and 'g' #if args['N_cav'] == 0: if args['N_cav'] > 0: Numb1 = qt.tensor(qt.qeye(2),qt.qeye(2),qt.num(args['NH1']),qt.qeye(args['NH2'])) Numb2 = qt.tensor(qt.qeye(2),qt.qeye(2),qt.qeye(args['NH1']),qt.num(args['NH2'])) a1 = qt.tensor(qt.destroy(args['NH1']),qt.qeye(args['NH2'])) a2 = qt.tensor(qt.qeye(args['NH1']),qt.destroy(args['NH2'])) N1 = a1.dag()*a1 N2 = a2.dag()*a2 Lm1 = sqrt(args['kappa_1']*(1+args['n_th1']))*a1 #Loss of a photon in C1 Lm2 = sqrt(args['kappa_2']*(1+args['n_th2']))*a2 #Loss of a photon in C2 Lp1 = sqrt(args['kappa_1']*(args['n_th1']))*a1.dag() #Absorption of a photon in C1 Lp2 = sqrt(args['kappa_2']*(args['n_th2']))*a2.dag() #Absorption of a photon in C2 # Initial states psi_g = qt.basis(2,1) psi_e = qt.basis(2,0) psi_at_0 = 1/sqrt(2)*(qt.basis(2,0)+qt.basis(2,1)) #Atom in e+g # Global state psie = qt.tensor(psi_e, psi_e, qt.basis(args['NH1'],0),qt.basis(args['NH2'],0)) # Initial state N_atoms = len(atomic_states) psie = initial_state(N_atoms,atomic_states,qt.fock(args['NH1'],0),qt.fock(args['NH2'],0)) H_jc = build_hamiltonians(args['NH1'],args['NH2'],N_atoms,killer,f1,f2, args) # Measurement operators Numb1 = local_operator(qt.num(args['NH1']),N_atoms,args['NH1'],args['NH2'],N_atoms) Numb2 = local_operator(qt.num(args['NH1']),N_atoms+1,args['NH1'],args['NH2'],N_atoms) ee = [] for i in range(N_atoms): ee += [local_operator(qt.basis(2,0)*qt.basis(2,0).dag(),i,args['NH1'],args['NH2'],N_atoms) ] # |e><e| For atom i e_ops = [Numb1,Numb2] + ee # Evolution opts = Options(store_states=True, store_final_state=True) res = qt.mesolve(H_jc,psie,args['t'],[],e_ops,args=args,options=opts) rho_after_interaction = res.states[-1] #.ptrace((N_atoms,N_atoms+1)) -> the partial trace is computed in detection.py #print (rho_after_interaction) if figs_interaction: # Plot the evolution of the number of photons in the cavities and the states of the atoms during interaction plt.plot(args['t_real'],res.expect[0],label='N1, '+str(N_atoms)+' atoms') plt.plot(args['t_real'],res.expect[1],label='N2, '+str(N_atoms)+' atoms') for i in range(len(ee)): plt.plot(args['t_real'],res.expect[2+i],label='Pe '+str(i)) plt.xlabel("t_real") plt.title("Pour "+str(N_atoms)+" atomes") plt.legend() if N_atoms == 1: plt.suptitle("Etats de l'atome et des cavités en fonction du temps") if N_atoms > 1: plt.suptitle("Etats des atomes et des cavités en fonction du temps") # Plot the density matrix after interaction : state of the cavities + the atoms, since we have not yet taken the partial trace fig = qt.hinton(qt.ket2dm(rho_after_interaction)) plt.suptitle("State of the cavities + atoms") plt.show() #Return the mean number of photons in C1, the mean number of photons in C2, and the mean number of atoms is still excited print ("\n APRES INTERACTION AVEC LES DEUX CAVITES \n") print ("Le nombre moyen de photons dans la cavite 1 est "+str(res.expect[0][-1])) print ("Le nombre moyen de photons dans la cavite 2 est "+str(res.expect[1][-1])) print ("Le nombre moyen d'atomes encore excites est "+str(res.expect[2][-1])) return qt.ket2dm(rho_after_interaction) else: print ("Please specify a correct number of cavities") sys.exit()
def genertate_bell_state(state, noise, tc, dec): ''' state [int]: 0 : |00> + |11> 1 : |00> - |11> 2 : |01> - |10> 3 : |01> + |10> noise [boolean]: add noise to the exp tc [boolean]: turn tunnelcoupling completely off when you do single qubit gates dec [boolean]: # not yet implemented. enable decoupled gate ''' # Start in |00> psi0 = np.array(list(basis(6, 0) * basis(6, 0).dag()))[:, 0] # define hamiltonian if tc == True: db = double_dot_hamiltonian(19.7e9, 18.4e9, 850e9, 840e9, 0 * 0.250e9) else: db = double_dot_hamiltonian(19.7e9, 18.4e9, 850e9, 840e9, 0.250e9) # # # J = ~6MHZ @ epsilon 835e9, t = 210e6 // note a bit of assymetry, so you will get a tiny bit of phase chargingE = 850e9 * np.pi * 2 detuningE = 828.6e9 * np.pi * 2 # Number of simulation to average. num_sim = 500 if noise == True: db = my_noise.add_nuclear_and_charge_noise(db) db.number_of_sim_for_static_noise(num_sim) # Do MW on both qubits. if state == 0 or state == 3: db.mw_pulse(19.7e9, np.pi / 2, 2e6, 0e-9, 125e-9) else: db.mw_pulse(19.7e9, -np.pi / 2, 2e6, 0e-9, 125e-9) db.mw_pulse(18.4e9, np.pi / 2, 2e6, 0e-9, 125e-9) # If decoupled is used if dec == True: # implement tunnel coupling pulse. if tc == True: a = 49e-9 else: a = 40e-9 db.awg_pulse(detuningE / np.pi / 2, 125e-9, 125e-9 + a, 1e-9) if tc == True: db.awg_pulse_tc(0.25e9, 123e-9, 127e-9 + a, 0.05e-9) db.mw_pulse(18.4e9, 0, 2e6, 200e-9, 450e-9) db.mw_pulse(19.7e9, 0, 2e6, 200e-9, 450e-9) db.awg_pulse(detuningE / np.pi / 2, 450e-9, 450e-9 + a, 1e-9) if tc == True: db.awg_pulse_tc(0.25e9, 448e-9, 452e-9 + a, 0.05e-9) if state == 1 or state == 3: db.mw_pulse(19.7e9, 0, 2e6, 500e-9, 625e-9) else: db.mw_pulse(19.7e9, np.pi, 2e6, 500e-9, 625e-9) db.calc_time_evolution(psi0, 0e-9, 625e-9, int((625e-9) * 1e9 * 100)) else: if tc == True: a = 91e-9 else: a = 85e-9 db.awg_pulse(detuningE / np.pi / 2, 130e-9, 130e-9 + a, 1e-9) if tc == True: db.awg_pulse_tc(0.25e9, 125e-9, 135e-9 + a, 0.05e-9) if state == 1 or state == 3: db.mw_pulse(19.7e9, 0, 2e6, 235e-9, 360e-9) else: db.mw_pulse(19.7e9, np.pi, 2e6, 235e-9, 360e-9) db.calc_time_evolution(psi0, 0e-9, 365e-9, int((625e-9) * 1e9 * 100)) rho = db.get_density_matrix_final()[:4, :4] rho_full = db.get_density_matrix_final() C = calc_concurrence(rho) bell_states = ['00', '01', '11', '10'] Bell = bell_state(bell_states[state]) Bell.dims = [[4], [1]] F = (Bell.dag() * Qobj(rho) * Bell)[0, 0] fig, ax = hinton(rho, ['00', '01', '10', '11'], ['00', '01', '10', '11']) plt.savefig('Bell_' + str(state) + '_hinton_dec_' + str(dec) + '_noise_' + str(noise) + "_tc_" + str(tc) + '.png') fig, ax = matrix_histogram(rho, ['00', '01', '10', '11'], ['00', '01', '10', '11']) plt.savefig('Bell_' + str(state) + '_hist_dec_' + str(dec) + '_noise_' + str(noise) + "_tc_" + str(tc) + '.png') np.savetxt('Bell_' + str(state) + "_dec_" + str(dec) + '_noise_' + str(noise) + '_tc_' + str(tc) + '_DM.txt', rho_full, header='density matrix data, 00,01,10,11,0S,S0') np.savetxt('Bell_' + str(state) + "_dec_" + str(dec) + '_noise_' + str(noise) + '_tc_' + str(tc) + '_FID.txt', np.array([F, C]), header='State overlap -- Concurrence') db.clear()
fig3.tight_layout() fig3.savefig("transmon_pulse.pdf") fig3.show() plt.rcParams.update({"text.usetex": False, "font.size": 9}) # Plot hinton from qutip import hinton fig4, ax4 = plt.subplots(figsize=(LINEWIDTH * 0.9, LINEWIDTH * 0.7), dpi=200) first_two_qubits = result1.states[-1].ptrace([0, 1]) _, ax4 = hinton(first_two_qubits, ax=ax4, xlabels=[ '$|00\\rangle$', '$|01\\rangle$', '$|10\\rangle$', '$|11\\rangle$' ], ylabels=[ '$|00\\rangle$', '$|01\\rangle$', '$|10\\rangle$', '$|11\\rangle$' ]) fig4.savefig("hinton.pdf") fig4.show() # Plot trajectory expect = [] for state in result1.states: tmp = state.ptrace([0, 1]) tmp = basis([2, 2], [0, 0]).dag() * tmp * basis([2, 2], [0, 0]) expect.append(np.real(tmp[0, 0])) fig5, ax5 = plt.subplots(figsize=(LINEWIDTH, LINEWIDTH * 0.7), dpi=200)
#print(c_count) #print(self.cnots[c_count],qt.tensor(squt)) u = self.cnots[c_count] * qt.tensor(squt) * u c_count += 1 self.uni = u return u target_state = np.load('out_state.npy') target_state = qt.Qobj(target_state, dims=[[2] * 8, [1] * 8]).unit() n = 8 g = 1 sq = [0 for _ in range(n * (n + 1))] sq[0:8] = [1 for i in range(8)] circ = circuit(n, g) circ.optimise() np.save('circ_full_State', circ.state) np.save('one_qubit', circ.sq) np.save('two_qubit', circ.tq) np.save('phases', circ.sqp) print(circ.sq) print(circ.tq) import matplotlib.pyplot as plt fig, ax = qt.hinton(circ.state.ptrace((0, 1, 2, 3))) plt.show()
""" Created on Wed Aug 1 07:15:05 2018 @author: huang For qubits, a particularly useful way to visualize superoperators is to plot them in the Pauli basis, such that Sμ,ν=⟨⟨σμ|S[σν]⟩⟩. Because the Pauli basis is Hermitian, Sμ,ν is a real number for all Hermitian-preserving superoperators S, allowing us to plot the elements of S as a Hinton diagram. In such diagrams, positive elements are indicated by white squares, and negative elements by black squares. The size of each element is indicated by the size of the corresponding square. For instance, let S[ρ]=σxρσ†xS[ρ]=σxρσx†. We can quickly see this by noting that the Y and Z elements of the Hinton diagram for S are negative: """ import qutip as qt qt.settings.colorblind_safe = True import matplotlib.pyplot as plt plt.rcParams['savefig.transparent'] = True X = qt.sigmax() S = qt.spre(X) * qt.spost(X.dag()) print(S) qt.hinton(S)
def Quantum_map(Nreal, Detection, args, fig_qm=True): # This function returns the quantum map for a given number of real atoms Nreal # 'Detection' is the sequence of detected atoms (post-selection) # Return the null matrix if the number of real atoms is 0 or if there are more detected than real atoms Null_vector1 = qt.Qobj([[0] * args['NH1']]) Null_vector2 = qt.Qobj([[0] * args['NH2']]) Null_matrix = qt.tensor(qt.ket2dm(Null_vector1), qt.ket2dm(Null_vector2)) if Nreal == 0 or len(Detection) > Nreal: return Null_matrix # Store in a list the possible real states Possible_real_states = PreparedStates(Nreal) # Store in a dictionary the possible real states with their respective probabilities Possible_real_states_with_probas = ProbaPreparedStates(Nreal, args) # Compute all density matrices after interaction for each possible real state, and store them in a dictionary Rho_after_interaction = {} for state in Possible_real_states: Rho_after_interaction[tuple(state)] = DensityMatrixAfterInteraction( state, args, figs_interaction=False) # Compute all possible partial traces, for each density matrix after interaction, and for each possible ideal detection (two-level dictionary) All_Ptraces = {} for state_dm in Possible_real_states: All_Ptraces[tuple(state_dm)] = {} for state_ideal_detection in Possible_real_states: All_Ptraces[tuple(state_dm)][tuple( state_ideal_detection)] = Partial_trace( Rho_after_interaction[tuple(state_dm)], state_ideal_detection, args) # Multiply each Ptrace by the probability of having the considered state before interaction All_Ptraces_with_weights = {} for state_dm in Possible_real_states: All_Ptraces_with_weights[tuple(state_dm)] = {} for state_ideal_detection in Possible_real_states: All_Ptraces_with_weights[tuple(state_dm)][tuple( state_ideal_detection)] = Possible_real_states_with_probas[ tuple(state_dm)] * All_Ptraces[tuple(state_dm)][tuple( state_ideal_detection)] # Compute a dictionary of all possible detections with their respective probabilities All_Possible_detections_with_probas = {} for state_ideal_detection in Possible_real_states: All_Possible_detections_with_probas[tuple( state_ideal_detection)] = ProbasPossibleDetections( state_ideal_detection, args) # Select detections compatible with the 'Detection' sequence given as an argument # For example, if the post-selection is 'g' when there are 2 real atoms, the possible detections are '0g' and 'g0', # where '0' means : the real atom was not detected Selected_detections = SelectDetection(Nreal, Detection, args) # Store every possible partial traces with weights (probabilities) corresponding to the Detection Ptraces = [] for state_dm in Possible_real_states: for state_ideal_detection in Possible_real_states: for real_detection in Selected_detections: Ptraces += [ All_Ptraces_with_weights[tuple(state_dm)][tuple( state_ideal_detection)] * All_Possible_detections_with_probas[tuple( state_ideal_detection)][tuple(real_detection)] ] if debug: print("\n NUMBER OF REAL ATOMS = " + str(Nreal) + "\n") print("\n POSSIBLE REAL STATES \n") print(Possible_real_states) print("\n POSSIBLE REAL STATES WITH PROBABILITIES \n") print(Possible_real_states_with_probas) print("\n DENSITY MATRICES AFTER INTERACTIONS \n") print(Rho_after_interaction) print("\n POSSIBLE DETECTIONS \n") print(Selected_detections) print("\n PARTIAL TRACES \n") print(All_Ptraces) print("\n PARTIAL TRACES NORMALIZED \n") print(All_Ptraces_with_weights) # Calculate the quantum map by adding all these partial traces and dividing by the global trace quantum_map = Ptraces[0] for i in range(1, len(Ptraces)): quantum_map += Ptraces[i] quantum_map = quantum_map / quantum_map.tr() # Plot if fig_qm: fig = qt.hinton(quantum_map) plt.suptitle("State of the cavities") plt.show() return quantum_map