Пример #1
0
	def add_noise_generic_heis2(self, matrix, spectral_power_density, A_noise_power, H_pulse=None):
		'''
		add generic noise model

		same as add_noise_generic, but for a exponentially varying hamiltonian with saturation, see docs.
		'''
		spectrum = lambda u, x=spectral_power_density: x(u)*A_noise_power
		my_noise = noise_desciption(SPECTRUM_NOISE, spectrum, 0)
		H_data = hamiltonian_data(matrix, pulse(), signal_type.SWO2, noise = my_noise)
		self.hamiltonian_data += H_data
Пример #2
0
	def add_noise_static_heis2(self, matrix, gamma):
		'''
		add static noise model

		same as add_noise_static, but for a exponentially varying hamiltonian with saturation, see docs.
		'''
# 		my_noise = noise_desciption(STATIC_NOISE, None, 2./(2.*np.pi*T2)**2)
		my_noise = noise_desciption(STATIC_NOISE, None, gamma)
		H_data = hamiltonian_data(matrix, pulse(), signal_type.SWO2, noise = my_noise)
		self.hamiltonian_data += H_data
Пример #3
0
	def add_H0(self, matrix, amplitude):
		'''
		add a constant hamiltonian to the system

		Args:
			matrix (np.ndarray[dtype=np.complex, ndim=2]) : matrix element of the Hamiltonian (e.g. Pauli Z matrix)
			amplitude (double) : amplitude of the matrix element (e.g. 1e7 (Hz))
		'''
		H_pulse = pulse()
		H_pulse.add_block(0,-1,amplitude)
		H_data = hamiltonian_data(matrix, H_pulse,signal_type.NORMAL)
		self.hamiltonian_data += H_data
Пример #4
0
	def add_noise_static(self, matrix, T2, H_pulse=None):
		'''
		add static noise model

		Args:
			matrix (np.ndarray[dtype=np.complex, ndim=2]) : input matrix on what the noise needs to act.
			T2 (double) : the T2 you which you want to provide.
			TODO (later) H_pulse (pulse) : pulse describing a modulation of the noise. Optional variable
		'''
		my_noise = noise_desciption(STATIC_NOISE, None, 2./(2.*np.pi*T2)**2)
		H_data = hamiltonian_data(matrix, pulse(), signal_type.NORMAL, noise = my_noise)
		self.hamiltonian_data += H_data
Пример #5
0
	def add_noise_generic(self, matrix, spectral_power_density, A_noise_power, H_pulse=None):
		'''
		add generic noise model

		Args:
			matrix (np.ndarray[dtype=np.complex, ndim=2]) : input matrix on what the noise needs to act.
			spectral_power_density (lamda) : function describing S(omega) (frequency expected in 2pi*f)
			A_noise_power (double) : the noise power to provide.
			TODO (later) H_pulse (pulse) : pulse describing a modulation of the noise. Optional variable
		'''
		spectrum = lambda u, x=spectral_power_density: x(u)*A_noise_power
		my_noise = noise_desciption(SPECTRUM_NOISE, spectrum, 0)
		H_data = hamiltonian_data(matrix, pulse(), signal_type.NORMAL, noise = my_noise)
		self.hamiltonian_data += H_data
Пример #6
0
    def __init__(self, list_frequency, list_exchange, pos_q1=0, pos_q2=1):

        # Set up Hamiltonian
        self.position_Q1 = pos_q1
        self.position_Q2 = pos_q2

        self.f_qubits = list_frequency
        self.ex_qubits = list_exchange

        self.number_qubits = np.count_nonzero(self.f_qubits)
        self.dimension = 2**self.number_qubits

        #Time of the simulation in nanoseconds

        self.ramp_time = 10
        self.total_time = (1. / j_max / 2 + self.ramp_time)

        self.delta_z = (f1 - f2) * 1e9
        self.exchange_dc = j_max * 1e9

        self.H_zeeman = np.zeros([self.dimension, self.dimension],
                                 dtype=np.complex)
        self.H_zeeman[1, 1] = 1 / 2
        self.H_zeeman[2, 2] = -1 / 2

        self.H_heisenberg = np.zeros([4, 4], dtype=np.complex)
        self.H_heisenberg[1, 1] = -1 / 2
        self.H_heisenberg[2, 2] = -1 / 2
        self.H_heisenberg[1, 2] = 1 / 2
        self.H_heisenberg[2, 1] = 1 / 2

        oneoverfnoise = lambda omega: 1 / 2 / np.pi / omega
        #whitenoise=lambda omega: 0.*omega + 1
        self.init = np.zeros([4, 4], dtype=np.complex)
        self.init[2, 2] = 1
        #self.init[2,2] = 1/2
        #self.init[1,2] = 1/2
        #self.init[2,1] = 1/2
        self.pulseDummy = pgen.pulse()

        def add_dc_exchange_pulse(self, t_ramp, t_start, t_stop):
            delay = 1

            def enevlope_fun(time):
                return self.exchange_dc * (np.arctan(3) + np.arctan(
                    6 * (time - delay / 2) / delay)) / (2 * np.arctan(3))

            def enevlope_fun_ss(time):
                return self.exchange_dc * (np.arctan(3) + np.arctan(
                    6 * (1 - time - delay / 2) / delay)) / (2 * np.arctan(3))

            #self.pulseDummy.add_ramp(t_start,(t_start+t_ramp),self.exchange_dc)
            self.pulseDummy.add_function(t_start, (t_start + t_ramp),
                                         enevlope_fun)
            self.pulseDummy.add_block((t_start + t_ramp), (t_stop - t_ramp),
                                      self.exchange_dc)
            #self.pulseDummy.add_ramp_ss((t_stop-t_ramp),t_stop,self.exchange_dc,0)
            self.pulseDummy.add_function((t_stop - t_ramp), t_stop,
                                         enevlope_fun_ss)

            self.solver_obj.add_H1(2 * np.pi * self.H_heisenberg,
                                   self.pulseDummy)

# Create the solver
#self.solver_obj = DM.calculate_evolution(4)
# Add the init hamiltonian

        self.solver_obj = DM.DM_solver()
        self.solver_obj.add_H0(2 * np.pi * self.H_zeeman, self.delta_z)
        #self.solver_obj.add_noise_static(self.H_zeeman,18*1e6)
        #self.solver_obj.add_noise_generic(self.H_heisenberg,oneoverfnoise,self.exchange_dc/100)
        add_dc_exchange_pulse(self, self.ramp_time, 0., self.total_time)

        #self.pulseDummy.add_ramp(0,9.4,self.exchange_dc)
        #self.pulseDummy.add_block(9.4,50-9.4,self.exchange_dc)
        #self.pulseDummy.add_ramp_ss(50-9.4,50,self.exchange_dc,0)

        #self.solver_obj.add_H1(self.H_heisenberg,self.pulseDummy)

        self.solver_obj.calculate_evolution(self.init, self.total_time, 50000,
                                            10)
        self.solver_obj.plot_pop()

        #print(2*np.pi*self.delta_z*(self.total_time*1e-9))
        #print(2*np.pi*np.sum(self.pulseDummy.get_pulse(self.total_time,1e11))*1e-11)
        #print(qt.Qobj(self.solver_obj.return_final_unitary()))

        def get_unitary_gate_fidelity(self, U=None):
            """
            returns unitary gate fidelity
            Args
                runs (str/tuple) : number of runs to compute the average gate fidelity
            """
            self.solver_obj.calculate_evolution(self.init, self.total_time,
                                                50000, 1)
            U = qt.Qobj(self.solver_obj.get_unitary()[0])

            target = qt.Qobj(
                sp.linalg.expm(-np.pi / 4. * 1j *
                               sp.sparse.diags([0., -1., -1., 0.]).todense()))
            temp_phase = self.delta_z * (self.total_time * 1e-9)
            SQphase = qt.Qobj(
                sp.linalg.expm(-2 * np.pi * 1j * temp_phase * self.H_zeeman))
            fidelity = qt.average_gate_fidelity(U, target * SQphase)

            return fidelity

        def get_average_gate_fidelity(self, runs=500, target=None):
            """
            returns average gate fidelity
            Args
                runs (int) : number of runs to compute the average gate fidelity
                target (4x4 numpy array) : target unitary to compute fidelity
            """

            self.solver_obj.calculate_evolution(self.init, self.total_time,
                                                10000, 1)
            U_ideal = self.solver_obj.get_unitary()[0]
            self.solver_obj.add_noise_static(2 * np.pi * self.H_zeeman,
                                             18 * 1e-6)
            self.solver_obj.add_noise_generic(2 * np.pi * self.H_heisenberg,
                                              oneoverfnoise,
                                              self.exchange_dc / 100)
            self.solver_obj.calculate_evolution(self.init, self.total_time,
                                                10000, int(runs))

            U_list = self.solver_obj.get_unitary()

            # Calculate the averaged super operator in the Lioville superoperator form using column convention
            basis = [qt.basis(4, it) for it in range(4)]
            superoperator_basis = [
                basis_it1 * basis_it2.dag() for basis_it2 in basis
                for basis_it1 in basis
            ]
            averaged_map = np.zeros([16, 16], dtype=np.complex)
            for u in U_list:
                temp_U = qt.Qobj(u)
                output_density = list()
                for it in range(len(superoperator_basis)):
                    temp_vec = np.array(
                        qt.operator_to_vector(
                            temp_U * superoperator_basis[it] * temp_U.dag() /
                            float(runs)).full()).flatten()
                    output_density.append(np.array(temp_vec))
                averaged_map = np.add(averaged_map, np.array(output_density))

            # Define the target unitary operation
            if target is None:
                target = sp.linalg.expm(
                    -np.pi / 2. * 1j *
                    sp.sparse.diags([0., -1., -1., 0.]).todense())

            # get phase from optimizing noiseless unitary evolution
            def to_minimize_fidelity(theta):
                temp_z_gate = np.matmul(
                    sp.linalg.expm(-2 * np.pi * 1j * theta * self.H_zeeman),
                    U_ideal)
                temp_m = np.matmul(sp.conjugate(sp.transpose(target)),
                                   temp_z_gate)
                return np.real(1. - (sp.trace(
                    np.matmul(temp_m, sp.conjugate(sp.transpose(temp_m)))) +
                                     np.abs(sp.trace(temp_m))**2.) / 20.)

            ideal_phase = sp.optimize.minimize(
                to_minimize_fidelity,
                [self.delta_z * (self.total_time * 1e-9)],
                method='Nelder-Mead',
                tol=1e-6).x[0]

            target = np.matmul(
                sp.linalg.expm(2 * np.pi * 1j * ideal_phase * self.H_zeeman),
                target)

            # Change the shape of the averaged super operator to match the definitions used in QuTip (row convention)
            target = qt.Qobj(target)
            averaged_map = qt.Qobj(averaged_map).trans()
            averaged_map._type = 'super'
            averaged_map.dims = [[[4], [4]], [[4], [4]]]
            averaged_map.superrep = qt.to_super(target).superrep

            # Calculate the average gate fidelity of the superoperator with the target unitary gate

            fidelity = qt.average_gate_fidelity(averaged_map, target)
            return fidelity

        def show_pulse_sequence(self):
            t, v = self.pulseDummy.get_pulse(self.total_time, 1e11)
            plt.plot(t, v)
            plt.xlabel('time (ns)')
            plt.ylabel('amplitude (a.u.)')
            plt.show()

        #print(self.solver_obj.get_unitary())
        print((1 - get_average_gate_fidelity(self)) * 100)
    def __init__(self,
                 leverarm=0.021,
                 offset=1e4,
                 j_sat=0.300,
                 b_diff=0.200,
                 j_dc=0.025,
                 noise_strength=1. * 1e-5):
        #Time of the simulation in nanoseconds

        # add offset to plotting
        # think of a way to scale down

        #Preset fundamental system parameters
        self.delta_z = b_diff * 1e9
        self.exchange_sat = j_sat * 1e9
        self.vB_leverarm = leverarm
        self.exchange_residual = offset
        self.noise_amplitude_voltage = noise_strength * self.vB_leverarm

        #Preset Hamiltonians
        self.H_zeeman = 2. * np.pi * (
            qt.tensor(qt.sigmaz(), qt.qeye(2)) / 4. -
            qt.tensor(qt.qeye(2), qt.sigmaz()) / 4.)[:, :]

        self.H_zeeman_Q1 = 2. * np.pi * (qt.tensor(qt.sigmaz(), qt.qeye(2)) /
                                         2.)[:, :]
        self.H_zeeman_Q2 = 2. * np.pi * (qt.tensor(qt.qeye(2), qt.sigmaz()) /
                                         2.)[:, :]

        self.H_zeeman_ac = 2. * np.pi * (
            qt.tensor(qt.sigmax(), qt.qeye(2)) / 2. +
            qt.tensor(qt.qeye(2), qt.sigmax()) / 2.)[:, :]

        #Preset exchange Hamiltonian. Multiplication with saturated exchange interaction is necessary since formula is neither linear nor exponentional, thus, factors cannot be moved infront of whole formula.
        self.H_heisenberg_raw = 2. * np.pi * (
            (qt.tensor(qt.sigmax(), qt.sigmax()) + qt.tensor(
                qt.sigmay(), qt.sigmay()) + qt.tensor(qt.sigmaz(), qt.sigmaz())
             - qt.tensor(qt.qeye(2), qt.qeye(2))) / 4.)[:, :]

        self.H_heisenberg = self.H_heisenberg_raw * self.exchange_sat

        #whitenoise=lambda omega: 0.*omega + 1
        self.init = np.zeros([4, 4], dtype=np.complex)
        self.init[1, 1] = 1.

        # formula to set value of residual exchange coupling in Hz
        def residual_exchange(res_ex):
            if self.exchange_sat <= res_ex:
                print(
                    "Saturation level is greater or equal than residual exchange"
                )
                return None
            else:
                #return np.log(np.sqrt(self.exchange_sat*res_ex)/(self.exchange_sat-res_ex))
                return exchange_sat_inverse(res_ex / self.exchange_sat)

        self.offset = residual_exchange(self.exchange_residual)
        self.exchange_dc = j_dc * 1e9

        self.runs = int(5000)
        #        self.total_time=15000

        self.delta_z = b_diff * 1e9
        self.exchange_dc = [self.exchange_dc / 5., self.exchange_dc]

        self.vB_operation_point = [(exchange_sat_inverse(
            (exchange_it + 0. * self.exchange_residual) / self.exchange_sat) -
                                    self.offset) / self.vB_leverarm
                                   for exchange_it in self.exchange_dc]

        #Set initial states for exchange settings
        self.init_states_ST = list()
        self.init_states_Bell = list()
        for exch in self.exchange_dc:
            eig_val, eig_vec = sp.linalg.eigh(
                np.diag(1e10 * np.array([1., 0., 0., -1.])) +
                self.H_zeeman * self.delta_z + self.H_heisenberg_raw * exch)
            temp_vec = (qt.Qobj(eig_vec[1]) + qt.Qobj(eig_vec[2])) / np.sqrt(2)
            self.init_states_ST.append(
                np.array((temp_vec * temp_vec.dag()).full()))
            temp_vec = (qt.Qobj(eig_vec[0]) + qt.Qobj(eig_vec[1])) / np.sqrt(2)
            self.init_states_Bell.append(
                np.array((temp_vec * temp_vec.dag()).full()))

        # Set up noise parameters
        oneoverfnoise = lambda omega: 1. / 2. / np.pi / omega
        self.T2sQ1 = 15. * 1e-5  #1.7*1e-6
        self.T2sQ2 = 14. * 1e-5  #1.2*1e-6

        # Is Ramsey possible to map full decay of charge noise in exchange

        # Set up noise Hamiltonians

        self.noise_amplitude_voltage_list = np.linspace(0.01, 0.1,
                                                        2) * self.vB_leverarm
        #        self.noise_amplitude_voltage_list = np.linspace(0.1,1.,10)*1e-6
        self.total_time_exch = [1000., 1000.]

        #        self.list_exp_Q1 = list()
        #        self.list_exp_Q2 = list()
        self.list_exp_J_ST = list()
        self.list_exp_J_Bell = list()
        self.time = [0., 0.]

        for iterator in range(len(self.total_time_exch)):
            # Add noise to Hamiltonian
            self.solver_obj = DM.DM_solver()
            self.solver_obj.add_H0(self.H_zeeman, self.delta_z)

            exchange_pulse = pgen.pulse()
            exchange_pulse.add_offset(self.vB_operation_point[1] *
                                      self.vB_leverarm + self.offset)
            self.solver_obj.add_H1_expsat(self.H_heisenberg, exchange_pulse)

            #            self.solver_obj.add_noise_static(self.H_zeeman_Q1,self.T2sQ1)
            #            self.solver_obj.add_noise_static(self.H_zeeman_Q2,self.T2sQ2)
            self.solver_obj.add_noise_generic_expsat(
                self.H_heisenberg, oneoverfnoise,
                self.noise_amplitude_voltage_list[1])

            self.init = self.init_states_ST[iterator]
            self.solver_obj.calculate_evolution(
                self.init, self.total_time_exch[iterator],
                self.total_time_exch[iterator] * 10, self.runs)
            temp_list, temp_time = self.solver_obj.return_expectation_values_general(
                [self.init])
            self.list_exp_J_ST.append(temp_list[0])

            self.init = self.init_states_Bell[iterator]
            self.solver_obj.calculate_evolution(
                self.init, self.total_time_exch[iterator],
                self.total_time_exch[iterator] * 10, self.runs)
            temp_list, temp_time = self.solver_obj.return_expectation_values_general(
                [self.init])
            self.list_exp_J_Bell.append(temp_list[0])

            self.time[iterator] = temp_time


#        np.savetxt("./data/calibration_exchange_ST_5000.csv", np.array(self.list_exp_J_ST), delimiter=',')
        np.savetxt("./data/calibration_exchange_ST_j_5_bz_02_dv_01.csv",
                   np.array(self.list_exp_J_ST[0]),
                   delimiter=',')
        np.savetxt("./data/calibration_exchange_ST_j_25_bz_02_dv_01.csv",
                   np.array(self.list_exp_J_ST[1]),
                   delimiter=',')

        np.savetxt("./data/calibration_exchange_Bell_j_5_bz_02_dv_01.csv",
                   np.array(self.list_exp_J_Bell[0]),
                   delimiter=',')
        np.savetxt("./data/calibration_exchange_Bell_j_25_bz_02_dv_01.csv",
                   np.array(self.list_exp_J_Bell[1]),
                   delimiter=',')

        fig, axs = plt.subplots(2, 1)

        expect = self.list_exp_J_ST[0]
        axs[0].plot(self.time[0], expect, 'b', label="J = 5MHz")
        axs[0].set_xlabel("time (ns)")
        axs[0].set_ylabel("expectation |01>+|10>")
        axs[0].set_xlim(0, 1000)
        axs[0].grid(True)

        expect = self.list_exp_J_ST[1]
        axs[1].plot(self.time[1], expect, 'b', label="J = 25MHz")
        axs[1].set_xlabel("time (ns)")
        axs[1].set_ylabel("expectation |01>+|10>")
        axs[1].set_xlim(0, 1000)
        axs[1].grid(True)

        fig.savefig('./dephasing_exchange_bell.png', dpi=1200)
        plt.show()