def get_f_pulse_double_sided(fluxlutman, theta_i): thetawave_A = wfl.martinis_flux_pulse( length=fluxlutman.cz_length() * fluxlutman.czd_length_ratio(), lambda_2=fluxlutman.cz_lambda_2(), lambda_3=fluxlutman.cz_lambda_3(), theta_i=theta_i, theta_f=np.deg2rad(fluxlutman.cz_theta_f()), sampling_rate=fluxlutman.sampling_rate()) # return in terms of theta epsilon_A = wfl.theta_to_eps(thetawave_A, fluxlutman.q_J2()) amp_A = fluxlutman.calc_eps_to_amp(epsilon_A, state_A='11', state_B='02') # transform detuning frequency to positive amplitude # Generate the second CZ pulse thetawave_B = wfl.martinis_flux_pulse( length=fluxlutman.cz_length() * (1 - fluxlutman.czd_length_ratio()), lambda_2=fluxlutman.cz_lambda_2(), lambda_3=fluxlutman.cz_lambda_3(), theta_i=theta_i, theta_f=np.deg2rad(fluxlutman.cz_theta_f()), sampling_rate=fluxlutman.sampling_rate()) # return in terms of theta epsilon_B = wfl.theta_to_eps(thetawave_B, fluxlutman.q_J2()) amp_B = fluxlutman.calc_eps_to_amp(epsilon_B, state_A='11', state_B='02', positive_branch=False) # transform detuning frequency to negative amplitude # N.B. No amp scaling and offset present amp = np.concatenate([amp_A, amp_B]) return amp
def get_f_pulse_double_sided(self): thetawave_A = wfl.martinis_flux_pulse( length=self.fluxlutman.cz_length() * self.fluxlutman.czd_length_ratio(), lambda_2=self.fluxlutman.cz_lambda_2(), lambda_3=self.fluxlutman.cz_lambda_3(), theta_i=self.theta_i, theta_f=np.deg2rad(self.fluxlutman.cz_theta_f()), sampling_rate=self.fluxlutman.sampling_rate( )) # return in terms of theta epsilon_A = wfl.theta_to_eps(thetawave_A, self.fluxlutman.q_J2()) amp_A = self.fluxlutman.calc_eps_to_amp(epsilon_A, state_A='11', state_B='02') # transform detuning frequency to positive amplitude f_pulse_A = self.fluxlutman.calc_amp_to_freq(amp_A, '01') # Generate the second CZ pulse. If the params are np.nan, default # to the main parameter if not np.isnan(self.fluxlutman.czd_theta_f()): d_theta_f = self.fluxlutman.czd_theta_f() else: d_theta_f = self.fluxlutman.cz_theta_f() if not np.isnan(self.fluxlutman.czd_lambda_2()): d_lambda_2 = self.fluxlutman.czd_lambda_2() else: d_lambda_2 = self.fluxlutman.cz_lambda_2() if not np.isnan(self.fluxlutman.czd_lambda_3()): d_lambda_3 = self.fluxlutman.czd_lambda_3() else: d_lambda_3 = self.fluxlutman.cz_lambda_3() thetawave_B = wfl.martinis_flux_pulse( length=self.fluxlutman.cz_length() * (1 - self.fluxlutman.czd_length_ratio()), lambda_2=d_lambda_2, lambda_3=d_lambda_3, theta_i=self.theta_i, theta_f=np.deg2rad(d_theta_f), sampling_rate=self.fluxlutman.sampling_rate( )) # return in terms of theta epsilon_B = wfl.theta_to_eps(thetawave_B, self.fluxlutman.q_J2()) amp_B = self.fluxlutman.calc_eps_to_amp(epsilon_B, state_A='11', state_B='02', positive_branch=False) # transform detuning frequency to negative amplitude f_pulse_B = self.fluxlutman.calc_amp_to_freq(amp_B, '01') # N.B. No amp scaling and offset present f_pulse = np.concatenate([f_pulse_A, f_pulse_B]) amp = np.concatenate([amp_A, amp_B]) return f_pulse, amp
def test_martinis_flux_pulse_theta_bounds(self): """ Tests that the constraint setting theta_f and theta_i is working correctly """ for theta_f in [40, 60, 80, 90]: theta_f = np.deg2rad(theta_f) for lambda_2 in np.linspace(-.2, .2, 5): for lambda_3 in np.linspace(-.2, .2, 5): theta_i = wfl.eps_to_theta(800e6, 25e6) thetas = wfl.martinis_flux_pulse(35e-9, theta_i=theta_i, theta_f=theta_f, lambda_2=lambda_2, lambda_3=lambda_3, sampling_rate=1e9) np.testing.assert_almost_equal(thetas[0], theta_i, decimal=3) np.testing.assert_almost_equal(thetas[-1], theta_i, decimal=2) np.testing.assert_almost_equal(thetas[len(thetas) // 2], theta_f, decimal=3) # The martinis_flux_pulse was change to always clip values # It breaks sometimes running optmizations if the optmizer tries # certains values that are not allowed. It is a well know "issue" # It is ok to go almost silent with self.assertLogs("", level='DEBUG') as cm: # with self.assertRaises(ValueError): theta_i = np.deg2rad(40) theta_f = np.deg2rad(30) thetas = wfl.martinis_flux_pulse(35e-9, theta_i=theta_i, theta_f=theta_f, lambda_2=lambda_2, lambda_3=lambda_3, sampling_rate=1e9) msg0 = "final coupling weaker than initial coupling" msg1 = "Martinis flux wave form has been clipped to" self.assertIn(msg0, cm.output[0]) self.assertIn(msg1, cm.output[1])
def get_f_pulse_double_sided(fluxlutman, theta_i, which_gate: str = 'NE'): cz_lambda_2 = fluxlutman.get('cz_lambda_2_{}'.format(which_gate)) cz_lambda_3 = fluxlutman.get('cz_lambda_3_{}'.format(which_gate)) cz_length = fluxlutman.get('cz_length_{}'.format(which_gate)) cz_theta_f = fluxlutman.get('cz_theta_f_{}'.format(which_gate)) czd_length_ratio = fluxlutman.get('czd_length_ratio_{}'.format(which_gate)) q_J2 = fluxlutman.get('q_J2_{}'.format(which_gate)) thetawave_A = wfl.martinis_flux_pulse( length=cz_length * czd_length_ratio, lambda_2=cz_lambda_2, lambda_3=cz_lambda_3, theta_i=theta_i, theta_f=np.deg2rad(cz_theta_f), sampling_rate=fluxlutman.sampling_rate()) # return in terms of theta epsilon_A = wfl.theta_to_eps(thetawave_A, q_J2) amp_A = fluxlutman.calc_eps_to_amp(epsilon_A, state_A='11', state_B='02', which_gate=which_gate) # transform detuning frequency to positive amplitude # Generate the second CZ pulse thetawave_B = wfl.martinis_flux_pulse( length=cz_length * (1 - czd_length_ratio), lambda_2=cz_lambda_2, lambda_3=cz_lambda_3, theta_i=theta_i, theta_f=np.deg2rad(cz_theta_f), sampling_rate=fluxlutman.sampling_rate()) # return in terms of theta epsilon_B = wfl.theta_to_eps(thetawave_B, q_J2) amp_B = fluxlutman.calc_eps_to_amp(epsilon_B, state_A='11', state_B='02', positive_branch=False, which_gate=which_gate) # transform detuning frequency to negative amplitude # N.B. No amp scaling and offset present amp = np.concatenate([amp_A, amp_B]) return amp
def test_martinis_flux_pulse_theta_bounds(self): """ Tests that the constraint setting theta_f and theta_i is working correctly """ for theta_f in [40, 60, 80, 90]: theta_f = np.deg2rad(theta_f) for lambda_2 in np.linspace(-.2, .2, 5): for lambda_3 in np.linspace(-.2, .2, 5): theta_i = wfl.eps_to_theta(800e6, 25e6) thetas = wfl.martinis_flux_pulse(35e-9, theta_i=theta_i, theta_f=theta_f, lambda_2=lambda_2, lambda_3=lambda_3, sampling_rate=1e9) np.testing.assert_almost_equal(thetas[0], theta_i, decimal=3) np.testing.assert_almost_equal(thetas[-1], theta_i, decimal=2) np.testing.assert_almost_equal(thetas[len(thetas) // 2], theta_f, decimal=3) with self.assertRaises(ValueError): theta_i = np.deg2rad(40) theta_f = np.deg2rad(30) thetas = wfl.martinis_flux_pulse(35e-9, theta_i=theta_i, theta_f=theta_f, lambda_2=lambda_2, lambda_3=lambda_3, sampling_rate=1e9)
def compute_propagator(arglist): # I was parallelizing this function in the cluster, then I changed but the list as an argument remains. # Below each list item is assigned to its own variable fluxbias_q0 = arglist['fluxbias_q0'] fluxbias_q1 = arglist['fluxbias_q1'] fitted_stepresponse_ty = arglist['fitted_stepresponse_ty'] fluxlutman = arglist['fluxlutman'] noise_parameters_CZ = arglist['noise_parameters_CZ'] sim_step = 1 / fluxlutman.sampling_rate() subdivisions_of_simstep = 4 # 4 is a good one, corresponding to a time step of 0.1 ns sim_step_new = sim_step / subdivisions_of_simstep # waveform is generated according to sampling rate of AWG, # but we can use a different step for simulating the time evolution tlist = np.arange(0, fluxlutman.cz_length(), sim_step) # residual_coupling=czf.conditional_frequency(0,fluxlutman,noise_parameters_CZ) # To check residual coupling at the operating point. # print(residual_coupling) # Change amp to get the residual coupling at different points eps_i = fluxlutman.calc_amp_to_eps(0, state_A='11', state_B='02') theta_i = wfl.eps_to_theta(eps_i, g=fluxlutman.q_J2()) # Beware theta in radian! if not fluxlutman.czd_double_sided(): thetawave = wfl.martinis_flux_pulse( length=fluxlutman.cz_length(), lambda_2=fluxlutman.cz_lambda_2(), lambda_3=fluxlutman.cz_lambda_3(), theta_i=theta_i, theta_f=np.deg2rad(fluxlutman.cz_theta_f()), sampling_rate=fluxlutman.sampling_rate( )) # return in terms of theta epsilon = wfl.theta_to_eps(thetawave, fluxlutman.q_J2()) amp = fluxlutman.calc_eps_to_amp(epsilon, state_A='11', state_B='02') # transform detuning frequency to (positive) amplitude else: amp = get_f_pulse_double_sided(fluxlutman, theta_i) # For better accuracy in simulations, redefine amp in terms of sim_step_new. # We split here below in two cases to keep into account that certain times net-zero is one AWG time-step longer # than the conventional pulse with the same pulse length. if len(tlist) == len(amp): tlist_temp = np.concatenate( (tlist, np.array([fluxlutman.cz_length()]))) tlist_new = np.arange(0, fluxlutman.cz_length(), sim_step_new) else: tlist_temp = np.concatenate( (tlist, np.array( [fluxlutman.cz_length(), fluxlutman.cz_length() + sim_step]))) tlist_new = np.arange(0, fluxlutman.cz_length() + sim_step, sim_step_new) amp_temp = np.concatenate((amp, np.array([ 0 ]))) # amp should come back to the initial value, i.e. at the sweet spot amp_interp = interp1d(tlist_temp, amp_temp) amp = amp_interp(tlist_new) if fluxlutman.czd_double_sided( ) and noise_parameters_CZ.waiting_at_sweetspot() != 0: tlist_new, amp = czf.add_waiting_at_sweetspot( tlist_new, amp, noise_parameters_CZ.waiting_at_sweetspot()) # Apply voltage scaling amp = amp * noise_parameters_CZ.voltage_scaling_factor() ### Apply distortions if noise_parameters_CZ.distortions(): amp_final = czf.distort_amplitude( fitted_stepresponse_ty=fitted_stepresponse_ty, amp=amp, tlist_new=tlist_new, sim_step_new=sim_step_new) else: amp_final = amp # Uncomment to get plots of the distorted pulse. # czf.plot(x_plot_vec=[np.array(tlist_new)*1e9],y_plot_vec=[amp_final], # title='Pulse with distortions, absolute', # xlabel='Time (ns)',ylabel='Amplitude (volts)') # czf.plot(x_plot_vec=[np.array(tlist_new)*1e9],y_plot_vec=[amp_final-amp], # title='Pulse with distortions, difference', # xlabel='Time (ns)',ylabel='Amplitude (volts)') ### the fluxbias_q0 affects the pulse shape after the distortions have been taken into account amp_final, f_pulse_final = czf.shift_due_to_fluxbias_q0( fluxlutman=fluxlutman, amp_final=amp_final, fluxbias_q0=fluxbias_q0, noise_parameters_CZ=noise_parameters_CZ) intervals_list = np.zeros(np.size(tlist_new)) + sim_step_new # We add the single qubit rotations at the end of the pulse if noise_parameters_CZ.Z_rotations_length() != 0: actual_Z_rotations_length = np.arange( 0, noise_parameters_CZ.Z_rotations_length(), sim_step_new)[-1] + sim_step_new intervals_list = np.append( intervals_list, [actual_Z_rotations_length / 2, actual_Z_rotations_length / 2]) amp_Z_rotation = [0, 0] amp_Z_rotation, f_pulse_Z_rotation = czf.shift_due_to_fluxbias_q0( fluxlutman=fluxlutman, amp_final=amp_Z_rotation, fluxbias_q0=fluxbias_q0, noise_parameters_CZ=noise_parameters_CZ) # We add the idle time at the end of the pulse (even if it's not at the end. It doesn't matter) if noise_parameters_CZ.total_idle_time() != 0: actual_total_idle_time = np.arange( 0, noise_parameters_CZ.total_idle_time(), sim_step_new)[-1] + sim_step_new intervals_list = np.append( intervals_list, [actual_total_idle_time / 2, actual_total_idle_time / 2]) amp_idle_time = [0, 0] double_sided = fluxlutman.czd_double_sided( ) # idle time is single-sided so we save the fluxlutman.czd_double_sided() value, set it to False # and later restore it to the original value fluxlutman.czd_double_sided(False) amp_idle_time, f_pulse_idle_time = czf.shift_due_to_fluxbias_q0( fluxlutman=fluxlutman, amp_final=amp_idle_time, fluxbias_q0=fluxbias_q0, noise_parameters_CZ=noise_parameters_CZ) fluxlutman.czd_double_sided(double_sided) # We concatenate amp and f_pulse with the values they take during the Zrotations and idle_time. # It comes after the previous line because of details of the function czf.shift_due_to_fluxbias_q0 if noise_parameters_CZ.Z_rotations_length() != 0: amp_final = np.concatenate((amp_final, amp_Z_rotation)) f_pulse_final = np.concatenate((f_pulse_final, f_pulse_Z_rotation)) if noise_parameters_CZ.total_idle_time() != 0: amp_final = np.concatenate((amp_final, amp_idle_time)) f_pulse_final = np.concatenate((f_pulse_final, f_pulse_idle_time)) # czf.plot(x_plot_vec=[np.arange(0,np.size(intervals_list))],y_plot_vec=[amp_final], # title='Pulse with (possibly) single qubit rotations and idle time', # xlabel='Time (ns)',ylabel='Amplitude (volts)') # czf.plot(x_plot_vec=[np.array(tlist_new)*1e9],y_plot_vec=[amp_final-amp_final_new], # title='Pulse with distortions and shift due to fluxbias_q0, difference', # xlabel='Time (ns)',ylabel='Amplitude (volts)') # amp_final = amp_final_new # czf.plot(x_plot_vec=[np.arange(0,np.size(intervals_list))],y_plot_vec=[f_pulse_final/1e9], # title='Pulse with distortions and shift due to fluxbias_q0', # xlabel='Time (ns)',ylabel='Frequency (GHz)') t_final = np.sum(intervals_list) # actual overall gate length ### Obtain jump operators for Lindblad equation c_ops = czf.return_jump_operators(noise_parameters_CZ=noise_parameters_CZ, f_pulse_final=f_pulse_final, fluxlutman=fluxlutman) ### Compute propagator U_final = czf.time_evolution_new(c_ops=c_ops, noise_parameters_CZ=noise_parameters_CZ, fluxlutman=fluxlutman, fluxbias_q1=fluxbias_q1, amp=amp_final, sim_step=sim_step_new, intervals_list=intervals_list) #print(czf.verify_CPTP(U_superop_average)) # simple check of CPTP property return [U_final, t_final]
def compute_propagator(arglist): # I was parallelizing this function in the cluster, then I changed but the list as an argument remains. # Below each list item is assigned to its own variable fluxbias_q0 = arglist['fluxbias_q0'] fluxbias_q1 = arglist['fluxbias_q1'] fitted_stepresponse_ty = arglist['fitted_stepresponse_ty'] fluxlutman = arglist['fluxlutman'] fluxlutman_static = arglist['fluxlutman_static'] sim_control_CZ = arglist['sim_control_CZ'] which_gate = sim_control_CZ.which_gate() gates_num = sim_control_CZ.gates_num( ) # repeat the same gate this number of times gates_interval = sim_control_CZ.gates_interval( ) # idle time between repeated gates q_J2 = fluxlutman.get('q_J2_{}'.format(which_gate)) czd_double_sided = fluxlutman.get('czd_double_sided_{}'.format(which_gate)) cz_length = fluxlutman.get('cz_length_{}'.format(which_gate)) cz_lambda_2 = fluxlutman.get('cz_lambda_2_{}'.format(which_gate)) cz_lambda_3 = fluxlutman.get('cz_lambda_3_{}'.format(which_gate)) cz_theta_f = fluxlutman.get('cz_theta_f_{}'.format(which_gate)) sim_step = 1 / fluxlutman.sampling_rate() subdivisions_of_simstep = sim_control_CZ.simstep_div( ) # 4 is a good one, corresponding to a time step of 0.1 ns sim_step_new = sim_step / subdivisions_of_simstep # waveform is generated according to sampling rate of AWG, # but we can use a different step for simulating the time evolution tlist = np.arange(0, cz_length, sim_step) # residual_coupling=czf.conditional_frequency(0,fluxlutman,fluxlutman_static, which_gate=which_gate) # To check residual coupling at the operating point. # print(residual_coupling) # Change amp to get the residual coupling at different points eps_i = fluxlutman.calc_amp_to_eps(0, state_A='11', state_B='02', which_gate=which_gate) theta_i = wfl.eps_to_theta(eps_i, g=q_J2) # Beware theta in radian! if not czd_double_sided: thetawave = wfl.martinis_flux_pulse( length=cz_length, lambda_2=cz_lambda_2, lambda_3=cz_lambda_3, theta_i=theta_i, theta_f=np.deg2rad(cz_theta_f), sampling_rate=fluxlutman.sampling_rate( )) # return in terms of theta epsilon = wfl.theta_to_eps(thetawave, q_J2) amp = fluxlutman.calc_eps_to_amp(epsilon, state_A='11', state_B='02', which_gate=which_gate) # transform detuning frequency to (positive) amplitude else: amp = get_f_pulse_double_sided(fluxlutman, theta_i, which_gate=which_gate) # For better accuracy in simulations, redefine amp in terms of sim_step_new. # We split here below in two cases to keep into account that certain times net-zero is one AWG time-step longer # than the conventional pulse with the same pulse length. if len(tlist) == len(amp): tlist_temp = np.concatenate((tlist, np.array([cz_length]))) tlist_new = np.arange(0, cz_length, sim_step_new) else: tlist_temp = np.concatenate( (tlist, np.array([cz_length, cz_length + sim_step]))) tlist_new = np.arange(0, cz_length + sim_step, sim_step_new) amp_temp = np.concatenate((amp, np.array([ 0 ]))) # amp should come back to the initial value, i.e. at the sweet spot amp_interp = interp1d(tlist_temp, amp_temp) amp = amp_interp(tlist_new) if czd_double_sided and sim_control_CZ.waiting_at_sweetspot() != 0: tlist_new, amp = czf.add_waiting_at_sweetspot( tlist_new, amp, sim_control_CZ.waiting_at_sweetspot()) # Apply voltage scaling amp = amp * sim_control_CZ.voltage_scaling_factor() # Apply distortions if sim_control_CZ.distortions(): amp_final = czf.distort_amplitude( fitted_stepresponse_ty=fitted_stepresponse_ty, amp=amp, tlist_new=tlist_new, sim_step_new=sim_step_new) else: amp_final = amp # Uncomment to get plots of the distorted pulse. # czf.plot(x_plot_vec=[np.array(tlist_new)*1e9],y_plot_vec=[amp_final], # title='Pulse with distortions, absolute', # xlabel='Time (ns)',ylabel='Amplitude (volts)') # czf.plot(x_plot_vec=[np.array(tlist_new)*1e9],y_plot_vec=[amp_final-amp], # title='Pulse with distortions, difference', # xlabel='Time (ns)',ylabel='Amplitude (volts)') # The fluxbias_q0 affects the pulse shape after the distortions have been taken into account if sim_control_CZ.sigma_q0() != 0: amp_final = czf.shift_due_to_fluxbias_q0(fluxlutman=fluxlutman, amp_final=amp_final, fluxbias_q0=fluxbias_q0, sim_control_CZ=sim_control_CZ, which_gate=which_gate) intervals_list = np.zeros(np.size(tlist_new)) + sim_step_new # We add the single qubit rotations at the end of the pulse if sim_control_CZ.Z_rotations_length() != 0: actual_Z_rotations_length = np.arange( 0, sim_control_CZ.Z_rotations_length(), sim_step_new)[-1] + sim_step_new intervals_list = np.append( intervals_list, [actual_Z_rotations_length / 2, actual_Z_rotations_length / 2]) amp_Z_rotation = [0, 0] if sim_control_CZ.sigma_q0() != 0: amp_Z_rotation = czf.shift_due_to_fluxbias_q0( fluxlutman=fluxlutman, amp_final=amp_Z_rotation, fluxbias_q0=fluxbias_q0, sim_control_CZ=sim_control_CZ, which_gate=which_gate) # We add the idle time at the end of the pulse (even if it's not at the end. It doesn't matter) if sim_control_CZ.total_idle_time() != 0: actual_total_idle_time = np.arange(0, sim_control_CZ.total_idle_time(), sim_step_new)[-1] + sim_step_new intervals_list = np.append( intervals_list, [actual_total_idle_time / 2, actual_total_idle_time / 2]) amp_idle_time = [0, 0] # idle time is single-sided so we save the czd_double_sided value, set it to False # and later restore it to the original value double_sided = czd_double_sided log.debug('Changing fluxlutman czd_double_sided_{} value to {}'.format( which_gate, False)) fluxlutman.set('czd_double_sided_{}'.format(which_gate), False) if sim_control_CZ.sigma_q0() != 0: amp_idle_time = czf.shift_due_to_fluxbias_q0( fluxlutman=fluxlutman, amp_final=amp_idle_time, fluxbias_q0=fluxbias_q0, sim_control_CZ=sim_control_CZ, which_gate=which_gate) log.debug( 'Changing fluxlutman czd_double_sided_{} value back to {}'.format( which_gate, double_sided)) fluxlutman.set('czd_double_sided_{}'.format(which_gate), double_sided) # We concatenate amp and f_pulse with the values they take during the Zrotations and idle_x # It comes after the previous line because of details of the function czf.shift_due_to_fluxbias_q0 if sim_control_CZ.Z_rotations_length() != 0: amp_final = np.concatenate((amp_final, amp_Z_rotation)) if sim_control_CZ.total_idle_time() != 0: amp_final = np.concatenate((amp_final, amp_idle_time)) # czf.plot(x_plot_vec=[np.arange(0,np.size(intervals_list))],y_plot_vec=[amp_final], # title='Pulse with (possibly) single qubit rotations and idle time', # xlabel='Time (ns)',ylabel='Amplitude (volts)') # czf.plot(x_plot_vec=[np.array(tlist_new)*1e9],y_plot_vec=[amp_final-amp_final_new], # title='Pulse with distortions and shift due to fluxbias_q0, difference', # xlabel='Time (ns)',ylabel='Amplitude (volts)') # if gates_num > 1: # orig_size = np.size(intervals_list) # idle_size = int(gates_interval / sim_step_new) # intervals_list = np.full(orig_size * gates_num + idle_size * (gates_num - 1), sim_step_new) # amp_append = np.concatenate((np.zeros(idle_size), amp_final[:orig_size])) # for gate in range(gates_num - 1): # amp_final = np.append(amp_final, amp_append) if gates_num > 1: # This is intended to make the simulation faster by skipping # all the amp = 0 steps, verified to encrease sim speed # 4.7s/data point -> 4.0s/data point # Errors in simulation outcomes are < 1e-10 actual_gates_interval = np.arange(0, gates_interval, sim_step_new)[-1] + sim_step_new # We add an extra small step to ensure the amp signal goes to # zero first interval_append = np.concatenate( ([sim_step_new, actual_gates_interval - sim_step_new], intervals_list)) amp_append = np.concatenate(([0, 0], amp_final)) # Append arbitrary number of same gate for gate in range(gates_num - 1): amp_final = np.append(amp_final, amp_append) intervals_list = np.append(intervals_list, interval_append) t_final = np.sum(intervals_list) # actual overall gate length # Obtain jump operators for Lindblad equation c_ops = czf.return_jump_operators(sim_control_CZ=sim_control_CZ, amp_final=amp_final, fluxlutman=fluxlutman, which_gate=which_gate) # for waveformcomparizon purposes # sim_control_CZ.sim_waveform(amp_final) # Compute propagator U_final = czf.time_evolution_new(c_ops=c_ops, sim_control_CZ=sim_control_CZ, fluxlutman_static=fluxlutman_static, fluxlutman=fluxlutman, fluxbias_q1=fluxbias_q1, amp=amp_final, sim_step=sim_step_new, intervals_list=intervals_list, which_gate=which_gate) # print(czf.verify_CPTP(U_superop_average)) # simple check of CPTP property return [U_final, t_final]
def compute_propagator_parallelizable(arglist): # arglist = [samplepoint_q0,samplepoint_q1,fluxlutman_args,noise_parameters_CZ_args,fitted_stepresponse_ty,instrument_number,cluster] fluxbias_q0 = arglist['fluxbias_q0'] fluxbias_q1 = arglist['fluxbias_q1'] fitted_stepresponse_ty = arglist['fitted_stepresponse_ty'] if arglist['cluster']: fluxlutman_args = arglist[ 'fluxlutman_args'] # [sampling_rate, cz_length, q_J2, czd_double_sided, cz_lambda_2, cz_lambda_3, # cz_theta_f, czd_length_ratio] noise_parameters_CZ_args = arglist[ 'noise_parameters_CZ_args'] # [Z_rotations_length, voltage_scaling_factor, distortions, T1_q0, T1_q1, T2_q0_sweetspot, T2_q0_interaction_point, # T2_q0_amplitude_dependent, T2_q1] number = arglist['number'] fluxlutman = flm.AWG8_Flux_LutMan('fluxlutman_' + '{}'.format(number)) noise_parameters_CZ = npCZ.NoiseParametersCZ('noise_parameters_CZ_' + '{}'.format(number)) fluxlutman.sampling_rate(fluxlutman_args['sampling_rate']) fluxlutman.cz_length(fluxlutman_args['cz_length']) fluxlutman.q_J2(fluxlutman_args['q_J2']) fluxlutman.czd_double_sided(fluxlutman_args['czd_double_sided']) fluxlutman.cz_lambda_2(fluxlutman_args['cz_lambda_2']) fluxlutman.cz_lambda_3(fluxlutman_args['cz_lambda_3']) fluxlutman.cz_theta_f(fluxlutman_args['cz_theta_f']) fluxlutman.czd_length_ratio(fluxlutman_args['czd_length_ratio']) fluxlutman.q_polycoeffs_freq_01_det( fluxlutman_args['q_polycoeffs_freq_01_det']) fluxlutman.q_polycoeffs_anharm(fluxlutman_args['q_polycoeffs_anharm']) fluxlutman.q_freq_01(fluxlutman_args['q_freq_01']) fluxlutman.q_freq_10(fluxlutman_args['q_freq_10']) noise_parameters_CZ.Z_rotations_length( noise_parameters_CZ_args['Z_rotations_length']) noise_parameters_CZ.voltage_scaling_factor( noise_parameters_CZ_args['voltage_scaling_factor']) noise_parameters_CZ.distortions( noise_parameters_CZ_args['distortions']) noise_parameters_CZ.T1_q0(noise_parameters_CZ_args['T1_q0']) noise_parameters_CZ.T1_q1(noise_parameters_CZ_args['T1_q1']) noise_parameters_CZ.T2_q0_amplitude_dependent( noise_parameters_CZ_args['T2_q0_amplitude_dependent']) noise_parameters_CZ.T2_q1(noise_parameters_CZ_args['T2_q1']) noise_parameters_CZ.w_q1_sweetspot( noise_parameters_CZ_args['w_q1_sweetspot']) noise_parameters_CZ.alpha_q1(noise_parameters_CZ_args['alpha_q1']) noise_parameters_CZ.w_bus(noise_parameters_CZ_args['w_bus']) noise_parameters_CZ.dressed_compsub( noise_parameters_CZ_args['dressed_compsub']) noise_parameters_CZ.sigma_q0(noise_parameters_CZ_args['sigma_q0']) noise_parameters_CZ.sigma_q1(noise_parameters_CZ_args['sigma_q1']) noise_parameters_CZ.T2_scaling(noise_parameters_CZ_args['T2_scaling']) else: fluxlutman = arglist['fluxlutman'] noise_parameters_CZ = arglist['noise_parameters_CZ'] sim_step = 1 / fluxlutman.sampling_rate() subdivisions_of_simstep = 4 # 4 is a good one, corresponding to a time step of 0.1 ns sim_step_new = sim_step / subdivisions_of_simstep # waveform is generated according to sampling rate of AWG, # but we can use a different step for simulating the time evolution tlist = np.arange(0, fluxlutman.cz_length(), sim_step) eps_i = fluxlutman.calc_amp_to_eps(0, state_A='11', state_B='02') theta_i = wfl.eps_to_theta(eps_i, g=fluxlutman.q_J2()) # Beware theta in radian! if not fluxlutman.czd_double_sided(): thetawave = wfl.martinis_flux_pulse( length=fluxlutman.cz_length(), lambda_2=fluxlutman.cz_lambda_2(), lambda_3=fluxlutman.cz_lambda_3(), theta_i=theta_i, theta_f=np.deg2rad(fluxlutman.cz_theta_f()), sampling_rate=fluxlutman.sampling_rate( )) # return in terms of theta epsilon = wfl.theta_to_eps(thetawave, fluxlutman.q_J2()) amp = fluxlutman.calc_eps_to_amp(epsilon, state_A='11', state_B='02') # transform detuning frequency to (positive) amplitude else: amp = get_f_pulse_double_sided(fluxlutman, theta_i) # For better accuracy in simulations, redefine amp in terms of sim_step_new. # We split here below in two cases to keep into account that certain times net-zero is one AWG time-step longer # than the conventional pulse with the same pulse length. if len(tlist) == len(amp): tlist_temp = np.concatenate( (tlist, np.array([fluxlutman.cz_length()]))) tlist_new = np.arange(0, fluxlutman.cz_length(), sim_step_new) else: tlist_temp = np.concatenate( (tlist, np.array( [fluxlutman.cz_length(), fluxlutman.cz_length() + sim_step]))) tlist_new = np.arange(0, fluxlutman.cz_length() + sim_step, sim_step_new) amp_temp = np.concatenate((amp, np.array([ amp[0] ]))) # amp should come back to the initial value, i.e. at the sweet spot amp_interp = interp1d(tlist_temp, amp_temp) amp = amp_interp(tlist_new) # We add the single qubit rotations at the end of the pulse if noise_parameters_CZ.Z_rotations_length() != 0: tlist_singlequbitrotations = np.arange( 0, noise_parameters_CZ.Z_rotations_length(), sim_step_new) amp = np.concatenate( [amp, np.zeros(len(tlist_singlequbitrotations)) + amp[0]]) tlist_new = czf.concatenate_CZpulse_and_Zrotations( noise_parameters_CZ.Z_rotations_length(), sim_step_new, tlist_new) t_final = tlist_new[-1] + sim_step_new # czf.plot(x_plot_vec=[np.array(tlist_new)*1e9],y_plot_vec=[amp], # title='Pulse with (possibly) single qubit rotations', # xlabel='Time (ns)',ylabel='Amplitude (volts)') amp = amp * noise_parameters_CZ.voltage_scaling_factor( ) # recommended to change discretely the scaling factor ### Apply distortions if noise_parameters_CZ.distortions(): amp_final = czf.distort_amplitude( fitted_stepresponse_ty=fitted_stepresponse_ty, amp=amp, tlist_new=tlist_new, sim_step_new=sim_step_new) else: amp_final = amp # czf.plot(x_plot_vec=[np.array(tlist_new)*1e9],y_plot_vec=[amp_final], # title='Pulse with distortions, absolute', # xlabel='Time (ns)',ylabel='Amplitude (volts)') # czf.plot(x_plot_vec=[np.array(tlist_new)*1e9],y_plot_vec=[amp_final-amp], # title='Pulse with distortions, difference', # xlabel='Time (ns)',ylabel='Amplitude (volts)') ### the fluxbias_q0 affects the pulse shape after the distortions have been taken into account amp_final, f_pulse_final = czf.shift_due_to_fluxbias_q0( fluxlutman=fluxlutman, amp_final=amp_final, fluxbias_q0=fluxbias_q0) # czf.plot(x_plot_vec=[np.array(tlist_new)*1e9],y_plot_vec=[amp_final-amp_final_new], # title='Pulse with distortions and shift due to fluxbias_q0, difference', # xlabel='Time (ns)',ylabel='Amplitude (volts)') # amp_final = amp_final_new # czf.plot(x_plot_vec=[np.array(tlist_new)*1e9],y_plot_vec=[f_pulse_final/1e9], # title='Pulse with distortions and shift due to fluxbias_q0', # xlabel='Time (ns)',ylabel='Frequency (GHz)') ### Obtain jump operators, possibly time-dependent (incoherent part of the noise) c_ops = czf.return_jump_operators(noise_parameters_CZ=noise_parameters_CZ, f_pulse_final=f_pulse_final) ### Compute propagator U_final = czf.time_evolution_new(c_ops=c_ops, noise_parameters_CZ=noise_parameters_CZ, fluxlutman=fluxlutman, fluxbias_q1=fluxbias_q1, amp=amp_final, sim_step=sim_step_new) #print(czf.verify_CPTP(U_superop_average)) if arglist['cluster']: fluxlutman.close() noise_parameters_CZ.close() return [U_final, t_final]
def acquire_data_point(self, **kw): sim_step = 1 / self.fluxlutman.sampling_rate() subdivisions_of_simstep = 4 sim_step_new = sim_step / subdivisions_of_simstep # waveform is generated according to sampling rate of AWG, # but we can use a different step for simulating the time evolution tlist = (np.arange(0, self.fluxlutman.cz_length(), sim_step)) tlist_new = (np.arange(0, self.fluxlutman.cz_length(), sim_step_new)) eps_i = self.fluxlutman.calc_amp_to_eps(0, state_A='11', state_B='02') self.theta_i = wfl.eps_to_theta( eps_i, g=self.fluxlutman.q_J2()) # Beware theta in radian! if not self.fluxlutman.czd_double_sided(): thetawave = wfl.martinis_flux_pulse( length=self.fluxlutman.cz_length(), lambda_2=self.fluxlutman.cz_lambda_2(), lambda_3=self.fluxlutman.cz_lambda_3(), theta_i=self.theta_i, theta_f=np.deg2rad(self.fluxlutman.cz_theta_f()), sampling_rate=self.fluxlutman.sampling_rate( )) # return in terms of theta epsilon = wfl.theta_to_eps(thetawave, self.fluxlutman.q_J2()) amp = self.fluxlutman.calc_eps_to_amp(epsilon, state_A='11', state_B='02') # transform detuning frequency to (positive) amplitude f_pulse = self.fluxlutman.calc_amp_to_freq(amp, '01') else: f_pulse, amp = self.get_f_pulse_double_sided() # For better accuracy in simulations, redefine f_pulse and amp in terms of sim_step_new tlist_temp = np.concatenate( (tlist, np.array([self.fluxlutman.cz_length()]))) f_pulse_temp = np.concatenate((f_pulse, np.array([f_pulse[-1]]))) amp_temp = np.concatenate((amp, np.array([amp[-1]]))) f_pulse_interp = interp1d(tlist_temp, f_pulse_temp) amp_interp = interp1d(tlist_temp, amp_temp) f_pulse = f_pulse_interp(tlist_new) amp = amp_interp(tlist_new) # plot(x_plot_vec=[tlist_new*1e9], # y_plot_vec=[f_pulse/1e9], # title='Freq. of fluxing qubit during pulse', # xlabel='Time (ns)',ylabel='Freq. (GHz)',legend_labels=['omega_B(t)']) amp = amp * self.noise_parameters_CZ.voltage_scaling_factor( ) # recommended to change discretely the scaling factor if self.noise_parameters_CZ.distortions(): impulse_response = np.gradient(self.fitted_stepresponse_ty[1]) # plot(x_plot_vec=[np.array(self.fitted_stepresponse_ty[0])*1e9],y_plot_vec=[self.fitted_stepresponse_ty[1]], # title='Step response', # xlabel='Time (ns)') # plot(x_plot_vec=[np.array(self.fitted_stepresponse_ty[0])*1e9],y_plot_vec=[impulse_response], # title='Impulse response', # xlabel='Time (ns)') # use interpolation to be sure that amp and impulse_response have the same delta_t separating two values amp_interp = interp1d(tlist_new, amp) impulse_response_interp = interp1d(self.fitted_stepresponse_ty[0], impulse_response) tlist_convol1 = tlist_new tlist_convol2 = np.arange(0, self.fitted_stepresponse_ty[0][-1], sim_step_new) amp_convol = amp_interp(tlist_convol1) impulse_response_convol = impulse_response_interp(tlist_convol2) convolved_amp = scipy.signal.convolve( amp_convol, impulse_response_convol) / sum(impulse_response_convol) # plot(x_plot_vec=[tlist_convol1*1e9,np.arange(np.size(convolved_amp))*sim_step_new*1e9], # y_plot_vec=[amp_convol, convolved_amp], # title='Pulse_length= {} ns'.format(self.fluxlutman.cz_length()*1e9), # xlabel='Time (ns)',ylabel='Amplitude (V)',legend_labels=['Ideal','Distorted']) amp_final = convolved_amp[0:np.size(tlist_convol1)] f_pulse_convolved_new = self.fluxlutman.calc_amp_to_freq( convolved_amp, '01') # plot(x_plot_vec=[tlist_convol1*1e9], # y_plot_vec=[amp_convol, amp_final], # title='Pulse_length= {} ns'.format(self.fluxlutman.cz_length()*1e9), # xlabel='Time (ns)',ylabel='Amplitude (V)',legend_labels=['Ideal','Distorted']) else: amp_final = amp f_pulse_convolved_new = self.fluxlutman.calc_amp_to_freq( amp_final, '01') # Noise T1_q0 = self.noise_parameters_CZ.T1_q0() T1_q1 = self.noise_parameters_CZ.T1_q1() T2_q0_sweetspot = self.noise_parameters_CZ.T2_q0_sweetspot() T2_q0_interaction_point = self.noise_parameters_CZ.T2_q0_interaction_point( ) T2_q0_amplitude_dependent = self.noise_parameters_CZ.T2_q0_amplitude_dependent( ) T2_q1 = self.noise_parameters_CZ.T2_q1() def Tphi_from_T1andT2(T1, T2): return 1 / (-1 / (2 * T1) + 1 / T2) if T2_q0_sweetspot != 0: Tphi01_q0_sweetspot = Tphi_from_T1andT2(T1_q0, T2_q0_sweetspot) else: Tphi01_q0_sweetspot = 0 if T2_q0_interaction_point != 0: Tphi01_q0_interaction_point = Tphi_from_T1andT2( T1_q0, T2_q0_interaction_point) else: Tphi01_q0_interaction_point = 0 # Tphi01=Tphi12=2*Tphi02 if T2_q1 != 0: Tphi01_q1 = Tphi_from_T1andT2(T1_q1, T2_q1) else: Tphi01_q1 = 0 if T2_q0_amplitude_dependent[ 0] != -1: # preferred way to handle T2 amplitude-dependent def expT2(x, gc, amp, tau): return gc + gc * amp * np.exp( -x / tau) # formula used to fit the experimental data T2_q0_vec = expT2(f_pulse_convolved_new, T2_q0_amplitude_dependent[0], T2_q0_amplitude_dependent[1], T2_q0_amplitude_dependent[2]) Tphi01_q0_vec = Tphi_from_T1andT2(T1_q0, T2_q0_vec) c_ops = c_ops_amplitudedependent(T1_q0, T1_q1, Tphi01_q0_vec, Tphi01_q1) else: def omega_prime(omega): # derivative of f_pulse ''' frequency is w = w_0 * cos(phi_e/2) where phi_e is the external flux through the SQUID. So the derivative wrt phi_e is w_prime = - w_0/2 sin(phi_e/2) = - w_0/2 * sqrt(1-cos(phi_e/2)**2) = - w_0/2 * sqrt(1-(w/w_0)**2) Note: no need to know what phi_e is. ''' return np.abs( (self.fluxlutman.q_freq_01() / 2) * np.sqrt(1 - (omega / self.fluxlutman.q_freq_01())**2) ) # we actually return the absolute value because it's the only one who matters later if Tphi01_q0_interaction_point != 0: # mode where the pure dephazing is amplitude-dependent w_min = np.nanmin(f_pulse_convolved_new) omega_prime_min = omega_prime(w_min) f_pulse_convolved_new = np.clip(f_pulse_convolved_new, 0, self.fluxlutman.q_freq_01()) f_pulse_convolved_new_prime = omega_prime( f_pulse_convolved_new) Tphi01_q0_vec = Tphi01_q0_sweetspot - f_pulse_convolved_new_prime / omega_prime_min * ( Tphi01_q0_sweetspot - Tphi01_q0_interaction_point) # we interpolate Tphi from the sweetspot to the interaction point (=worst point in terms of Tphi) # by weighting depending on the derivative of f_pulse compared to the derivative at the interaction point c_ops = c_ops_amplitudedependent(T1_q0, T1_q1, Tphi01_q0_vec, Tphi01_q1) else: # mode where the collapse operators are time-independent, and possibly are 0 if T1_q1 != 0: c_ops = jump_operators(T1_q0, T1_q1, 0, 0, 0, 0, 0, Tphi01_q0_sweetspot, Tphi01_q0_sweetspot, Tphi01_q0_sweetspot / 2, Tphi01_q1, Tphi01_q1, Tphi01_q1 / 2) else: c_ops = [] qoi = simulate_quantities_of_interest_superoperator( tlist=tlist_new, c_ops=c_ops, noise_parameters_CZ=self.noise_parameters_CZ, fluxlutman=self.fluxlutman, amp=amp_final, sim_step=sim_step_new, verbose=False) cost_func_val = -np.log10( 1 - qoi['avgatefid_compsubspace_pc']) # new cost function: infidelity return cost_func_val, qoi['phi_cond'], qoi['L1']*100, qoi['L2']*100, qoi['avgatefid_pc']*100, \ qoi['avgatefid_compsubspace_pc']*100, qoi['phase_q0'], qoi['phase_q1'], \ qoi['avgatefid_compsubspace']*100
def acquire_data_point(self, **kw): sim_step = 1 / self.fluxlutman.sampling_rate() subdivisions_of_simstep = 4 sim_step_new = sim_step / subdivisions_of_simstep # waveform is generated according to sampling rate of AWG, # but we can use a different step for simulating the time evolution tlist = (np.arange(0, self.fluxlutman.cz_length(), sim_step)) eps_i = self.fluxlutman.calc_amp_to_eps(0, state_A='11', state_B='02') self.theta_i = wfl.eps_to_theta( eps_i, g=self.fluxlutman.q_J2()) # Beware theta in radian! # sample flux bias from a Gaussian, in units of the flux quantum mean = 0 sigma = self.noise_parameters_CZ.sigma( ) # 4e-6 is the same value as in the surface-17 paper of tom&brian self.fluxbias = np.random.normal(mean, sigma) if not self.fluxlutman.czd_double_sided(): thetawave = wfl.martinis_flux_pulse( length=self.fluxlutman.cz_length(), lambda_2=self.fluxlutman.cz_lambda_2(), lambda_3=self.fluxlutman.cz_lambda_3(), theta_i=self.theta_i, theta_f=np.deg2rad(self.fluxlutman.cz_theta_f()), sampling_rate=self.fluxlutman.sampling_rate( )) # return in terms of theta epsilon = wfl.theta_to_eps(thetawave, self.fluxlutman.q_J2()) amp = self.fluxlutman.calc_eps_to_amp(epsilon, state_A='11', state_B='02') # transform detuning frequency to (positive) amplitude f_pulse = self.fluxlutman.calc_amp_to_freq(amp, '01') omega_0 = self.fluxlutman.calc_amp_to_freq(0, '01') f_pulse = f_pulse - np.pi/2 * (omega_0**2/f_pulse) * np.sqrt(1 - (f_pulse**4/omega_0**4)) * self.fluxbias - \ - np.pi**2/2 * omega_0 * (1+(f_pulse**4/omega_0**4)) / (f_pulse/omega_0)**3 * self.fluxbias**2 # with sigma 4e-6 the second order is irrelevant amp = self.fluxlutman.calc_freq_to_amp(f_pulse, state='01') # plot(x_plot_vec=[tlist*1e9], # y_plot_vec=[f_pulse-f_pulse_new], # title='Diff. of freq. of fluxing qubit w/o flux bias', # xlabel='Time (ns)',ylabel='Freq. (GHz)',legend_labels=['diff']) else: f_pulse, amp = self.get_f_pulse_double_sided() # For better accuracy in simulations, redefine f_pulse and amp in terms of sim_step_new if len(tlist) == len(amp): tlist_temp = np.concatenate( (tlist, np.array([self.fluxlutman.cz_length()]))) tlist_new = (np.arange(0, self.fluxlutman.cz_length(), sim_step_new)) else: tlist_temp = np.concatenate( (tlist, np.array([ self.fluxlutman.cz_length(), self.fluxlutman.cz_length() + sim_step ]))) tlist_new = (np.arange(0, self.fluxlutman.cz_length() + sim_step, sim_step_new)) f_pulse_temp = np.concatenate((f_pulse, np.array([f_pulse[-1]]))) amp_temp = np.concatenate((amp, np.array([amp[-1]]))) f_pulse_interp = interp1d(tlist_temp, f_pulse_temp) amp_interp = interp1d(tlist_temp, amp_temp) f_pulse = f_pulse_interp(tlist_new) amp = amp_interp(tlist_new) # plot(x_plot_vec=[tlist_new*1e9], # y_plot_vec=[f_pulse/1e9], # title='Freq. of fluxing qubit during pulse', # xlabel='Time (ns)',ylabel='Freq. (GHz)',legend_labels=['omega_B(t)']) amp = amp * self.noise_parameters_CZ.voltage_scaling_factor( ) # recommended to change discretely the scaling factor if self.noise_parameters_CZ.distortions(): impulse_response = np.gradient(self.fitted_stepresponse_ty[1]) # plot(x_plot_vec=[np.array(self.fitted_stepresponse_ty[0])*1e9],y_plot_vec=[self.fitted_stepresponse_ty[1]], # title='Step response', # xlabel='Time (ns)') # plot(x_plot_vec=[np.array(self.fitted_stepresponse_ty[0])*1e9],y_plot_vec=[impulse_response], # title='Impulse response', # xlabel='Time (ns)') # use interpolation to be sure that amp and impulse_response have the same delta_t separating two values amp_interp = interp1d(tlist_new, amp) impulse_response_interp = interp1d(self.fitted_stepresponse_ty[0], impulse_response) tlist_convol1 = tlist_new tlist_convol2 = np.arange(0, self.fitted_stepresponse_ty[0][-1], sim_step_new) amp_convol = amp_interp(tlist_convol1) impulse_response_convol = impulse_response_interp(tlist_convol2) convolved_amp = scipy.signal.convolve( amp_convol, impulse_response_convol) / sum(impulse_response_convol) # plot(x_plot_vec=[tlist_convol1*1e9,np.arange(np.size(convolved_amp))*sim_step_new*1e9], # y_plot_vec=[amp_convol, convolved_amp], # title='Pulse_length= {} ns'.format(self.fluxlutman.cz_length()*1e9), # xlabel='Time (ns)',ylabel='Amplitude (V)',legend_labels=['Ideal','Distorted']) amp_final = convolved_amp[0:np.size(tlist_convol1)] f_pulse_convolved_new = self.fluxlutman.calc_amp_to_freq( amp_final, '01') # plot(x_plot_vec=[tlist_convol1*1e9], # y_plot_vec=[amp_convol, amp_final], # title='Pulse_length= {} ns'.format(self.fluxlutman.cz_length()*1e9), # xlabel='Time (ns)',ylabel='Amplitude (V)',legend_labels=['Ideal','Distorted']) else: amp_final = amp f_pulse_convolved_new = self.fluxlutman.calc_amp_to_freq( amp_final, '01') # Noise T1_q0 = self.noise_parameters_CZ.T1_q0() T1_q1 = self.noise_parameters_CZ.T1_q1() T2_q0_sweetspot = self.noise_parameters_CZ.T2_q0_sweetspot() T2_q0_interaction_point = self.noise_parameters_CZ.T2_q0_interaction_point( ) T2_q0_amplitude_dependent = self.noise_parameters_CZ.T2_q0_amplitude_dependent( ) T2_q1 = self.noise_parameters_CZ.T2_q1() def Tphi_from_T1andT2(T1, T2): return 1 / (-1 / (2 * T1) + 1 / T2) if T2_q0_sweetspot != 0: Tphi01_q0_sweetspot = Tphi_from_T1andT2(T1_q0, T2_q0_sweetspot) else: Tphi01_q0_sweetspot = 0 if T2_q0_interaction_point != 0: Tphi01_q0_interaction_point = Tphi_from_T1andT2( T1_q0, T2_q0_interaction_point) else: Tphi01_q0_interaction_point = 0 # Tphi01=Tphi12=2*Tphi02 if T2_q1 != 0: Tphi01_q1 = Tphi_from_T1andT2(T1_q1, T2_q1) else: Tphi01_q1 = 0 if T2_q0_amplitude_dependent[ 0] != -1: # preferred way to handle T2 amplitude-dependent def expT2(x, gc, amp, tau): return gc + gc * amp * np.exp( -x / tau) # formula used to fit the experimental data T2_q0_vec = expT2(f_pulse_convolved_new, T2_q0_amplitude_dependent[0], T2_q0_amplitude_dependent[1], T2_q0_amplitude_dependent[2]) Tphi01_q0_vec = Tphi_from_T1andT2(T1_q0, T2_q0_vec) c_ops = c_ops_amplitudedependent(T1_q0, T1_q1, Tphi01_q0_vec, Tphi01_q1) else: # mode where the collapse operators are time-independent, and possibly are 0 if T1_q1 != 0: c_ops = jump_operators(T1_q0, T1_q1) else: c_ops = [] qoi = simulate_quantities_of_interest_superoperator( tlist=tlist_new, c_ops=c_ops, noise_parameters_CZ=self.noise_parameters_CZ, fluxlutman=self.fluxlutman, amp=amp_final, sim_step=sim_step_new, verbose=False) cost_func_val = -np.log10(1 - qoi['avgatefid_compsubspace_pc']) return cost_func_val, qoi['phi_cond'], qoi['L1']*100, qoi['L2']*100, qoi['avgatefid_pc']*100, \ qoi['avgatefid_compsubspace_pc']*100, qoi['phase_q0'], qoi['phase_q1'], \ qoi['avgatefid_compsubspace']*100, qoi['avgatefid_compsubspace_pc_onlystaticqubit']*100
def get_f_pulse_double_sided(self): thetawave_A = wfl.martinis_flux_pulse( length=self.fluxlutman.cz_length() * self.fluxlutman.czd_length_ratio(), lambda_2=self.fluxlutman.cz_lambda_2(), lambda_3=self.fluxlutman.cz_lambda_3(), theta_i=self.theta_i, theta_f=np.deg2rad(self.fluxlutman.cz_theta_f()), sampling_rate=self.fluxlutman.sampling_rate( )) # return in terms of theta epsilon_A = wfl.theta_to_eps(thetawave_A, self.fluxlutman.q_J2()) amp_A = self.fluxlutman.calc_eps_to_amp(epsilon_A, state_A='11', state_B='02') # transform detuning frequency to positive amplitude f_pulse_A = self.fluxlutman.calc_amp_to_freq(amp_A, '01') omega_0 = self.fluxlutman.calc_amp_to_freq(0, '01') f_pulse_A = f_pulse_A - np.pi/2 * (omega_0**2/f_pulse_A) * np.sqrt(1 - (f_pulse_A**4/omega_0**4)) * self.fluxbias - \ - np.pi**2/2 * omega_0 * (1+(f_pulse_A**4/omega_0**4)) / (f_pulse_A/omega_0)**3 * self.fluxbias**2 # with sigma 4e-6 the second order is irrelevant amp_A = self.fluxlutman.calc_freq_to_amp(f_pulse_A, state='01') # Generate the second CZ pulse. If the params are np.nan, default # to the main parameter if not np.isnan(self.fluxlutman.czd_theta_f()): d_theta_f = self.fluxlutman.czd_theta_f() else: d_theta_f = self.fluxlutman.cz_theta_f() if not np.isnan(self.fluxlutman.czd_lambda_2()): d_lambda_2 = self.fluxlutman.czd_lambda_2() else: d_lambda_2 = self.fluxlutman.cz_lambda_2() if not np.isnan(self.fluxlutman.czd_lambda_3()): d_lambda_3 = self.fluxlutman.czd_lambda_3() else: d_lambda_3 = self.fluxlutman.cz_lambda_3() thetawave_B = wfl.martinis_flux_pulse( length=self.fluxlutman.cz_length() * (1 - self.fluxlutman.czd_length_ratio()), lambda_2=d_lambda_2, lambda_3=d_lambda_3, theta_i=self.theta_i, theta_f=np.deg2rad(d_theta_f), sampling_rate=self.fluxlutman.sampling_rate( )) # return in terms of theta epsilon_B = wfl.theta_to_eps(thetawave_B, self.fluxlutman.q_J2()) amp_B = self.fluxlutman.calc_eps_to_amp(epsilon_B, state_A='11', state_B='02', positive_branch=False) # transform detuning frequency to negative amplitude f_pulse_B = self.fluxlutman.calc_amp_to_freq(amp_B, '01') f_pulse_B = f_pulse_B - np.pi/2 * (omega_0**2/f_pulse_B) * np.sqrt(1 - (f_pulse_B**4/omega_0**4)) * self.fluxbias * (-1) - \ - np.pi**2/2 * omega_0 * (1+(f_pulse_B**4/omega_0**4)) / (f_pulse_B/omega_0)**3 * self.fluxbias**2 # with sigma 4e-6 the second order is irrelevant amp_B = self.fluxlutman.calc_freq_to_amp(f_pulse_B, state='01', positive_branch=False) # N.B. No amp scaling and offset present f_pulse = np.concatenate([f_pulse_A, f_pulse_B]) amp = np.concatenate([amp_A, amp_B]) return f_pulse, amp