def test_quasi_static_noise_monte_carlo(self): np.random.seed(0) h_ctrl = [ DenseOperator(np.diag([.5, -.5])), ] h_drift = [DenseOperator(np.zeros((2, 2)))] n_noise_values = 20 noise_levels = 1e-4 * np.arange(1, n_noise_values + 1) actual_noise_levels = np.zeros((n_noise_values, )) average_infids = np.zeros((n_noise_values, )) for i, std_dev in enumerate(noise_levels): ntg = NTGQuasiStatic(standard_deviation=[ std_dev, ], n_samples_per_trace=1, n_traces=2000, sampling_mode='monte_carlo') ctrl_amps = 2 * np.pi * np.ones((1, 1)) * 0 t_slot_comp = SchroedingerSMonteCarlo(h_drift=h_drift, h_ctrl=h_ctrl, initial_state=DenseOperator( np.eye(2)), tau=[1], h_noise=h_ctrl, noise_trace_generator=ntg) t_slot_comp.set_optimization_parameters(ctrl_amps) quasi_static_infid = OperationNoiseInfidelity( solver=t_slot_comp, target=DenseOperator(np.eye(2)), neglect_systematic_errors=False, fidelity_measure='entanglement') average_infids[i] = quasi_static_infid.costs() * (2 / 3) actual_noise_levels[i] = np.std(ntg.noise_samples) self.assertLess( np.sum( np.abs((np.ones_like(average_infids) - average_infids / (noise_levels**2 / 6)))) / 100, 0.05) self.assertLess( np.sum( np.abs((np.ones_like(average_infids) - average_infids / (actual_noise_levels**2 / 6)))) / 100, 0.05)
def test_quasi_static_noise_deterministic_sampling(self): """ The same problem has also been positively tested with two time steps. """ h_ctrl = [ DenseOperator(np.diag([.5, -.5])), ] h_drift = [DenseOperator(np.zeros((2, 2)))] noise_levels = 1e-4 * np.arange(1, 101) actual_noise_levels = np.zeros((100, )) average_infids = np.zeros((100, )) for i, std_dev in enumerate(noise_levels): ntg = NTGQuasiStatic(standard_deviation=[ std_dev, ], n_samples_per_trace=1, n_traces=200, sampling_mode='uncorrelated_deterministic') ctrl_amps = 2 * np.pi * np.ones((1, 1)) t_slot_comp = SchroedingerSMonteCarlo(h_drift=h_drift, h_ctrl=h_ctrl, initial_state=DenseOperator( np.eye(2)), tau=[1], h_noise=h_ctrl, noise_trace_generator=ntg) t_slot_comp.set_optimization_parameters(ctrl_amps) quasi_static_infid = OperationNoiseInfidelity( solver=t_slot_comp, target=DenseOperator(np.eye(2)), neglect_systematic_errors=True, fidelity_measure='entanglement') average_infids[i] = quasi_static_infid.costs() * (2 / 3) actual_noise_levels[i] = np.std(ntg.noise_samples) self.assertLess( np.sum( np.abs((np.ones_like(average_infids) - average_infids / (noise_levels**2 / 6)))) / 100, 0.05) self.assertLess( np.sum( np.abs((np.ones_like(average_infids) - average_infids / (actual_noise_levels**2 / 6)))) / 100, 1e-5)
def quasi_static_noise(self): sigma_z = DenseOperator(np.asarray([[1, 0], [0, -1]])) sigma_x = DenseOperator(np.asarray([[0, 1], [1, 0]])) h_drift = DenseOperator(np.zeros((2, 2))) # reference_frequency = 20e9 * 2 * np.pi reference_frequency = 100e6 * 2 * np.pi driving_frequency = 1e6 * 2 * np.pi # 100 per reference period # int(reference_frequency / driving_frequency) to make one driving period # 20 driving periods n_time_steps = int(35 * reference_frequency / driving_frequency * 20) n_noise_traces = 100 # int(10 * 60 * 1e6 / 35) evolution_time = 35e-6 delta_t = evolution_time / n_time_steps down = np.asarray([[0], [1]]) up = np.asarray([[1], [0]]) x_half = rabi.x_half.data projector_left = up.T projector_right = up def up_amplitude(unitary): probability = projector_left @ unitary.data @ projector_right return np.abs(probability) ** 2 ctrl_amps = delta_t * np.arange(1, 1 + n_time_steps) ctrl_amps = driving_frequency * np.sin(reference_frequency * ctrl_amps) def rabi_driving(transferred_parameters, **_): ctrl_amps = delta_t * np.arange(1, 1 + n_time_steps) ctrl_amps = 2 * np.sin(reference_frequency * ctrl_amps) # times 2 because the rabi frequency is .5 * Amplitude ctrl_amps = np.einsum("tc, t->tc", transferred_parameters, ctrl_amps) return ctrl_amps def rabi_driving_noise(noise_samples, **_): ctrl_amps = delta_t * np.arange(1, 1 + n_time_steps) ctrl_amps = 2 * np.sin(reference_frequency * ctrl_amps) ctrl_amps = np.einsum("sno, t->tno", noise_samples, ctrl_amps) return ctrl_amps rabi_driving_amp_func = CustomAmpFunc(value_function=rabi_driving, derivative_function=None) id_transfer_func = OversamplingTF(oversampling=n_time_steps) id_transfer_func.set_times(np.asarray([evolution_time])) ts_comp_unperturbed = SchroedingerSolver( h_drift=[reference_frequency * .5 * sigma_z, ] * n_time_steps, h_ctrl=[.5 * sigma_x, ], initial_state=DenseOperator(np.eye(2)), tau=[delta_t, ] * n_time_steps, exponential_method='Frechet', ) ts_comp_lindblad = LindbladSolver( h_drift=[reference_frequency * .5 * sigma_z, ] * n_time_steps, h_ctrl=[.5 * sigma_x, ], initial_state=DenseOperator(np.eye(2)), tau=[delta_t, ] * n_time_steps, exponential_method='Frechet' ) ts_comp_unperturbed.set_optimization_parameters(np.expand_dims(ctrl_amps, 1)) """ # unperturbed: forward_propagators = ts_comp_unperturbed.forward_propagators propabilities = np.zeros((n_time_steps, )) for j in range(n_time_steps): propabilities[j] = up_amplitude(forward_propagators[j]) plt.figure() plt.plot(delta_t * np.arange(n_time_steps), propabilities) """ # Tom # todo: he seems to assume angular frequencies in his spectrum S_01 = 3e8 S_02 = 3e4 # S(f) = S_01 / f + S_02 / f^2 f_min = 1 / 10 / 60 # 1 over 10 minutes f_max = 1 / 35e-6 variance_f = S_01 * (np.log(f_max) - np.log(f_min)) \ - S_02 * (1 / f_max - 1 / f_min) sigma_f = np.sqrt(variance_f) """ # Yoneda S_0 = 3.2 * 1e6 * 4 * np.pi * np.pi f_min = 1e-2 f_max = 1 / 35e-6 variance_f = S_0 * (np.log(f_max) - np.log(f_min)) sigma_f = np.sqrt(variance_f) # 29 kHz """ expected_t2star = np.sqrt(2 / variance_f) ntg = NTGQuasiStatic( standard_deviation=[sigma_f, ], n_samples_per_trace=1, n_traces=n_noise_traces, always_redraw_samples=False, sampling_mode='monte_carlo' ) tslot_comp = SchroedingerSMonteCarlo( h_drift=[reference_frequency * .5 * sigma_z, ] * n_time_steps, h_ctrl=[.5 * sigma_x, ], h_noise=[.5 * sigma_x], initial_state=DenseOperator(np.eye(2)), tau=[delta_t, ] * n_time_steps, noise_trace_generator=ntg, exponential_method='Frechet', transfer_function=id_transfer_func, amplitude_function=rabi_driving_amp_func, noise_amplitude_function=rabi_driving_noise ) """ # for the rotating frame delta_rabi = 1.5 / 10 * 1e6 tslot_comp.set_optimization_parameters( (2 * np.pi * delta_rabi) * np.ones((n_time_steps, 1))) """ tslot_comp.set_optimization_parameters(np.asarray([[driving_frequency]])) forward_propagators = tslot_comp.forward_propagators_noise propabilities = np.zeros((n_noise_traces, n_time_steps)) for i in range(n_noise_traces): for j in range(n_time_steps): propabilities[i, j] = up_amplitude(forward_propagators[i][j]) propabilities = np.mean(propabilities, axis=0) """ def t2star_decay(t, delta_f, t2_star): return .5 * np.exp(-(t / t2_star) ** 2) * np.cos( 2 * np.pi * delta_f * t) + .5 """ def t2star_decay(t, sigma_driving): return .5 * np.exp(-.5 * (sigma_driving * t) ** 2) * np.cos(driving_frequency * t) + .5 def t2star_decay_2(t, sigma_driving): return .5 * (1 + (sigma_driving ** 2 / driving_frequency * t)) ** -.25 * np.cos(driving_frequency * t) + .5 def t2star_decay_3(t, sigma_driving, sigma_ref): up_prop = np.exp(-.5 * (sigma_driving * t) ** 2) up_prop *= (1 + (sigma_ref ** 2 / driving_frequency * t) ** 2) ** -.25 up_prop *= .5 * np.cos(driving_frequency * t) up_prop += .5 return up_prop def t2star_decay_4(t, sigma_driving, sigma_ref, periodicity): up_prop = np.exp(-.5 * (sigma_driving * t) ** 2) up_prop *= (1 + ((sigma_ref ** 2) / periodicity * t) ** 2) ** -.25 up_prop *= .5 * np.cos(periodicity * t) up_prop += .5 return up_prop def t2star_decay_5(t, sigma_driving, sigma_ref, periodicity, lin_decay): up_prop = np.exp(-.5 * (sigma_driving * t) ** 2) up_prop *= np.exp(-1 * lin_decay * t) up_prop *= (1 + ((sigma_ref ** 2) / periodicity * t) ** 2) ** -.25 up_prop *= .5 * np.cos(periodicity * t) up_prop += .5 return up_prop popt, pcov = scipy.optimize.curve_fit( t2star_decay_3, xdata=delta_t * np.arange(n_time_steps), ydata=propabilities, p0=np.asarray([sigma_f, sigma_f]) ) popt, pcov = scipy.optimize.curve_fit( t2star_decay_5, xdata=delta_t * np.arange(n_time_steps), ydata=propabilities, p0=np.asarray([sigma_f, sigma_f, driving_frequency, sigma_f]) ) self.assertLess(np.linalg.norm( propabilities - t2star_decay(delta_t * np.arange(n_time_steps), sigma_driving=sigma_f)) / len(propabilities), 1e-3) """
def test_relative_gradients_xy(self): amp_bound = rabi.rabi_frequency_max / rabi.lin_freq_rel np.random.seed(0) initial_pulse = amp_bound * ( 2 * np.random.rand(rabi.n_time_samples, 2) - 1) ntg_quasi_static = NTGQuasiStatic( standard_deviation=[ rabi.sigma_rabi, ], n_samples_per_trace=rabi.n_time_samples * rabi.oversampling, n_traces=10, always_redraw_samples=False, sampling_mode='uncorrelated_deterministic') tslot = SchroedingerSMonteCarlo( h_drift=[ 0 * rabi.h_drift, ], h_ctrl=rabi.h_ctrl, h_noise=[ rabi.h_drift, ], noise_trace_generator=ntg_quasi_static, initial_state=DenseOperator(np.eye(2)), tau=[ rabi.time_step, ] * rabi.n_time_samples, is_skew_hermitian=True, exponential_method='Frechet', transfer_function=rabi.exponential_transfer_function, amplitude_function=rabi.lin_amp_func) entanglement_infid = OperationInfidelity( solver=tslot, target=rabi.x_half, fidelity_measure='entanglement', index=['Entanglement Fidelity QS-Noise XY-Control']) tslot_noise = SchroedingerSMonteCarlo( h_drift=[ 0 * rabi.h_drift, ], h_ctrl=rabi.h_ctrl, h_noise=[ rabi.h_drift, ], noise_trace_generator=ntg_quasi_static, initial_state=DenseOperator(np.eye(2)), tau=[ rabi.time_step, ] * rabi.n_time_samples, is_skew_hermitian=True, exponential_method='Frechet', transfer_function=rabi.exponential_transfer_function, amplitude_function=rabi.lin_amp_func) entanglement_infid_qs_noise_xy = OperationNoiseInfidelity( solver=tslot_noise, target=rabi.x_half, fidelity_measure='entanglement', index=['Entanglement Fidelity QS-Noise XY-Control'], neglect_systematic_errors=True) dynamics = Simulator(solvers=[ tslot, ], cost_fktns=[ entanglement_infid, ]) dynamics_noise = Simulator(solvers=[ tslot_noise, ], cost_fktns=[entanglement_infid_qs_noise_xy]) _, rel_grad_deviation_unperturbed = \ dynamics.compare_numeric_to_analytic_gradient(initial_pulse) self.assertLess(rel_grad_deviation_unperturbed, 1e-6) _, rel_grad_deviation_qs_noise = \ dynamics_noise.compare_numeric_to_analytic_gradient(initial_pulse) self.assertLess(rel_grad_deviation_qs_noise, 1e-4)
def test_phase_control_gradient(self): amp_bound = rabi.rabi_frequency_max / rabi.lin_freq_rel phase_bound_upper = 50 / 180 * np.pi phase_bound_lower = -50 / 180 * np.pi def random_phase_control_pulse(n): amp = amp_bound * (2 * np.random.rand(n) - 1) phase = (phase_bound_upper - phase_bound_lower) \ * np.random.rand(n) \ - (phase_bound_upper - phase_bound_lower) / 2 return np.concatenate( (np.expand_dims(amp, 1), np.expand_dims(phase, 1)), axis=1) dynamics_phase_control = Simulator( solvers=[rabi.solver_qs_noise_phase_control], cost_fktns=[rabi.entanglement_infid_phase_control]) ntg_quasi_static = NTGQuasiStatic( standard_deviation=[ rabi.sigma_rabi, ], n_samples_per_trace=rabi.n_time_samples * rabi.oversampling, n_traces=10, always_redraw_samples=False, sampling_mode='uncorrelated_deterministic') time_slot_comp_qs_noise_phase_control = SchroedingerSMonteCarlo( h_drift=[ 0 * rabi.h_drift, ], h_ctrl=rabi.h_ctrl, h_noise=[ rabi.h_drift, ], noise_trace_generator=ntg_quasi_static, initial_state=DenseOperator(np.eye(2)), tau=[ rabi.time_step, ] * rabi.n_time_samples, is_skew_hermitian=True, exponential_method='Frechet', transfer_function=rabi.identity_transfer_function, amplitude_function=rabi.phase_ctrl_amp_func) entanglement_infid_qs_noise_phase_control = OperationNoiseInfidelity( solver=time_slot_comp_qs_noise_phase_control, target=rabi.x_half, fidelity_measure='entanglement', index=['Entanglement Fidelity QS-Noise Phase Control'], neglect_systematic_errors=True) dynamics_phase_control_qs_noise = Simulator( solvers=[ time_slot_comp_qs_noise_phase_control, ], cost_fktns=[ entanglement_infid_qs_noise_phase_control, ]) np.random.seed(0) inital_pulse = random_phase_control_pulse(rabi.n_time_samples) _, rel_grad_deviation_unperturbed = dynamics_phase_control.\ compare_numeric_to_analytic_gradient(inital_pulse) self.assertLess(rel_grad_deviation_unperturbed, 2e-6) _, rel_grad_deviation_qs_noise = dynamics_phase_control_qs_noise.\ compare_numeric_to_analytic_gradient(inital_pulse) self.assertLess(rel_grad_deviation_qs_noise, 5e-5)
time_step, ] * n_time_samples, is_skew_hermitian=True, exponential_method=exponential_method, transfer_function=exponential_transfer_function, amplitude_function=lin_amp_func) solver_qs_noise_xy = SchroedingerSMonteCarlo( h_drift=[ 0 * h_drift, ], h_ctrl=h_ctrl, h_noise=[ h_drift, ], noise_trace_generator=ntg_quasi_static, initial_state=DenseOperator(np.eye(2)), tau=[ time_step, ] * n_time_samples, is_skew_hermitian=True, exponential_method=exponential_method, transfer_function=exponential_transfer_function, amplitude_function=lin_amp_func) solver_qs_noise_xy_spectral = SchroedingerSMonteCarlo( h_drift=[ 0 * h_drift, ], h_ctrl=h_ctrl, h_noise=[
def create_discrete_classes(n_bit_ph: int, n_bit_amp: int): n_max_phase = 2**n_bit_ph - 1 delta_phase = phase_max / n_max_phase * np.pi / 180 # 2.2: from our group amp_bound = rabi_frequency_max * 2 * np.pi / lin_freq_rel n_max_amp = 2**n_bit_amp - 1 delta_amp = amp_bound / n_max_amp discrete_tf_phase = LinearTF(oversampling=1, bound_type=None, num_ctrls=1, linear_factor=delta_phase) discrete_tf_amp = LinearTF(oversampling=1, bound_type=None, num_ctrls=1, linear_factor=delta_amp) discrete_tf = ParallelTF(tf1=discrete_tf_amp, tf2=discrete_tf_phase) total_tf = ConcatenateTF(tf1=discrete_tf, tf2=exponential_transfer_function) total_tf.set_times(time_step * np.ones(n_time_samples)) ts_comp_unperturbed_pc_discrete = SchroedingerSolver( h_drift=[ 0 * h_drift, ] * n_time_samples * oversampling, h_ctrl=h_ctrl, initial_state=DenseOperator(np.eye(2)), tau=[ time_step / oversampling, ] * n_time_samples * oversampling, is_skew_hermitian=True, exponential_method=exponential_method, transfer_function=total_tf, amplitude_function=phase_ctrl_amp_func) time_slot_comp_qs_noise_pc_discrete = SchroedingerSMonteCarlo( h_drift=[ 0 * h_drift, ] * n_time_samples * oversampling, h_ctrl=h_ctrl, h_noise=[ h_drift, ], noise_trace_generator=ntg_quasi_static, initial_state=DenseOperator(np.eye(2)), tau=[ time_step / oversampling, ] * n_time_samples * oversampling, is_skew_hermitian=True, exponential_method=exponential_method, transfer_function=total_tf, amplitude_function=phase_ctrl_amp_func) qs_noise_pc_discrete = OperationNoiseInfidelity( solver=time_slot_comp_qs_noise_pc_discrete, target=x_half, fidelity_measure='entanglement', index=['Entanglement Fidelity QS-Noise Phase Control'], neglect_systematic_errors=True) entanglement_infid_pc_discrete = OperationInfidelity( solver=ts_comp_unperturbed_pc_discrete, target=x_half, fidelity_measure='entanglement', index=['Entanglement Fidelity Phase Control']) return [ts_comp_unperturbed_pc_discrete, time_slot_comp_qs_noise_pc_discrete], \ [entanglement_infid_pc_discrete, qs_noise_pc_discrete]
def test_quasi_static_noise(self): expected_t2star = np.sqrt(2 / variance_f) ntg = NTGQuasiStatic(standard_deviation=[ sigma_f, ], n_samples_per_trace=n_time_steps, n_traces=n_noise_traces, always_redraw_samples=False, sampling_mode='uncorrelated_deterministic') tslot_comp = SchroedingerSMonteCarlo(h_drift=[ h_drift, ] * n_time_steps, h_ctrl=[ .5 * sigma_z, ], h_noise=[.5 * sigma_z], initial_state=DenseOperator( np.eye(2)), tau=[ delta_t, ] * n_time_steps, noise_trace_generator=ntg, exponential_method='Frechet') def up_amplitude(unitary): probability = projector_left @ unitary.data @ projector_right return np.abs(probability)**2 tslot_comp.set_optimization_parameters( (2 * np.pi * delta_rabi) * np.ones((n_time_steps, 1))) forward_propagators = tslot_comp.forward_propagators_noise propabilities = np.zeros((n_noise_traces, n_time_steps)) for i in range(n_noise_traces): for j in range(n_time_steps): propabilities[i, j] = up_amplitude(forward_propagators[i][j]) propabilities = np.mean(propabilities, axis=0) # plt.figure() # plt.plot(delta_t * np.arange(n_time_steps), propabilities, marker='.') def t2star_decay(t, delta_f, t2_star): return .5 * np.exp(-(t / t2_star)**2) * np.cos( 2 * np.pi * delta_f * t) + .5 popt, pcov = scipy.optimize.curve_fit( t2star_decay, xdata=delta_t * np.arange(n_time_steps), ydata=propabilities, p0=np.asarray([delta_rabi, expected_t2star])) self.assertLess( np.linalg.norm(propabilities - t2star_decay( delta_t * np.arange(n_time_steps), popt[0], popt[1])) / len(propabilities), 1e-3) self.assertLess( np.abs((expected_t2star - popt[1]) / (expected_t2star + popt[1])), 1e-2) """