Beispiel #1
0
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')
Beispiel #3
0
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()
Beispiel #6
0
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()
Beispiel #8
0
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()
Beispiel #9
0
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()
Beispiel #11
0
"""
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