示例#1
0
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_eps_theta_conversion(self):

        eps = 800e6
        J2 = 40e6
        theta = wfl.eps_to_theta(eps=eps, g=J2)
        theta_exp = 5.71059
        self.assertAlmostEqual(np.rad2deg(theta), theta_exp, places=4)

        eps_inv = wfl.theta_to_eps(theta=theta, g=J2)
        self.assertAlmostEqual(eps, eps_inv, places=4)
    def test_eps_theta_conversion_arrays(self):
        eps = np.linspace(800e6, 0, 5)
        J2 = 40e6
        thetas = wfl.eps_to_theta(eps=eps, g=J2)
        thetas_exp = np.array(
            [0.09966865, 0.13255153, 0.19739556, 0.38050638, 1.57079633])
        np.testing.assert_array_almost_equal(thetas, thetas_exp)

        eps_inv = wfl.theta_to_eps(thetas, g=J2)
        np.testing.assert_array_almost_equal(eps, eps_inv)
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
示例#6
0
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]
示例#8
0
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
示例#10
0
    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
示例#11
0
    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